diff mbox

C++ PATCH for c++/61382 (init-list evaluation order)

Message ID 538F4056.7020009@redhat.com
State New
Headers show

Commit Message

Jason Merrill June 4, 2014, 3:50 p.m. UTC
My patch for 51253 didn't handle all cases of this; I was forgetting 
that when we direct-initialize a variable, we never build an 
AGGR_INIT_EXPR.  So let's handle this in cp_gimplify_expr.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 2cddc650aac580698d4ff47c31670f168aa3ce31
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 4 10:46:15 2014 -0400

    	PR c++/51253
    	PR c++/61382
    gcc/
    	* gimplify.c (gimplify_arg): Non-static.
    	* gimplify.h: Declare it.
    gcc/cp/
    	* cp-gimplify.c (cp_gimplify_expr): Handle CALL_EXPR_LIST_INIT_P here.
    	* semantics.c (simplify_aggr_init_expr): Not here, just copy it.

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index ef4b043..18142bf 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -723,6 +723,27 @@  cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 	  && !seen_error ())
 	return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
 
+      /* DR 1030 says that we need to evaluate the elements of an
+	 initializer-list in forward order even when it's used as arguments to
+	 a constructor.  So if the target wants to evaluate them in reverse
+	 order and there's more than one argument other than 'this', gimplify
+	 them in order.  */
+      ret = GS_OK;
+      if (PUSH_ARGS_REVERSED && CALL_EXPR_LIST_INIT_P (*expr_p)
+	  && call_expr_nargs (*expr_p) > 2)
+	{
+	  int nargs = call_expr_nargs (*expr_p);
+	  location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
+	  for (int i = 1; i < nargs; ++i)
+	    {
+	      enum gimplify_status t
+		= gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, loc);
+	      if (t == GS_ERROR)
+		ret = GS_ERROR;
+	    }
+	}
+      break;
+
     default:
       ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
       break;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c1c16f4..ca0c34b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3869,6 +3869,7 @@  simplify_aggr_init_expr (tree *tp)
 				    aggr_init_expr_nargs (aggr_init_expr),
 				    AGGR_INIT_EXPR_ARGP (aggr_init_expr));
   TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr);
+  CALL_EXPR_LIST_INIT_P (call_expr) = CALL_EXPR_LIST_INIT_P (aggr_init_expr);
   tree ret = call_expr;
 
   if (style == ctor)
@@ -3900,20 +3901,6 @@  simplify_aggr_init_expr (tree *tp)
       ret = build2 (COMPOUND_EXPR, TREE_TYPE (slot), ret, slot);
     }
 
-  /* DR 1030 says that we need to evaluate the elements of an
-     initializer-list in forward order even when it's used as arguments to
-     a constructor.  So if the target wants to evaluate them in reverse
-     order and there's more than one argument other than 'this', force
-     pre-evaluation.  */
-  if (PUSH_ARGS_REVERSED && CALL_EXPR_LIST_INIT_P (aggr_init_expr)
-      && aggr_init_expr_nargs (aggr_init_expr) > 2)
-    {
-      tree preinit;
-      stabilize_call (call_expr, &preinit);
-      if (preinit)
-	ret = build2 (COMPOUND_EXPR, TREE_TYPE (ret), preinit, ret);
-    }
-
   if (AGGR_INIT_ZERO_FIRST (aggr_init_expr))
     {
       tree init = build_zero_init (type, NULL_TREE,
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 92714b5..89ae41f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2170,7 +2170,7 @@  maybe_with_size_expr (tree *expr_p)
    Store any side-effects in PRE_P.  CALL_LOCATION is the location of
    the CALL_EXPR.  */
 
-static enum gimplify_status
+enum gimplify_status
 gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location)
 {
   bool (*test) (tree);
diff --git a/gcc/gimplify.h b/gcc/gimplify.h
index 47e7213..5085ccf 100644
--- a/gcc/gimplify.h
+++ b/gcc/gimplify.h
@@ -77,6 +77,7 @@  extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
 extern void gimplify_type_sizes (tree, gimple_seq *);
 extern void gimplify_one_sizepos (tree *, gimple_seq *);
 extern gimple gimplify_body (tree, bool);
+extern enum gimplify_status gimplify_arg (tree *, gimple_seq *, location_t);
 extern void gimplify_function_tree (tree);
 extern enum gimplify_status gimplify_va_arg_expr (tree *, gimple_seq *,
 						  gimple_seq *);
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist86.C b/gcc/testsuite/g++.dg/cpp0x/initlist86.C
new file mode 100644
index 0000000..16af476
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist86.C
@@ -0,0 +1,18 @@ 
+// PR c++/61382
+// { dg-do run { target c++11 } }
+
+struct A
+{
+  int i,j;
+  A(int i,int j):i(i),j(j){}
+};
+
+extern "C" int printf (const char *, ...);
+
+int main()
+{
+  int i;
+  A a{i++,i++};
+  if (a.i != 0 || a.j != 1)
+    __builtin_abort();
+}