diff mbox

C++ PATCH for c++/78572 (ICE with self-modifying array initializer)

Message ID CADzB+2nSGRN6-E+rRmX5WhW45apLPPTGXKXvBtLndxzBiRTFQQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Feb. 16, 2017, 4:41 p.m. UTC
Here, the problem was that the constexpr code for handling assignments
within a constexpr function, or to a temporary object created within
the constant-expression, was also allowing assignment to the target of
the initialization.  Fixed by specifically excluding that case.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 13c6ee3097eb21b4e1594504fda53c479b194796
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 15 16:55:39 2017 -0500

            PR c++/78572 - ICE with self-modifying array initializer
    
            * constexpr.c (cxx_eval_store_expression): The object we're
            initializing is outside the constant-expression.
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 004bb45..fc7d46c 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1635,6 +1635,7 @@  cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
 	  constexpr_ctx ctx_with_save_exprs = *ctx;
 	  hash_set<tree> save_exprs;
 	  ctx_with_save_exprs.save_exprs = &save_exprs;
+	  ctx_with_save_exprs.call = &new_call;
 
 	  tree jump_target = NULL_TREE;
 	  cxx_eval_constant_expression (&ctx_with_save_exprs, body,
@@ -3386,7 +3387,13 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   /* And then find/build up our initializer for the path to the subobject
      we're initializing.  */
   tree *valp;
-  if (DECL_P (object))
+  if (object == ctx->object && VAR_P (object)
+      && DECL_NAME (object) && ctx->call == NULL)
+    /* The variable we're building up an aggregate initializer for is outside
+       the constant-expression, so don't evaluate the store.  We check
+       DECL_NAME to handle TARGET_EXPR temporaries, which are fair game.  */
+    valp = NULL;
+  else if (DECL_P (object))
     valp = ctx->values->get (object);
   else
     valp = NULL;
diff --git a/gcc/testsuite/g++.dg/init/array47.C b/gcc/testsuite/g++.dg/init/array47.C
new file mode 100644
index 0000000..e3cb1b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array47.C
@@ -0,0 +1,3 @@ 
+// PR c++/78572
+
+static int array[10] = { array[3]=5, array[7]=3, };