logic: fixed respecting the provided order of template arguments of partial template specialization
This commit is contained in:
committed by
Eberhard Graether
parent
0498d68f5b
commit
5a18d0973e
@@ -2,6 +2,11 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
std::unique_ptr<CxxTypeName> CxxTypeName::getUnsolved()
|
||||
{
|
||||
return std::make_unique<CxxTypeName>(L"unsolved-type");
|
||||
}
|
||||
|
||||
std::unique_ptr<CxxTypeName> CxxTypeName::makeUnsolvedIfNull(std::unique_ptr<CxxTypeName> name)
|
||||
{
|
||||
if (name)
|
||||
@@ -9,7 +14,7 @@ std::unique_ptr<CxxTypeName> CxxTypeName::makeUnsolvedIfNull(std::unique_ptr<Cxx
|
||||
return name;
|
||||
}
|
||||
|
||||
return std::make_unique<CxxTypeName>(L"unsolved-type");
|
||||
return getUnsolved();
|
||||
}
|
||||
|
||||
CxxTypeName::Modifier::Modifier(std::wstring symbol)
|
||||
|
||||
@@ -13,6 +13,7 @@ class CxxTypeName
|
||||
: public CxxName
|
||||
{
|
||||
public:
|
||||
static std::unique_ptr<CxxTypeName> getUnsolved();
|
||||
static std::unique_ptr<CxxTypeName> makeUnsolvedIfNull(std::unique_ptr<CxxTypeName> name);
|
||||
|
||||
struct Modifier
|
||||
|
||||
@@ -102,6 +102,7 @@ std::unique_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
|
||||
ScopedSwitcher<const clang::NamedDecl*> switcher(m_currentDecl, declaration);
|
||||
|
||||
std::wstring declNameString = utility::decodeFromUtf8(declaration->getNameAsString());
|
||||
|
||||
if (const clang::TagDecl* tagDecl = clang::dyn_cast_or_null<clang::TagDecl>(declaration))
|
||||
{
|
||||
if (const clang::TypedefNameDecl* typedefNameDecl = tagDecl->getTypedefNameForAnonDecl())
|
||||
@@ -118,6 +119,7 @@ std::unique_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
|
||||
return getDeclName(templatedDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null<clang::RecordDecl>(declaration))
|
||||
{
|
||||
if (recordDecl->isLambda())
|
||||
|
||||
@@ -37,26 +37,57 @@ std::vector<std::wstring> CxxDeclNameResolver::getTemplateParameterStringsOfPart
|
||||
{
|
||||
std::vector<std::wstring> templateParameterNames;
|
||||
clang::TemplateParameterList* parameterList = partialSpecializationDecl->getTemplateParameters();
|
||||
unsigned int currentParameterIndex = 0;
|
||||
|
||||
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
|
||||
const int templateArgumentCount = templateArgumentList.size();
|
||||
for (int i = 0; i < templateArgumentCount; i++)
|
||||
for (int i = 0; i < templateArgumentList.size(); i++)
|
||||
{
|
||||
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
|
||||
if (templateArgument.isDependent()) // IMPORTANT_TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
|
||||
if (templateArgument.isDependent())
|
||||
{
|
||||
if (currentParameterIndex < parameterList->size())
|
||||
if (templateArgument.getKind() == clang::TemplateArgument::Type && !templateArgument.getAsType().isNull())
|
||||
{
|
||||
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(currentParameterIndex)));
|
||||
const clang::Type* argumentType = templateArgument.getAsType().getTypePtr();
|
||||
if (const clang::TemplateTypeParmType* ttpt = clang::dyn_cast<clang::TemplateTypeParmType>(argumentType))
|
||||
{
|
||||
if (ttpt->getDepth() == parameterList->getDepth())
|
||||
{
|
||||
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(ttpt->getIndex())));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
|
||||
templateParameterNames.push_back(L"arg" + std::to_wstring(ttpt->getDepth()) + L"_" + std::to_wstring(ttpt->getIndex()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
templateParameterNames.push_back(std::move(CxxTypeName::makeUnsolvedIfNull(CxxTypeNameResolver(this).getName(argumentType))->toString()));
|
||||
}
|
||||
}
|
||||
else if (templateArgument.getKind() == clang::TemplateArgument::Template && !templateArgument.getAsTemplate().isNull())
|
||||
{
|
||||
const clang::TemplateTemplateParmDecl* decl = clang::dyn_cast<clang::TemplateTemplateParmDecl>(templateArgument.getAsTemplate().getAsTemplateDecl());
|
||||
if (decl)
|
||||
{
|
||||
if (decl->getDepth() == parameterList->getDepth())
|
||||
{
|
||||
templateParameterNames.push_back(getTemplateParameterString(parameterList->getParam(decl->getIndex())));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: fix case when arg depends on template parameter of outer template class, or depends on first template parameter.
|
||||
templateParameterNames.push_back(L"arg" + std::to_wstring(decl->getDepth()) + L"_" + std::to_wstring(decl->getIndex()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//this if fixes the crash, but not the problem TODO
|
||||
// const clang::SourceManager& sourceManager = declaration->getASTContext().getSourceManager();
|
||||
// LOG_ERROR("Template getParam out of Range " + declaration->getLocation().printToString(sourceManager));
|
||||
templateParameterNames.push_back(getTemplateArgumentName(templateArgument));
|
||||
}
|
||||
currentParameterIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -16,22 +16,65 @@ class CxxParserTestSuite: public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
|
||||
//void test_foofooofooofow()
|
||||
//{
|
||||
// std::shared_ptr<TestIntermediateStorage> client = parseCode(
|
||||
// "template <typename T1, typename T2>\n"
|
||||
// "class vector { };\n"
|
||||
// "template<class T>\n"
|
||||
// "struct Alloc { };\n"
|
||||
// "template<class T>\n"
|
||||
// "using Vec = vector<T, Alloc<T>>;\n"
|
||||
// "Vec<int> v;\n"
|
||||
// );
|
||||
void test_foofooofooofow()
|
||||
{
|
||||
{
|
||||
std::shared_ptr<TestIntermediateStorage> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A {};\n"
|
||||
"template <typename T1, typename T2>\n"
|
||||
"class vector { };\n"
|
||||
"template<class Foo1>\n"
|
||||
"class vector<Foo1, A<Foo1>> { };\n"
|
||||
);
|
||||
|
||||
// TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
// client->typeUses, L"B<A, template<typename> typename U> -> A<typename T> <8:9 8:9>"
|
||||
// ));
|
||||
//}
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->classes, L"vector<class Foo1, A<typename T>> <5:1 <6:7 6:12> 6:31>"
|
||||
));
|
||||
}
|
||||
{
|
||||
std::shared_ptr<TestIntermediateStorage> client = parseCode(
|
||||
"template <typename T1, typename T2, typename T3>\n"
|
||||
"class vector { };\n"
|
||||
"template<class Foo1, class Foo2>\n"
|
||||
"class vector<Foo2, Foo1, int> { };\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->classes, L"vector<class Foo2, class Foo1, int> <3:1 <4:7 4:12> 4:33>"
|
||||
));
|
||||
}
|
||||
{
|
||||
std::shared_ptr<TestIntermediateStorage> client = parseCode(
|
||||
"template <typename T0>\n"
|
||||
"class foo {\n"
|
||||
" template <typename T1, typename T2>\n"
|
||||
" class vector { };\n"
|
||||
" template<class T1>\n"
|
||||
" class vector<T0, T1> { };\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->classes, L"foo<typename T0>::vector<arg0_0, class T1> <5:2 <6:8 6:13> 6:25>"
|
||||
));
|
||||
}
|
||||
{
|
||||
//std::shared_ptr<TestIntermediateStorage> client = parseCode(
|
||||
// "template <typename T1, typename T2>\n"
|
||||
// "class vector { };\n"
|
||||
// "template<class T>\n"
|
||||
// "struct Alloc { };\n"
|
||||
// "template<class T>\n"
|
||||
// "using Vec = vector<T, Alloc<T>>;\n" // record not Vector<vec<T>::T.........
|
||||
// "Vec<int> v;\n"
|
||||
//);
|
||||
|
||||
//TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
// client->typeUses, L"B<A, template<typename> typename U> -> A<typename T> <8:9 8:9>"
|
||||
// ));
|
||||
}
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_usage_of_field_in_function_call_arguments()
|
||||
{
|
||||
@@ -3614,7 +3657,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->typeUses, L"A<&g_p, P * q> -> P g_p <8:10 8:12>" //TODO this is completely wrong? should be a normal usage
|
||||
client->typeUses, L"A<&g_p, q> -> P g_p <8:10 8:12>" //TODO this is completely wrong? should be a normal usage
|
||||
));
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->localSymbols, L"input.cc<7:14> <8:15 8:15>"
|
||||
@@ -3637,7 +3680,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->typeUses, L"A<&g_p, P & q> -> P g_p <8:9 8:11>"
|
||||
client->typeUses, L"A<&g_p, q> -> P g_p <8:9 8:11>"
|
||||
));
|
||||
TS_ASSERT(utility::containsElement<std::wstring>(
|
||||
client->localSymbols, L"input.cc<7:14> <8:14 8:14>"
|
||||
|
||||
Reference in New Issue
Block a user