From 5a18d0973e46c6bc093735e74efb9e4c1e98a3d7 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 30 Sep 2019 11:36:23 +0200 Subject: [PATCH] logic: fixed respecting the provided order of template arguments of partial template specialization --- .../data/parser/cxx/name/CxxTypeName.cpp | 7 +- .../data/parser/cxx/name/CxxTypeName.h | 1 + .../cxx/name_resolver/CxxDeclNameResolver.cpp | 2 + .../cxx/name_resolver/CxxDeclNameResolver.h | 51 +++++++++--- src/test/CxxParserTestSuite.h | 77 +++++++++++++++---- 5 files changed, 110 insertions(+), 28 deletions(-) diff --git a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp index 411e3345..0e62e5e3 100644 --- a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp +++ b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.cpp @@ -2,6 +2,11 @@ #include +std::unique_ptr CxxTypeName::getUnsolved() +{ + return std::make_unique(L"unsolved-type"); +} + std::unique_ptr CxxTypeName::makeUnsolvedIfNull(std::unique_ptr name) { if (name) @@ -9,7 +14,7 @@ std::unique_ptr CxxTypeName::makeUnsolvedIfNull(std::unique_ptr(L"unsolved-type"); + return getUnsolved(); } CxxTypeName::Modifier::Modifier(std::wstring symbol) diff --git a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h index cc5ee577..0a3fe570 100644 --- a/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h +++ b/src/lib_cxx/data/parser/cxx/name/CxxTypeName.h @@ -13,6 +13,7 @@ class CxxTypeName : public CxxName { public: + static std::unique_ptr getUnsolved(); static std::unique_ptr makeUnsolvedIfNull(std::unique_ptr name); struct Modifier diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp index 10f7a297..6f47db03 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp @@ -102,6 +102,7 @@ std::unique_ptr CxxDeclNameResolver::getDeclName(const clang::Named ScopedSwitcher switcher(m_currentDecl, declaration); std::wstring declNameString = utility::decodeFromUtf8(declaration->getNameAsString()); + if (const clang::TagDecl* tagDecl = clang::dyn_cast_or_null(declaration)) { if (const clang::TypedefNameDecl* typedefNameDecl = tagDecl->getTypedefNameForAnonDecl()) @@ -118,6 +119,7 @@ std::unique_ptr CxxDeclNameResolver::getDeclName(const clang::Named return getDeclName(templatedDeclaration); } } + if (const clang::RecordDecl* recordDecl = clang::dyn_cast_or_null(declaration)) { if (recordDecl->isLambda()) diff --git a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h index 40e6da1d..b7dcb45d 100644 --- a/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h +++ b/src/lib_cxx/data/parser/cxx/name_resolver/CxxDeclNameResolver.h @@ -37,26 +37,57 @@ std::vector CxxDeclNameResolver::getTemplateParameterStringsOfPart { std::vector 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(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(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 { diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 6ea5c28c..1cc7564d 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -16,22 +16,65 @@ class CxxParserTestSuite: public CxxTest::TestSuite { public: - //void test_foofooofooofow() - //{ - // std::shared_ptr client = parseCode( - // "template \n" - // "class vector { };\n" - // "template\n" - // "struct Alloc { };\n" - // "template\n" - // "using Vec = vector>;\n" - // "Vec v;\n" - // ); + void test_foofooofooofow() + { + { + std::shared_ptr client = parseCode( + "template \n" + "class A {};\n" + "template \n" + "class vector { };\n" + "template\n" + "class vector> { };\n" + ); - // TS_ASSERT(utility::containsElement( - // client->typeUses, L"B typename U> -> A <8:9 8:9>" - // )); - //} + TS_ASSERT(utility::containsElement( + client->classes, L"vector> <5:1 <6:7 6:12> 6:31>" + )); + } + { + std::shared_ptr client = parseCode( + "template \n" + "class vector { };\n" + "template\n" + "class vector { };\n" + ); + + TS_ASSERT(utility::containsElement( + client->classes, L"vector <3:1 <4:7 4:12> 4:33>" + )); + } + { + std::shared_ptr client = parseCode( + "template \n" + "class foo {\n" + " template \n" + " class vector { };\n" + " template\n" + " class vector { };\n" + "};\n" + ); + + TS_ASSERT(utility::containsElement( + client->classes, L"foo::vector <5:2 <6:8 6:13> 6:25>" + )); + } + { + //std::shared_ptr client = parseCode( + // "template \n" + // "class vector { };\n" + // "template\n" + // "struct Alloc { };\n" + // "template\n" + // "using Vec = vector>;\n" // record not Vector::T......... + // "Vec v;\n" + //); + + //TS_ASSERT(utility::containsElement( + // client->typeUses, L"B typename U> -> A <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( - 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( client->localSymbols, L"input.cc<7:14> <8:15 8:15>" @@ -3637,7 +3680,7 @@ public: ); TS_ASSERT(utility::containsElement( - 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( client->localSymbols, L"input.cc<7:14> <8:14 8:14>"