summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp20
-rw-r--r--clang/test/SemaTemplate/instantiate-local-class.cpp13
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>();
+}
OpenPOWER on IntegriCloud