https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110850
Bug ID: 110850
Summary: Evaluation order of assignment operands
Product: gcc
Version: 13.2.0
URL: https://godbolt.org/z/89TPG4eaK
Status: UNCONFIRMED
Keywords: diagnostic, wrong-code
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: bugreport0 at proton dot me
Target Milestone: ---
In C++17 in assignment expressions the right-hand side evaluation and its side
effects are sequenced before the left-hand side evaluation and its side
effects, so this snippet
struct Trivial {
int x;
};
int postincrement(int& i) {
std::cout << "postincrement\n";
return i++;
}
int load(int& i) {
std::cout << "load\n";
return i;
}
int main() {
Trivial a[1]{};
int i = 0;
(std::cout << "LHS\n", a[postincrement(i)])
= (std::cout << "RHS\n", Trivial{load(i)});
std::cout << a->x << '\n';
}
should output "RHS load LHS postincrement 0". Instead, it outputs "RHS LHS
postincrement load 1". Around gcc 7.1 evaluation order seems to have been fixed
in many cases, but not for "aggregate assignment" such as with this Trivial
type.
The URL associated with this report demonstrates several variations of this
example, showing in addition discrepancy between compile- and run-time
behaviour and between optimization levels, and inconsistency in warning
messages in cases other than "aggregate assignment".
Bug report #97288 is related, but it assumes implicit lvalue-to-rvalue
conversion to be part of the right operand evaluation, and in later versions
described behaviour disappears, reappears and finally disappears.