================
@@ -5232,6 +5232,26 @@ void CodeGenFunction::EmitWritebacks(const CallArgList 
&args) {
     emitWriteback(*this, I);
 }
 
+/// Whether emitting this glvalue neither has side effects nor reads mutable
+/// state, so deferring its byte read to the call boundary is equivalent to
+/// initializing the argument last, a sequencing C++17 [expr.call]/8 allows.
----------------
xroche wrote:

Hummm, you're right, and it is wider than your example. At runtime `<<`, `>>`, 
`&&`, `||`, `,` and `->*` all give wrong values, and assignment operators fail 
the other way round, since there the right operand is read first. Skipping the 
copy is not the cause: a local or member source still gets a real copy, just 
too late.

I never looked one frame up. `EmitCallArgs` already gets an `EvaluationOrder` 
computed from your list. The fix passes it into `EmitCallArg` and declines to 
forward when the order is fixed. That switch has no `operator[]`/`operator()` 
case though, so a C++23 explicit-object `operator[]` looks unordered while 
[expr.sub]/1 orders it. I flag any overloaded operator rather than add the two 
cases, which would also change MS ABI evaluation order.

Testing also found a crash: a class with both a copy constructor and a copy 
assignment operator hits the `EmitAggregateCopy` assert. The test type here 
declares only a copy constructor, which hid it. Relocation is now limited to 
byte-copyable types, `trivial_abi` included.

Would you prefer I fix the switch and depend on that? Should the crash fix be a 
separate commit?


https://github.com/llvm/llvm-project/pull/199351
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to