Index: cfe/trunk/include/clang/Index/IndexSymbol.h =================================================================== --- cfe/trunk/include/clang/Index/IndexSymbol.h +++ cfe/trunk/include/clang/Index/IndexSymbol.h @@ -106,8 +106,9 @@ RelationAccessorOf = 1 << 15, RelationContainedBy = 1 << 16, RelationIBTypeOf = 1 << 17, + RelationSpecializationOf = 1 << 18, }; -static const unsigned SymbolRoleBitNum = 18; +static const unsigned SymbolRoleBitNum = 19; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. Index: cfe/trunk/lib/Index/IndexDecl.cpp =================================================================== --- cfe/trunk/lib/Index/IndexDecl.cpp +++ cfe/trunk/lib/Index/IndexDecl.cpp @@ -495,8 +495,18 @@ ClassTemplateSpecializationDecl *D) { // FIXME: Notify subsequent callbacks if info comes from implicit // instantiation. - if (D->isThisDeclarationADefinition()) - IndexCtx.indexTagDecl(D); + if (D->isThisDeclarationADefinition()) { + llvm::PointerUnion + Template = D->getSpecializedTemplateOrPartial(); + const Decl *SpecializationOf = + Template.is() + ? (Decl *)Template.get() + : Template.get(); + IndexCtx.indexTagDecl( + D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), + SpecializationOf)); + } return true; } Index: cfe/trunk/lib/Index/IndexSymbol.cpp =================================================================== --- cfe/trunk/lib/Index/IndexSymbol.cpp +++ cfe/trunk/lib/Index/IndexSymbol.cpp @@ -346,6 +346,7 @@ APPLY_FOR_ROLE(RelationAccessorOf); APPLY_FOR_ROLE(RelationContainedBy); APPLY_FOR_ROLE(RelationIBTypeOf); + APPLY_FOR_ROLE(RelationSpecializationOf); #undef APPLY_FOR_ROLE @@ -386,6 +387,7 @@ case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; case SymbolRole::RelationContainedBy: OS << "RelCont"; break; case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; + case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; } }); } Index: cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp =================================================================== --- cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp +++ cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp @@ -208,11 +208,12 @@ } } -void IndexingContext::indexTagDecl(const TagDecl *D) { +void IndexingContext::indexTagDecl(const TagDecl *D, + ArrayRef Relations) { if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) return; - if (handleDecl(D)) { + if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) { if (D->isThisDeclarationADefinition()) { indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); if (auto CXXRD = dyn_cast(D)) { Index: cfe/trunk/lib/Index/IndexingContext.h =================================================================== --- cfe/trunk/lib/Index/IndexingContext.h +++ cfe/trunk/lib/Index/IndexingContext.h @@ -80,7 +80,8 @@ bool indexDecl(const Decl *D); - void indexTagDecl(const TagDecl *D); + void indexTagDecl(const TagDecl *D, + ArrayRef Relations = None); void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC = nullptr, Index: cfe/trunk/lib/Index/IndexingContext.cpp =================================================================== --- cfe/trunk/lib/Index/IndexingContext.cpp +++ cfe/trunk/lib/Index/IndexingContext.cpp @@ -233,6 +233,7 @@ case SymbolRole::RelationReceivedBy: case SymbolRole::RelationCalledBy: case SymbolRole::RelationContainedBy: + case SymbolRole::RelationSpecializationOf: return true; } llvm_unreachable("Unsupported SymbolRole value!"); Index: cfe/trunk/test/Index/Core/index-source.cpp =================================================================== --- cfe/trunk/test/Index/Core/index-source.cpp +++ cfe/trunk/test/Index/Core/index-source.cpp @@ -50,6 +50,12 @@ // CHECK-NEXT: RelChild | TemplCls | c:@ST>1#T@TemplCls }; +template<> +class TemplCls { +// CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | TemplCls | c:@S@TemplCls>#d | | Def,RelSpecialization | rel: 1 +// CHECK: RelSpecialization | TemplCls | c:@ST>1#T@TemplCls +}; + TemplCls gtv(0); // CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | TemplCls | c:@ST>1#T@TemplCls | | Ref,RelCont | rel: 1 @@ -91,3 +97,17 @@ // CHECK: [[@LINE+2]]:5 | variable/C | gvf | c:@gvf | _gvf | Def | rel: 0 // CHECK: [[@LINE+1]]:11 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Ref,Read,RelCont | rel: 1 int gvf = tmplVar; + +template +class PartialSpecilizationClass { }; +// CHECK: [[@LINE-1]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass | | Def | rel: 0 + +template +class PartialSpecilizationClass { }; +// CHECK: [[@LINE-1]]:7 | class(Gen,TPS)/C++ | PartialSpecilizationClass | c:@SP>1#T@PartialSpecilizationClass>#I#*t0.0 | | Def,RelSpecialization | rel: 1 +// CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass + +template<> +class PartialSpecilizationClass { }; +// CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#I#I | | Def,RelSpecialization | rel: 1 +// CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass