diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2dd042b1ef..3649706d319 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-11-08 Jakub Jelinek + + PR c++/92384 + * function.c (assign_parm_setup_block, assign_parm_setup_stack): Don't + copy TYPE_EMPTY_P arguments from data->entry_parm to data->stack_parm + slot. + (assign_parms): For TREE_ADDRESSABLE parms with TYPE_EMPTY_P type + force creation of a unique data.stack_parm slot. + 2019-11-08 Richard Biener * genmatch.c (expr::gen_transform): Use the resimplify diff --git a/gcc/function.c b/gcc/function.c index 3f79a38aeae..1fe956bd1a5 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3087,7 +3087,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all, move_block_from_reg (REGNO (entry_parm), mem, size_stored / UNITS_PER_WORD); } - else if (data->stack_parm == 0) + else if (data->stack_parm == 0 && !TYPE_EMPTY_P (data->arg.type)) { push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn); emit_block_move (stack_parm, data->entry_parm, GEN_INT (size), @@ -3488,7 +3488,9 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm, dest = validize_mem (copy_rtx (data->stack_parm)); src = validize_mem (copy_rtx (data->entry_parm)); - if (MEM_P (src)) + if (TYPE_EMPTY_P (data->arg.type)) + /* Empty types don't really need to be copied. */; + else if (MEM_P (src)) { /* Use a block move to handle potentially misaligned entry_parm. */ if (!to_conversion) @@ -3643,6 +3645,16 @@ assign_parms (tree fndecl) { assign_parm_find_stack_rtl (parm, &data); assign_parm_adjust_entry_rtl (&data); + /* For arguments that occupy no space in the parameter + passing area, have non-zero size and have address taken, + force creation of a stack slot so that they have distinct + address from other parameters. */ + if (TYPE_EMPTY_P (data.arg.type) + && TREE_ADDRESSABLE (parm) + && data.entry_parm == data.stack_parm + && MEM_P (data.entry_parm) + && int_size_in_bytes (data.arg.type)) + data.stack_parm = NULL_RTX; } /* Record permanently how this parm was passed. */ if (data.arg.pass_by_reference) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b7bea0b6e2..6e3027ff046 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-11-08 Jakub Jelinek + + PR c++/92384 + * g++.dg/torture/pr92384.C: New test. + 2019-11-08 Martin Liska * g++.dg/pr92339.C: Rename identifiers to something diff --git a/gcc/testsuite/g++.dg/torture/pr92384.C b/gcc/testsuite/g++.dg/torture/pr92384.C new file mode 100644 index 00000000000..049a45a0154 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr92384.C @@ -0,0 +1,38 @@ +// PR c++/92384 +// { dg-do run } + +struct S {}; +struct T : public S { S a, b, c, d, e, f, g, h, i, j, k, l, m; }; +struct U { long long a, b, c; }; + +U +foo (S, S, S, T, T, T, U g) +{ + return g; +} + +__attribute__((noipa)) bool +bar (S a, S b, S c, T d, T e, T f, U g, void **h) +{ + h[0] = (void *) &a; + h[1] = (void *) &b; + h[2] = (void *) &c; + h[3] = (void *) &d; + h[4] = (void *) &e; + h[5] = (void *) &f; + h[6] = (void *) &g; + asm volatile ("" : : "r" (h) : "memory"); + return (h[0] != h[1] && h[1] != h[2] && h[2] != h[3] + && h[3] != h[4] && h[4] != h[5] && h[5] != h[6]); +} + +int +main () +{ + S a; + T b; + U c = { 1, 2, 3 }; + void *d[7]; + if (!bar (a, a, a, b, b, b, c, d)) + __builtin_abort (); +}