Hi!

The following testcase ICEs, because gimple_call_arg_ptr (..., 0)
asserts that there is at least one argument, while we were using
it even if we didn't copy anything just to get a pointer from/to which
the zero arguments should be copied.

Fixed by guarding the memcpy calls.  Also, the code was calling
gimple_call_num_args too many times - 5 times instead of 2, so the patch
adds two temporaries for those.

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

2021-06-06  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/100898
        * tree-inline.c (copy_bb): Only use gimple_call_arg_ptr if memcpy
        should copy any arguments.  Don't call gimple_call_num_args
        on id->call_stmt or call_stmt more than once.

        * g++.dg/ext/va-arg-pack-3.C: New test.

--- gcc/tree-inline.c.jj        2021-06-04 11:15:26.000000000 +0200
+++ gcc/tree-inline.c   2021-06-04 15:15:07.358413674 +0200
@@ -2090,27 +2090,29 @@ copy_bb (copy_body_data *id, basic_block
              tree p;
              gcall *new_call;
              vec<tree> argarray;
-             size_t nargs = gimple_call_num_args (id->call_stmt);
-             size_t n;
+             size_t nargs_caller = gimple_call_num_args (id->call_stmt);
+             size_t nargs = nargs_caller;
 
              for (p = DECL_ARGUMENTS (id->src_fn); p; p = DECL_CHAIN (p))
                nargs--;
 
              /* Create the new array of arguments.  */
-             n = nargs + gimple_call_num_args (call_stmt);
+             size_t nargs_callee = gimple_call_num_args (call_stmt);
+             size_t n = nargs + nargs_callee;
              argarray.create (n);
              argarray.safe_grow_cleared (n, true);
 
              /* Copy all the arguments before '...'  */
-             memcpy (argarray.address (),
-                     gimple_call_arg_ptr (call_stmt, 0),
-                     gimple_call_num_args (call_stmt) * sizeof (tree));
+             if (nargs_callee)
+               memcpy (argarray.address (),
+                       gimple_call_arg_ptr (call_stmt, 0),
+                       nargs_callee * sizeof (tree));
 
              /* Append the arguments passed in '...'  */
-             memcpy (argarray.address () + gimple_call_num_args (call_stmt),
-                     gimple_call_arg_ptr (id->call_stmt, 0)
-                     + (gimple_call_num_args (id->call_stmt) - nargs),
-                     nargs * sizeof (tree));
+             if (nargs)
+               memcpy (argarray.address () + nargs_callee,
+                       gimple_call_arg_ptr (id->call_stmt, 0)
+                       + (nargs_caller - nargs), nargs * sizeof (tree));
 
              new_call = gimple_build_call_vec (gimple_call_fn (call_stmt),
                                                argarray);
--- gcc/testsuite/g++.dg/ext/va-arg-pack-3.C.jj 2021-06-04 15:32:28.213079130 
+0200
+++ gcc/testsuite/g++.dg/ext/va-arg-pack-3.C    2021-06-04 15:31:29.777883575 
+0200
@@ -0,0 +1,18 @@
+// PR middle-end/100898
+
+int a;
+int bar (int, ...);
+
+static inline __attribute__((always_inline)) int
+foo (...)
+{
+  while (a)
+    return bar (0, __builtin_va_arg_pack ());
+  return 0;
+}
+
+void
+baz (void)
+{
+  foo ();
+}

        Jakub

Reply via email to