summaryrefslogtreecommitdiffstats
path: root/lib/Index/IndexDecl.cpp
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-04-24 14:04:58 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-04-24 14:04:58 +0000
commit6d3ec86383860d5c48a026ae32b2d5483585b920 (patch)
treee836ead944beefc7743cf406f49ba0972bcca44e /lib/Index/IndexDecl.cpp
parenta55881cab3c23ffcfc6876d1d058cecc062cc9ac (diff)
[index] The relation between the declarations in template specializations
that 'override' declarations in the base template should be recorded This can be used for improved "go to definition" feature in Xcode. rdar://31604739 Differential Revision: https://reviews.llvm.org/D32020 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301180 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Index/IndexDecl.cpp')
-rw-r--r--lib/Index/IndexDecl.cpp64
1 files changed, 60 insertions, 4 deletions
diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp
index 8028f8892f..ba65889a6f 100644
--- a/lib/Index/IndexDecl.cpp
+++ b/lib/Index/IndexDecl.cpp
@@ -144,6 +144,53 @@ public:
return true;
}
+ /// Gather the declarations which the given declaration \D overrides in a
+ /// pseudo-override manner.
+ ///
+ /// Pseudo-overrides occur when a class template specialization declares
+ /// a declaration that has the same name as a similar declaration in the
+ /// non-specialized template.
+ void
+ gatherTemplatePseudoOverrides(const NamedDecl *D,
+ SmallVectorImpl<SymbolRelation> &Relations) {
+ if (!IndexCtx.getLangOpts().CPlusPlus)
+ return;
+ const auto *CTSD =
+ dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
+ if (!CTSD)
+ return;
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ Template = CTSD->getSpecializedTemplateOrPartial();
+ if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
+ const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
+ bool TypeOverride = isa<TypeDecl>(D);
+ for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
+ if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
+ ND = CTD->getTemplatedDecl();
+ if (ND->isImplicit())
+ continue;
+ // Types can override other types.
+ if (!TypeOverride) {
+ if (ND->getKind() != D->getKind())
+ continue;
+ } else if (!isa<TypeDecl>(ND))
+ continue;
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+ const auto *DFD = cast<FunctionDecl>(D);
+ // Function overrides are approximated using the number of parameters.
+ if (FD->getStorageClass() != DFD->getStorageClass() ||
+ FD->getNumParams() != DFD->getNumParams())
+ continue;
+ }
+ Relations.emplace_back(
+ SymbolRoleSet(SymbolRole::RelationOverrideOf) |
+ SymbolRoleSet(SymbolRole::RelationSpecializationOf),
+ ND);
+ }
+ }
+ }
+
bool VisitFunctionDecl(const FunctionDecl *D) {
if (D->isDeleted())
return true;
@@ -158,6 +205,7 @@ public:
Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
}
}
+ gatherTemplatePseudoOverrides(D, Relations);
TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
handleDeclarator(D);
@@ -194,14 +242,18 @@ public:
}
bool VisitVarDecl(const VarDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
+ SmallVector<SymbolRelation, 4> Relations;
+ gatherTemplatePseudoOverrides(D, Relations);
+ TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
handleDeclarator(D);
IndexCtx.indexBody(D->getInit(), D);
return true;
}
bool VisitFieldDecl(const FieldDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
+ SmallVector<SymbolRelation, 4> Relations;
+ gatherTemplatePseudoOverrides(D, Relations);
+ TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
handleDeclarator(D);
if (D->isBitField())
IndexCtx.indexBody(D->getBitWidth(), D);
@@ -233,7 +285,9 @@ public:
bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
if (!D->isTransparentTag()) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
+ SmallVector<SymbolRelation, 4> Relations;
+ gatherTemplatePseudoOverrides(D, Relations);
+ TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
}
return true;
@@ -243,7 +297,9 @@ public:
// Non-free standing tags are handled in indexTypeSourceInfo.
if (D->isFreeStanding()) {
if (D->isThisDeclarationADefinition()) {
- IndexCtx.indexTagDecl(D);
+ SmallVector<SymbolRelation, 4> Relations;
+ gatherTemplatePseudoOverrides(D, Relations);
+ IndexCtx.indexTagDecl(D, Relations);
} else {
auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
return IndexCtx.handleReference(D, D->getLocation(), Parent,