<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/148536>148536</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[Clang][RISCV] Unexpectedly lost writes to C99 flexible array member when guaranteed return copy elision should apply
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
resistor
</td>
</tr>
</table>
<pre>
Consider a function on RV32 that returns this struct by value:
```
struct FooStruct {
int a;
int b;
int c[];
};
FooStruct foo() {
FooStruct ret;
ret.a = 0;
ret.b = 0;
ret.c[0] = 0x124512;
ret.c[1] = 0x535;
return ret;
}
```
Because of guaranteed return copy elision in C++17, the caller of `foo` should be allocating space for the return value, and providing a hidden "out" parameter for `foo` to write through.
This is complicated in this case because this struct hits the case in the RV ABI where two XLEN-size members are passed in registers rather than on the stack.
What I would expect to happen is that `a` and `b` are returned in registers, and an out-pointer is taken as an argument and used to write to `c`.
What actually seems to happen is that the writes to `c` are entirely elided: https://godbolt.org/z/P7b1TzjTq
```
foo():
li a0, 0
li a1, 0
ret
```
If the types of the `a` and `b` fields are changed to `long long` (thereby avoiding the two-XLEN-sized-fields ABI case), then the writes to `c` are suddenly preserved!
```
foo():
sw zero, 0(a0)
sw zero, 4(a0)
sw zero, 8(a0)
sw zero, 12(a0)
lui a1, 292
li a2, 1333
addi a1, a1, 1298
sw a1, 16(a0)
sw a2, 20(a0)
ret
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMVd-P4jYQ_mvMywiUOCTAAw_AFmmlqqruttu-TuIh8Z2xU9uBZf_6apLswu2i3kVRftgz38x8_sbGEHRtidYi34r8YYJdbJxfewo6ROcnpVOX9c7ZoBV5QDh0toraWXAWvjxnEmKDETzFztsAsdEBQvRdFaG8wAlNRyLbiKS_i2S8k81os3fu6_AlFluRbAAAtI2AIrv9LX_8rYZch0GxePtINle4g3NCLoVcvQFfpzzFdwdG9BRnCCJ7gOQahgfLe4McOxH5wzD3ksp5nsrPJunVJM_yj_E6b2_SWDx8IEckmy1V2AUCd4C6Q482Eqk318q1FyCjA6-DtrATcivkNl0IuYPYEFRoDHl2FkXCVBQJhMZ1RkFJgMa4CqO2NYQWK4KD873bCD-smtwBWgWtdyet2Bah0UqRBSGl66KQElr0eKRIvoe4xooOzl5Hgth419XNbCjqidWhA1Tu2BpdYSTF6feiqTAQlGPVtzJqdAxjUYEGc4Ivz7DZPsK5IU8Qzw7--f23P6ZBvxIc6ViSD4CeoMUQhhieah0ij3uMDXG92GuY0ULE6vuY498s50c492TRS0tV5HIabFuynHyvd1EkyIUyQ6JIyv7bvzH4IeQblRywi9PWacuUMRZ-JwsYeAp93R2JtW8VdJz2lUXHQSpRJLdJYhU7NOYCgegY7iTJpfUA4QahT5Ns1J5MLyJFSmQbaGJsA7eq3Au5r50qnYkz52sh969C7v9clOnT67enfz_38nuvDZ0O42X08MaECWDD61D6PjRe3A2fmuDx0NcQLy0FFjP_3GP-oMmoYcWrBm09cCeKxDhbAz_YSsglrzyVF8CTGzTdw5_d9F0-ajqCsbxYcVzW0FX2fwgNHXeGuUDrKZA_kRIy_TlT4TxU_0reDYzIJdO1umHmo838F2yWv2CTyjtGptM3CyRX8sf1RNl7Zll2M45K6avP8Ezlankn9jhZ3EZ-n-ux5T0KPMWJWmdqla1wQut0kcu5nOf5ctKsV1Rl87JU1aIiucJSlQXOMV3kiaS8KFYTvZaJzJNFmqVFlufL2VLN1aHAPFHFslykUswTOqI2M2NOR1b8RIfQ0TqdL_OsmBgsyYT-eJSyMmhrISWflH7NDtOyq4OYJ0aHGK4QUUfTn6m73iN_EPn2y-PX3TOfC3_ZYWMhZS5gXIg3qtqtVnAw9KJLQ4De42Xc0Xizsz87DMZNHtvWXCadN-sPba1j05Wzyh2F3HOu42vaeveNqijkvq89CLkfyz-t5X8BAAD__3m2bzA">