diff options
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 20 | ||||
| -rw-r--r-- | clang/test/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 37d8d8cb53d..2fa4ac5b0b2 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<const Decl *, Decl *>::iterator Found - = Current->LocalDecls.find(D); - if (Found != Current->LocalDecls.end()) - return Found->second; - + const Decl *CheckD = D; + do { + llvm::DenseMap<const Decl *, Decl *>::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<TagDecl>(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 d57ba8a6828..954fd650858 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<S>(); } } + +namespace PR8801 { + template<typename T> + void foo() { + class X; + int (X::*pmf)(T) = 0; + class X : public T { }; + } + + struct Y { }; + + template void foo<Y>(); +} |

