tree-inline: Fix up __builtin_va_arg_pack handling [PR100898]

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.

2021-06-07  Jakub Jelinek  <jakub@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.
This commit is contained in:
Jakub Jelinek 2021-06-07 09:25:37 +02:00
parent be5efe9c12
commit d66a703c8b
2 changed files with 30 additions and 10 deletions

View File

@ -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 ();
}

View File

@ -2090,27 +2090,29 @@ copy_bb (copy_body_data *id, basic_block bb,
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);