<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/68747>68747</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            no lifetime markers emitted for returned aggregates
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            backend:ARM,
            c,
            clang:codegen,
            missed-optimization
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            nickdesaulniers
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          nickdesaulniers
      </td>
    </tr>
</table>

<pre>
    forked from #43598 (and https://reviews.llvm.org/D74094) which is C++ specific; there are different rules for C FWICT.

```c
struct foo {
    long long x;
};

struct foo foo_factory (void);
struct foo div (struct foo, struct foo);

long long bar (void) {
    return div(div(foo_factory(), foo_factory()), div(foo_factory(), foo_factory())).x;
}
```
We should emit lifetime intrinsics for those temporary aggregates returned from functions

The [latest C23 draft](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf) § 6.2.4 Storage durations of objects

> 8 A non-lvalue expression with structure or union type, where the structure or union contains a
member with array type (including, recursively, members of all contained structures and unions)
refers to an object with automatic storage duration and temporary lifetime. 39) Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends
when the evaluation of the containing full expression ends. Any attempt to modify an object with
temporary lifetime results in undefined behavior. An object with temporary lifetime behaves as if it
were declared with the type of its value for the purposes of effective type. Such an object need not
have a unique address.

Speaking more with @AaronBallman , Aaron found https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1285.htm introduced the current wording into c11. https://wiki.sei.cmu.edu/confluence/display/c/EXP35-C.+Do+not+modify+objects+with+temporary+lifetime talks more about this.  https://web.archive.org/web/20231010182056/https://yarchive.net/comp/struct_return.html talks more about this in regards to arrays within the returned struct.

Also, this is quite painful for 32b ARM due to [ARM AAPCS32](https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#result-return) § 6.4   Result Return

> A Composite Type larger than 4 bytes, or whose size cannot be determined statically by both caller and callee, is stored in memory at an address passed as an extra argument when the function was called ([Parameter Passing (base PCS)](https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#parameter-passing-base-pcs), [Rule A.4](https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#rule-a-4)). The memory to be used for the result may be modified at any point during the function call.

(I'll tag the ARM backend folks for the CC, though this isn't a backend specific bug)

So I think if the type contains an array, we need to have the lifetime be emitted after the full expression ends. `CodeGenFunction::pushFullExprCleanup` and `CodeGenFunction::pushCleanupAfterFullExpr` look useful, though I'm not sure that's precisely what they do (or what the difference is between them yet).  Otherwise I guess these temporaries can just be cleaned up after the function call they are passed to.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V0tv4zgS_jXMpWDBpvw8-GA77UUfGttIGpi9DSixJLFDkRo-4vb8-kWR8isTDLALDBA4EsWqYn311YPCe9UaxC1b7BnnRtVvEr2I2ih0nnHOFs9PIobOuu2Hj0-VledtY90bSmic7YHxcl4uNmtgfC2MhC6EwbNyx_iR8aPDd4UnX2j93hfWtYwfn1fz6WbO-AZOnao7UB4OjO8Z34MfsFaNqlm5h9ChQxAOQaqmQYcmgIsaPTTWwQGOv309_CjY9JlNd-Pvcpr_6vzug4t1gMZaYKt9XgMA0Na0-ecXK8d1tnq-PX-Ubqz9vRF1sO5MXr5bJRnfXPff7ZTqnXbcVhg_wP3b5oOV21kq4e6UP57YYYjOkHbG1_n37kyMr0kxP8Ani2n9fxbZFI_QPOKbX39D8J2NWgL2KoBWDQbVIygTnDJe1TlSobMeIWA_WCfcGUTbOmxFQD-6dSFSE00dlDX-Hp8fHQJb7DXtD3DgJUgnmsAWz4yvH6l2Op0KO6CZ-CBHqv0M9Yzxo685pw3tbJ73MX6UtvaMH0053SyLQTYJ8wNnuxUsC17M4TVYJ1oEGZ1IxwLbgK1-Yh0eTsjKL7CGHRhrJvpd6IiAvwaH3itr4KRCNxIgOgTrIBpaD-cBCf5TYnno8LNNtTVBKONBZFM99hW6rFM4J85JDbFGmVpHqUxLOh3W0Xn1jvpMr1kqHV9ofVGK8mbRAyVusukp_MmYw4akggVhRr9HyzHYXgRVg_8AUVJzi_SFEQWURCn4GvyNJRW25NmpQ5Pcv8NMeUACUgSUSaUKHpRRQQkNGWHlk1B-sc0HDcWjKTRyjNjNWtZP1kbpERZlWmii1vfnIfkCduYMIpB3gUDprVTN-QM22cpfEQCHPurkBUQjsUn4V9iJd2Ud6X5A-BMFaS8FyoNqQIXRHyKPxFoLh3KU7TCzwjYJtwxRTkSEIbrBekxkwKbBOqj3vL-A11h3d_4YRAnGjpbIOgjiyB8RQUhJ4DxU39cBxRvB11uH-SxsPt0JZ81eaN0LA8TGtACNjX9pFf9f_s74elF0oU9lx8pYo8zxjC61jJN1lBf02UI9mxUfrao3VXhURd3HAmVk_Fhb0-iIpkayo_ygxZmWGT9--c_3cjE5FIzvny3je8KH7zMXGN9fygPfJzbw_TWSjO-vsQxCv_kMk6hsDBA65Qv4eDCsCuHqTr3jiMYJK8aPfMrL2XQ2na35dLFk_Pgodr7IGAzJl34gBFOq_54LLsGlPz8FEZSqs5M586nI-BRMlRPnWrKzxgcG7LRP_S4r8vBHVAFhEMo0UScKlryC3cs3kBFJPVvs6W23-354LflnNb1VoYtVUdue8ePu5dvE2yachKPIiEpNhGD8WGlLwPRCGVoWQ-1LfnsqnA-MlzkFJ9mBh2o_B4CX9BVe8tcP5X0HB9sP1pM7Pyi3tHAtUkYJA3OozgE9OW4dnFK38-pPhFoYYwNUlKEBXT_WXKqcQuszVGeobOiA3tClQpceU19QPlVXlBSRHnsaPUSg9BxzDwbhPdVHKt6Av4ITIFwb-0T6S5279FQ4CZ-1S2oXbLH_Lpzo6VzwncZB09J6JTzC98MrNYF_NhrDxfxkyOYnZHsy1H6cS9hi_xI1wq6Y_9PEiBonYjIfBx-gkWNEPFgKXyScLxU00wh6caZPKfMVhYFic4bBKhOoHxKgDwEg8B-nVb7-yvhKUybmvZQLlajf0JA5ys6L0cMh55WNbXdJL8P4KoC4SlxmZ6hie23iY2m28JXEzBs1j2uHuI0XJmd6GkgwV_5gIdV82n3XhdKsl_pyE9CNLn7WLtlyerAS_4XmOEJAsSt3Q_TdMWr95dfgDhqFiQNbThP7_05k3LojqxdxktPWvlGAmqjvICJge2pe4GMar0RgfOVhcFgrj_oMp05QxcMzSEvMT6mbl673jTrNGRWGE-Z06uFMRXVTAPybricn5RG-QhspH0OHd3OuQso3Az-jTyWgpvOjhDg8IHdHjnwauu-MmR1s8SS3pdyUG_GE29lys9ys5uvp7KnbTis-LXFT1otytuQLLqqGl0KKhayrerWST2p76RN8tij5rJiXq6ZupJxvcCGnOGPzKfZC6evN7El5H3G7XK_mqyctKtR-vB-ODGPlbvfyjW6H_MA4r29PWpiWlbvaSmzRXNd7RX5M7BBUr_5M09Z4t3RbsjqpYuvZfKqVD7cb4lNQQePW2BvteuHeaBa9cI_S4tqIbveJp-j09m_KBFkY_00GZ6lVM35MbtMokTz_bwAAAP__I8AIcA">