зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
c4421e966d
Коммит
dd7744d01e
|
@ -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}}
|
||||
};
|
||||
};
|
Загрузка…
Ссылка в новой задаче