]> granicus.if.org Git - clang/commitdiff
Fix "regression" caused by updating our notion of POD to better match the C++11
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 Jan 2014 00:53:35 +0000 (00:53 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 11 Jan 2014 00:53:35 +0000 (00:53 +0000)
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).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198983 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/ARCMT/cxx-checking.mm
test/SemaCXX/flexible-array-test.cpp

index a43ce7f32b2968c4393282f6cdff499e7fd262af..837862e575b649a72614563d5ce13dd5baa941b9 100644 (file)
@@ -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<FlexibleArrayExtensions>;
index 78ead1ee92b6eddb50a5a156c428896cac0f88e8..222211dab97ee7280364bf1347f0dc3d114586e4 100644 (file)
@@ -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();
index 35bc71d992e3a476268e54223c2a9f1734ceef65..aa3bc466f672deac2fc450105c176fc4f014f66e 100644 (file)
@@ -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 {
index f287711eeb6a5de5442ea31475235019a9720db2..e58f19a62eca93c9380aa71cf1e570ff51f624b8 100644 (file)
@@ -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();
+  }
+};