diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-08-31 17:01:39 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-08-31 17:01:39 +0000 |
| commit | 713602bb09f09b971f55c565e7bbdf2aba173e98 (patch) | |
| tree | 084fe44d30c91c1d1c11e8d94369ec3f963394e9 /clang/tools/libclang | |
| parent | 04dc9572601fb6ae976156326797a8888e00edad (diff) | |
| download | bcm5719-llvm-713602bb09f09b971f55c565e7bbdf2aba173e98.tar.gz bcm5719-llvm-713602bb09f09b971f55c565e7bbdf2aba173e98.zip | |
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.
llvm-svn: 112604
Diffstat (limited to 'clang/tools/libclang')
| -rw-r--r-- | clang/tools/libclang/CIndex.cpp | 101 | ||||
| -rw-r--r-- | clang/tools/libclang/CIndexUSRs.cpp | 124 | ||||
| -rw-r--r-- | clang/tools/libclang/CXCursor.cpp | 4 |
3 files changed, 223 insertions, 6 deletions
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index fc665926f28..6629f5c0acf 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -290,11 +290,13 @@ public: 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 @@ public: 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 @@ public: 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 @@ bool CursorVisitor::VisitTagDecl(TagDecl *D) { 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 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) { 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 @@ bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { 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 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { 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 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) { 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 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { 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/clang/tools/libclang/CIndexUSRs.cpp b/clang/tools/libclang/CIndexUSRs.cpp index 0227b2c037e..6dfe9df4dd7 100644 --- a/clang/tools/libclang/CIndexUSRs.cpp +++ b/clang/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 @@ public: 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 @@ public: 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 @@ public: 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 @@ void USRGenerator::VisitFunctionDecl(FunctionDecl *D) { 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 @@ void USRGenerator::VisitVarDecl(VarDecl *D) { 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 @@ void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) { 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 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) { 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 @@ void USRGenerator::VisitType(QualType T) { 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/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 029b3d237dc..86cf83d75e5 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -60,6 +60,10 @@ static CXCursorKind GetCursorKind(Decl *D) { 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()) { |

