From: Alex Lorenz Date: Mon, 15 May 2017 14:26:22 +0000 (+0000) Subject: [index] References to fields from template instantiations should refer to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=96ab5e60807c5fd92e00c5ed8e9e268cb687f4fc;p=clang [index] References to fields from template instantiations should refer to fields in base templates rdar://32197158 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303068 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp index 709a23657b..5cebb19846 100644 --- a/lib/Index/IndexingContext.cpp +++ b/lib/Index/IndexingContext.cpp @@ -124,6 +124,10 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { TKind = FD->getTemplateSpecializationKind(); } else if (auto *VD = dyn_cast(D)) { TKind = VD->getTemplateSpecializationKind(); + } else if (isa(D)) { + if (const auto *Parent = + dyn_cast(D->getDeclContext())) + TKind = Parent->getSpecializationKind(); } switch (TKind) { case TSK_Undeclared: @@ -159,6 +163,17 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { return FD->getTemplateInstantiationPattern(); } else if (auto *VD = dyn_cast(D)) { return VD->getTemplateInstantiationPattern(); + } else if (const auto *FD = dyn_cast(D)) { + if (const auto *Parent = + dyn_cast(D->getDeclContext())) { + const CXXRecordDecl *Pattern = Parent->getTemplateInstantiationPattern(); + for (const NamedDecl *ND : Pattern->lookup(FD->getDeclName())) { + if (ND->isImplicit()) + continue; + if (isa(ND)) + return ND; + } + } } return nullptr; } diff --git a/test/Index/Core/index-instantiated-source.cpp b/test/Index/Core/index-instantiated-source.cpp new file mode 100644 index 0000000000..f61795da54 --- /dev/null +++ b/test/Index/Core/index-instantiated-source.cpp @@ -0,0 +1,39 @@ +// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s +// References to declarations in instantiations should be canonicalized: + +template +class BaseTemplate { +public: + T baseTemplateFunction(); +// CHECK: [[@LINE-1]]:5 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# + + T baseTemplateField; +// CHECK: [[@LINE-1]]:5 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField +}; + +template +class TemplateClass: public BaseTemplate { +public: + T function() { return T(); } +// CHECK: [[@LINE-1]]:5 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# + + static void staticFunction() { } +// CHECK: [[@LINE-1]]:15 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S + + T field; +// CHECK: [[@LINE-1]]:5 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field +}; + +void canonicalizeInstaniationReferences(TemplateClass &object) { + (void)object.function(); +// CHECK: [[@LINE-1]]:16 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# | + (void)object.field; +// CHECK: [[@LINE-1]]:16 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field | | Ref,RelCont | rel: 1 + (void)object.baseTemplateFunction(); +// CHECK: [[@LINE-1]]:16 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# | + (void)object.baseTemplateField; +// CHECK: [[@LINE-1]]:16 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField | | Ref,RelCont | rel: 1 + + TemplateClass::staticFunction(); +// CHECK: [[@LINE-1]]:30 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S |