From: Argyrios Kyrtzidis Date: Fri, 10 Feb 2012 20:10:44 +0000 (+0000) Subject: [libclang] Indexing API: Fully index implict template instantiations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d968363877388f0a0268711d59367907b465ae1;p=clang [libclang] Indexing API: Fully index implict template instantiations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150267 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index c1cde7f3ce..3c0e0fc9dc 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -24,6 +24,7 @@ namespace clang { class SemaConsumer; // layering violation required for safe SemaConsumer class TagDecl; class VarDecl; + class FunctionDecl; /// ASTConsumer - This is an abstract interface that should be implemented by /// clients that read ASTs. This abstraction layer allows the client to be @@ -67,6 +68,12 @@ public: /// can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) {} + /// \brief Invoked when a function is implicitly instantiated. + /// Note that at this point point it does not have a body, its body is + /// instantiated at the end of the translation unit and passed to + /// HandleTopLevelDecl. + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {} + /// \brief Handle the specified top-level declaration that occurred inside /// and ObjC container. /// The default implementation ignored them. diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index 0c4f7dcc39..8814aa31bb 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -39,6 +39,7 @@ public: virtual void HandleInterestingDecl(DeclGroupRef D); virtual void HandleTranslationUnit(ASTContext &Ctx); virtual void HandleTagDeclDefinition(TagDecl *D); + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D); virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); virtual void CompleteTentativeDefinition(VarDecl *D); virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired); diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 5afa1cdadb..cef4590955 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -224,6 +224,11 @@ void MultiplexConsumer::HandleTagDeclDefinition(TagDecl *D) { Consumers[i]->HandleTagDeclDefinition(D); } +void MultiplexConsumer::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D){ + for (size_t i = 0, e = Consumers.size(); i != e; ++i) + Consumers[i]->HandleCXXImplicitFunctionInstantiation(D); +} + void MultiplexConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { for (size_t i = 0, e = Consumers.size(); i != e; ++i) Consumers[i]->HandleTopLevelDeclInObjCContainer(D); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7be1a441c4..baf4d64872 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -9483,8 +9484,11 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { // expression evaluator needing to call back into Sema if it sees a // call to such a function. InstantiateFunctionDefinition(Loc, Func); - else + else { PendingInstantiations.push_back(std::make_pair(Func, Loc)); + // Notify the consumer that a function was implicitly instantiated. + Consumer.HandleCXXImplicitFunctionInstantiation(Func); + } } } else { // Walk redefinitions, as some of them may be instantiable. diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp index d2eb402ba2..3e9266995e 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/tools/libclang/IndexDecl.cpp @@ -220,6 +220,15 @@ public: return true; } + bool VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + // FIXME: Notify subsequent callbacks that info comes from implicit + // instantiation. + if (D->isThisDeclarationADefinition()) + IndexCtx.indexTagDecl(D); + return true; + } + bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { IndexCtx.handleFunctionTemplate(D); FunctionDecl *FD = D->getTemplatedDecl(); diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp index e326404842..012e422ef5 100644 --- a/tools/libclang/IndexTypeSourceInfo.cpp +++ b/tools/libclang/IndexTypeSourceInfo.cpp @@ -72,10 +72,14 @@ public: } bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { - if (const TemplateSpecializationType *T = TL.getTypePtr()) + if (const TemplateSpecializationType *T = TL.getTypePtr()) { if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), + Parent, ParentDC); + } return true; } }; diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index c42ef2308a..a70a341543 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -135,6 +135,15 @@ public: /// The default implementation forwards to HandleTopLevelDecl but we don't /// care about them when indexing, so have an empty definition. virtual void HandleInterestingDecl(DeclGroupRef D) {} + + virtual void HandleTagDeclDefinition(TagDecl *D) { + if (IndexCtx.isTemplateImplicitInstantiation(D)) + IndexCtx.indexDecl(D); + } + + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { + IndexCtx.indexDecl(D); + } }; //===----------------------------------------------------------------------===// @@ -185,7 +194,7 @@ public: indexDiagnostics(CXTU, IndexCtx); } - virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; } + virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } virtual bool hasCodeCompletionSupport() const { return false; } }; diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index 059d842515..47d7ff42a9 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -282,9 +282,23 @@ bool IndexingContext::handleDecl(const NamedDecl *D, DInfo.numAttributes = AttrList.getNumAttrs(); getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer); - getContainerInfo(D->getLexicalDeclContext(), DInfo.LexicalContainer); DInfo.semanticContainer = &DInfo.SemanticContainer; - DInfo.lexicalContainer = &DInfo.LexicalContainer; + + if (D->getLexicalDeclContext() == D->getDeclContext()) { + DInfo.lexicalContainer = &DInfo.SemanticContainer; + } else if (isTemplateImplicitInstantiation(D)) { + // Implicit instantiations have the lexical context of where they were + // instantiated first. We choose instead the semantic context because: + // 1) at the time that we see the instantiation we have not seen the + // function where it occurred yet. + // 2) the lexical context of the first instantiation is not useful + // information anyway. + DInfo.lexicalContainer = &DInfo.SemanticContainer; + } else { + getContainerInfo(D->getLexicalDeclContext(), DInfo.LexicalContainer); + DInfo.lexicalContainer = &DInfo.LexicalContainer; + } + if (DInfo.isContainer) { getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer); DInfo.declAsContainer = &DInfo.DeclAsContainer; @@ -1036,3 +1050,14 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { return false; return true; } + +bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { + if (const ClassTemplateSpecializationDecl * + SD = dyn_cast(D)) { + return SD->getSpecializationKind() == TSK_ImplicitInstantiation; + } + if (const FunctionDecl *FD = dyn_cast(D)) { + return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation; + } + return false; +} diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index ef8e24e7c3..38f7563b57 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -20,6 +20,7 @@ namespace clang { class ClassTemplateDecl; class FunctionTemplateDecl; class TypeAliasTemplateDecl; + class ClassTemplateSpecializationDecl; namespace cxindex { class IndexingContext; @@ -426,6 +427,8 @@ public: CXIdxClientEntity getClientEntity(const Decl *D) const; void setClientEntity(const Decl *D, CXIdxClientEntity client); + static bool isTemplateImplicitInstantiation(const Decl *D); + private: bool handleDecl(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,