From: Douglas Gregor Date: Tue, 31 Aug 2010 20:37:03 +0000 (+0000) Subject: Extend libclang with a new cursor kind that indicates a reference to a X-Git-Tag: llvmorg-2.8.0-rc0~370 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a23e8f7a0f2001d5d77c2be390e39288b128c812;p=platform%2Fupstream%2Fllvm.git Extend libclang with a new cursor kind that indicates a reference to a template. Such cursors occur, for example, in template specialization types such as vector. Note that we do not handle the super-interesting case where the template name is unresolved, e.g., within a template. llvm-svn: 112636 --- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 04d9bbcedfba..be02bcf8c394 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -1020,7 +1020,12 @@ enum CXCursorKind { */ CXCursor_TypeRef = 43, CXCursor_CXXBaseSpecifier = 44, - CXCursor_LastRef = CXCursor_CXXBaseSpecifier, + /** + * \brief A reference to a class template, function template, or template + * template parameter. + */ + CXCursor_TemplateRef = 45, + CXCursor_LastRef = CXCursor_TemplateRef, /* Error conditions */ CXCursor_FirstInvalid = 70, diff --git a/clang/test/Index/index-templates.cpp b/clang/test/Index/index-templates.cpp index fb22f884d368..bd2c2c0b50a8 100644 --- a/clang/test/Index/index-templates.cpp +++ b/clang/test/Index/index-templates.cpp @@ -19,7 +19,7 @@ class vector { }; // FIXME: Need the template type parameter here // CHECK-LOAD: index-templates.cpp:3:66: TemplateTemplateParameter=X:3:66 (Definition) Extent=[3:31 - 3:67] // CHECK-LOAD: index-templates.cpp:4:20: ParmDecl=x:4:20 (Definition) Extent=[4:8 - 4:21] -// FIXME: Need the template declaration here. +// CHECK-LOAD: index-templates.cpp:4:8: TemplateRef=X:3:66 Extent=[4:8 - 4:9] // FIXME: Need the template type parameter here // CHECK-LOAD: index-templates.cpp:4:13: DeclRefExpr=Value:3:24 Extent=[4:13 - 4:18] // CHECK-LOAD: index-templates.cpp:6:28: ClassTemplate=allocator:6:28 Extent=[6:1 - 6:37] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index ae53c16be077..1515ed3c2c6a 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -322,6 +322,7 @@ public: // Template visitors bool VisitTemplateParameters(const TemplateParameterList *Params); + bool VisitTemplateName(TemplateName Name, SourceLocation Loc); bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL); // Type visitors @@ -902,6 +903,30 @@ bool CursorVisitor::VisitTemplateParameters( return false; } +bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) { + switch (Name.getKind()) { + case TemplateName::Template: + return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU)); + + case TemplateName::OverloadedTemplate: + // FIXME: We need a way to return multiple lookup results in a single + // cursor. + return false; + + case TemplateName::DependentTemplate: + // FIXME: Visit nested-name-specifier. + return false; + + case TemplateName::QualifiedTemplate: + // FIXME: Visit nested-name-specifier. + return Visit(MakeCursorTemplateRef( + Name.getAsQualifiedTemplateName()->getDecl(), + Loc, TU)); + } + + return false; +} + bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { switch (TAL.getArgument().getKind()) { case TemplateArgument::Null: @@ -928,8 +953,8 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { return false; case TemplateArgument::Template: - // FIXME: Visit template name. - return false; + return VisitTemplateName(TAL.getArgument().getAsTemplate(), + TAL.getTemplateNameLoc()); } return false; @@ -1090,7 +1115,10 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) { bool CursorVisitor::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { - // FIXME: Visit the template name. + // Visit the template name. + if (VisitTemplateName(TL.getTypePtr()->getTemplateName(), + TL.getTemplateNameLoc())) + return true; // Visit the template arguments. for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) @@ -2023,6 +2051,12 @@ CXString clang_getCursorSpelling(CXCursor C) { return createCXString(getCursorContext(C).getTypeDeclType(Type). getAsString()); } + case CXCursor_TemplateRef: { + TemplateDecl *Template = getCursorTemplateRef(C).first; + assert(Template && "Missing type decl"); + + return createCXString(Template->getNameAsString()); + } default: return createCXString(""); @@ -2102,6 +2136,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ObjCClassRef"); case CXCursor_TypeRef: return createCXString("TypeRef"); + case CXCursor_TemplateRef: + return createCXString("TemplateRef"); case CXCursor_UnexposedExpr: return createCXString("UnexposedExpr"); case CXCursor_BlockExpr: @@ -2287,7 +2323,12 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { std::pair P = getCursorTypeRef(C); return cxloc::translateSourceLocation(P.first->getASTContext(), P.second); } - + + case CXCursor_TemplateRef: { + std::pair P = getCursorTemplateRef(C); + return cxloc::translateSourceLocation(P.first->getASTContext(), P.second); + } + case CXCursor_CXXBaseSpecifier: { // FIXME: Figure out what location to return for a CXXBaseSpecifier. return clang_getNullLocation(); @@ -2345,7 +2386,10 @@ static SourceRange getRawCursorExtent(CXCursor C) { case CXCursor_TypeRef: return getCursorTypeRef(C).second; - + + case CXCursor_TemplateRef: + return getCursorTemplateRef(C).second; + case CXCursor_CXXBaseSpecifier: // FIXME: Figure out what source range to use for a CXBaseSpecifier. return SourceRange(); @@ -2422,7 +2466,10 @@ CXCursor clang_getCursorReferenced(CXCursor C) { case CXCursor_TypeRef: return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit); - + + case CXCursor_TemplateRef: + return MakeCXCursor(getCursorTemplateRef(C).first, CXXUnit); + case CXCursor_CXXBaseSpecifier: { CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C); return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(), @@ -2539,8 +2586,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::ClassTemplate: { if (RecordDecl *Def = cast(D)->getTemplatedDecl() ->getDefinition()) - return MakeCXCursor( - cast(Def)->getDescribedClassTemplate(), + return MakeCXCursor(cast(Def)->getDescribedClassTemplate(), CXXUnit); return clang_getNullCursor(); } diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 691ccd5f3275..0fa201a146c7 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -313,6 +313,22 @@ cxcursor::getCursorTypeRef(CXCursor C) { reinterpret_cast(C.data[1]))); } +CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template, + SourceLocation Loc, ASTUnit *TU) { + assert(Template && TU && "Invalid arguments!"); + void *RawLoc = reinterpret_cast(Loc.getRawEncoding()); + CXCursor C = { CXCursor_TemplateRef, { Template, RawLoc, TU } }; + return C; +} + +std::pair +cxcursor::getCursorTemplateRef(CXCursor C) { + assert(C.kind == CXCursor_TemplateRef); + return std::make_pair(static_cast(C.data[0]), + SourceLocation::getFromRawEncoding( + reinterpret_cast(C.data[1]))); +} + CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU){ CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } }; return C; diff --git a/clang/tools/libclang/CXCursor.h b/clang/tools/libclang/CXCursor.h index 958e331674ab..2e5ff5811c08 100644 --- a/clang/tools/libclang/CXCursor.h +++ b/clang/tools/libclang/CXCursor.h @@ -32,6 +32,7 @@ class NamedDecl; class ObjCInterfaceDecl; class ObjCProtocolDecl; class Stmt; +class TemplateDecl; class TypeDecl; namespace cxcursor { @@ -71,11 +72,19 @@ std::pair /// \brief Create a type reference at the given location. CXCursor MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU); - + /// \brief Unpack a TypeRef cursor into the class it references /// and optionally the location where the reference occurred. std::pair getCursorTypeRef(CXCursor C); +/// \brief Create a reference to a template at the given location. +CXCursor MakeCursorTemplateRef(TemplateDecl *Template, SourceLocation Loc, + ASTUnit *TU); + +/// \brief Unpack a TemplateRef cursor into the template it references and +/// the location where the reference occurred. +std::pair getCursorTemplateRef(CXCursor C); + /// \brief Create a CXX base specifier cursor. CXCursor MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU);