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.

llvm-svn: 99657
This commit is contained in:
John McCall 2010-03-26 21:56:38 +00:00
parent 2f072e95e6
commit 93cc732ffc
2 changed files with 32 additions and 4 deletions

View 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;
}
}

View 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>;
}