Alf said:
* Buster:
It's unfortunate, but I'm confident the [Holy Standard's] text is
correct and the [Holy Standard's] comments incorrect.
Well, I'm confident that the comments are correct, as they are very
concrete examples. But that does not necessarily mean that the text is
incorrect. I've posted a question about this to clc++m.
You know what? I didn't read the first sentence of 5.4, but concentrated
on the other two sentences. Those commented code examples make much more
sense to me now, but it still seems to me that 5.4 says the first and
third invoke undefined behaviour.
Do let us know what clc++.moderated thinks.
For the benefit of those on this newsgroup who haven't got the standard
to hand,
5/4:
Except where noted, the order of evaluation of operands of individual
operators and subexpressions of individual expressions, and the order in
which side effects take place, is unspecified [footnote]. Between the
previous and next sequence point a scalar 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. The requirements of this paragraph shall be met for
each allowable ordering of the subexpressions of a full expression;
otherwise the behaviour is undefined.
[Example:
i = v [i++]; // the behaviour is unspecified
i = 7, i ++, i ++; // i becomes 9
i = ++i + 1; // the behaviour is unspecified
i = i + 1; // the value of i is incremented
--end example]
[footnote] The precedence of operators is not directly specified, but it
can be derived from the syntax.
Those sequence points are internal to the calls.
In what sense?
They do not affect the
evaluation order of the expression the calls appear in.
Of course not.
The term
"sequence point" is not some abstract unconnected term: it is a point
between re-orderable parts of an expression, a point that is guaranteed
to come in execution sequence after the previous such such point (and
the standard's various definitions of where sequence points are are the
details necessary to achieve that meaning), so the function call example
does not have any sequence point in the full-expression.
I don't think it follows. To give you something to push against, I will
say that I am thinking of the chronological ordering of inspections,
modifications and sequence points, not some lexical ordering. Therefore,
no matter in what order the subexpressions of "x = f (x) + g (x)" are
evaluated, the eventual evaluation of "f (x)" involves two sequence
points (sorry, three: i didn't mention the one at the end of "x += 7;"
which is itself a full expression), as does the evaluation of "g (x)",
and so those six sequence points occur, (at unspecified points) in time,
during the evaluation of the full expression.
Look it another way: the compiler is permitted to reorder f(x)+g(x) as
g(x)+f(x), and if not then the example could not be "unspecified" as you
maintain it is.
Sorry, you've lost me. Are you saying I've confused the issues of
sequence points and unspecified order of evaluation? Because I don't
think I have. f (x) must be evaluated 'all at once', and so must g (x).
Thus there is _no_ sequence imposed on the expression the calls appear
in, and hence _no_ sequence point in that expression: "previous" and
"next" sequence points in §5/4 do not refer to what happens down in
called functions, but in the expression under discussion.
Hence §5/4 applies, you have modified more than once between sequence
points in the expression, and if the standard's e.g. "x = ++x + 1"
example is UB according to that, then so is your example.
Well, I can sort of see that you might be right there. But you sneaked
in those three little words "in the expression", which are not in the
text of the standard. As far as I can see, the sequence points involved
in evaluating f and g are as much "in the expression" as the sequence
point after the evaluation of the full expression.
But I'm quite sure that neither is "undefined", defined in §1.3.12, just
"unspecified", defined in §1.3.13, and that that's why the standard says
"unspecified" in the concrete examples.
But the standard says (right out loud) that it _is_ undefined behaviour.
That's what the latter two sentence of 5/4 say. If "i = ++i + 1;"
doesn't invoke undefined behaviour in virtue of those sentences, then
what does?
Hold on, I might have just come up with a killer point. Look again at
the first commented code example after 5.4:
i = v [i++]; // the behaviour is unspecified
(i) There is no order-of-evaluation problem here (do you agree?).
(ii) If v is an std::vector (for instance), then [] is a real function
call. If I'm right about the relevance of sequence points in
functions to the evaluation of the calling expression, then it follows
that there is no problem whatsoever, and the behaviour is defined and
the result is specified. So (if I'm right) we have to assume [] is the
builtin subscript operator: that v and i are a pointer (or an array) and
an integer (but not necessarily in that order). (Getting a headache?)
(iii) Making that assumption, the only remaining problem is the lack of
a sequence point between the two modifications of i. (Huh? HUH?)
(iv) Therefore either the behaviour is undefined (I maintain it is),
or the result is specified. In either case the comment is wrong. What
do you think?
Note that the comment does not say "the result is unspecified", which
would be very clear.
BTW, I hope you're enjoying our little discussion.