Don't poke at an undefined class type of a field. Fixes PR7355.

llvm-svn: 106111
This commit is contained in:
Douglas Gregor 2010-06-16 16:54:04 +00:00
parent 010815a20b
commit 94584683fa
2 changed files with 43 additions and 33 deletions

View File

@ -5803,41 +5803,42 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!RDecl->hasTrivialConstructor())
CXXRecord->setHasTrivialConstructor(false);
if (!RDecl->hasTrivialCopyConstructor())
CXXRecord->setHasTrivialCopyConstructor(false);
if (!RDecl->hasTrivialCopyAssignment())
CXXRecord->setHasTrivialCopyAssignment(false);
if (!RDecl->hasTrivialDestructor())
CXXRecord->setHasTrivialDestructor(false);
// C++ 9.5p1: An object of a class with a non-trivial
// constructor, a non-trivial copy constructor, a non-trivial
// destructor, or a non-trivial copy assignment operator
// cannot be a member of a union, nor can an array of such
// objects.
// TODO: C++0x alters this restriction significantly.
if (Record->isUnion()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
// copy constructors.
CXXSpecialMember member = CXXInvalid;
if (RDecl->getDefinition()) {
if (!RDecl->hasTrivialConstructor())
CXXRecord->setHasTrivialConstructor(false);
if (!RDecl->hasTrivialCopyConstructor())
member = CXXCopyConstructor;
else if (!RDecl->hasTrivialConstructor())
member = CXXConstructor;
else if (!RDecl->hasTrivialCopyAssignment())
member = CXXCopyAssignment;
else if (!RDecl->hasTrivialDestructor())
member = CXXDestructor;
CXXRecord->setHasTrivialCopyConstructor(false);
if (!RDecl->hasTrivialCopyAssignment())
CXXRecord->setHasTrivialCopyAssignment(false);
if (!RDecl->hasTrivialDestructor())
CXXRecord->setHasTrivialDestructor(false);
if (member != CXXInvalid) {
Diag(Loc, diag::err_illegal_union_member) << Name << member;
DiagnoseNontrivial(RT, member);
NewFD->setInvalidDecl();
// C++ 9.5p1: An object of a class with a non-trivial
// constructor, a non-trivial copy constructor, a non-trivial
// destructor, or a non-trivial copy assignment operator
// cannot be a member of a union, nor can an array of such
// objects.
// TODO: C++0x alters this restriction significantly.
if (Record->isUnion()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
// copy constructors.
CXXSpecialMember member = CXXInvalid;
if (!RDecl->hasTrivialCopyConstructor())
member = CXXCopyConstructor;
else if (!RDecl->hasTrivialConstructor())
member = CXXConstructor;
else if (!RDecl->hasTrivialCopyAssignment())
member = CXXCopyAssignment;
else if (!RDecl->hasTrivialDestructor())
member = CXXDestructor;
if (member != CXXInvalid) {
Diag(Loc, diag::err_illegal_union_member) << Name << member;
DiagnoseNontrivial(RT, member);
NewFD->setInvalidDecl();
}
}
}
}

View File

@ -81,3 +81,12 @@ namespace PR7123 {
sort(x,x);
}
}
namespace PR7355 {
template<typename T1> class A {
class D; // expected-note{{declared here}}
D d; //expected-error{{implicit instantiation of undefined member 'PR7355::A<int>::D'}}
};
A<int> ai; // expected-note{{in instantiation of}}
}