Hi rsmith, rnk, andreadb,

Zero sized arrays are more or less the pre-standard version of flexible
array members.  It makes sense to mark structs which contain them as
hasFlexibleArrayMember.

Doing this has the side effect of resolving PR21040, a crash involving
one record inheriting from a base which is terminated with a zero sized
array field.

http://reviews.llvm.org/D5478

Files:
  include/clang/AST/ASTContext.h
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/Analysis/dtors-in-dtor-cfg-output.cpp
  test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
  test/CodeGenObjC/arc-captured-block-var-layout.m
  test/SemaCXX/flexible-array-test.cpp
  test/SemaCXX/zero-length-arrays.cpp
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1910,6 +1910,10 @@
   /// \brief Return number of constant array elements.
   uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
 
+  /// \brief Determine whether the given type is an incomplete or zero-length
+  /// array type.
+  bool isIncompleteOrZeroLengthArrayType(QualType T) const;
+
   /// \brief Perform adjustment on the parameter type of a function.
   ///
   /// This routine adjusts the given parameter type @p T to the actual
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -4323,6 +4323,20 @@
   return ElementCount;
 }
 
+bool ASTContext::isIncompleteOrZeroLengthArrayType(QualType T) const {
+  if (T->isIncompleteArrayType())
+    return true;
+
+  while (const ConstantArrayType *ArrayT = getAsConstantArrayType(T)) {
+    if (!ArrayT->getSize())
+      return true;
+
+    T = ArrayT->getElementType();
+  }
+
+  return false;
+}
+
 /// getFloatingRank - Return a relative rank for floating point types.
 /// This routine will assert if passed a built-in type that isn't a float.
 static FloatingRank getFloatingRank(QualType T) {
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -12618,7 +12618,7 @@
     FieldDecl *FD = cast<FieldDecl>(*i);
 
     // Get the type for the field.
-    const Type *FDTy = FD->getType().getTypePtr();
+    QualType FDTy = FD->getType();
 
     if (!FD->isAnonymousStructOrUnion()) {
       // Remember all fields written by the user.
@@ -12649,10 +12649,9 @@
       FD->setInvalidDecl();
       EnclosingDecl->setInvalidDecl();
       continue;
-    } else if (FDTy->isIncompleteArrayType() && Record && 
+    } else if (Context.isIncompleteOrZeroLengthArrayType(FDTy) && Record &&
                ((i + 1 == Fields.end() && !Record->isUnion()) ||
-                ((getLangOpts().MicrosoftExt ||
-                  getLangOpts().CPlusPlus) &&
+                ((getLangOpts().MicrosoftExt || getLangOpts().CPlusPlus) &&
                  (i + 1 == Fields.end() || Record->isUnion())))) {
       // Flexible array member.
       // Microsoft and g++ is more permissive regarding flexible array.
@@ -12674,7 +12673,7 @@
                                  ? diag::err_flexible_array_empty_aggregate
                                  : 0;
 
-      if (DiagID)
+      if (DiagID && FDTy->isIncompleteArrayType())
         Diag(FD->getLocation(), DiagID) << FD->getDeclName()
                                         << Record->getTagKind();
       // While the layout of types that contain virtual bases is not specified
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -3526,22 +3526,6 @@
 };
 }
 
-/// \brief Determine whether the given type is an incomplete or zero-lenfgth
-/// array type.
-static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
-  if (T->isIncompleteArrayType())
-    return true;
-  
-  while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
-    if (!ArrayT->getSize())
-      return true;
-    
-    T = ArrayT->getElementType();
-  }
-  
-  return false;
-}
-
 static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
                                     FieldDecl *Field, 
                                     IndirectFieldDecl *Indirect = nullptr) {
@@ -3586,7 +3570,7 @@
   }
 
   // Don't initialize incomplete or zero-length arrays.
-  if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
+  if (SemaRef.Context.isIncompleteOrZeroLengthArrayType(Field->getType()))
     return false;
 
   // Don't try to build an implicit initializer if there were semantic
@@ -4071,7 +4055,7 @@
       continue;
     
     // Don't destroy incomplete or zero-length arrays.
-    if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+    if (Context.isIncompleteOrZeroLengthArrayType(Field->getType()))
       continue;
 
     QualType FieldType = Context.getBaseElementType(Field->getType());
Index: test/Analysis/dtors-in-dtor-cfg-output.cpp
===================================================================
--- test/Analysis/dtors-in-dtor-cfg-output.cpp
+++ test/Analysis/dtors-in-dtor-cfg-output.cpp
@@ -27,7 +27,6 @@
 
 class TestArray {
   A a[2];
-  A b[0];
 public:
   ~TestArray();
 };
Index: test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
===================================================================
--- test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
+++ test/CodeGenObjC/arc-captured-32bit-block-var-layout.m
@@ -152,10 +152,10 @@
 void arr3() {
   struct S {
    int a;
-    __unsafe_unretained id unsafe_unretained_var[0];
+    __unsafe_unretained id unsafe_unretained_var[7];
  } imported_s;
 
-// CHECK: block variable layout: BL_OPERATOR:0
+// CHECK: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:7, BL_OPERATOR:0
     void (^c)() = ^{
       int i = imported_s.a;
     };    
Index: test/CodeGenObjC/arc-captured-block-var-layout.m
===================================================================
--- test/CodeGenObjC/arc-captured-block-var-layout.m
+++ test/CodeGenObjC/arc-captured-block-var-layout.m
@@ -151,10 +151,10 @@
 void arr3() {
   struct S {
    int a;
-    __unsafe_unretained id unsafe_unretained_var[0];
+    __unsafe_unretained id unsafe_unretained_var[7];
  } imported_s;
 
-// CHECK-LP64: block variable layout: BL_OPERATOR:0
+// CHECK-LP64: block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:7, BL_OPERATOR:0
     void (^c)() = ^{
       int i = imported_s.a;
     };    
Index: test/SemaCXX/flexible-array-test.cpp
===================================================================
--- test/SemaCXX/flexible-array-test.cpp
+++ test/SemaCXX/flexible-array-test.cpp
@@ -94,3 +94,15 @@
       ntd[i-1].~NonTrivDtor();
   }
 };
+
+namespace PR21040 {
+struct A {
+  int a0[0];
+};
+
+struct B : private A { // expected-error {{base class 'A' has a flexible array member}}
+  int b;
+};
+
+B bb;
+}
Index: test/SemaCXX/zero-length-arrays.cpp
===================================================================
--- test/SemaCXX/zero-length-arrays.cpp
+++ test/SemaCXX/zero-length-arrays.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 // <rdar://problem/10228639>
 class Foo {
@@ -11,9 +10,7 @@
 
 class Bar {
   int foo_count;
-  Foo foos[0];
-  Foo foos2[0][2];
-  Foo foos3[2][0];
+  Foo foos[0]; // expected-error-re {{flexible array member {{.*}} with non-trivial destruction}}
 
 public:
   Bar(): foo_count(0) { }    
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to