Emit diagnostic error when the field of an anonymous struct is non trivial.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111158 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Argyrios Kyrtzidis 2010-08-16 17:27:08 +00:00
Родитель c4421e966d
Коммит dd7744d01e
4 изменённых файлов: 57 добавлений и 24 удалений

Просмотреть файл

@ -633,9 +633,9 @@ def err_missing_default_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{base class|member}2 %3 which does not have a default "
"constructor">;
def err_illegal_union_member : Error<
"union member %0 has a non-trivial %select{constructor|"
"copy constructor|copy assignment operator|destructor}1">;
def err_illegal_union_or_anon_struct_member : Error<
"%select{anonymous struct|union}0 member %1 has a non-trivial "
"%select{constructor|copy constructor|copy assignment operator|destructor}2">;
def note_nontrivial_has_virtual : Note<
"because type %0 has a virtual %select{member function|base class}1">;
def note_nontrivial_has_nontrivial : Note<

Просмотреть файл

@ -1019,6 +1019,7 @@ public:
CXXCopyAssignment = 2,
CXXDestructor = 3
};
bool CheckNontrivialField(FieldDecl *FD);
void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);

Просмотреть файл

@ -1855,6 +1855,9 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
<< (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
Invalid = true;
}
if (CheckNontrivialField(FD))
Invalid = true;
} else if ((*Mem)->isImplicit()) {
// Any implicit members are fine.
} else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
@ -6044,27 +6047,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// 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();
}
}
if (Record->isUnion() && CheckNontrivialField(NewFD))
NewFD->setInvalidDecl();
}
}
}
@ -6094,6 +6078,43 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
return NewFD;
}
bool Sema::CheckNontrivialField(FieldDecl *FD) {
assert(FD);
assert(getLangOptions().CPlusPlus && "valid check only for C++");
if (FD->isInvalidDecl())
return true;
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
// 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(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member)
<< (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
DiagnoseNontrivial(RT, member);
return true;
}
}
}
return false;
}
/// DiagnoseNontrivial - Given that a class has a non-trivial
/// special member, figure out why.
void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {

Просмотреть файл

@ -0,0 +1,11 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct S {
S(); // expected-note {{because type 'S' has a user-declared constructor}}
};
struct E {
struct {
S x; // expected-error {{anonymous struct member 'x' has a non-trivial constructor}}
};
};