Basic support for flexible array members in constant evaluation.
authorRichard Smith <richard@metafoo.co.uk>
Mon, 13 Jul 2020 23:54:39 +0000 (16:54 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Mon, 13 Jul 2020 23:57:53 +0000 (16:57 -0700)
We don't allow runtime-sized flexible array members, nor initialization
of flexible array members, but it seems reasonable to support the most
basic case where the flexible array member is empty.

clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp

index a4dc0cc..d20c238 100644 (file)
@@ -9929,8 +9929,18 @@ namespace {
     bool ZeroInitialization(const Expr *E) {
       const ConstantArrayType *CAT =
           Info.Ctx.getAsConstantArrayType(E->getType());
-      if (!CAT)
+      if (!CAT) {
+        if (const IncompleteArrayType *IAT =
+                Info.Ctx.getAsIncompleteArrayType(E->getType())) {
+          // We can be asked to zero-initialize a flexible array member; this
+          // is represented as an ImplicitValueInitExpr of incomplete array
+          // type. In this case, the array has zero elements.
+          Result = APValue(APValue::UninitArray(), 0, 0);
+          return true;
+        }
+        // FIXME: We could handle VLAs here.
         return Error(E);
+      }
 
       Result = APValue(APValue::UninitArray(), 0,
                        CAT->getSize().getZExtValue());
index 78e9fef..b69bcb2 100644 (file)
@@ -2322,3 +2322,22 @@ namespace array_size {
     f3(a);
   }
 }
+
+namespace flexible_array {
+  struct A { int x; char arr[]; }; // expected-warning {{C99}} expected-note {{here}}
+  constexpr A a = {1};
+  static_assert(a.x == 1, "");
+  static_assert(&a.arr != nullptr, "");
+  static_assert(a.arr[0], ""); // expected-error {{constant expression}} expected-note {{array member without known bound}}
+  static_assert(a.arr[1], ""); // expected-error {{constant expression}} expected-note {{array member without known bound}}
+
+  constexpr A b[] = {{1}, {2}, {3}}; // expected-warning {{flexible array member}}
+  static_assert(b[0].x == 1, "");
+  static_assert(b[1].x == 2, "");
+  static_assert(b[2].x == 3, "");
+  static_assert(b[2].arr[0], ""); // expected-error {{constant expression}} expected-note {{array member without known bound}}
+
+  // If we ever start to accept this, we'll need to ensure we can
+  // constant-evaluate it properly.
+  constexpr A c = {1, 2, 3}; // expected-error {{initialization of flexible array member}}
+}