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

Reply via email to