Here, when we start to modify an array element, we add a
constructor_elt for it to the CONSTRUCTOR.  When calculating the value
to store there we found this empty element and tried to use it,
leading to an ICE because it was NULL.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit b472cebfc4ce1bc44d2d328f5f693322e04c905b
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Jul 25 09:54:04 2016 -0400

        PR c++/71972 - constexpr array self-modification
    
        * constexpr.c (cxx_eval_array_reference): Handle looking for the
        value of an element we're currently modifying.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index f139260..47fb39b 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2129,8 +2129,32 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
   else
     found = (i < len);
 
-  if (!found)
+  if (found)
     {
+      tree r;
+      if (TREE_CODE (ary) == CONSTRUCTOR)
+       r = (*CONSTRUCTOR_ELTS (ary))[i].value;
+      else if (TREE_CODE (ary) == VECTOR_CST)
+       r = VECTOR_CST_ELT (ary, i);
+      else if (elem_nchars == 1)
+       r = build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
+                          TREE_STRING_POINTER (ary)[i]);
+      else
+       {
+         tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
+         r = native_interpret_expr (type, (const unsigned char *)
+                                    TREE_STRING_POINTER (ary)
+                                    + i * elem_nchars, elem_nchars);
+       }
+      if (r)
+       /* Don't VERIFY_CONSTANT here.  */
+       return r;
+
+      /* Otherwise the element doesn't have a value yet.  */
+    }
+
+  /* Not found.  */
+
   if (TREE_CODE (ary) == CONSTRUCTOR
       && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary))
     {
@@ -2150,23 +2174,6 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree 
t,
                                       overflow_p);
 }
 
-  if (TREE_CODE (ary) == CONSTRUCTOR)
-    return (*CONSTRUCTOR_ELTS (ary))[i].value;
-  else if (TREE_CODE (ary) == VECTOR_CST)
-    return VECTOR_CST_ELT (ary, i);
-  else if (elem_nchars == 1)
-    return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))),
-                         TREE_STRING_POINTER (ary)[i]);
-  else
-    {
-      tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (ary)));
-      return native_interpret_expr (type, (const unsigned char *)
-                                         TREE_STRING_POINTER (ary)
-                                         + i * elem_nchars, elem_nchars);
-    }
-  /* Don't VERIFY_CONSTANT here.  */
-}
-
 /* Subroutine of cxx_eval_constant_expression.
    Attempt to reduce a field access of a value of class type.  */
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C
new file mode 100644
index 0000000..3abdd84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-array5.C
@@ -0,0 +1,13 @@
+// PR c++/71972
+// { dg-do compile { target c++14 } }
+
+typedef int size_t;
+template <int N> struct S {
+  template <size_t M> constexpr S(const char (&)[M]) : data{} {
+    data[0] = data[0];
+  }
+  char data[N];
+};
+int main() {
+  constexpr S<1> s1("");
+}

Reply via email to