diff --git a/bin/app/data/src/test2/header.h b/bin/app/data/src/test2/header.h index 57396acb..0af9b18b 100644 --- a/bin/app/data/src/test2/header.h +++ b/bin/app/data/src/test2/header.h @@ -1,10 +1,14 @@ -template +template class TemplateTestClass { - void run(T param); +public: + template + void run(P param); }; -template -void TemplateTestClass::run(T param) +template +template +void TemplateTestClass::run(P param) { -} \ No newline at end of file +} + diff --git a/bin/app/data/src/test2/main.cpp b/bin/app/data/src/test2/main.cpp index a5eb0926..1ed9e739 100644 --- a/bin/app/data/src/test2/main.cpp +++ b/bin/app/data/src/test2/main.cpp @@ -2,6 +2,9 @@ int main() { - TemplateTestClass t2; + TemplateTestClass t1; + t1.run(6.9f); + TemplateTestClass t2; + t2.run(6); return 0; } \ No newline at end of file diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 7de310f7..dcb05365 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -534,13 +534,11 @@ Id Storage::onTemplateDefaultArgumentTypeParsed( } Id Storage::onTemplateRecordParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const std::vector& templateRecordNameHierarchy ){ - log("template record type parameter", templateParameterTypeName, location); + log("template record type parameter", utility::join(templateParameterTypeNameHierarchy, "::"), location); - std::vector templateParameterTypeNameHierarchy = templateRecordNameHierarchy; - templateParameterTypeNameHierarchy.back() += "::" + templateParameterTypeName; Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy); addTokenLocation(templateParameterNode, location); @@ -576,12 +574,10 @@ Id Storage::onTemplateRecordSpecializationParsed( } Id Storage::onTemplateFunctionParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const ParseFunction function ){ - log("template function type parameter", templateParameterTypeName, location); + log("template function type parameter", utility::join(templateParameterTypeNameHierarchy, "::"), location); - std::vector templateParameterTypeNameHierarchy; - templateParameterTypeNameHierarchy.push_back(function.getFullName() + "::"+ templateParameterTypeName); Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy); addTokenLocation(templateParameterNode, location); diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 41c3bd06..7370b34a 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -90,13 +90,13 @@ public: virtual Id onTemplateDefaultArgumentTypeParsed( const ParseTypeUsage& type, const std::vector& templateArgumentTypeNameHierarchy); virtual Id onTemplateRecordParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const std::vector& templateRecordNameHierarchy); virtual Id onTemplateRecordSpecializationParsed( const ParseLocation& location, const std::vector& specializedRecordNameHierarchy, const RecordType specializedRecordType, const std::vector& specializedFromNameHierarchy); virtual Id onTemplateFunctionParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function); + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const ParseFunction function); virtual Id onTemplateFunctionSpecializationParsed( const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction); diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index eae22cae..b90ce635 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -106,13 +106,13 @@ public: virtual Id onTemplateDefaultArgumentTypeParsed( const ParseTypeUsage& type, const std::vector& templateArgumentTypeNameHierarchy) = 0; virtual Id onTemplateRecordParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const std::vector& templateRecordNameHierarchy) = 0; virtual Id onTemplateRecordSpecializationParsed( const ParseLocation& location, const std::vector& specializedRecordNameHierarchy, const RecordType specializedRecordType, const std::vector& specializedFromNameHierarchy) = 0; virtual Id onTemplateFunctionParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const ParseFunction function) = 0; virtual Id onTemplateFunctionSpecializationParsed( const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction) = 0; diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index c05e181c..38251c1f 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -305,7 +305,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration) { m_client->onTemplateRecordParameterTypeParsed( getParseLocationForNamedDecl(namedDecl), - namedDecl->getNameAsString(), + utility::getDeclNameHierarchy(namedDecl), templateRecordNameHierarchy ); } @@ -369,7 +369,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat { m_client->onTemplateRecordParameterTypeParsed( getParseLocationForNamedDecl(namedDecl), - namedDecl->getNameAsString(), + utility::getDeclNameHierarchy(namedDecl), specializedRecordNameHierarchy ); } @@ -402,11 +402,11 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat if (isLocatedInMainFile(namedDecl)) { - std::string templateParameterTypeName = namedDecl->getNameAsString(); + std::vector templateParameterTypeNameHierarchy = utility::getDeclNameHierarchy(namedDecl); m_client->onTemplateFunctionParameterTypeParsed( getParseLocationForNamedDecl(namedDecl), - templateParameterTypeName, + templateParameterTypeNameHierarchy, templateFunction ); } diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index b87c9778..c64d5c91 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -6,47 +6,47 @@ #include "data/parser/cxx/ASTActionFactory.h" #include "data/parser/cxx/CxxDiagnosticConsumer.h" -namespace { - -static std::vector getSyntaxOnlyToolArgs(const std::vector &ExtraArgs, llvm::StringRef FileName) +namespace { - std::vector Args; - Args.push_back("clang-tool"); - Args.push_back("-fsyntax-only"); - Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end()); - Args.push_back(FileName.str()); - return Args; -} - -// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer -static bool runToolOnCodeWithArgs( - clang::DiagnosticConsumer* DiagConsumer, - clang::FrontendAction *ToolAction, - const llvm::Twine &Code, - const std::vector &Args, - const llvm::Twine &FileName = "input.cc", - const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings() -){ - llvm::SmallString<16> FileNameStorage; - llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); - llvm::IntrusiveRefCntPtr Files(new clang::FileManager(clang::FileSystemOptions())); - clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get()); - - llvm::SmallString<1024> CodeStorage; - Invocation.mapVirtualFile(FileNameRef, - Code.toNullTerminatedStringRef(CodeStorage)); - - for (auto &FilenameWithContent : VirtualMappedFiles) + static std::vector getSyntaxOnlyToolArgs(const std::vector &ExtraArgs, llvm::StringRef FileName) { - Invocation.mapVirtualFile(FilenameWithContent.first, - FilenameWithContent.second); + std::vector Args; + Args.push_back("clang-tool"); + Args.push_back("-fsyntax-only"); + Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end()); + Args.push_back(FileName.str()); + return Args; } - Invocation.setDiagnosticConsumer(DiagConsumer); + // custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer + static bool runToolOnCodeWithArgs( + clang::DiagnosticConsumer* DiagConsumer, + clang::FrontendAction *ToolAction, + const llvm::Twine &Code, + const std::vector &Args, + const llvm::Twine &FileName = "input.cc", + const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings() + ) + { + llvm::SmallString<16> FileNameStorage; + llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); + llvm::IntrusiveRefCntPtr Files(new clang::FileManager(clang::FileSystemOptions())); + clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get()); - return Invocation.run(); -} + llvm::SmallString<1024> CodeStorage; + Invocation.mapVirtualFile(FileNameRef, + Code.toNullTerminatedStringRef(CodeStorage)); + for (auto &FilenameWithContent : VirtualMappedFiles) + { + Invocation.mapVirtualFile(FilenameWithContent.first, + FilenameWithContent.second); + } + + Invocation.setDiagnosticConsumer(DiagConsumer); + + return Invocation.run(); + } } CxxParser::CxxParser(ParserClient* client, FileManager* fileManager) diff --git a/src/lib/data/parser/cxx/utilityCxx.cpp b/src/lib/data/parser/cxx/utilityCxx.cpp index 6a75c754..c160106a 100644 --- a/src/lib/data/parser/cxx/utilityCxx.cpp +++ b/src/lib/data/parser/cxx/utilityCxx.cpp @@ -105,17 +105,24 @@ namespace utility } case clang::Type::TemplateTypeParm: { - clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions()); - pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A" - pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool" - std::string typeName = qualType.getUnqualifiedType().getAsString(pp); - clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast(qualType)->getDecl(); - typeNameHerarchy = getContextNameHierarchy(templateTypeParmDecl->getDeclContext()); + std::string typeName = getDeclName(templateTypeParmDecl); + + clang::ASTContext& astContext = templateTypeParmDecl->getASTContext(); + llvm::ArrayRef parents = astContext.getParents(*(clang::dyn_cast(templateTypeParmDecl))); + if (parents.size() > 0) // usually this list contains just one parent node. + { + const clang::Decl* parentNode = parents[0].get(); // use the fist parent node. + if (clang::isa(parentNode)) + { + const clang::NamedDecl* parentNamedDecl = clang::dyn_cast(parentNode); + typeNameHerarchy = getDeclNameHierarchy(parentNamedDecl); + } + } if (typeNameHerarchy.size() == 0) { - int gogo = 0; - typeNameHerarchy.push_back(typeName); // HOT: fix this one! definition of template function outside of class scope! + LOG_ERROR("Unable to resolve type name hierarchy for template parameter \"" + typeName + "\""); + typeNameHerarchy.push_back(typeName); } else { @@ -165,7 +172,7 @@ namespace utility } else { - LOG_ERROR("unhandled declaration type"); + LOG_ERROR("unhandled declaration type: " + std::string(declaration->getDeclKindName())); } contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext()); if (clang::isa(declaration)) diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index e764b863..1324d27a 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1211,7 +1211,7 @@ public: TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); } - void test_cxx_parser_finds_template_parameter_type_of_template_class_with_multiple_parameters() + void test_cxx_parser_finds_template_parameter_types_of_template_class_with_multiple_parameters() { std::shared_ptr client = parseCode( "template \n" @@ -1225,6 +1225,26 @@ public: TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::U <1:32 1:32>"); } + void test_cxx_parser_finds_template_parameter_of_template_method_definition_outside_template_class() + { + std::shared_ptr client = parseCode( + "template \n" + "class A\n" + "{\n" + " template \n" + " U foo();\n" + "};\n" + "template \n" + "template \n" + "U A::foo()\n" + "{}\n" + ); + TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 3); + TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A::T <1:20 1:20>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A::foo::U <4:21 4:21>"); + TS_ASSERT_EQUALS(client->templateParameterTypes[2], "A::foo::U <8:20 8:20>"); + } + void test_cxx_parser_finds_template_argument_of_implicit_template_specialization() { std::shared_ptr client = parseCode( @@ -1895,11 +1915,11 @@ private: } virtual Id onTemplateRecordParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const std::vector& templateRecordNameHierarchy) { templateParameterTypes.push_back( - addLocationSuffix(utility::join(templateRecordNameHierarchy, "::") + "::" + templateParameterTypeName, location) + addLocationSuffix(utility::join(templateParameterTypeNameHierarchy, "::"), location) ); return 0; } @@ -1916,11 +1936,11 @@ private: } virtual Id onTemplateFunctionParameterTypeParsed( - const ParseLocation& location, const std::string& templateParameterTypeName, + const ParseLocation& location, const std::vector& templateParameterTypeNameHierarchy, const ParseFunction function) { templateParameterTypes.push_back( - addLocationSuffix(function.getFullName() + "::" + templateParameterTypeName, location) + addLocationSuffix(utility::join(templateParameterTypeNameHierarchy, "::"), location) ); return 0; }