[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 c1cde7f..3c0e0fc 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -24,6 +24,7 @@
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 @@
/// 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 0c4f7dc..8814aa3 100644
--- a/include/clang/Frontend/MultiplexConsumer.h
+++ b/include/clang/Frontend/MultiplexConsumer.h
@@ -39,6 +39,7 @@
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 5afa1cd..cef4590 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -224,6 +224,11 @@
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 7be1a44..baf4d64 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 @@
// 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 d2eb402..3e92669 100644
--- a/tools/libclang/IndexDecl.cpp
+++ b/tools/libclang/IndexDecl.cpp
@@ -220,6 +220,15 @@
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 e326404..012e422 100644
--- a/tools/libclang/IndexTypeSourceInfo.cpp
+++ b/tools/libclang/IndexTypeSourceInfo.cpp
@@ -72,10 +72,14 @@
}
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 c42ef23..a70a341 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -135,6 +135,15 @@
/// 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 @@
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 059d842..47d7ff4 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -282,9 +282,23 @@
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 @@
return false;
return true;
}
+
+bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
+ if (const ClassTemplateSpecializationDecl *
+ SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
+ }
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
+ }
+ return false;
+}
diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h
index ef8e24e..38f7563 100644
--- a/tools/libclang/IndexingContext.h
+++ b/tools/libclang/IndexingContext.h
@@ -20,6 +20,7 @@
class ClassTemplateDecl;
class FunctionTemplateDecl;
class TypeAliasTemplateDecl;
+ class ClassTemplateSpecializationDecl;
namespace cxindex {
class IndexingContext;
@@ -426,6 +427,8 @@
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,