[libclang] Indexing API: Fully index implict template instantiations.

llvm-svn: 150267
This commit is contained in:
Argyrios Kyrtzidis 2012-02-10 20:10:44 +00:00
parent 9e0cd46d93
commit e5dc5b31f2
9 changed files with 72 additions and 5 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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();

View File

@ -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;
}
};

View File

@ -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; }
};

View File

@ -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<ClassTemplateSpecializationDecl>(D)) {
return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
}
return false;
}

View File

@ -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,