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