re PR c++/91974 (function not sequenced before function argument)
authorJakub Jelinek <jakub@redhat.com>
Fri, 4 Oct 2019 06:54:05 +0000 (08:54 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 4 Oct 2019 06:54:05 +0000 (08:54 +0200)
PR c++/91974
* cp-gimplify.c (cp_gimplify_expr) <case CALL_EXPR>: For
-fstrong-eval-order ensure CALL_EXPR_FN side-effects are evaluated
before any arguments.  Additionally, ensure CALL_EXPR_FN that isn't
invariant nor OBJ_TYPE_REF nor SSA_NAME is forced into a temporary.

* g++.dg/cpp1z/eval-order5.C: New test.

From-SVN: r276562

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/eval-order5.C [new file with mode: 0644]

index bd3592a..a11bdaf 100644 (file)
@@ -1,3 +1,11 @@
+2019-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/91974
+       * cp-gimplify.c (cp_gimplify_expr) <case CALL_EXPR>: For
+       -fstrong-eval-order ensure CALL_EXPR_FN side-effects are evaluated
+       before any arguments.  Additionally, ensure CALL_EXPR_FN that isn't
+       invariant nor OBJ_TYPE_REF nor SSA_NAME is forced into a temporary.
+
 2019-10-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * init.c (build_new): Use cp_expr_loc_or_input_loc in two places.
index 8bda736..6545392 100644 (file)
@@ -818,6 +818,21 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
     case CALL_EXPR:
       ret = GS_OK;
+      if (flag_strong_eval_order == 2
+         && CALL_EXPR_FN (*expr_p)
+         && cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE)
+       {
+         enum gimplify_status t
+           = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
+                            is_gimple_call_addr, fb_rvalue);
+         if (t == GS_ERROR)
+           ret = GS_ERROR;
+         else if (is_gimple_variable (CALL_EXPR_FN (*expr_p))
+                  && TREE_CODE (CALL_EXPR_FN (*expr_p)) != SSA_NAME)
+           CALL_EXPR_FN (*expr_p)
+             = get_initialized_tmp_var (CALL_EXPR_FN (*expr_p), pre_p,
+                                        NULL);
+       }
       if (!CALL_EXPR_FN (*expr_p))
        /* Internal function call.  */;
       else if (CALL_EXPR_REVERSE_ARGS (*expr_p))
index fdfcde2..1dce341 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/91974
+       * g++.dg/cpp1z/eval-order5.C: New test.
+
 2019-10-03  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/91497
diff --git a/gcc/testsuite/g++.dg/cpp1z/eval-order5.C b/gcc/testsuite/g++.dg/cpp1z/eval-order5.C
new file mode 100644 (file)
index 0000000..a8f06ed
--- /dev/null
@@ -0,0 +1,31 @@
+// PR c++/91974
+// { dg-do run }
+// { dg-options "-fstrong-eval-order" }
+
+extern "C" void abort ();
+
+bool ok = false;
+
+void
+foo (int x)
+{
+  if (x != 0)
+    abort ();
+  ok = true;
+}
+
+void
+bar (int)
+{
+  abort ();
+}
+
+int
+main ()
+{
+  typedef void (*T) (int);
+  T fn = foo;
+  fn ((fn = bar, 0));
+  if (fn != bar || !ok)
+    abort ();
+}