diff options
-rw-r--r-- | include/clang-c/Index.h | 30 | ||||
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 3 | ||||
-rw-r--r-- | test/Index/index-templates.cpp | 9 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 13 | ||||
-rw-r--r-- | tools/libclang/CIndexCXX.cpp | 47 | ||||
-rw-r--r-- | tools/libclang/libclang.darwin.exports | 1 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 1 |
7 files changed, 97 insertions, 7 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index d5e3373b91..4631c65bf0 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1751,6 +1751,36 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C); /** + * \brief Given a cursor that may represent a specialization or instantiation + * of a template, retrieve the cursor that represents the template that it + * specializes or from which it was instantiated. + * + * This routine determines the template involved both for explicit + * specializations of templates and for implicit instantiations of the template, + * both of which are referred to as "specializations". For a class template + * specialization (e.g., \c std::vector<bool>), this routine will return + * either the primary template (\c std::vector) or, if the specialization was + * instantiated from a class template partial specialization, the class template + * partial specialization. For a class template partial specialization and a + * function template specialization (including instantiations), this + * this routine will return the specialized template. + * + * For members of a class template (e.g., member functions, member classes, or + * static data members), returns the specialized or instantiated member. + * Although not strictly "templates" in the C++ language, members of class + * templates have the same notions of specializations and instantiations that + * templates do, so this routine treats them similarly. + * + * \param C A cursor that may be a specialization of a template or a member + * of a template. + * + * \returns If the given cursor is a specialization or instantiation of a + * template or a member thereof, the template or member that it specializes or + * from which it was instantiated. Otherwise, returns a NULL cursor. + */ +CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C); + +/** * @} */ diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 5ffd192271..b532668242 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1300,7 +1300,8 @@ public: if (getSpecializationKind() != TSK_ImplicitInstantiation && getSpecializationKind() != TSK_ExplicitInstantiationDefinition && getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) - return (ClassTemplateDecl*)0; + return llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *>(); if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) diff --git a/test/Index/index-templates.cpp b/test/Index/index-templates.cpp index 1070e06a4c..5024103480 100644 --- a/test/Index/index-templates.cpp +++ b/test/Index/index-templates.cpp @@ -44,6 +44,8 @@ typedef unsigned Unsigned; template<typename T, Unsigned Value> struct value_c; +template class vector<int*>; + // RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-LOAD %s // CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22] // CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:19 - 3:20] @@ -61,14 +63,14 @@ struct value_c; // CHECK-LOAD: index-templates.cpp:8:31: TemplateTypeParameter=Alloc:8:31 (Definition) Extent=[8:31 - 8:36] // CHECK-LOAD: index-templates.cpp:8:39: TemplateRef=allocator:6:28 Extent=[8:39 - 8:48] // CHECK-LOAD: index-templates.cpp:10:8: CXXMethod=clear:10:8 Extent=[10:8 - 10:15] -// CHECK-LOAD: index-templates.cpp:14:7: ClassTemplatePartialSpecialization=vector:14:7 (Definition) Extent=[13:1 - 14:21] +// CHECK-LOAD: index-templates.cpp:14:7: ClassTemplatePartialSpecialization=vector:14:7 (Definition) [Specialization of vector:9:7] Extent=[13:1 - 14:21] // CHECK-LOAD: index-templates.cpp:13:19: TemplateTypeParameter=T:13:19 (Definition) Extent=[13:19 - 13:20] // CHECK-LOAD: index-templates.cpp:16:8: StructDecl=Z1:16:8 (Definition) Extent=[16:1 - 16:14] -// CHECK-LOAD: index-templates.cpp:18:16: ClassDecl=vector:18:16 (Definition) Extent=[18:1 - 18:22] +// CHECK-LOAD: index-templates.cpp:18:16: ClassDecl=vector:18:16 (Definition) [Specialization of vector:9:7] Extent=[18:1 - 18:22] // CHECK-LOAD: index-templates.cpp:18:23: TypeRef=struct Z1:16:8 Extent=[18:23 - 18:25] // CHECK-LOAD-NOT: CXXMethod=clear // CHECK-LOAD: index-templates.cpp:20:8: StructDecl=Z2:20:8 (Definition) Extent=[20:1 - 20:14] -// CHECK-LOAD: index-templates.cpp:23:7: ClassDecl=vector:23:7 (Definition) Extent=[22:1 - 25:2] +// CHECK-LOAD: index-templates.cpp:23:7: ClassDecl=vector:23:7 (Definition) [Specialization of vector:9:7] Extent=[22:1 - 25:2] // CHECK-LOAD: index-templates.cpp:23:14: TypeRef=struct Z2:20:8 Extent=[23:14 - 23:16] // CHECK-LOAD: index-templates.cpp:24:8: CXXMethod=clear:24:8 Extent=[24:8 - 24:15] // CHECK-LOAD: index-templates.cpp:28:8: ClassTemplate=Y:28:8 (Definition) Extent=[27:1 - 31:2] @@ -94,6 +96,7 @@ struct value_c; // CHECK-LOAD: index-templates.cpp:44:19: TemplateTypeParameter=T:44:19 (Definition) Extent=[44:19 - 44:20] // CHECK-LOAD: index-templates.cpp:44:31: NonTypeTemplateParameter=Value:44:31 (Definition) Extent=[44:22 - 44:36] // CHECK-LOAD: index-templates.cpp:44:22: TypeRef=Unsigned:42:18 Extent=[44:22 - 44:30] +// CHECK-LOAD: index-templates.cpp:47:16: ClassDecl=vector:47:16 (Definition) [Specialization of vector:14:7] Extent=[47:1 - 47:22] // RUN: c-index-test -test-load-source-usrs all %s | FileCheck -check-prefix=CHECK-USRS %s // CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0# Extent=[3:1 - 4:22] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index cdf0cd06b5..58eff97ef8 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -166,7 +166,8 @@ static void PrintCursor(CXCursor Cursor) { CXString string, ks; CXCursor Referenced; unsigned line, column; - + CXCursor SpecializationOf; + ks = clang_getCursorKindSpelling(Cursor.kind); string = clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCString(ks), @@ -224,6 +225,16 @@ static void PrintCursor(CXCursor Cursor) { printf(" [access=%s isVirtual=%s]", accessStr, isVirtual ? "true" : "false"); } + + SpecializationOf = clang_getSpecializedCursorTemplate(Cursor); + if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) { + CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf); + CXString Name = clang_getCursorSpelling(SpecializationOf); + clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + printf(" [Specialization of %s:%d:%d]", + clang_getCString(Name), line, column); + clang_disposeString(Name); + } } } diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp index ee83f98722..3ade5195d8 100644 --- a/tools/libclang/CIndexCXX.cpp +++ b/tools/libclang/CIndexCXX.cpp @@ -19,6 +19,7 @@ using namespace clang; using namespace clang::cxstring; +using namespace clang::cxcursor; extern "C" { @@ -26,7 +27,7 @@ unsigned clang_isVirtualBase(CXCursor C) { if (C.kind != CXCursor_CXXBaseSpecifier) return 0; - CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C); + CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); return B->isVirtual(); } @@ -34,7 +35,7 @@ enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { if (C.kind != CXCursor_CXXBaseSpecifier) return CX_CXXInvalidAccessSpecifier; - CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C); + CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); switch (B->getAccessSpecifier()) { case AS_public: return CX_CXXPublic; case AS_protected: return CX_CXXProtected; @@ -78,4 +79,46 @@ enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { return CXCursor_NoDeclFound; } +CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return clang_getNullCursor(); + + Decl *D = getCursorDecl(C); + if (!D) + return clang_getNullCursor(); + + Decl *Template = 0; + if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) + Template = PartialSpec->getSpecializedTemplate(); + else if (ClassTemplateSpecializationDecl *ClassSpec + = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> Result + = ClassSpec->getSpecializedTemplateOrPartial(); + if (Result.is<ClassTemplateDecl *>()) + Template = Result.get<ClassTemplateDecl *>(); + else + Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); + + } else + Template = CXXRecord->getInstantiatedFromMemberClass(); + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + Template = Function->getPrimaryTemplate(); + if (!Template) + Template = Function->getInstantiatedFromMemberFunction(); + } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (Var->isStaticDataMember()) + Template = Var->getInstantiatedFromStaticDataMember(); + } else if (RedeclarableTemplateDecl *Tmpl + = dyn_cast<RedeclarableTemplateDecl>(D)) + Template = Tmpl->getInstantiatedFromMemberTemplate(); + + if (!Template) + return clang_getNullCursor(); + + return MakeCXCursor(Template, getCursorASTUnit(C)); +} + } // end extern "C" diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports index 289026510f..d1b45a2486 100644 --- a/tools/libclang/libclang.darwin.exports +++ b/tools/libclang/libclang.darwin.exports @@ -78,6 +78,7 @@ _clang_getRange _clang_getRangeEnd _clang_getRangeStart _clang_getResultType +_clang_getSpecializedCursorTemplate _clang_getTemplateCursorKind _clang_getTokenExtent _clang_getTokenKind diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 254ba98a73..0ea6993b21 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -78,6 +78,7 @@ clang_getRange clang_getRangeEnd clang_getRangeStart clang_getResultType +clang_getSpecializedCursorTemplate clang_getTemplateCursorKind clang_getTokenExtent clang_getTokenKind |