From e9fc8dc84c4da2e9aea44c6e1a7bcc2af99d91c2 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 21 Dec 2010 21:22:51 +0000 Subject: [PATCH] When searching for the instantiation of a locally-scoped tag declaration, also look for an instantiation of its previous declarations. Fixes PR8801. llvm-svn: 122361 --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 20 ++++++++++++++----- .../SemaTemplate/instantiate-local-class.cpp | 13 ++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 37d8d8cb53de..2fa4ac5b0b24 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1735,11 +1735,21 @@ Decl *LocalInstantiationScope::getInstantiationOf(const Decl *D) { for (LocalInstantiationScope *Current = this; Current; Current = Current->Outer) { // Check if we found something within this scope. - llvm::DenseMap::iterator Found - = Current->LocalDecls.find(D); - if (Found != Current->LocalDecls.end()) - return Found->second; - + const Decl *CheckD = D; + do { + llvm::DenseMap::iterator Found + = Current->LocalDecls.find(CheckD); + if (Found != Current->LocalDecls.end()) + return Found->second; + + // If this is a tag declaration, it's possible that we need to look for + // a previous declaration. + if (const TagDecl *Tag = dyn_cast(CheckD)) + CheckD = Tag->getPreviousDeclaration(); + else + CheckD = 0; + } while (CheckD); + // If we aren't combined with our outer scope, we're done. if (!Current->CombineWithOuterScope) break; diff --git a/clang/test/SemaTemplate/instantiate-local-class.cpp b/clang/test/SemaTemplate/instantiate-local-class.cpp index d57ba8a68288..954fd6508589 100644 --- a/clang/test/SemaTemplate/instantiate-local-class.cpp +++ b/clang/test/SemaTemplate/instantiate-local-class.cpp @@ -50,3 +50,16 @@ namespace local_class_with_virtual_functions { struct S { }; void test() { f(); } } + +namespace PR8801 { + template + void foo() { + class X; + int (X::*pmf)(T) = 0; + class X : public T { }; + } + + struct Y { }; + + template void foo(); +}