From 73e27a603101e77cfceb34540ff51fac292f250e Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 23 May 2017 16:25:06 +0000 Subject: [PATCH] [index] The references to fields from nested records in template instantiations should refer to the pattern fields in the nested records in the base templates rdar://32352429 llvm-svn: 303647 --- clang/lib/Index/IndexingContext.cpp | 20 ++++++++++++++------ clang/test/Index/Core/index-instantiated-source.cpp | 7 +++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp index b9f991d..1a341b0 100644 --- a/clang/lib/Index/IndexingContext.cpp +++ b/clang/lib/Index/IndexingContext.cpp @@ -128,9 +128,8 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { if (RD->getInstantiatedFromMemberClass()) TKind = RD->getTemplateSpecializationKind(); } else if (isa(D)) { - if (const auto *Parent = - dyn_cast(D->getDeclContext())) - TKind = Parent->getSpecializationKind(); + if (const auto *Parent = dyn_cast(D->getDeclContext())) + return isTemplateImplicitInstantiation(Parent); } switch (TKind) { case TSK_Undeclared: @@ -158,6 +157,16 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { return true; } +static const CXXRecordDecl * +getDeclContextForTemplateInstationPattern(const Decl *D) { + if (const auto *CTSD = + dyn_cast(D->getDeclContext())) + return CTSD->getTemplateInstantiationPattern(); + else if (const auto *RD = dyn_cast(D->getDeclContext())) + return RD->getInstantiatedFromMemberClass(); + return nullptr; +} + static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { if (const ClassTemplateSpecializationDecl * SD = dyn_cast(D)) { @@ -169,9 +178,8 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { } else if (const auto *RD = dyn_cast(D)) { return RD->getInstantiatedFromMemberClass(); } else if (const auto *FD = dyn_cast(D)) { - if (const auto *Parent = - dyn_cast(D->getDeclContext())) { - const CXXRecordDecl *Pattern = Parent->getTemplateInstantiationPattern(); + if (const CXXRecordDecl *Pattern = + getDeclContextForTemplateInstationPattern(FD)) { for (const NamedDecl *ND : Pattern->lookup(FD->getDeclName())) { if (ND->isImplicit()) continue; diff --git a/clang/test/Index/Core/index-instantiated-source.cpp b/clang/test/Index/Core/index-instantiated-source.cpp index a1fe4a3..b0c9419 100644 --- a/clang/test/Index/Core/index-instantiated-source.cpp +++ b/clang/test/Index/Core/index-instantiated-source.cpp @@ -28,6 +28,10 @@ public: struct NestedType { // CHECK: [[@LINE-1]]:10 | struct/C++ | NestedType | c:@ST>2#T#T@TemplateClass@S@NestedType | + + T nestedField; +// CHECK: [[@LINE-1]]:7 | field/C++ | nestedField | c:@ST>2#T#T@TemplateClass@S@NestedType@FI@nestedField | + class SubNestedType { // CHECK: [[@LINE-1]]:11 | class/C++ | SubNestedType | c:@ST>2#T#T@TemplateClass@S@NestedType@S@SubNestedType | public: @@ -53,6 +57,9 @@ void canonicalizeInstaniationReferences(TemplateClass &object) { // CHECK: [[@LINE-1]]:30 | struct/C | NestedBaseType | c:@ST>1#T@BaseTemplate@S@NestedBaseType | TemplateClass::NestedType nestedSubType; // CHECK: [[@LINE-1]]:30 | struct/C++ | NestedType | c:@ST>2#T#T@TemplateClass@S@NestedType | + (void)nestedSubType.nestedField; +// CHECK: [[@LINE-1]]:23 | field/C++ | nestedField | c:@ST>2#T#T@TemplateClass@S@NestedType@FI@nestedField | + typedef TemplateClass TT; TT::NestedType::SubNestedType subNestedType(0); // CHECK: [[@LINE-1]]:7 | struct/C++ | NestedType | c:@ST>2#T#T@TemplateClass@S@NestedType | -- 2.7.4