diff --git a/gcc/expr.cc b/gcc/expr.cc index 2918c4697354..8a1875d7809a 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -5466,6 +5466,7 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size, /* If source is a constant VAR_DECL with a simple constructor, store the constructor to the stack instead of moving it. */ const_tree decl; + HOST_WIDE_INT sz; if (partial == 0 && MEM_P (xinner) && SYMBOL_REF_P (XEXP (xinner, 0)) @@ -5473,9 +5474,11 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size, && VAR_P (decl) && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl) - && immediate_const_ctor_p (DECL_INITIAL (decl), 2)) - store_constructor (DECL_INITIAL (decl), target, 0, - int_expr_size (DECL_INITIAL (decl)), false); + && immediate_const_ctor_p (DECL_INITIAL (decl), 2) + && (sz = int_expr_size (DECL_INITIAL (decl))) > 0 + && CONST_INT_P (size) + && INTVAL (size) == sz) + store_constructor (DECL_INITIAL (decl), target, 0, sz, false); else emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM); } diff --git a/gcc/testsuite/gcc.c-torture/execute/pr114552.c b/gcc/testsuite/gcc.c-torture/execute/pr114552.c new file mode 100644 index 000000000000..22cb4ee351f2 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr114552.c @@ -0,0 +1,24 @@ +/* PR middle-end/114552 */ + +struct __attribute__((packed)) S { short b; int c; }; +struct T { struct S b; int e; }; +static const struct T k = { { 1, 0 }, 0 }; + +__attribute__((noinline)) void +foo (void) +{ + asm volatile ("" : : : "memory"); +} + +__attribute__((noinline)) void +bar (struct S n) +{ + foo (); +} + +int +main () +{ + bar (k.b); + return 0; +}