possibly undefined behavior

K

Kaz Kylheku

Oh? Then what exactly did you mean by "In this case, the abstract
semantics says that, literally, the value is stored into p->next, and
then the assignment expression's value is derived by accessing the
value of p->next."?

I'm aware of that problem.

But suppose that an assignment can go to some temporary location which is then
later synchronized with the real one (without requiring any further evaluation
of any part of the original expression).

E.g. the machine determines where the assignment is suposed to go, and what the
value is, but instead of updating the location immediately, it issues
a store event. In this event, the value and location are identified
concretely; nothing needs to be evaluated any longer. The store events are
performed in some arbitrary order before the next sequence point.
In effect, part of the assignment has already taken place: the event
has been issued, and the assigned value temporarily lives inside that
event, which awaits completion.

So ``after the assignment'' doesn't have to mean ``after the actual target
location is updated'', because we allow the abstract machine to have
freedom in doing the updates anywhere within the evaluation phase.

Updates can always be delayed and reordered by performing the updates to
temporary locations. So arbitrary order of side effects in the abstract
semantics is logically compatible with various evaluation ordering constraints
within the evaluation phase like requiring that the value of
an assignment expression be that of the target after the assignment.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Kaz Kylheku said:
I think of

p = p -> next = q;
[snip-snip-snip]
If such an ordering were not required, then the standard wouldn't
use the phrase ``after the assignment'', but only something like
``the value of the assignment expression is the same as that which
is stored in the left operand, of the same type''.

That's not a bad argument, but it implies that the side effect of
storing the value in the target must occur before the result of the
assignment is used.

Actually, no it doesn't.

Oh? Then what exactly did you mean by "In this case, the abstract
semantics says that, literally, the value is stored into p->next, and
then the assignment expression's value is derived by accessing the
value of p->next."?

It seems clear (to me anyway) that the two updates can occur in
either order (or arbitrarily interleaved, for that matter).
However, the value being assigned to p is the value of the right
hand side (namely, p->next = q), which in turn is "the value of
the left operand [p->next] after the assignment." Regardless of
when the two updates occur, saying "after the assignment" means
the assignment operation has been evaluated, so p->next must have
been evaluated (the result being one operand of the assignment
here).

Ok. It seemed to me that you were arguing that "after the
assignment" meant after the update occurs (the update is part of the
assignment, after all). One could make that argument without being
entirely unreasonable, and I thought that was what you were doing
-- but that was inconsistent with other things you were saying.
Thus my confusion, which I'll assume was purely my own.

My contention is that C99 / N1256 is poorly worded in this area
(I think we agree on that), and that at least one sensible reading
implies the behavior of ``p = p -> next = q;'' is undefined.

In any case, it's sufficiently unclear that I'd avoid that kind of
construct in real code. I'm not a big fan of overly terse code
anyway (though that doesn't let the standard off the hook when
it comes to either defining what it does or clearly stating that
it's undefined).
Also, to repeat myself, N1362 clearly establishes the behavior
in such statements as well-defined.

I'll have to study that after I've caught up on sleep. If so,
it might be reasonable to assume that N1362 reflects the *intent*
of C99 / N1256. The question is whether compiler authors drew the
same conclusions. If not, I can imagine aggresive optimization
causing problems here.

[...]
This example isn't really on point since x_addr() and y_addr() can
both be evaluated before either assignment operator has started,
let alone when they may have finished or produced a value.

Ah, you're right.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
I think of

p = p -> next = q;

[snip-snip-snip]

If such an ordering were not required, then the standard wouldn't
use the phrase ``after the assignment'', but only something like
``the value of the assignment expression is the same as that which
is stored in the left operand, of the same type''.

That's not a bad argument, but it implies that the side effect of
storing the value in the target must occur before the result of the
assignment is used.

Actually, no it doesn't.

Oh? Then what exactly did you mean by "In this case, the abstract
semantics says that, literally, the value is stored into p->next, and
then the assignment expression's value is derived by accessing the
value of p->next."?

It seems clear (to me anyway) that the two updates can occur in
either order (or arbitrarily interleaved, for that matter).
However, the value being assigned to p is the value of the right
hand side (namely, p->next = q), which in turn is "the value of
the left operand [p->next] after the assignment." Regardless of
when the two updates occur, saying "after the assignment" means
the assignment operation has been evaluated, so p->next must have
been evaluated (the result being one operand of the assignment
here).

Ok. It seemed to me that you were arguing that "after the
assignment" meant after the update occurs (the update is part of the
assignment, after all). One could make that argument without being
entirely unreasonable, and I thought that was what you were doing
-- but that was inconsistent with other things you were saying.
Thus my confusion, which I'll assume was purely my own.

To set the record straight, it wasn't me who made the earlier
argument. I was simply responding to your comments in response
to that earlier argument.

My contention is that C99 / N1256 is poorly worded in this area
(I think we agree on that), and that at least one sensible reading
implies the behavior of ``p = p -> next = q;'' is undefined.

Oh yes, definitely.
In any case, it's sufficiently unclear that I'd avoid that kind of
construct in real code. I'm not a big fan of overly terse code
anyway (though that doesn't let the standard off the hook when
it comes to either defining what it does or clearly stating that
it's undefined).

I understand the sentiment, but this example doesn't seem to
me to be overly terse. And it might be written this way:

p = (p->next = q);

in which case it would be VERY surprising, I think, to most
developers if that code didn't work. Yet it's the same as
far as the Standard is concerned.

One would hope that implementors would consider the wording for
these kinds of cases sufficiently unclear so that they would
avoid unduly optimizing them.

I'll have to study that after I've caught up on sleep. If so,
it might be reasonable to assume that N1362 reflects the *intent*
of C99 / N1256. The question is whether compiler authors drew the
same conclusions. If not, I can imagine aggresive optimization
causing problems here.

Unfortunately, I can imagine it also. It seems idiotic that
implementors wouldn't think through the consequences of such
decisions in the context of what most developers would expect in
such cases rather than just what the Standard says (and what it
_might_ mean), but sadly I think that some implementors don't.
 
K

Keith Thompson

Tim Rentsch said:
To set the record straight, it wasn't me who made the earlier
argument. I was simply responding to your comments in response
to that earlier argument.
[...]

Sorry, I'll try to keep better track of who said what.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
To set the record straight, it wasn't me who made the earlier
argument. I was simply responding to your comments in response
to that earlier argument.
[...]

Sorry, I'll try to keep better track of who said what.

No worries. I wasn't offended, I just didn't want to take credit
for someone else's comments.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top