From: John McCall Date: Fri, 26 Mar 2010 21:56:38 +0000 (+0000) Subject: Properly account for redeclarations when explicitly instantiating class templates. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2243288c4826905b5a0837f6f21d9d821688652e;p=clang Properly account for redeclarations when explicitly instantiating class templates. 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 --- diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 6c9a45ef6c..dc9fb59e30 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1413,10 +1413,8 @@ void TagDecl::startDefinition() { CXXRecordDecl *D = cast(this); struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); - do { - D->DefinitionData = Data; - D = cast_or_null(D->getPreviousDeclaration()); - } while (D); + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) + cast(*I)->DefinitionData = Data; } } diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp index 5d69b50a76..44f396e47a 100644 --- a/test/SemaTemplate/instantiate-member-class.cpp +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -50,3 +50,33 @@ namespace test1 { Registry::node node(0); } } + +// Redeclarations during explicit instantiations. +namespace test2 { + template class A { + class Foo; + class Foo { + int foo(); + }; + }; + template class A; + + template class B { + class Foo; + class Foo { + typedef int X; + }; + typename Foo::X x; + class Foo; + }; + template class B; + + template class C { + class Foo; + class Foo; + }; + template class C::Foo { + int x; + }; + template class C; +}