diff --git a/src/lib_parser/data/parser/cxx/ASTVisitor.cpp b/src/lib_parser/data/parser/cxx/ASTVisitor.cpp index 132fe8b9..ffb47aef 100644 --- a/src/lib_parser/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib_parser/data/parser/cxx/ASTVisitor.cpp @@ -38,10 +38,23 @@ ASTVisitor::ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preproce , m_typeContext(RT_Reference) , m_contextAccess(ParserClient::ACCESS_NONE) { - m_declNameCache = std::make_shared(); - m_typeNameCache = std::make_shared(); - m_contextNameGenerator = std::make_shared(nullptr, m_declNameCache); - m_childContextNameGenerator = std::make_shared(nullptr, m_declNameCache); + m_declNameCache = std::make_shared([](const clang::NamedDecl* decl) -> NameHierarchy + { + if (decl) + { + return utility::getDeclNameHierarchy(decl); + } + return NameHierarchy("global"); + }); + m_typeNameCache = std::make_shared([](const clang::Type* type) -> NameHierarchy + { + if (type) + { + CxxTypeNameResolver resolver; + return resolver.getTypeNameHierarchy(type); + } + return NameHierarchy("global"); + }); } ASTVisitor::~ASTVisitor() @@ -50,7 +63,7 @@ ASTVisitor::~ASTVisitor() bool ASTVisitor::VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl) { - //decl->dump(); + decl->dump(); return true; } @@ -152,8 +165,8 @@ bool ASTVisitor::TraverseVarDecl(clang::VarDecl *d) { std::shared_ptr>> switcher; - NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName(); - if (!(contextNameHierarchy.size() > 0 && contextNameHierarchy.back()->hasSignature())) // TODO: optimize this: remove requirement to get the name here! + NameHierarchy contextNameHierarchy = getContextName(); + if (!(contextNameHierarchy.size() > 0 && contextNameHierarchy.back()->hasSignature())) // TODO: whle test if its a function. optimize this: remove requirement to get the name here! { switcher = std::make_shared>>(m_contextNameGenerator, std::make_shared(d, m_declNameCache)); } @@ -166,6 +179,13 @@ bool ASTVisitor::TraverseClassTemplateDecl(clang::ClassTemplateDecl* d) return base::TraverseClassTemplateDecl(d); } +bool ASTVisitor::TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d) +{ + // we need to use the templated decl here because name resolving for FunctionTemplateDecl is not returning a correct signature yet. + ScopedSwitcher> switcher(m_contextNameGenerator, std::make_shared(d->getTemplatedDecl(), m_declNameCache)); + return base::TraverseFunctionTemplateDecl(d); +} + bool ASTVisitor::TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) { // same as base::TraverseTemplateTypeParmDecl(..) but we need to integrate the setter for the context info. @@ -194,7 +214,6 @@ bool ASTVisitor::TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDec ScopedSwitcher sw1(m_typeContext, RT_TemplateDefaultArgument); ScopedSwitcher> sw2(m_contextNameGenerator, std::make_shared(d, m_declNameCache)); - //d->getDefaultArgument TraverseTemplateArgumentLoc(d->getDefaultArgument()); } @@ -230,12 +249,22 @@ bool ASTVisitor::TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializa return base::TraverseTemplateSpecializationTypeLoc(loc); } +bool ASTVisitor::TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff +{ + std::shared_ptr n; + ScopedSwitcher> sw(m_childContextNameGenerator, n); + return base::TraverseUnresolvedLookupExpr(e); +} + bool ASTVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) { std::shared_ptr> sw1; std::shared_ptr>> sw2; - if (m_typeContext != RT_TemplateDefaultArgument) + if (m_typeContext != RT_TemplateDefaultArgument + && + m_childContextNameGenerator + ) { sw1 = std::make_shared>(m_typeContext, RT_TemplateArgument); sw2 = std::make_shared>>(m_contextNameGenerator, m_childContextNameGenerator); @@ -250,12 +279,6 @@ bool ASTVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& l return base::TraverseTemplateArgumentLoc(loc); } -//bool ASTVisitor::TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d) -//{ -// ScopedSwitcher switcher(m_contextDecl, d); -// return base::TraverseFunctionTemplateDecl(d); -//} - /////////////////////////////////////////////////////////////////////////////// // Expression context propagation @@ -1052,8 +1075,8 @@ void ASTVisitor::RecordTypeRef( if (isLocatedInProjectFile(beginLoc)) { ParseLocation parseLocation = getDeclRefRange(0, beginLoc); - NameHierarchy typeNameHierarchy = m_typeNameCache->getName(type); - NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName(); + NameHierarchy typeNameHierarchy = m_typeNameCache->getValue(type); + NameHierarchy contextNameHierarchy = getContextName(); if (refType == RT_TemplateArgument) { @@ -1112,7 +1135,8 @@ void ASTVisitor::RecordDeclRef( } ParseLocation parseLocation = getDeclRefRange(d, beginLoc); - NameHierarchy declNameHierarchy = m_declNameCache->getName(d); + //NameHierarchy declNameHierarchy = m_declNameCache->getValue(d); + NameHierarchy declNameHierarchy = utility::getDeclNameHierarchy(d); bool fallback = false; @@ -1192,7 +1216,7 @@ void ASTVisitor::RecordDeclRef( { m_client->onMethodOverrideParsed( parseLocation, - m_declNameCache->getName(*it), + m_declNameCache->getValue(*it), declNameHierarchy); } @@ -1205,7 +1229,7 @@ void ASTVisitor::RecordDeclRef( m_client->onTemplateMemberFunctionSpecializationParsed( parseLocation, declNameHierarchy, - m_declNameCache->getName(specializedNamedDecl)); + m_declNameCache->getValue(specializedNamedDecl)); } } } @@ -1266,7 +1290,7 @@ void ASTVisitor::RecordDeclRef( m_client->onTemplateSpecializationParsed( parseLocation, declNameHierarchy, - m_declNameCache->getName(specializedFromDecl)); // use context and childcontext!! + m_declNameCache->getValue(specializedFromDecl)); // use context and childcontext!! } break; case ST_FunctionTemplateSpecialization: @@ -1275,7 +1299,7 @@ void ASTVisitor::RecordDeclRef( m_client->onTemplateSpecializationParsed( parseLocation, declNameHierarchy, - m_declNameCache->getName(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use contect and childcontext!! + m_declNameCache->getValue(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use contect and childcontext!! } break; case ST_LocalVariable: @@ -1289,7 +1313,7 @@ void ASTVisitor::RecordDeclRef( } else { - const NameHierarchy contextNameHierarchy = m_contextNameGenerator->getName(); + const NameHierarchy contextNameHierarchy = getContextName(); switch (symbolType) { case ST_Field: @@ -1570,3 +1594,12 @@ ParseLocation ASTVisitor::getParseLocation(const clang::SourceRange& sourceRange presumedEnd.getColumn() ); } + +NameHierarchy ASTVisitor::getContextName() +{ + if (m_contextNameGenerator) + { + return m_contextNameGenerator->getName(); + } + return NameHierarchy("global"); +} diff --git a/src/lib_parser/data/parser/cxx/ASTVisitor.h b/src/lib_parser/data/parser/cxx/ASTVisitor.h index 36b5ee42..7c59fa3b 100644 --- a/src/lib_parser/data/parser/cxx/ASTVisitor.h +++ b/src/lib_parser/data/parser/cxx/ASTVisitor.h @@ -10,6 +10,7 @@ #include "data/parser/ParserClient.h" #include "utility/file/FileRegister.h" +#include "utility/Cache.h" @@ -19,61 +20,8 @@ class ASTVisitor: clang::RecursiveASTVisitor { public: - - class TypeNameCache - { - public: - NameHierarchy getName(const clang::Type* type) - { - if (type) - { - NameHierarchy nameHierarchy; - std::unordered_map::const_iterator it = m_typeNameMap.find(type); - if (it != m_typeNameMap.end()) - { - nameHierarchy = it->second; - } - else - { - CxxTypeNameResolver resolver; - nameHierarchy = resolver.getTypeNameHierarchy(type); - m_typeNameMap[type] = nameHierarchy; - } - return nameHierarchy; - } - return NameHierarchy("global"); - } - - private: - std::unordered_map m_typeNameMap; - }; - - class DeclNameCache - { - public: - NameHierarchy getName(const clang::NamedDecl* decl) - { - if (decl) - { - NameHierarchy nameHierarchy; - std::unordered_map::const_iterator it = m_declNameCache.find(decl); - if (it != m_declNameCache.end()) - { - nameHierarchy = it->second; - } - else - { - nameHierarchy = utility::getDeclNameHierarchy(decl); - m_declNameCache[decl] = nameHierarchy; - } - return nameHierarchy; - } - return NameHierarchy("global"); - } - - private: - std::unordered_map m_declNameCache; - }; + typedef Cache DeclNameCache; + typedef Cache TypeNameCache; class ContextNameGenerator { @@ -94,8 +42,9 @@ public: virtual NameHierarchy getName() const { - return m_nameCache->getName(m_decl); + return m_nameCache->getValue(m_decl); } + private: const clang::NamedDecl* m_decl; std::shared_ptr m_nameCache; @@ -113,8 +62,9 @@ public: virtual NameHierarchy getName() const { - return m_nameCache->getName(m_type); + return m_nameCache->getValue(m_type); } + private: const clang::Type* m_type; std::shared_ptr m_nameCache; @@ -225,11 +175,13 @@ private: bool TraverseFieldDecl(clang::FieldDecl *d); bool TraverseVarDecl(clang::VarDecl *d); bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* d); + bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d); bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d); bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d); bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d); - bool TraverseDeclRefExpr(clang::DeclRefExpr* expr); + bool TraverseDeclRefExpr(clang::DeclRefExpr* e); bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc); + bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e); bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc); // Expression context propagation @@ -302,6 +254,8 @@ private: ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const; ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; + NameHierarchy getContextName(); + struct FileIdHash { size_t operator()(clang::FileID fileID) const { return fileID.getHashValue(); @@ -312,7 +266,7 @@ private: std::unordered_map m_inProjectFileMap; std::shared_ptr m_contextNameGenerator; - std::shared_ptr m_childContextNameGenerator; + std::shared_ptr m_childContextNameGenerator; // TODO: rename templateArgumentContextNameGenerator std::shared_ptr m_declNameCache; std::shared_ptr m_typeNameCache; diff --git a/src/lib_parser/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp b/src/lib_parser/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp index 2b29e2e9..4d3737c9 100644 --- a/src/lib_parser/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp +++ b/src/lib_parser/data/parser/cxx/name_resolver/CxxDeclNameResolver.cpp @@ -10,14 +10,24 @@ CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration) : CxxNameResolver(std::vector()) - , m_declaration(declaration) { + const clang::Decl* prev = declaration; + while (prev) + { + m_declaration = prev; + prev = prev->getPreviousDecl(); + } } CxxDeclNameResolver::CxxDeclNameResolver(const clang::Decl* declaration, std::vector ignoredContextDecls) : CxxNameResolver(ignoredContextDecls) - , m_declaration(declaration) { + const clang::Decl* prev = declaration; + while (prev) + { + m_declaration = prev; + prev = prev->getPreviousDecl(); + } } CxxDeclNameResolver::~CxxDeclNameResolver() diff --git a/src/lib_parser/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp b/src/lib_parser/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp index 2aa45246..699aca77 100644 --- a/src/lib_parser/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp +++ b/src/lib_parser/data/parser/cxx/name_resolver/CxxTemplateArgumentNameResolver.cpp @@ -23,6 +23,8 @@ CxxTemplateArgumentNameResolver::~CxxTemplateArgumentNameResolver() std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang::TemplateArgument& argument) { + // This doesn't work correctly if the template argument is dependent. + // If that's required: build name from depth and index of template arg. const clang::TemplateArgument::ArgKind kind = argument.getKind(); switch (kind) { diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 55beda5e..afdbb733 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -2625,6 +2625,27 @@ public: TS_ASSERT_EQUALS(client->calls[1], "void lambdaCaller::lambda at 4:2() -> void func() <6:3 6:6>"); } + void test_cxx_parser_finds_template_argument_of_unresolved_lookup_expression_as_type_use() + { + std::shared_ptr client = parseCode( + "template \n" + "void a()\n" + "{\n" + "}\n" + "\n" + "template\n" + "void dispatch()\n" + "{\n" + " a();\n" + "}\n" + ); + + TS_ASSERT_EQUALS(client->typeUses.size(), 3); + TS_ASSERT_EQUALS(client->typeUses[0], "void a() -> void <2:1 2:4>"); + TS_ASSERT_EQUALS(client->typeUses[1], "void dispatch() -> void <7:1 7:4>"); + TS_ASSERT_EQUALS(client->typeUses[2], "void dispatch() -> dispatch::MessageType <9:4 9:14>"); + } + /////////////////////////////////////////////////////////////////////////////// // test finding symbol locations