]> granicus.if.org Git - clang/commitdiff
Properly account for redeclarations when explicitly instantiating class templates.
authorJohn McCall <rjmccall@apple.com>
Fri, 26 Mar 2010 21:56:38 +0000 (21:56 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 26 Mar 2010 21:56:38 +0000 (21:56 +0000)
What happens here is that we actually turn the first declaration into a
definition, regardless of whether it was actually originally a definition,
and furthermore we do this all after we've instantiated all the declarations.
This exposes a bug in my DefinitionData patch where it was only setting the
DefinitionData for previous declarations, not future declarations.
Fortunately, there's an iterator for that.

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

lib/AST/Decl.cpp
test/SemaTemplate/instantiate-member-class.cpp

index 6c9a45ef6c44f94c2b37de66796a1389e100e408..dc9fb59e3090c79064a328577c7cf760939e5d1c 100644 (file)
@@ -1413,10 +1413,8 @@ void TagDecl::startDefinition() {
     CXXRecordDecl *D = cast<CXXRecordDecl>(this);
     struct CXXRecordDecl::DefinitionData *Data = 
       new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
-    do {
-      D->DefinitionData = Data;
-      D = cast_or_null<CXXRecordDecl>(D->getPreviousDeclaration());
-    } while (D);
+    for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
+      cast<CXXRecordDecl>(*I)->DefinitionData = Data;
   }
 }
 
index 5d69b50a760680ccb5fade8b1ae1d441c1b4a5ac..44f396e47af7cebf7412e2d0ce2e2246acb1345a 100644 (file)
@@ -50,3 +50,33 @@ namespace test1 {
     Registry<int>::node node(0);
   }
 }
+
+// Redeclarations during explicit instantiations.
+namespace test2 {
+  template <typename T> class A {
+    class Foo;
+    class Foo {
+      int foo();
+    };
+  };
+  template class A<int>;
+
+  template <typename T> class B {
+    class Foo;
+    class Foo {
+      typedef int X;
+    };
+    typename Foo::X x;
+    class Foo;
+  };
+  template class B<int>;
+
+  template <typename T> class C {
+    class Foo;
+    class Foo;
+  };
+  template <typename T> class C<T>::Foo {
+    int x;
+  };
+  template class C<int>;
+}