diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a43ce7f32b29..837862e575b6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3970,8 +3970,8 @@ def err_flexible_array_virtual_base : Error< def err_flexible_array_empty_aggregate : Error< "flexible array member %0 not allowed in otherwise empty " "%select{struct|interface|union|class|enum}1">; -def err_flexible_array_has_nonpod_type : Error< - "flexible array member %0 of non-POD element type %1">; +def err_flexible_array_has_nontrivial_dtor : Error< + "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< "%0 may not be nested in a struct due to flexible array member">, InGroup; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 78ead1ee92b6..222211dab97e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11994,9 +11994,14 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) << FD->getDeclName() << Record->getTagKind(); - if (!FD->getType()->isDependentType() && - !Context.getBaseElementType(FD->getType()).isPODType(Context)) { - Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) + // If the element type has a non-trivial destructor, we would not + // implicitly destroy the elements, so disallow it for now. + // + // 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->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); diff --git a/clang/test/ARCMT/cxx-checking.mm b/clang/test/ARCMT/cxx-checking.mm index 35bc71d992e3..aa3bc466f672 100644 --- a/clang/test/ARCMT/cxx-checking.mm +++ b/clang/test/ARCMT/cxx-checking.mm @@ -80,7 +80,7 @@ int check_non_pod_block1[__is_pod(int (^ __unsafe_unretained)(int))? 1 : -1]; struct FlexibleArrayMember0 { 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 { diff --git a/clang/test/SemaCXX/flexible-array-test.cpp b/clang/test/SemaCXX/flexible-array-test.cpp index f287711eeb6a..e58f19a62eca 100644 --- a/clang/test/SemaCXX/flexible-array-test.cpp +++ b/clang/test/SemaCXX/flexible-array-test.cpp @@ -36,14 +36,20 @@ void foo() } struct S { - virtual void foo(); + virtual void foo(); }; struct X { 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 { int s; 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(); + } +};