https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99122
--- Comment #34 from Richard Biener <rguenth at gcc dot gnu.org> --- interestingly I see a.9_70 = .builtin_alloca_with_align (iftmp.8_1, 8); (*a.9_70) = inline22.get_zero (); [static-chain: &FRAME.20] [return slot optimization] so there's no WITH_SIZE_EXPR, but the return value ends up done by reference: leaq -80(%rbp), %rdx movq %rdx, %r10 movq %rax, %rdi call inline22__get_zero.0 movq %rbx, %rsp movq -8(%rbp), %rbx leave so I wonder if omitting DECL_BY_REFERENCE is simply a bug? I mean the ABI of the callee must be aware and it seems CALL_EXPR_RETURN_SLOT_OPT is set by gimplification. IIRC CALL_EXPR_RETURN_SLOT_OPT also only means we _may_ return by reference not that we must. /* In a CALL_EXPR, means that it's safe to use the target of the call expansion as the return slot for a call that returns in memory. */ #define CALL_EXPR_RETURN_SLOT_OPT(NODE) \ (CALL_EXPR_CHECK (NODE)->base.private_flag) But of course if we do not exercise the return slot opt then there definitely is a WITH_SIZE_EXPR missing. Unless I'm missing somehting ... The gimplifier code checks else if (TREE_CODE (*to_p) != SSA_NAME && (!is_gimple_variable (*to_p) || needs_to_live_in_memory (*to_p))) /* Don't use the original target if it's already addressable; if its address escapes, and the called function uses the NRV optimization, a conforming program could see *to_p change before the called function returns; see c++/19317. When optimizing, the return_slot pass marks more functions as safe after we have escape info. */ use_target = false; so I wonder if you can modify the Ada testcase so that CALL_EXPR_RETURN_SLOT_OPT is not set?