Implement basic support for indexing function templates in
libclang. This includes:
- Cursor kind for function templates, with visitation logic
- Cursor kinds for template parameters, with visitation logic
- Visitation logic for template specialization types, qualified type
locations
- USR generation for function templates, template specialization
types, template parameter types.
Also happens to fix PR7804, which I tripped across while testing.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112604 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index fc66592..6629f5c 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -290,11 +290,13 @@
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitTypedefDecl(TypedefDecl *D);
bool VisitTagDecl(TagDecl *D);
+ bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
bool VisitEnumConstantDecl(EnumConstantDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitFieldDecl(FieldDecl *D);
bool VisitVarDecl(VarDecl *);
+ bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
@@ -311,17 +313,21 @@
bool VisitObjCClassDecl(ObjCClassDecl *D);
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
-
+
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
+ // Template visitors
+ bool VisitTemplateParameters(const TemplateParameterList *Params);
+ bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
+
// Type visitors
bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
bool VisitTagTypeLoc(TagTypeLoc TL);
- // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
@@ -332,7 +338,7 @@
bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
bool VisitArrayTypeLoc(ArrayTypeLoc TL);
- // FIXME: Implement for TemplateSpecializationTypeLoc
+ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
// FIXME: Implement visitors here when the unimplemented TypeLocs get
// implemented
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
@@ -593,6 +599,11 @@
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ // FIXME: Visit default argument
+ return false;
+}
+
bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
if (Expr *Init = D->getInitExpr())
return Visit(MakeCXCursor(Init, StmtParent, TU));
@@ -663,6 +674,15 @@
return false;
}
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitFunctionDecl(D->getTemplatedDecl());
+}
+
bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -839,6 +859,54 @@
return false;
}
+bool CursorVisitor::VisitTemplateParameters(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return false;
+
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+ switch (TAL.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ return false;
+
+ case TemplateArgument::Pack:
+ // FIXME: Implement when variadic templates come along.
+ return false;
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case TemplateArgument::Declaration:
+ if (Expr *E = TAL.getSourceDeclExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Expression:
+ if (Expr *E = TAL.getSourceExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Template:
+ // FIXME: Visit template name.
+ return false;
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return VisitDeclContext(D);
}
@@ -918,6 +986,13 @@
return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ // FIXME: We can't visit the template template parameter, but there's
+ // no context information with which we can match up the depth/index in the
+ // type to the appropriate
+ return false;
+}
+
bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
return true;
@@ -985,6 +1060,18 @@
return false;
}
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ // FIXME: Visit the template name.
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
}
@@ -2037,6 +2124,14 @@
return createCXString("CXXDestructor");
case CXCursor_ConversionFunction:
return createCXString("CXXConversion");
+ case CXCursor_TemplateTypeParameter:
+ return createCXString("TemplateTypeParameter");
+ case CXCursor_NonTypeTemplateParameter:
+ return createCXString("NonTypeTemplateParameter");
+ case CXCursor_TemplateTemplateParameter:
+ return createCXString("TemplateTemplateParameter");
+ case CXCursor_FunctionTemplate:
+ return createCXString("FunctionTemplate");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index 0227b2c..6dfe9df 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -13,6 +13,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Lex/PreprocessingRecord.h"
@@ -64,6 +65,7 @@
void VisitFunctionDecl(FunctionDecl *D);
void VisitNamedDecl(NamedDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitObjCClassDecl(ObjCClassDecl *CD);
void VisitObjCContainerDecl(ObjCContainerDecl *CD);
void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
@@ -72,7 +74,10 @@
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitTagDecl(TagDecl *D);
void VisitTypedefDecl(TypedefDecl *D);
+ void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
void VisitVarDecl(VarDecl *D);
+ void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
IgnoreResults = true;
return;
@@ -104,7 +109,10 @@
void GenObjCProtocol(llvm::StringRef prot);
void VisitType(QualType T);
-
+ void VisitTemplateParameterList(const TemplateParameterList *Params);
+ void VisitTemplateName(TemplateName Name);
+ void VisitTemplateArgument(const TemplateArgument &Arg);
+
/// Emit a Decl's name using NamedDecl::printName() and return true if
/// the decl had no name.
bool EmitDeclName(const NamedDecl *D);
@@ -155,7 +163,11 @@
return;
VisitDeclContext(D->getDeclContext());
- Out << "@F@";
+ if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
+ Out << "@FT@";
+ VisitTemplateParameterList(FunTmpl->getTemplateParameters());
+ } else
+ Out << "@F@";
D->printName(Out);
ASTContext &Ctx = AU->getASTContext();
@@ -215,6 +227,16 @@
Out << '@' << s;
}
+void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
+void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
if (D->isAnonymousNamespace()) {
Out << "@aN";
@@ -226,6 +248,10 @@
Out << "@N@" << D->getName();
}
+void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitFunctionDecl(D->getTemplatedDecl());
+}
+
void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Decl *container = cast<Decl>(D->getDeclContext());
@@ -366,6 +392,11 @@
Out << D->getName();
}
+void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
bool USRGenerator::GenLoc(const Decl *D) {
if (generatedLoc)
return IgnoreResults;
@@ -515,13 +546,100 @@
VisitTagDecl(TT->getDecl());
return;
}
-
+ if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>()) {
+ Out << '>';
+ VisitTemplateName(Spec->getTemplateName());
+ Out << Spec->getNumArgs();
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ VisitTemplateArgument(Spec->getArg(I));
+ return;
+ }
+
// Unhandled type.
Out << ' ';
break;
} while (true);
}
+void USRGenerator::VisitTemplateParameterList(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return;
+ Out << '>' << Params->size();
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ Out << '#';
+ if (isa<TemplateTypeParmDecl>(*P)) {
+ Out << 'T';
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ Out << 'N';
+ VisitType(NTTP->getType());
+ continue;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ Out << 't';
+ VisitTemplateParameterList(TTP->getTemplateParameters());
+ }
+}
+
+void USRGenerator::VisitTemplateName(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+
+ Visit(Template);
+ return;
+ }
+
+ // FIXME: Visit dependent template names.
+}
+
+void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Declaration:
+ Visit(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplate());
+ break;
+
+ case TemplateArgument::Expression:
+ // FIXME: Visit expressions.
+ break;
+
+ case TemplateArgument::Pack:
+ // FIXME: Variadic templates
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Integral:
+ Out << 'V';
+ VisitType(Arg.getIntegralType());
+ Out << *Arg.getAsIntegral();
+ break;
+ }
+}
+
//===----------------------------------------------------------------------===//
// General purpose USR generation methods.
//===----------------------------------------------------------------------===//
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 029b3d2..86cf83d 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -60,6 +60,10 @@
case Decl::Typedef: return CXCursor_TypedefDecl;
case Decl::Var: return CXCursor_VarDecl;
case Decl::Namespace: return CXCursor_Namespace;
+ case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
+ case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
default:
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {