summaryrefslogtreecommitdiffstats
path: root/clang/tools/libclang
diff options
context:
space:
mode:
Diffstat (limited to 'clang/tools/libclang')
-rw-r--r--clang/tools/libclang/CIndex.cpp11
-rw-r--r--clang/tools/libclang/RecursiveASTVisitor.h89
2 files changed, 99 insertions, 1 deletions
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 20079510620..0db94d6121f 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -4582,7 +4582,9 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
return clang_getNullCursor();
}
- case Decl::Var: {
+ case Decl::Var:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization: {
// Ask the variable if it has a definition.
if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition())
return MakeCXCursor(Def, TU);
@@ -4604,6 +4606,13 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
return clang_getNullCursor();
}
+ case Decl::VarTemplate: {
+ if (VarDecl *Def =
+ cast<VarTemplateDecl>(D)->getTemplatedDecl()->getDefinition())
+ return MakeCXCursor(cast<VarDecl>(Def)->getDescribedVarTemplate(), TU);
+ return clang_getNullCursor();
+ }
+
case Decl::Using:
return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D),
D->getLocation(), TU);
diff --git a/clang/tools/libclang/RecursiveASTVisitor.h b/clang/tools/libclang/RecursiveASTVisitor.h
index 2668db54797..92a6dd743ee 100644
--- a/clang/tools/libclang/RecursiveASTVisitor.h
+++ b/clang/tools/libclang/RecursiveASTVisitor.h
@@ -395,6 +395,7 @@ private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
bool TraverseClassInstantiations(ClassTemplateDecl *D);
+ bool TraverseVariableInstantiations(VarTemplateDecl *D);
bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
@@ -1418,6 +1419,57 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
// it was instantiated, and thus should not be traversed.
})
+// A helper method for traversing the implicit instantiations of a
+// class template.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
+ VarTemplateDecl *D) {
+ VarTemplateDecl::spec_iterator end = D->spec_end();
+ for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ VarTemplateSpecializationDecl *SD = *it;
+
+ switch (SD->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ TRY_TO(TraverseDecl(SD));
+ break;
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(
+ VarTemplateDecl,
+ {
+ VarDecl *TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // variable templates since they do not appear in the user code. The
+ // following code optionally traverses them.
+ //
+ // We only traverse the variable instantiations when we see the canonical
+ // declaration of the template, to ensure we only visit them once.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D == D->getCanonicalDecl())
+ TRY_TO(TraverseVariableInstantiations(D));
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
+})
+
// A helper method for traversing the instantiations of a
// function while skipping its specializations.
template<typename Derived>
@@ -1744,6 +1796,43 @@ DEF_TRAVERSE_DECL(VarDecl, {
TRY_TO(TraverseVarHelper(D));
})
+DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
+ // For implicit instantiations, we don't want to
+ // recurse at all, since the instatiated class isn't written in
+ // the source code anywhere.
+ if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the VarTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro).
+ return true;
+})
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl,
+ {
+ // The partial specialization.
+ if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ // The args that remains unspecialized.
+ TRY_TO(TraverseTemplateArgumentLocsHelper(D->getTemplateArgsAsWritten(),
+ D->getNumTemplateArgsAsWritten()));
+
+ // Don't need the VarTemplatePartialSpecializationHelper, even
+ // though that's our parent class -- we already visit all the
+ // template args here.
+ TRY_TO(TraverseVarHelper(D));
+
+ // Instantiations will have been visited with the primary
+ // template.
+})
+
DEF_TRAVERSE_DECL(ImplicitParamDecl, {
TRY_TO(TraverseVarHelper(D));
})
OpenPOWER on IntegriCloud