When passing an aggregate to a implicitly declared function that's later declared as receiving a register type we can run into a sanity assert that cannot hold for such gross mismatches. Instead of asserting avoid emitting a debug temp that's invalid.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR middle-end/112487 * tree-inline.cc (setup_one_parameter): When the parameter is unused only insert a debug bind when there's not a gross mismatch in value and declared parameter type. Do not assert there effectively isn't. * gcc.dg/torture/pr112487.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr112487.c | 18 ++++++++++++++++++ gcc/tree-inline.cc | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr112487.c diff --git a/gcc/testsuite/gcc.dg/torture/pr112487.c b/gcc/testsuite/gcc.dg/torture/pr112487.c new file mode 100644 index 00000000000..bc2838ee3eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr112487.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-w -std=gnu89" } */ + +struct A { char i; }; +struct B { + struct C *p; + struct A *q; +}; +struct C { struct B a[1]; }; +struct T { struct U *ptr; }; + +volatile struct T v; +void f1(volatile struct T v) { f2(v); } +void f2(volatile struct T *const v) { } +void bar() { + struct U *ptr; + f1(v); +} diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 00d05102e7a..0b14118b94b 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -3562,7 +3562,11 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn, it. */ if (optimize && gimple_in_ssa_p (cfun) && !def && is_gimple_reg (p)) { - gcc_assert (!value || !TREE_SIDE_EFFECTS (value)); + /* When there's a gross type mismatch between the passed value + and the declared argument type drop it on the floor and do + not bother to insert a debug bind. */ + if (value && !is_gimple_reg_type (TREE_TYPE (value))) + return NULL; return insert_init_debug_bind (id, bb, var, rhs, NULL); } -- 2.35.3