]> granicus.if.org Git - clang/commitdiff
When searching for the instantiation of a locally-scoped tag
authorDouglas Gregor <dgregor@apple.com>
Tue, 21 Dec 2010 21:22:51 +0000 (21:22 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 21 Dec 2010 21:22:51 +0000 (21:22 +0000)
declaration, also look for an instantiation of its previous
declarations. Fixes PR8801.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122361 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/instantiate-local-class.cpp

index 37d8d8cb53ded86317c44103b0be417796016010..2fa4ac5b0b24cded89db2ca4b8f7477c48094a0b 100644 (file)
@@ -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;
index d57ba8a68288bbe529c2346c55f2e28784f177bd..954fd6508589e19a42a9e34a03d596700d4ed92c 100644 (file)
@@ -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>();
+}