We ICE in cxx_eval_vec_init_1 whereby we try to initialize a flexible array
member, because the code computing the number of elements of ATYPE wasn't
prepared to handle arrays with no bounds.  Fixed by using
get_array_or_vector_nelts, broken out of existing code.

Martin suggested to reject this code, but I decided to leave this as-is for
now; we already reject code that actually tries to initialize the flexible
array member with some data, e.g.:

struct A {
  constexpr A() : i(), x("foo") {}
  int i;
  char x[];
};
A a;

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-03-02  Marek Polacek  <pola...@redhat.com>

        PR c++/84578
        * constexpr.c (get_array_or_vector_nelts): New.
        (cxx_eval_array_reference): Use it.
        (cxx_eval_vec_init_1): Likewise.
        (cxx_eval_store_expression): Likewise.

        * g++.dg/ext/flexary29.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 39e6cdfb33d..27f841db38f 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -2300,6 +2300,32 @@ diag_array_subscript (const constexpr_ctx *ctx, tree 
array, tree index)
     }
 }
 
+/* Return the number of elements for TYPE (which is an ARRAY_TYPE or
+   a VECTOR_TYPE).  */
+
+static tree
+get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
+                          bool *non_constant_p, bool *overflow_p)
+{
+  tree nelts;
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (type))
+       nelts = array_type_nelts_top (type);
+      else
+       nelts = size_zero_node;
+    }
+  else if (VECTOR_TYPE_P (type))
+    nelts = size_int (TYPE_VECTOR_SUBPARTS (type));
+  else
+    gcc_unreachable ();
+
+  /* For VLAs, the number of elements won't be an integer constant.  */
+  nelts = cxx_eval_constant_expression (ctx, nelts, false,
+                                       non_constant_p, overflow_p);
+  return nelts;
+}
+
 /* Extract element INDEX consisting of CHARS_PER_ELT chars from
    STRING_CST STRING.  */
 
@@ -2379,22 +2405,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
        }
     }
 
-  tree nelts;
-  if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-    {
-      if (TYPE_DOMAIN (TREE_TYPE (ary)))
-       nelts = array_type_nelts_top (TREE_TYPE (ary));
-      else
-       nelts = size_zero_node;
-    }
-  else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
-    nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
-  else
-    gcc_unreachable ();
-
-  /* For VLAs, the number of elements won't be an integer constant.  */
-  nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
-                                       overflow_p);
+  tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
+                                         overflow_p);
   VERIFY_CONSTANT (nelts);
   if ((lval
        ? !tree_int_cst_le (index, nelts)
@@ -2895,7 +2907,6 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree 
atype, tree init,
                     bool *non_constant_p, bool *overflow_p)
 {
   tree elttype = TREE_TYPE (atype);
-  unsigned HOST_WIDE_INT max = tree_to_uhwi (array_type_nelts_top (atype));
   verify_ctor_sanity (ctx, atype);
   vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
   bool pre_init = false;
@@ -2924,6 +2935,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree 
atype, tree init,
       pre_init = true;
     }
 
+  tree nelts = get_array_or_vector_nelts (ctx, atype, non_constant_p,
+                                         overflow_p);
+  unsigned HOST_WIDE_INT max = tree_to_uhwi (nelts);
   for (i = 0; i < max; ++i)
     {
       tree idx = build_int_cst (size_type_node, i);
@@ -3480,19 +3494,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, 
tree t,
        case ARRAY_REF:
          tree nelts, ary;
          ary = TREE_OPERAND (probe, 0);
-         if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE)
-           {
-             if (TYPE_DOMAIN (TREE_TYPE (ary)))
-               nelts = array_type_nelts_top (TREE_TYPE (ary));
-             else
-               nelts = size_zero_node;
-           }
-         else if (VECTOR_TYPE_P (TREE_TYPE (ary)))
-           nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary)));
-         else
-           gcc_unreachable ();
-         nelts = cxx_eval_constant_expression (ctx, nelts, false,
-                                               non_constant_p, overflow_p);
+         nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary),
+                                            non_constant_p, overflow_p);
          VERIFY_CONSTANT (nelts);
          gcc_assert (TREE_CODE (nelts) == INTEGER_CST
                      && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
diff --git gcc/testsuite/g++.dg/ext/flexary29.C 
gcc/testsuite/g++.dg/ext/flexary29.C
index e69de29bb2d..a696fd9804f 100644
--- gcc/testsuite/g++.dg/ext/flexary29.C
+++ gcc/testsuite/g++.dg/ext/flexary29.C
@@ -0,0 +1,12 @@
+// PR c++/84578
+// { dg-do compile { target c++11 } }
+// { dg-options -Wno-pedantic }
+
+struct A
+{
+  constexpr A() : i(), x() {}
+  int i;
+  char x[];
+};
+
+A a;

        Marek

Reply via email to