Fix "regression" caused by updating our notion of POD to better match the C++11

rules: instead of requiring flexible array members to be POD, require them to
be trivially-destructible. This seems to be the only constraint that actually
matters here (and even then, it's questionable whether this matters).

llvm-svn: 198983
This commit is contained in:
Richard Smith 2014-01-11 00:53:35 +00:00
parent c26e63e986
commit 6fa28ffd5a
4 changed files with 30 additions and 8 deletions

View File

@ -3970,8 +3970,8 @@ def err_flexible_array_virtual_base : Error<
def err_flexible_array_empty_aggregate : Error< def err_flexible_array_empty_aggregate : Error<
"flexible array member %0 not allowed in otherwise empty " "flexible array member %0 not allowed in otherwise empty "
"%select{struct|interface|union|class|enum}1">; "%select{struct|interface|union|class|enum}1">;
def err_flexible_array_has_nonpod_type : Error< def err_flexible_array_has_nontrivial_dtor : Error<
"flexible array member %0 of non-POD element type %1">; "flexible array member %0 of type %1 with non-trivial destruction">;
def ext_flexible_array_in_struct : Extension< def ext_flexible_array_in_struct : Extension<
"%0 may not be nested in a struct due to flexible array member">, "%0 may not be nested in a struct due to flexible array member">,
InGroup<FlexibleArrayExtensions>; InGroup<FlexibleArrayExtensions>;

View File

@ -11994,9 +11994,14 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) Diag(FD->getLocation(), diag::ext_c99_flexible_array_member)
<< FD->getDeclName() << Record->getTagKind(); << FD->getDeclName() << Record->getTagKind();
if (!FD->getType()->isDependentType() && // If the element type has a non-trivial destructor, we would not
!Context.getBaseElementType(FD->getType()).isPODType(Context)) { // implicitly destroy the elements, so disallow it for now.
Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) //
// FIXME: GCC allows this. We should probably either implicitly delete
// the destructor of the containing class, or just allow this.
QualType BaseElem = Context.getBaseElementType(FD->getType());
if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) {
Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor)
<< FD->getDeclName() << FD->getType(); << FD->getDeclName() << FD->getType();
FD->setInvalidDecl(); FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl(); EnclosingDecl->setInvalidDecl();

View File

@ -80,7 +80,7 @@ int check_non_pod_block1[__is_pod(int (^ __unsafe_unretained)(int))? 1 : -1];
struct FlexibleArrayMember0 { struct FlexibleArrayMember0 {
int length; int length;
id array[]; // expected-error{{flexible array member 'array' of non-POD element type 'id __strong[]'}} id array[]; // expected-error{{flexible array member 'array' of type 'id __strong[]' with non-trivial destruction}}
}; };
struct FlexibleArrayMember1 { struct FlexibleArrayMember1 {

View File

@ -36,14 +36,20 @@ void foo()
} }
struct S { struct S {
virtual void foo(); virtual void foo();
}; };
struct X { struct X {
int blah; int blah;
S strings[]; // expected-error {{flexible array member 'strings' of non-POD element type 'S []'}} S strings[];
}; };
S a, b = a;
S f(X &x) {
a = b;
return x.strings[0];
}
class A { class A {
int s; int s;
char c[]; char c[];
@ -71,3 +77,14 @@ struct VirtStorage : virtual StorageBase {
}; };
} }
struct NonTrivDtor { ~NonTrivDtor(); };
// FIXME: It's not clear whether we should disallow examples like this. GCC accepts.
struct FlexNonTrivDtor {
int n;
NonTrivDtor ntd[]; // expected-error {{flexible array member 'ntd' of type 'NonTrivDtor []' with non-trivial destruction}}
~FlexNonTrivDtor() {
for (int i = n; i != 0; --i)
ntd[i-1].~NonTrivDtor();
}
};