The (invalid) testcase was causing an ICE because we were passing the result
of array_type_nelts_top immediately into tree_int_cst_lt, but for VLAs, the
result doesn't have to be a constant.  Fixed by evaluating the bound of the
array so that we're able to give a proper out-of-bounds diagnostics.  And the
VERIFY_CONSTANT should ensure that if the array bound couldn't be reduced to
a constant, we bail out rather than evoke an ICE.

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

2016-01-26  Marek Polacek  <pola...@redhat.com>

        PR c++/69496
        * constexpr.c (cxx_eval_array_reference): Evaluate the number of
        elements of the array.

        * g++.dg/cpp1y/constexpr-vla1.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 6b0e5a8..6324e45 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -1855,7 +1855,12 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
 
   if (!found)
     {
-      if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
+      tree nelts = array_type_nelts_top (TREE_TYPE (ary));
+      /* 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);
+      VERIFY_CONSTANT (nelts);
+      if (tree_int_cst_lt (index, nelts))
        {
          if (TREE_CODE (ary) == CONSTRUCTOR
              && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary))
diff --git gcc/testsuite/g++.dg/cpp1y/constexpr-vla1.C 
gcc/testsuite/g++.dg/cpp1y/constexpr-vla1.C
index e69de29..a5615bb 100644
--- gcc/testsuite/g++.dg/cpp1y/constexpr-vla1.C
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-vla1.C
@@ -0,0 +1,30 @@
+// PR c++/69496
+// { dg-do compile { target c++14 } }
+
+constexpr int
+fn_ok (int n)
+{
+    __extension__ int a[n] = { };
+    int z = 0;
+
+    for (unsigned i = 0; i < sizeof (a) / sizeof (int); ++i)
+      z += a[i];
+
+    return z;
+}
+
+
+constexpr int
+fn_not_ok (int n)
+{
+    __extension__ int a[n] = { };
+    int z = 0;
+
+    for (unsigned i = 0; i < sizeof (a); ++i)
+      z += a[i];
+
+    return z;
+}
+
+constexpr int n1 = fn_ok (3);
+constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript out of bound" 
}

        Marek

Reply via email to