Correct, except for the UB part.
Chapter and verse, please.
"Can't be" is perhaps too strong. The implementation is required to
produce code that acts as if it isn't, though.
(All quotes from N869)
6.5.16#1 gives the syntax for assignment operators:
assignment-expr:
conditional-expr
unary-expr assignment-operator assignment-expr
assignment-operator: one of
= *= /= %= += -= <<= >>= &= ^= |=
So `st.A+=A' is the right operand of '=' in the expression `A=st.A+=A'.
6.5.16#3 (semantics of assignment operators):
[#3] An assignment operator stores a value in the object
designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but
is not an lvalue. The type of an assignment expression is
the type of the left operand unless the left operand has
qualified type, in which case it is the unqualified version
of the type of the left operand. The side effect of
updating the stored value of the left operand shall occur
between the previous and the next sequence point.
So we're storing a value in A. What's that value?
6.5.16.1#2 (semantics for simple assignment):
[#2] In simple assignment (=), the value of the right
operand is converted to the type of the assignment
expression and replaces the value stored in the object
designated by the left operand.
So it's the value of the right operand, `st.A+=A', converted appropriately
(in this case, no conversion, since both st.A and A are ints).
What's that value?
6.5.16.2#3 (semantics for compound assignment):
[#3] A compound assignment of the form E1 op= E2 differs
from the simple assignment expression E1 = E1 op (E2) only
in that the lvalue E1 is evaluated only once.
So (with a stop back at 6.5.16#3 where the value of the expression is
defined to be the value stored in the left operand) 6.5.16.2#3 applies:
It's the new value of st.A, which is the value of `st.A + (A)' evaluated
before the values of the objects are updated[%], converted appropriately.
So the value stored in A is required to be the sum of the old value of
st.A and the old value of A, converted appropriately (to the type of
st.A and then to the type of A).
[%] I'm assuming without proof that `a=a+b' requires that the old value
of a be used as an operand to the addition. If you really want me
to, I can dig up chapter and verse for this too, but hopefully at
least this much is clear.
None of this violates 6.5#2:
[#2] Between the previous and next sequence point an object
shall have its stored value modified at most once by the
evaluation of an expression. Furthermore, the prior value
shall be accessed only to determine the value to be
stored.60) *
The prior values of both A and st.A are accessed only to determine the
value to be stored in st.A, and the value to be stored in A is determined
directly from this (and indirectly from the old values) without further
access to the objects.
So since everything can be reduced to storing well-defined values into
objects, and the non-store accesses are used only to determine those
values to be stored, the entire expression is well-defined and has
well-defined side effects.
This is /obviously/ wrong, since by the second "result" you either mean
the result of st.A+A, which is /not/ necessarily the value stored in A (it
gets the result of st.A+=A, which may have a different type and even a
different value, depending on the types of A and st.A);
In the code under discussion, both were ints, so no conversions were
necessary. But since we like pedantic nitpickery here:
The order of operations is:
sequence point
compute st.A+A (call it "result", for notational convenience)
unordered
{
store "result", converted appropriately, into st.A
store "result", converted appropriately, into A
(Note that this involves two (possibly no-op) conversions, to type
of st.A and then to type of A)
}
sequence point
or else you mean
the result of updating st.A with st.A+A, in which case you're mistaken
about the "unordered" part.
I'm trying and failing to see how that interpretation could be considered
sensible enough to not be immediately discarded in favor of the more
sensible alternative, even by the most pedantic nitpicker.
dave