mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 01:16:06 +00:00
[libclang] Indexing API: Fully index implict template instantiations.
llvm-svn: 150267
This commit is contained in:
parent
9e0cd46d93
commit
e5dc5b31f2
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user