https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109945
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |ibuclaw at gcc dot gnu.org --- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #9) > (In reply to Andrew Pinski from comment #8) > > (In reply to Arthur O'Dwyer from comment #7) > > > // https://godbolt.org/z/Ea43Y65z4 > > > struct Widget { > > > int i = 1; > > ... > > > In this case, Widget has no constructors, > > > > No, it has a constructor because of the NSDMI . NSDMI causes a non-trival > > constexpr constructor to be created. > > Now this version does not: > ``` > struct Widget { > int i; > int a[4]; > }; > Widget *global = 0; > Widget make2() { Widget w; w.i = 1; global = &w; return w; } > void g() { global->i = 42; } > int main() { > Widget w = make2(); > int i = w.i; > g(); > return (i == w.i); > // Does this need to be reloaded and > // compared? or is it obviously true? > } > ``` > > But does w go out of the scope at the end of make2? Similar question to make > in the original testcase, does the temp go out of scope? In this example we don't have TYPE_NEEDS_CONSTRUCTING set, in the NSDMI case it's still set. I'm happy to do points-to analysis adjustments but C++ folks have to answer whether using return-slot-opt is valid here and what constraints apply. >From the middle-end description /* 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) I'd read that - unless we have another bit unknown to me explicitely indicating this - the return destination escapes. Besides the C++ frontend the D frontend uses return-slot-opt as well. I'll also note that the gimplifier in gimplify_modify_expr_rhs can make calls CALL_EXPR_RETURN_SLOT_OPT when they were not before and the only common condition is the CALL_EXPR is aggregate_value_p (*from_p, *from_p) For the fun of it I'm testing diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc index 56021c59cb9..1e7f0383371 100644 --- a/gcc/tree-ssa-structalias.cc +++ b/gcc/tree-ssa-structalias.cc @@ -4366,7 +4366,7 @@ handle_rhs_call (gcall *stmt, vec<ce_s> *results, /* And if we applied NRV the address of the return slot escapes as well. */ if (gimple_call_return_slot_opt_p (stmt) && gimple_call_lhs (stmt) != NULL_TREE - && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt)))) + && aggregate_value_p (gimple_call_lhs (stmt), gimple_call_fntype (stmt))) { int flags = gimple_call_retslot_flags (stmt); const int relevant_flags = EAF_NO_DIRECT_ESCAPE