From: Alex Lorenz Date: Thu, 20 Apr 2017 10:43:22 +0000 (+0000) Subject: [index] Record class template specializations using a new 'SpecializationOf' X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=59a0c5ecb8467168e3b6a47c2252e0c24608b491;p=clang [index] Record class template specializations using a new 'SpecializationOf' relationship rdar://31603531 Differential Revision: https://reviews.llvm.org/D32010 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300832 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 217d6b1fb1..bc34938fb4 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -106,8 +106,9 @@ enum class SymbolRole : uint32_t { 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. diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp index dae0cdc0d9..0e89350551 100644 --- a/lib/Index/IndexDecl.cpp +++ b/lib/Index/IndexDecl.cpp @@ -495,8 +495,18 @@ public: 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; } diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index fe3c17845d..ea66b70179 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -346,6 +346,7 @@ bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, APPLY_FOR_ROLE(RelationAccessorOf); APPLY_FOR_ROLE(RelationContainedBy); APPLY_FOR_ROLE(RelationIBTypeOf); + APPLY_FOR_ROLE(RelationSpecializationOf); #undef APPLY_FOR_ROLE @@ -386,6 +387,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; case SymbolRole::RelationContainedBy: OS << "RelCont"; break; case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; + case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; } }); } diff --git a/lib/Index/IndexTypeSourceInfo.cpp b/lib/Index/IndexTypeSourceInfo.cpp index 0645d5be52..a3566a9f2a 100644 --- a/lib/Index/IndexTypeSourceInfo.cpp +++ b/lib/Index/IndexTypeSourceInfo.cpp @@ -208,11 +208,12 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, } } -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)) { diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index f393b11ab8..85574d0a31 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -233,6 +233,7 @@ static bool shouldReportOccurrenceForSystemDeclOnlyMode( case SymbolRole::RelationReceivedBy: case SymbolRole::RelationCalledBy: case SymbolRole::RelationContainedBy: + case SymbolRole::RelationSpecializationOf: return true; } llvm_unreachable("Unsupported SymbolRole value!"); diff --git a/lib/Index/IndexingContext.h b/lib/Index/IndexingContext.h index 933b0a2cda..1ebf6f9ce6 100644 --- a/lib/Index/IndexingContext.h +++ b/lib/Index/IndexingContext.h @@ -80,7 +80,8 @@ public: 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, diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp index 356d4a08de..5d4a1be456 100644 --- a/test/Index/Core/index-source.cpp +++ b/test/Index/Core/index-source.cpp @@ -50,6 +50,12 @@ public: // 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 @@ int gvi = tmplVar; // 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