Topic: (&++x[0])[0]


Author: John Potter <jpotter@lhup.edu>
Date: Fri, 3 Sep 2004 00:45:50 GMT
Raw View
On Wed,  1 Sep 2004 16:32:56 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> John Potter <jpotter@lhup.edu> wrote:

> > Let's not talk about indeterminacy.  On a uniprocessor with no
> > reordering of anything the following is a valid translation of
> > v = a[a[0]=0].
> >
> >   v = a[0];
> >   a[0] = 0;

> I don't think so.  Generally the operand must be evaluated first as
> in

>     a[0] = 0;  // critical sequence point
>     v = a[a[0]];

Are we both talking about C?

I'm not sure where we may disagree.  The only sequence point in the
complete expression is at the end.  The implementation is allowed to
do the two stores at any time.  Are you reading a sequence point into
the translation?  My argument is that the rvalue of a[0] = 0 is known
at compile time and may be used as the result of the subexpression.

> > In C++, the inner expression is an lvalue and the point of the
> > current issue is to require the store prior to the access.
> > With the current wording, it may be argued that the store must take
> > place prior to the access and the new value must be the result of
> > the expression.

> IIUC, the assignment operator must "execute" prior to the read but its
> side effects don't have to be "committed" until the soonest sequence
> point.

Take another look at 5.17/1.  "The result of the assignment operation
is the value stored in the left operand after the assignment has taken
place; the result is an lvalue."  Are you reading "which will be"
between "value" and "stored"?  The result is an lvalue which must be
converted to an rvalue if needed.  The issue is all about making what
it says be possible by explicitely adding the implied sequencing.  By
making it a sequence point, the issue also allows multiple modification
which was not implied by the above wording.

> In the interim, the object a[0] is *undergoing modifcation*
> and any access to it should invoke undefined behavior:

I don't think so.  See above.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Wed, 8 Sep 2004 11:30:47 GMT
Raw View
John Potter <jpotter@lhup.edu> wrote:
> On Wed,  1 Sep 2004 16:32:56 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>
>> John Potter <jpotter@lhup.edu> wrote:
>
>> > Let's not talk about indeterminacy.  On a uniprocessor with no
>> > reordering of anything the following is a valid translation of
>> > v = a[a[0]=0].
>> >
>> >   v = a[0];
>> >   a[0] = 0;
>
>> I don't think so.  Generally the operand must be evaluated first as
>> in
>
>>     a[0] = 0;  // critical sequence point
>>     v = a[a[0]];
>
> Are we both talking about C?
>
> I'm not sure where we may disagree.  The only sequence point in the
> complete expression is at the end.  The implementation is allowed to
> do the two stores at any time.  Are you reading a sequence point into
> the translation?  My argument is that the rvalue of a[0] = 0 is known
> at compile time and may be used as the result of the subexpression.

Okay then consider "a[a[0]=zero()];", where zero() is separately compile.

>> > In C++, the inner expression is an lvalue and the point of the
>> > current issue is to require the store prior to the access.
>> > With the current wording, it may be argued that the store must take
>> > place prior to the access and the new value must be the result of
>> > the expression.
>
>> IIUC, the assignment operator must "execute" prior to the read but its
>> side effects don't have to be "committed" until the soonest sequence
>> point.
>
> Take another look at 5.17/1.  "The result of the assignment operation
> is the value stored in the left operand after the assignment has taken
> place; the result is an lvalue."  Are you reading "which will be"
> between "value" and "stored"?

Not necessarily, but I was assuming that the lvalue designates the
same object as does the lhs, i.e., "a[0]".  That seems to be a common
(mis)impression about the semantics of assignment.  If you had in mind
the case where that lvalue designated something different then that
might explain our different impressions.

> The result is an lvalue which must be converted to an rvalue if
> needed.

Agreed.

> The issue is all about making what it says be possible by
> explicitely adding the implied sequencing.  By making it a sequence
> point, the issue also allows multiple modification which was not
> implied by the above wording.

Hmmmmm.  IMHO what is says is probably not what the authors had in
mind.  The behavior is not explicitly undefined in the case where the
evauation of "a[0]=zero()" designates a[0] and yields zero rather than
a[0]'s prior value, which let's presume to be other than zero.  I
suspect that the authors intended the behavior to be undefined even in
that case.

>> In the interim, the object a[0] is *undergoing modifcation*
>> and any access to it should invoke undefined behavior:
>
> I don't think so.  See above.

Which part?

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@lhup.edu (John Potter)
Date: Tue, 31 Aug 2004 00:25:10 GMT
Raw View
On Mon, 30 Aug 2004 07:43:50 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> > On Sat, 28 Aug 2004 06:17:31 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> >> John Potter <jpotter@falcon.lhup.edu> wrote:

> >> > The expression, a[a[0]] = 42, has the sequencing requirement.  If

> > The
> > clear intent is that the old value may only be used if it must be
> > obtained before the modification may be started.

> I agree on the matter of intent.  Unfortunately, the words don't match
> the intent, they allow access to determine the new value but not to
> determine the address of the target object.

We could argue that the new value of a[0] is 42 if the old value is
0 and the old value if the old value is not 0.  The old value is used
to determine the new value if it changes.  Anyway, if someone thinks
that it is important to change the wording, they may raise an issue.

> Digressing a bit, you earlier argued (more or less) that if any
> nondeterministic outcome can yield undefined behavior, then by
> definition the behavior of all outcomes is undefined.  (The case at
> hand involved the value found by accessing an object the occurrence of
> an operation that modifies it and the next sequence point.)  I didn't
> completely buy that notion at first, but I'm now having second
> thoughts.  Did I properly characterize your position, and if so, do
> you have any wording from the Standard that supports it?

I'm not sure why you are using nondeterministic.

int i = 3, j = 5, k;
k = ++i + j;

A valid ordering of subexpressions.

t = j;
++i;
t += i;
k = t;

Now replace j with i.

k = ++i + i;

With the above valid ordering, the old value of i is accessed and
does not determine the new value.  With our understanding of the
intent, it is allowed to access the old value, the new value, or
some inbetween mess.  Since that is a valid ordering, the expression
has undefined behavior.  That only states that the standard makes no
requirements on any implementation evaluating that expression.  It
does not say that bad things will happen, it says anything is
conforming.

> The way I'm starting to look at it, the implementation is the only
> thing that sees the outcone of these nondeterministic events.  Under
> the as-if rule, the implementation could claim that the worst case
> always occurs.  How can anyone prove that it isn't conforming?

Much easier to accept that the standard says the expression has UB.
There is no need for any implementation to prove anything about the
bad code.  I think the point is that there are so many different
results for that expression that it makes no sense to try to define
it even as unspecified.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Tue, 31 Aug 2004 15:33:07 GMT
Raw View
John Potter <jpotter@lhup.edu> wrote:
> On Mon, 30 Aug 2004 07:43:50 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>
>> John Potter <jpotter@falcon.lhup.edu> wrote:
>
>> > On Sat, 28 Aug 2004 06:17:31 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>
>> >> John Potter <jpotter@falcon.lhup.edu> wrote:
>
>> >> > The expression, a[a[0]] = 42, has the sequencing requirement.  If
>
>> > The
>> > clear intent is that the old value may only be used if it must be
>> > obtained before the modification may be started.
>
>> I agree on the matter of intent.  Unfortunately, the words don't match
>> the intent, they allow access to determine the new value but not to
>> determine the address of the target object.
>
> We could argue that the new value of a[0] is 42 if the old value is
> 0 and the old value if the old value is not 0.  The old value is used
> to determine the new value if it changes.  Anyway, if someone thinks
> that it is important to change the wording, they may raise an issue.

This matter has been discussed more than once on comp.std.c.  Most
contributors seem to agree that this represents an oversight in the
status quo, and that the whole business of sequence points etc. needs
to be placed on a more conceptually sound footing.  There was an
attempt to generate such an appendix for C99, but that effort was
never completed.  I'm told that there have been some promising
subsequent attempts that are circulating in draft form among the C
committee.

>> Digressing a bit, you earlier argued (more or less) that if any
>> nondeterministic outcome can yield undefined behavior, then by
>> definition the behavior of all outcomes is undefined.  (The case at
>> hand involved the value found by accessing an object the occurrence of
>> an operation that modifies it and the next sequence point.)  I didn't
>> completely buy that notion at first, but I'm now having second
>> thoughts.  Did I properly characterize your position, and if so, do
>> you have any wording from the Standard that supports it?
>
> I'm not sure why you are using nondeterministic.
>
> int i = 3, j = 5, k;
> k = ++i + j;
>
> A valid ordering of subexpressions.
>
> t = j;
> ++i;
> t += i;
> k = t;
>
> Now replace j with i.
>
> k = ++i + i;
>
> With the above valid ordering, the old value of i is accessed and
> does not determine the new value.  With our understanding of the
> intent, it is allowed to access the old value, the new value, or
> some inbetween mess.  Since that is a valid ordering, the expression
> has undefined behavior.  That only states that the standard makes no
> requirements on any implementation evaluating that expression.  It
> does not say that bad things will happen, it says anything is
> conforming.

Agreed.  The Standard explicitly says that the above invokes undefined
behavior: there is an allowable ordering of the operations in which
the prior value gets accessed for a purpose other than computing the new
value.

IIRC, the context in which this discussion came was the evaluation of
a[a[0]=0].  In this case, regardless of the ordering of the operations
there is an indeterminacy when the result of a[0]=0 is accessed, but
there is no ordering of the operations wherein the prior value is
necessarily accessed.  So, relative to the words in the Standard, it's
a different situation than the one above.  But, IIUC, relative to the
reason those words were put in the standard, a[a[0]=0] is equally
problematic.

>> The way I'm starting to look at it, the implementation is the only
>> thing that sees the outcone of these nondeterministic events.  Under
>> the as-if rule, the implementation could claim that the worst case
>> always occurs.  How can anyone prove that it isn't conforming?
>
> Much easier to accept that the standard says the expression has UB.

Of course.  But what I'm looking for is reasoning that leads from the
words in the standard to that conclusion.

> There is no need for any implementation to prove anything about the
> bad code.

The question is whether it follows from words in the standard that
such code is "bad".

> I think the point is that there are so many different results for
> that expression that it makes no sense to try to define it even as
> unspecified.

I agree that such code should have undefined behavior.  But does it
follow from words in the current standard that the behavior of such
code is undefined?  If so, how?

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@lhup.edu (John Potter)
Date: Wed, 1 Sep 2004 06:39:53 GMT
Raw View
On Tue, 31 Aug 2004 15:33:07 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> This matter has been discussed more than once on comp.std.c.  Most
> contributors seem to agree that this represents an oversight in the
> status quo, and that the whole business of sequence points etc. needs
> to be placed on a more conceptually sound footing.  There was an
> attempt to generate such an appendix for C99, but that effort was
> never completed.  I'm told that there have been some promising
> subsequent attempts that are circulating in draft form among the C
> committee.

Sounds good.  I suspect that C and C++ resolutions might be different.

> IIRC, the context in which this discussion came was the evaluation of
> a[a[0]=0].  In this case, regardless of the ordering of the operations
> there is an indeterminacy when the result of a[0]=0 is accessed, but
> there is no ordering of the operations wherein the prior value is
> necessarily accessed.  So, relative to the words in the Standard, it's
> a different situation than the one above.  But, IIUC, relative to the
> reason those words were put in the standard, a[a[0]=0] is equally
> problematic.

Ouch!

Let's assume that initially a[0] != 0.  In C, the inner expression has
an rvalue of 0 and no requirement that a store to a[0] take place prior
to the outer access.  A valid translation could access the old value
prior to the store which is not used to determine the new value.  It is
UB.

Let's not talk about indeterminacy.  On a uniprocessor with no
reordering of anything the following is a valid translation of
v = a[a[0]=0].

   v = a[0];
   a[0] = 0;

In C++, the inner expression is an lvalue and the point of the
current issue is to require the store prior to the access.  With the
current wording, it may be argued that the store must take place prior
to the access and the new value must be the result of the expression.
As-if at least.  The issue should settle it.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Wed, 1 Sep 2004 16:32:56 GMT
Raw View
John Potter <jpotter@lhup.edu> wrote:
> On Tue, 31 Aug 2004 15:33:07 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
[...]
>> IIRC, the context in which this discussion came was the evaluation of
>> a[a[0]=0].  In this case, regardless of the ordering of the operations
>> there is an indeterminacy when the result of a[0]=0 is accessed, but
>> there is no ordering of the operations wherein the prior value is
>> necessarily accessed.  So, relative to the words in the Standard, it's
>> a different situation than the one above.  But, IIUC, relative to the
>> reason those words were put in the standard, a[a[0]=0] is equally
>> problematic.
>
> Ouch!
>
> Let's assume that initially a[0] != 0.  In C, the inner expression has
> an rvalue of 0 and no requirement that a store to a[0] take place prior
> to the outer access.  A valid translation could access the old value
> prior to the store which is not used to determine the new value.  It is
> UB.

Agreed.

> Let's not talk about indeterminacy.  On a uniprocessor with no
> reordering of anything the following is a valid translation of
> v = a[a[0]=0].
>
>   v = a[0];
>   a[0] = 0;

I don't think so.  Generally the operand must be evaluated first as
in

    a[0] = 0;  // critical sequence point
    v = a[a[0]];

> In C++, the inner expression is an lvalue and the point of the
> current issue is to require the store prior to the access.
> With the current wording, it may be argued that the store must take
> place prior to the access and the new value must be the result of
> the expression.

IIUC, the assignment operator must "execute" prior to the read but its
side effects don't have to be "committed" until the soonest sequence
point.  In the interim, the object a[0] is *undergoing modifcation*
and any access to it should invoke undefined behavior:

  - If the read yields the prior value, there's no question that the
    behavior is undefined.

  - If the read yields some other value, ...??

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 30 Aug 2004 05:36:12 GMT
Raw View
On Sat, 28 Aug 2004 06:17:31 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> > The expression, a[a[0]] = 42, has the sequencing requirement.  If
> > reads and writes were required to be atomic operations, the behavior
> > could be unspecified with only a few possibilities.  Since the
> > standards do not require reads and writes to be atomic, the behavior
> > is undefined.

> It appears to me that the inner subscripting operation needs to be
> completed before the outer subscripting can begin.  The outer
> subscripting must be completed before the value can be modified.  Thus
> the inner subscripting operation is certain to see the old value still
> intact.

We seem to agree that it is well defined.  Using the standard's wording
about using the old value only to determine the new value to claim that
it is undefined lacks any support from experts in standard intent.  The
clear intent is that the old value may only be used if it must be
obtained before the modification may be started.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Mon, 30 Aug 2004 07:43:50 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
> On Sat, 28 Aug 2004 06:17:31 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>
>> John Potter <jpotter@falcon.lhup.edu> wrote:
>
>> > The expression, a[a[0]] = 42, has the sequencing requirement.  If
>> > reads and writes were required to be atomic operations, the behavior
>> > could be unspecified with only a few possibilities.  Since the
>> > standards do not require reads and writes to be atomic, the behavior
>> > is undefined.
>
>> It appears to me that the inner subscripting operation needs to be
>> completed before the outer subscripting can begin.  The outer
>> subscripting must be completed before the value can be modified.  Thus
>> the inner subscripting operation is certain to see the old value still
>> intact.
>
> We seem to agree that it is well defined.  Using the standard's wording
> about using the old value only to determine the new value to claim that
> it is undefined lacks any support from experts in standard intent.  The
> clear intent is that the old value may only be used if it must be
> obtained before the modification may be started.

I agree on the matter of intent.  Unfortunately, the words don't match
the intent, they allow access to determine the new value but not to
determine the address of the target object.

Digressing a bit, you earlier argued (more or less) that if any
nondeterministic outcome can yield undefined behavior, then by
definition the behavior of all outcomes is undefined.  (The case at
hand involved the value found by accessing an object the occurrence of
an operation that modifies it and the next sequence point.)  I didn't
completely buy that notion at first, but I'm now having second
thoughts.  Did I properly characterize your position, and if so, do
you have any wording from the Standard that supports it?

The way I'm starting to look at it, the implementation is the only
thing that sees the outcone of these nondeterministic events.  Under
the as-if rule, the implementation could claim that the worst case
always occurs.  How can anyone prove that it isn't conforming?

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Fri, 27 Aug 2004 06:06:12 GMT
Raw View
James Kuyper <kuyper@wizard.net> wrote:
> jpotter@falcon.lhup.edu (John Potter) wrote in message news:<tsLVc.31268$nx2.31069@newsread2.news.atl.earthlink.net>...
>> On Fri, 20 Aug 2004 16:36:52 GMT, kuyper@wizard.net (James Kuyper)
>> wrote:
[...]
>>> The value is a number, where it's stored is a memory
>>> location. The memory location is a characterstic of the object that
>>> the value is stored in, it's not a characteristic of the value.
>>
>> Amusing interpretation based on pure senseless reading of words.  No
>> offense intended, that is what lawyers do.
>
> I don't consider it amusing or senseless, but then maybe that's just
> me. To me, it seems that you've had a major confusion about the
> difference between the value that is stored in a given location and
> the location where that value is stored. It's like confusing a car
> with a parking lot, or confusing a person with the house he lives in.
> The distinction seems so clear to me that I haven't been able to even
> guess at the way of thinking about it that allows you to confuse them.
>
[...]
>> The wording may be lacking, but the history of the subject makes the
>> intent clear.  Maybe you could give an example where the subject code
>> will not function or suggest new wording in a DR.  The above code must
>> be well defined and ++i + i must be undefined.
>
> I've never had a clear idea of the intent of that passage, so I'm not
> at all sure how it should be re-written. All I know is how it was
> actually written, and I find that rather confusing. However, I don't
> think it's sufficiently confusing to make your interpretation a
> plausible possibility.

The only explanation that makes sense to me is the one I got from Nick
Maclaren, which IIRC is that some aggressive architectures leave an
object in an inaccessible state for some time after a modification.
Any attempt to access that object while it is "undergoing
modification" results in indeterminate (probably unspecified)
behavior.

Most of this stuff makes sense from that perspective.  Some of it like
the example above does not, which indicates to me a misunderstanding
of the underlying motivation, either on the part of the standards
committee or on my part.  (It would please me to be corrected.)

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sat, 28 Aug 2004 02:55:06 GMT
Raw View
On Fri, 27 Aug 2004 06:06:12 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> The only explanation that makes sense to me is the one I got from Nick
> Maclaren, which IIRC is that some aggressive architectures leave an
> object in an inaccessible state for some time after a modification.
> Any attempt to access that object while it is "undergoing
> modification" results in indeterminate (probably unspecified)
> behavior.

That is a nice explanation of something, but I don't know what.

The subject here is access of the OLD value not the modified value.
There are no restrictions on access of the new value in the standard.
Likely because in C the new value is always accessed as an rvalue that
exists without the object.

   int a, b;
   a = b = 3;

C accesses the new value of b as the rvalue returned by the b = 3
expression.  C++ accesses the new value of b by an rvalue conversion
of the lvalue returned by the b = 3 expression.  Nick might have
explained why the C++ rules will require some adjustments, but he
did not explain access of the old value.

Other experts have explained in the C and C++ lang and std groups
that the undefined behavior results from the possibility of getting
some old bits and some new bits by attempting to access the old
value in a way which does not require sequencing.  The expression,
a[a[0]] = 42, has the sequencing requirement.  If reads and writes
were required to be atomic operations, the behavior could be
unspecified with only a few possibilities.  Since the standards do
not require reads and writes to be atomic, the behavior is undefined.

Statements from experts in these groups are the closest thing that
we have to a court system for the language lawyers to consult for
case history decisions on the wording of the law.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Sat, 28 Aug 2004 06:17:31 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
> On Fri, 27 Aug 2004 06:06:12 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>
>> The only explanation that makes sense to me is the one I got from Nick
>> Maclaren, which IIRC is that some aggressive architectures leave an
>> object in an inaccessible state for some time after a modification.
>> Any attempt to access that object while it is "undergoing
>> modification" results in indeterminate (probably unspecified)
>> behavior.
>
> That is a nice explanation of something, but I don't know what.
>
> The subject here is access of the OLD value not the modified value.
> There are no restrictions on access of the new value in the standard.
> Likely because in C the new value is always accessed as an rvalue that
> exists without the object.
>
>   int a, b;
>   a = b = 3;
>
> C accesses the new value of b as the rvalue returned by the b = 3
> expression.  C++ accesses the new value of b by an rvalue conversion
> of the lvalue returned by the b = 3 expression.  Nick might have
> explained why the C++ rules will require some adjustments, but he
> did not explain access of the old value.

IIRC, it was the other way around.  (It was a posting on comp.std.c.)

> Other experts have explained in the C and C++ lang and std groups
> that the undefined behavior results from the possibility of getting
> some old bits and some new bits by attempting to access the old
> value in a way which does not require sequencing.

That's exactly the sort of thing I understood Nick to be referring to.

> The expression, a[a[0]] = 42, has the sequencing requirement.  If
> reads and writes were required to be atomic operations, the behavior
> could be unspecified with only a few possibilities.  Since the
> standards do not require reads and writes to be atomic, the behavior
> is undefined.

It appears to me that the inner subscripting operation needs to be
completed before the outer subscripting can begin.  The outer
subscripting must be completed before the value can be modified.  Thus
the inner subscripting operation is certain to see the old value still
intact.

> Statements from experts in these groups are the closest thing that
> we have to a court system for the language lawyers to consult for
> case history decisions on the wording of the law.

That's exactly why I mentioned Nick's comments (as best I could
remember them).

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Tue, 24 Aug 2004 06:10:43 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
> On Fri, 20 Aug 2004 16:36:52 GMT, kuyper@wizard.net (James Kuyper)
> wrote:
[...]
>> >> a[a[0]] = 0;  // a[0] get read but not to determine the new value.
[...]
>> The value is a number, where it's stored is a memory
>> location. The memory location is a characterstic of the object that
>> the value is stored in, it's not a characteristic of the value.
>
> Amusing interpretation based on pure senseless reading of words.  No
> offense intended, that is what lawyers do.
>
> Consider the justifications given for those words

Presumably, you are referring to the wording of 5p4.

> and it is noted that the intent is to allow accesses of old values
> which must be performed before the new value may be stored,
                                                      ^^^^^^
Let's say "determined" rather than "stored".

> all accesses which must produce the new value and assign undefined
> behavior to any access which might produce the old or new value.

To be exact, 5p4 assign undefined behavior to any read access to the
old value for purposes other than to determine the new value.  IMHO,
determining where to store the new value would be another purpose.

> The wording may be lacking, but the history of the subject makes the
> intent clear.

Leaving intent aside -- I lack the ability to devine intent -- the
history makes it clear that the wording is dead wrong.

> Maybe you could give an example where the subject code will not
> function or suggest new wording in a DR.

Given that the C89, C99 and C++ standards got it wrong, it might be
fool hardy to attempt a correct statement of 5p4.  Nevertheless:

   Undefined behavior results from any attempt to access an object
   between a modifying operation on it and the soonest subsequent
   sequence point.

This wording can be made more precise by adding

   ... under any allowable ordering of operations ...

The notion of "soonest" can be made precise by referring to
topological orderings of the syntax tree.  And so on.

> The above code must be well defined and ++i + i must be undefined.

Thanks:

  - When a[0]==0, the evaluation of "a[a[0]]=0" is well defined since
    causality forces a[0] to be evaluated and its value determined
    before the lvalue "a[a[0]]" can be evaluated, which must happen
    before "a[a[0]]=0" can be evaluated.  So there is no way that the
    evaluation of the subexpression "a[0]" could occur between the
    modification of a[a[0]] and the soonest subsequent sequence point.

  - "++i+i" is not well defined because there is an order of evaluation,
    namely left-to-right, under which the expression "i" is evaluated
    between a modification of i and the soonest subsequent sequence
    point.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Tue, 24 Aug 2004 17:31:15 GMT
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote in message news:<tsLVc.31268$nx2.31069@newsread2.news.atl.earthlink.net>...
> On Fri, 20 Aug 2004 16:36:52 GMT, kuyper@wizard.net (James Kuyper)
> wrote:
>
>
>> jpotter@falcon.lhup.edu (John Potter) wrote in message news:<lkCUc.25403$nx2.3698@newsread2.news.atl.earthlink.net>...
>
>>> On Wed, 18 Aug 2004 05:25:36 GMT, thp@cs.ucr.edu wrote:
>
>>>> For another example, note that the C89 and C99 committees
>>
>> inadvertently
>>
>>>> assigned undefined behavior to
>
>>>>          a[0] = 0;
>>>>       a[a[0]] = 0;  // a[0] get read but not to determine the new
>> value.
>
>>> a[0] is read to determine where to put the new value which does
>>> determine the new value.
>
>> No it doesn't. The value is a number, where it's stored is a memory
>> location. The memory location is a characterstic of the object that
>> the value is stored in, it's not a characteristic of the value.
>
> Amusing interpretation based on pure senseless reading of words.  No
> offense intended, that is what lawyers do.


I don't consider it amusing or senseless, but then maybe that's just
me. To me, it seems that you've had a major confusion about the
difference between the value that is stored in a given location and
the location where that value is stored. It's like confusing a car
with a parking lot, or confusing a person with the house he lives in.
The distinction seems so clear to me that I haven't been able to even
guess at the way of thinking about it that allows you to confuse them.

..
> The wording may be lacking, but the history of the subject makes the
> intent clear.  Maybe you could give an example where the subject code
> will not function or suggest new wording in a DR.  The above code must
> be well defined and ++i + i must be undefined.

I've never had a clear idea of the intent of that passage, so I'm not
at all sure how it should be re-written. All I know is how it was
actually written, and I find that rather confusing. However, I don't
think it's sufficiently confusing to make your interpretation a
plausible possibility.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Sat, 21 Aug 2004 19:58:04 GMT
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
: In article <YmmVc.29598$nx2.15614@newsread2.news.atl.earthlink.net>,
: John Potter <jpotter@falcon.lhup.edu> writes
:>It seems that we are not able to follow a subthread.  It was suggested
:>that it might be useful to add a sequence point for parentheses.  I
:>questioned that and Francis then wandered off on signed overflow which
:>is the topic of another thread.
:
: Possibly I got confused and wandered, however I never proposed that
: parentheses introduce a sequence point but I do support the current
: proposed resolution of DR 222 IIUC. That makes such things as:
:
: (((i = a) += b) *=c);
:
: have fully determinate behaviour assuming that we manage to specify an
: ordering on sequence points. Which is something else I think we should
: address.

IIUC, getting rid of the problems discussed in 222 would require doing
the equivalent of adding a sequence point immediately after
assignment, prefix++, and prefix-- expressions of built-in types.
Adding them after suffix++ and suffix-- as well would put an immediate
sequence point after every modifing operation on built-in types, and
so far as I know, would make 5p4 superfluous.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 22 Aug 2004 04:48:50 GMT
Raw View
On Sat, 21 Aug 2004 17:04:13 GMT, francis@robinton.demon.co.uk (Francis
Glassborow) wrote:

> Possibly I got confused and wandered, however I never proposed that
> parentheses introduce a sequence point

I wondered why you made the nearly enflamatory reply to my objection
to that possible proposal from someone else.

> but I do support the current
> proposed resolution of DR 222 IIUC. That makes such things as:

> (((i = a) += b) *=c);

> have fully determinate behaviour assuming that we manage to specify an
> ordering on sequence points. Which is something else I think we should
> address.

Issue 222 would make j = ++ ++ i; well defined, but might not change
j = ++ i - ++ i from undefined to unspecified.  I don't think that
there is any requirement in the solution to that issue to require
any ordering on the read and store of the two increments.  It is
only required that the final read follow the write for each.  It is
still possible to do the two initial reads and stores in parallel.

To understand my point, consider a 2n bit type on an n bit machine.
The loads and stores to accomplish the increments may be interleaved.
The sequence point only occurs somewhere between the final store of
the subexpression and the load of the resulting value.  Neither the
value of i nor that of j is defined.

Are you suggesting that sequence points should propagate up the parse
tree?  I think you must push for deterministic evaluation without
depending upon 222 to provide anything.

In another article, you mentioned that unspecified is better than
undefined.  It seems that all arithmetic computations could be changed
from undefined to unspecified.  Producing any value is worthless in a
program, but seems better than crashing.  Since unspecified assumes a
set of possible values, any value is a set.  The problem is when an
expression could produce a non-value (trap value).  Not every possible
bit pattern produced must be a valid value on all implementations.  Do
you wish to prohibit a teaching implementation which uses trap values
to provide early termination with traceback?

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 22 Aug 2004 05:38:07 GMT
Raw View
On Sat, 21 Aug 2004 17:05:28 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> : It makes no difference how much you like the result, it is still UB.

> I would guess that the authors of the architectural specification get
> to make that call.

A final attempt.  Undefined behavior is a term defined in the language
standard to mean anything can happen.  If you write an expression which
the standard says has undefined behavior, it has undefined behavior.  It
has nothing to do with what actually happens on any given implementation
and hardware.

If you write int i(5); i = ++ i + 42; and the compiler generates code to
start nethack, the compiler is conforming.  Nothing outside of the C++
standard may define undefined behavior.  An implementation may tell you
what undefined behavior you will get on that implementation, but it may
not tell you what you will get on another implementation.  The whole
point of undefined behavior is that the standard makes no requirements
for what happens when the code is compiled and executed.  Any program
which uses undefined behavior is not portable.  Lots of programs use
undefined behavior with no intention of porting.  It does not change
the fact that the behavior is undefined by the C++ standard.

Please stop trying to define undefined behavior and accept that it is
undefined.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Sun, 22 Aug 2004 19:25:43 GMT
Raw View
thp@cs.ucr.edu (Tom Payne) wrote in message news:<cg668m$4br$2@glue.ucr.edu>...
> John Potter <jpotter@falcon.lhup.edu> wrote:
> : On Thu, 19 Aug 2004 19:01:20 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
> : :> : No.  The expression has undefined behavior because that is a valid
> :> : interpretation.  : :> I'm speaking of your assembly code running on an architecture such as
> :> Nick described.  Machines with protection features aren't supposed to
> :> have "undefined" behavior.
> : : One more time.  Expressions have undefined behavior because the standard
> : says they do.  Anything that the implementation software and hardware
> : does is a exibition of that undefined behavior.  Machines and compilers
> : do not have undefined behavior, expressions do.  Only a coder can
> : produce expressions which, if executed, always have undefined behavior.
>
> Machine architectures have specifications.  I'm told that some of them
> do not fully define what happens in every circumstance.  Hence certain
> machine language code segments can invoke behavior that is not
> defined/specified by the machine's architctural specifications.

Therefore, those machine code segments cannot be used by the compiler
when translating code that has standard-defined behavior. If there is
well-formed code with standard-defined behavior that cannot be
correctly implemented by any possible sequence of machine code on a
given platform, then a conforming implementation of C++ isn't possible
there.

That has no effect on whether or not the behavior is defined, because
definition of the behavior of code is determined by the C++ standard,
not by hardware specifications.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Mon, 23 Aug 2004 00:45:31 GMT
Raw View
In article <8VTVc.31736$nx2.14009@newsread2.news.atl.earthlink.net>,
John Potter <jpotter@falcon.lhup.edu> writes
>Issue 222 would make j = ++ ++ i; well defined, but might not change
>j = ++ i - ++ i from undefined to unspecified.  I don't think that
>there is any requirement in the solution to that issue to require
>any ordering on the read and store of the two increments.  It is
>only required that the final read follow the write for each.  It is
>still possible to do the two initial reads and stores in parallel.

OK, when I get a moment I will read the current commentary and proposed
resolution of 222 again. However I think this further strengthens my
belief that sequence points promise more than they deliver and are not
actually what they say they are.

>
>To understand my point, consider a 2n bit type on an n bit machine.
>The loads and stores to accomplish the increments may be interleaved.
>The sequence point only occurs somewhere between the final store of
>the subexpression and the load of the resulting value.  Neither the
>value of i nor that of j is defined.

The potential for interleaving of side-effects of evaluation of
sub-expressions is something with which I am familiar. However I think
we are getting into dangerous waters when we require some side effects
to be completed without an intervening sequence point. Sequence points
were intended to provide islands of stability where all prior
side-effects have been completed and no subsequent ones have been
started.

>
>Are you suggesting that sequence points should propagate up the parse
>tree?  I think you must push for deterministic evaluation without
>depending upon 222 to provide anything.

Possibly. However currently I would prefer two things:

1) That fundamental types have the same freedoms allowed to user defined
types.

2) That we should introduce syntax to declare a function pure which
would allow safe parallel evaluation of many sub-expressions, loop
unrolling etc.

>
>In another article, you mentioned that unspecified is better than
>undefined.  It seems that all arithmetic computations could be changed
>from undefined to unspecified.  Producing any value is worthless in a
>program, but seems better than crashing.  Since unspecified assumes a
>set of possible values, any value is a set.  The problem is when an
>expression could produce a non-value (trap value).  Not every possible
>bit pattern produced must be a valid value on all implementations.  Do
>you wish to prohibit a teaching implementation which uses trap values
>to provide early termination with traceback?

To the best of my limited knowledge there are very few implementations
that support trap values for integers. I am unconvinced that almost all
uses of signed integer types everywhere should incur undefined behaviour
purely on that basis. I think, but I might be wrong, that allowing an
exception to be thrown can be included in a set of unspecified actions.

Is there not something serious amiss with a language specification that
makes the following have undefined behaviour purely on the basis that
C++ only requires a minimum width for signed int and makes the actual
width implementation defined?

int i(32767), j(2);
int k = i*j + j;

Note that only strictly 16-bit ints can actually exhibit such behaviour.

It seems to me that this is a breach of 'You do not pay for what you do
not use.'


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Mon, 23 Aug 2004 00:46:09 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Sat, 21 Aug 2004 17:05:28 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
:
:> John Potter <jpotter@falcon.lhup.edu> wrote:
:
:> : It makes no difference how much you like the result, it is still UB.
:
:> I would guess that the authors of the architectural specification get
:> to make that call.
:
: A final attempt.  Undefined behavior is a term defined in the language
: standard to mean anything can happen.  If you write an expression which
: the standard says has undefined behavior, it has undefined behavior.  It
: has nothing to do with what actually happens on any given implementation
: and hardware.

Agreed.

I think there's a misunderstanding.  My last couple of postings
commented on the status of your assembly-code example relative to some
non-specific architectures that I was told motivated the authors of
C89 to introduce 6.3 (i.e., C++ 5p4).  As we both know, the C++
Standard does not apply to assembly code, rather the corresponding
architecture manual does.

[...]
: Please stop trying to define undefined behavior and accept that it is
: undefined.

I'm simply pointing out what I understand to be an abiguity in the
Standard with respect to the definedness of the behavior of the
expression "a[a[0]=0]".  The issue is that the current wording of the
Standard makes that behavior explicitly undefined if the final
lvalue-to-rvalue conversion reads "the prior value" and makes it
explicitly defined if that (non-deterministic) operation reads the new
value.

IIUC, you've argued that the behavior is undefined because it is
undefined in the "worst case".  But the Standard doesn't use the word
"case" here.  Rather it talks about "each allowable ordering of
subexpressions of the full expression", visibly referring to the
ordering of the evaluations of those subexpressions.  Unfortunately,
this is not about the ordering of subexpression evaluation but about
the outcome of a single, final, unary lvalue-to-rvalue operation ---
order of subexpressions is not an issue.  So, I don't agree that the
current wording of the Standard unambiguously makes that behavior
undefined.  (I agree, however, that the intent behind that wording
would be to make it undefined.  But at the moment we're being language
lawyers.)

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Mon, 23 Aug 2004 00:46:27 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
[...]
: Issue 222 would make j = ++ ++ i; well defined, but might not change
: j = ++ i - ++ i from undefined to unspecified.  I don't think that
: there is any requirement in the solution to that issue to require
: any ordering on the read and store of the two increments.  It is
: only required that the final read follow the write for each.  It is
: still possible to do the two initial reads and stores in parallel.
:
: To understand my point, consider a 2n bit type on an n bit machine.
: The loads and stores to accomplish the increments may be interleaved.
: The sequence point only occurs somewhere between the final store of
: the subexpression and the load of the resulting value.  Neither the
: value of i nor that of j is defined.

Hmmmmm.  I had thought, "j=(++i,++i)" is now well-defined and that
"j=(++i - ++i)" would be equally well defined if the recommendation of
issue 222 were adopted.

I would like to see (1) a sequence point immediately after each
modifying operation and (2) specified order of evaluation.  Your
argument shows that (1) without (2) would leave the current chaos
nearly intact.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Mon, 23 Aug 2004 00:49:23 GMT
Raw View
James Kuyper <kuyper@wizard.net> wrote:
> thp@cs.ucr.edu (Tom Payne) wrote in message news:<cg668m$4br$2@glue.ucr.edu>...
>> John Potter <jpotter@falcon.lhup.edu> wrote:
>> : On Thu, 19 Aug 2004 19:01:20 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
>> : :> : No.  The expression has undefined behavior because that is a valid
>> :> : interpretation.  : :> I'm speaking of your assembly code running on an architecture such as
>> :> Nick described.  Machines with protection features aren't supposed to
>> :> have "undefined" behavior.
>> : : One more time.  Expressions have undefined behavior because the standard
>> : says they do.  Anything that the implementation software and hardware
>> : does is a exibition of that undefined behavior.  Machines and compilers
>> : do not have undefined behavior, expressions do.  Only a coder can
>> : produce expressions which, if executed, always have undefined behavior.
>>
>> Machine architectures have specifications.  I'm told that some of them
>> do not fully define what happens in every circumstance.  Hence certain
>> machine language code segments can invoke behavior that is not
>> defined/specified by the machine's architctural specifications.
>
> Therefore, those machine code segments cannot be used by the compiler
> when translating code that has standard-defined behavior. If there is
> well-formed code with standard-defined behavior that cannot be
> correctly implemented by any possible sequence of machine code on a
> given platform, then a conforming implementation of C++ isn't possible
> there.

Exactly.  So, 5p4 attaches undefined behavior to C expressions whose
optimal could lead to such behavior in the underlying architecture.

> That has no effect on whether or not the behavior is defined,
> because definition of the behavior of code is determined by the C++
> standard, not by hardware specifications.

When mixing discussions of assembly-language code (e.g., John's
three-line segment mentioned a few postings back) with discussions of
C/C++ code, we have to be careful about which kind of code we are
talking about and which standard has jurisdiction over the definedness
of that code.  (But everyone knows that.)

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sat, 21 Aug 2004 17:04:13 GMT
Raw View
In article <YmmVc.29598$nx2.15614@newsread2.news.atl.earthlink.net>,
John Potter <jpotter@falcon.lhup.edu> writes
>It seems that we are not able to follow a subthread.  It was suggested
>that it might be useful to add a sequence point for parentheses.  I
>questioned that and Francis then wandered off on signed overflow which
>is the topic of another thread.

Possibly I got confused and wandered, however I never proposed that
parentheses introduce a sequence point but I do support the current
proposed resolution of DR 222 IIUC. That makes such things as:

(((i = a) += b) *=c);

have fully determinate behaviour assuming that we manage to specify an
ordering on sequence points. Which is something else I think we should
address.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Sat, 21 Aug 2004 17:05:28 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Thu, 19 Aug 2004 19:01:20 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
:
:> : No.  The expression has undefined behavior because that is a valid
:> : interpretation.
:
:> I'm speaking of your assembly code running on an architecture such as
:> Nick described.  Machines with protection features aren't supposed to
:> have "undefined" behavior.
:
: One more time.  Expressions have undefined behavior because the standard
: says they do.  Anything that the implementation software and hardware
: does is a exibition of that undefined behavior.  Machines and compilers
: do not have undefined behavior, expressions do.  Only a coder can
: produce expressions which, if executed, always have undefined behavior.

Machine architectures have specifications.  I'm told that some of them
do not fully define what happens in every circumstance.  Hence certain
machine language code segments can invoke behavior that is not
defined/specified by the machine's architctural specifications.

: It makes no difference how much you like the result, it is still UB.

I would guess that the authors of the architectural specification get
to make that call.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Thu, 19 Aug 2004 19:01:20 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Wed, 18 Aug 2004 16:52:16 GMT, thp@cs.ucr.edu wrote:

: > John Potter <jpotter@falcon.lhup.edu> wrote:
: > : On Wed, 18 Aug 2004 05:14:36 GMT, thp@cs.ucr.edu wrote:

: > :> John Potter <jpotter@falcon.lhup.edu> wrote:

: > :> : Very deterministic code for a single sequential processor is allowed.
: > :> :
: > :> :   mov r1,a+0
: > :> :   mov r1,[r1]
: > :> :   inc a+0

: > :> According to some postings a few years ago by Nick MacLaren on
: > :> comp.std.c, the model is that in some aggressive architectures one
: > :> must wait until its new value stabilizes before accessing a recently
: > :> modified object.

: > : So what?

: > IIUC, your sample code would yield unspecified behavior on such processors.

: No.  The expression has undefined behavior because that is a valid
: interpretation.

I'm speaking of your assembly code running on an architecture such as
Nick described.  Machines with protection features aren't supposed to
have "undefined" behavior.

Tom Payne

























---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Fri, 20 Aug 2004 16:36:24 GMT
Raw View
On Thu, 19 Aug 2004 19:01:20 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> : No.  The expression has undefined behavior because that is a valid
> : interpretation.

> I'm speaking of your assembly code running on an architecture such as
> Nick described.  Machines with protection features aren't supposed to
> have "undefined" behavior.

One more time.  Expressions have undefined behavior because the standard
says they do.  Anything that the implementation software and hardware
does is a exibition of that undefined behavior.  Machines and compilers
do not have undefined behavior, expressions do.  Only a coder can
produce expressions which, if executed, always have undefined behavior.
It makes no difference how much you like the result, it is still UB.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net (James Kuyper)
Date: Fri, 20 Aug 2004 16:36:52 GMT
Raw View
jpotter@falcon.lhup.edu (John Potter) wrote in message news:<lkCUc.25403$nx2.3698@newsread2.news.atl.earthlink.net>...
> On Wed, 18 Aug 2004 05:25:36 GMT, thp@cs.ucr.edu wrote:
>
>
>> For another example, note that the C89 and C99 committees
inadvertently
>> assigned undefined behavior to
>
>>           a[0] = 0;
>>        a[a[0]] = 0;  // a[0] get read but not to determine the new
value.
>
> a[0] is read to determine where to put the new value which does
> determine the new value.


No it doesn't. The value is a number, where it's stored is a memory
location. The memory location is a characterstic of the object that
the value is stored in, it's not a characteristic of the value.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Fri, 20 Aug 2004 20:43:49 GMT
Raw View
On Thu, 19 Aug 2004 18:38:47 GMT, thp@cs.ucr.edu (Tom Payne) wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> > int x(0);
> > int f () { return ++ x }
> > int g () { return 7 * f() - f() * 3 }
> > int h () { return (7 * f()) - (f() * 3); }

> > The result of both g and h is unspecified not undefined.  How does
> > adding a sequence point for the parentheses in h change things?  Do
> > you have an example where they would change things?  How would you
> > specify the sequence point?  How do you justify redundant parentheses
> > changing the meaning of an expression?

> Both expressions have unspecified behavior with the same two options
> for value, 1 and 11.  Under specified, say left-to-right, semantics
> both would have the value, namely 11.  (Please check my arithmetic.)

It seems that we are not able to follow a subthread.  It was suggested
that it might be useful to add a sequence point for parentheses.  I
questioned that and Francis then wandered off on signed overflow which
is the topic of another thread.  You are talking about left to right.
Do you claim that adding a sequence point to parentheses around the
two subexpressions would force left to right evaluation for the outer
expression?  A small modification to provide a sequence point today.

int x(-1);
int f () { return ++ x }
int h () { return (7 && f()) - (f() && 3); }

With the sequence points, it still has unspecified behavior.  How do
you support the call for a parentheses sequence point.  If you don't
want to talk about that, please put the forced left to right discussion
elsewhere.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Fri, 20 Aug 2004 21:53:37 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Thu, 19 Aug 2004 18:38:47 GMT, thp@cs.ucr.edu (Tom Payne) wrote:
:
:> John Potter <jpotter@falcon.lhup.edu> wrote:
:
:> > int x(0);
:> > int f () { return ++ x }
:> > int g () { return 7 * f() - f() * 3 }
:> > int h () { return (7 * f()) - (f() * 3); }
:
:> > The result of both g and h is unspecified not undefined.  How does
:> > adding a sequence point for the parentheses in h change things?  Do
:> > you have an example where they would change things?  How would you
:> > specify the sequence point?  How do you justify redundant parentheses
:> > changing the meaning of an expression?
:
:> Both expressions have unspecified behavior with the same two options
:> for value, 1 and 11.  Under specified, say left-to-right, semantics
:> both would have the value, namely 11.  (Please check my arithmetic.)
:
: It seems that we are not able to follow a subthread.

Apparently so.

: It was suggested
: that it might be useful to add a sequence point for parentheses.

: I questioned that and Francis then wandered off on signed overflow which
: is the topic of another thread.  You are talking about left to right.

Your example would seem to have nothing to do with any possible
discussion of additional sequence points.  The only modification to an
object occurs is the body of f and there's an immediate sequence point
--- any additional sequence points are therefore redundant.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 19 Aug 2004 06:15:06 GMT
Raw View
On Wed, 18 Aug 2004 10:46:07 GMT, francis@robinton.demon.co.uk (Francis
Glassborow) wrote:

> In article <2PBUc.25397$nx2.19224@newsread2.news.atl.earthlink.net>,
> John Potter <jpotter@falcon.lhup.edu> writes

> >On Tue, 17 Aug 2004 03:43:14 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:

> >> John Potter wrote:

> >> > On Fri, 13 Aug 2004 13:54:27 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
> >>> >Parentheses do not
> >>> >introduce a sequence point (maybe they should?).

> >> > I don't think they should.  It would make (a*b)+c*d different from
> >> > a*b+c*d.

> >> How so? If a, b, c and d are all built-in types, I don't see any side
> >> effects that would be written out early. If there's an 'operator *()'
> >> involved which produces side effects, then the compiler would have to
> >> evaluate a*b first anyway.

> >> What have I missed?

> >Maybe that abcd are expressions?  What does the sequence point from the
> >() do to things done in those expressions?  The point being that without
> >() it is unspecified and with () it might be specified.  Is the sequence
> >point related to the +?  If not, what does it mean?  Either of the
> >subexpressions of the + may be evaluated first.  How does the sequence
> >point change things?  If it does not, there is no reason to have it.

> It seems that you do not place any value on replacing undefined
> behaviour with unspecified behaviour. I, OYOH, think that undefined
> behaviour should be limited to cases where the Standard really cannot
> place any requirements on the result.

Please read the material and explain how things will change.

int x(0);
int f () { return ++ x }
int g () { return 7 * f() - f() * 3 }
int h () { return (7 * f()) - (f() * 3); }

The result of both g and h is unspecified not undefined.  How does
adding a sequence point for the parentheses in h change things?  Do
you have an example where they would change things?  How would you
specify the sequence point?  How do you justify redundant parentheses
changing the meaning of an expression?

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 19 Aug 2004 14:42:42 GMT
Raw View
In article <OEUUc.2278$2L3.587@newsread3.news.atl.earthlink.net>, John
Potter <jpotter@falcon.lhup.edu> writes
>Please read the material and explain how things will change.
>
>int x(0);
>int f () { return ++ x }
>int g () { return 7 * f() - f() * 3 }
>int h () { return (7 * f()) - (f() * 3); }
>
>The result of both g and h is unspecified not undefined.  How does
>adding a sequence point for the parentheses in h change things?  Do
>you have an example where they would change things?  How would you
>specify the sequence point?  How do you justify redundant parentheses
>changing the meaning of an expression?

It seems we are talking at cross purposes. I am quite happy with the
current requirements as regards parentheses. What I am unhappy with is:

1) Making signed integer overflow undefined. My preferred resolution of
this is to require that it wraps. The only systems that would incur a
penalty for such are those where overflow causes a system trap which
would have to be handled and those using ones complement or sign &
magnitude which would, in strictly conforming mode have to emulate the
behaviour of a 2's complement architecture.

2) The rules regarding storing and loading from the same address which
make fundamental types second class citizens:

i = ++i;

Has well defined and fully deterministic behaviour for any i whose type
is a udt for which it will compile. It has undefined behaviour for all
fundamental types. This has implications, among which is a compatibility
issue with C99, but one which WG21 cannot fix -- complex is a typedef
for a fundamental type in C, but a typedef for a user defined type in
C++. However that highlights the issue that changing a typedef (possibly
in the third party library) can change C++ source code from fully
defined with deterministic behaviour to undefined behaviour.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 19 Aug 2004 15:49:30 GMT
Raw View
On Wed, 18 Aug 2004 16:52:16 GMT, thp@cs.ucr.edu wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:
> : On Wed, 18 Aug 2004 05:14:36 GMT, thp@cs.ucr.edu wrote:

> :> John Potter <jpotter@falcon.lhup.edu> wrote:

> :> : Very deterministic code for a single sequential processor is allowed.
> :> :
> :> :   mov r1,a+0
> :> :   mov r1,[r1]
> :> :   inc a+0

> :> According to some postings a few years ago by Nick MacLaren on
> :> comp.std.c, the model is that in some aggressive architectures one
> :> must wait until its new value stabilizes before accessing a recently
> :> modified object.

> : So what?

> IIUC, your sample code would yield unspecified behavior on such processors.

No.  The expression has undefined behavior because that is a valid
interpretation.  If the expression did not have undefined behavior, the
implementation would be required to generate whatever extra code is
needed to provide the correct result.

Note that 5/4 allows accessing the new value for any purpose.

> Then, perr the Standard "a=b=c" has undefined behavior.  Issue 222
> doesn't change that fact.

The argument goes something like this.

   int a(1), b(2);
   a = b = 3;

Because there is no specification on when the store of b will take
place, a could get the value 2 rather than 3.  This would be UB
because it accesses the old value for a purpose other than to
determine the new value.  That seems at odds with 5.17/1 which states
that the value of the expression is the value stored after the
assignment.

The purpose of issue 222 is to require the write and read for a
volatile which was not clear and to allow multiple modifications
which was undefined behavior.  The second requires a sequence
point or special wording to overrule 5/4.

I see no problem with the subject expression being well defined.
Changing to postfix is ill-formed and not an issue.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Thu, 19 Aug 2004 18:38:47 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
[...]
> int x(0);
> int f () { return ++ x }
> int g () { return 7 * f() - f() * 3 }
> int h () { return (7 * f()) - (f() * 3); }
>
> The result of both g and h is unspecified not undefined.  How does
> adding a sequence point for the parentheses in h change things?  Do
> you have an example where they would change things?  How would you
> specify the sequence point?  How do you justify redundant parentheses
> changing the meaning of an expression?

Both expressions have unspecified behavior with the same two options
for value, 1 and 11.  Under specified, say left-to-right, semantics
both would have the value, namely 11.  (Please check my arithmetic.)

Tom Payne











---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Mon, 23 Aug 2004 08:28:47 GMT
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
> In article <8VTVc.31736$nx2.14009@newsread2.news.atl.earthlink.net>,
> John Potter <jpotter@falcon.lhup.edu> writes
>>Issue 222 would make j = ++ ++ i; well defined, but might not change
>>j = ++ i - ++ i from undefined to unspecified.  I don't think that
>>there is any requirement in the solution to that issue to require
>>any ordering on the read and store of the two increments.  It is
>>only required that the final read follow the write for each.  It is
>>still possible to do the two initial reads and stores in parallel.
>
> OK, when I get a moment I will read the current commentary and proposed
> resolution of 222 again. However I think this further strengthens my
> belief that sequence points promise more than they deliver and are not
> actually what they say they are.

They're merely deadlines for the delivery of side effects.

>>To understand my point, consider a 2n bit type on an n bit machine.
>>The loads and stores to accomplish the increments may be interleaved.
>>The sequence point only occurs somewhere between the final store of
>>the subexpression and the load of the resulting value.  Neither the
>>value of i nor that of j is defined.
>
> The potential for interleaving of side-effects of evaluation of
> sub-expressions is something with which I am familiar. However I think
> we are getting into dangerous waters when we require some side effects
> to be completed without an intervening sequence point.

Agreed.  By definition, sequence points are such deadlines for
completion.  Such deadlines should be the province of sequence
points and only of sequence points.

> Sequence points were intended to provide islands of stability where
> all prior side-effects have been completed and no subsequent ones
> have been started.

Exactly.

>>Are you suggesting that sequence points should propagate up the parse
>>tree?  I think you must push for deterministic evaluation without
>>depending upon 222 to provide anything.
>
> Possibly. However currently I would prefer two things:
>
> 1) That fundamental types have the same freedoms allowed to user defined
> types.

Operations on defined types are functions.  Therefore, they enjoy the
additional protection of atomicity relative to each other.  IIUC,
John's point is that even when they are terminated with a sequence
point, operations on built-in types enjoy no such atomicity.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 23 Aug 2004 15:49:29 GMT
Raw View
On Fri, 20 Aug 2004 16:36:52 GMT, kuyper@wizard.net (James Kuyper)
wrote:

> jpotter@falcon.lhup.edu (John Potter) wrote in message news:<lkCUc.25403$nx2.3698@newsread2.news.atl.earthlink.net>...

> > On Wed, 18 Aug 2004 05:25:36 GMT, thp@cs.ucr.edu wrote:

> >> For another example, note that the C89 and C99 committees
> inadvertently
> >> assigned undefined behavior to

> >>           a[0] = 0;
> >>        a[a[0]] = 0;  // a[0] get read but not to determine the new
> value.

> > a[0] is read to determine where to put the new value which does
> > determine the new value.

> No it doesn't. The value is a number, where it's stored is a memory
> location. The memory location is a characterstic of the object that
> the value is stored in, it's not a characteristic of the value.

Amusing interpretation based on pure senseless reading of words.  No
offense intended, that is what lawyers do.

Consider the justifications given for those words and it is noted that
the intent is to allow accesses of old values which must be performed
before the new value may be stored, all accesses which must produce
the new value and assign undefined behavior to any access which might
produce the old or new value.

The wording may be lacking, but the history of the subject makes the
intent clear.  Maybe you could give an example where the subject code
will not function or suggest new wording in a DR.  The above code must
be well defined and ++i + i must be undefined.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 18 Aug 2004 05:33:30 GMT
Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:OpNMEIB6QPIBFwNS@robinton.demon.co.uk...

> >Come again?  As I read the rules i = ++j has well defined behavior.
Provided
> >i and j are distinct objects.
>
> Absolutely true in C but in C++ ++j returns an lvalue which means that
> you now get an lvalue to rvalue conversion in order to make the
> assignment to i.

Ouch.   That seems like a defect in the standard, the definition of op++
should be extended to cover the case. And make safe it safe to use its
result either as lvalue or rvalue. I'd guess most uses of that operator
where its result is used wants the rvalue.

And the whole purpose of the operator is to yield the incremented value --
even if a reference (lvalue) is returned, it must be one to the already
modified object.

> I would be amazed if
> any compiler actually does anything dubious but we are being language
> lawyers here.

Yep. Being the std group I must ask if there already exist a DR on the
issue?   Fetching the current lists I couln't locate it.

Paul




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 18 Aug 2004 07:31:18 GMT
Raw View
On Tue, 17 Aug 2004 03:43:14 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:

> John Potter wrote:
>
> > On Fri, 13 Aug 2004 13:54:27 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
> >>Parentheses do not
> >>introduce a sequence point (maybe they should?).

> > I don't think they should.  It would make (a*b)+c*d different from
> > a*b+c*d.

> How so? If a, b, c and d are all built-in types, I don't see any side
> effects that would be written out early. If there's an 'operator *()'
> involved which produces side effects, then the compiler would have to
> evaluate a*b first anyway.

> What have I missed?

Maybe that abcd are expressions?  What does the sequence point from the
() do to things done in those expressions?  The point being that without
() it is unspecified and with () it might be specified.  Is the sequence
point related to the +?  If not, what does it mean?  Either of the
subexpressions of the + may be evaluated first.  How does the sequence
point change things?  If it does not, there is no reason to have it.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Wed, 18 Aug 2004 10:46:07 GMT
Raw View
In article <2PBUc.25397$nx2.19224@newsread2.news.atl.earthlink.net>,
John Potter <jpotter@falcon.lhup.edu> writes
>On Tue, 17 Aug 2004 03:43:14 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>
>> John Potter wrote:
>>
>> > On Fri, 13 Aug 2004 13:54:27 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>>> >Parentheses do not
>>> >introduce a sequence point (maybe they should?).
>
>> > I don't think they should.  It would make (a*b)+c*d different from
>> > a*b+c*d.
>
>> How so? If a, b, c and d are all built-in types, I don't see any side
>> effects that would be written out early. If there's an 'operator *()'
>> involved which produces side effects, then the compiler would have to
>> evaluate a*b first anyway.
>
>> What have I missed?
>
>Maybe that abcd are expressions?  What does the sequence point from the
>() do to things done in those expressions?  The point being that without
>() it is unspecified and with () it might be specified.  Is the sequence
>point related to the +?  If not, what does it mean?  Either of the
>subexpressions of the + may be evaluated first.  How does the sequence
>point change things?  If it does not, there is no reason to have it.

It seems that you do not place any value on replacing undefined
behaviour with unspecified behaviour. I, OYOH, think that undefined
behaviour should be limited to cases where the Standard really cannot
place any requirements on the result.

Of course, I would also prefer a deterministic order of evaluation and
leave it to compilers to provide out of order evaluation as an
optimisation but that is a different issue though I am surprised by the
vehemence with which some advocate that the higher risk rules that we
currently have should not be changed.

What both these have in common is that they move code up the spectrum
away from less defined behaviour towards more the predictable. IMO, if
software development is to aspire to being an engineering discipline it
must take risk potential seriously.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 18 Aug 2004 11:24:14 GMT
Raw View
On Wed, 18 Aug 2004 05:25:36 GMT, thp@cs.ucr.edu wrote:

> For another example, note that the C89 and C99 committees inadvertently
> assigned undefined behavior to

>            a[0] = 0;
>         a[a[0]] = 0;  // a[0] get read but not to determine the new value.

a[0] is read to determine where to put the new value which does
determine the new value.  I think you are being a bit too absurd.
There are problems, but your examples seem to be way out.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Wed, 18 Aug 2004 11:24:27 GMT
Raw View
On Wed, 18 Aug 2004 05:14:36 GMT, thp@cs.ucr.edu wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> : Very deterministic code for a single sequential processor is allowed.
> :
> :   mov r1,a+0
> :   mov r1,[r1]
> :   inc a+0

> According to some postings a few years ago by Nick MacLaren on
> comp.std.c, the model is that in some aggressive architectures one
> must wait until its new value stabilizes before accessing a recently
> modified object.

So what?

> :>     ... Furthermore, the object shall be accessed only to ...
> :
> : Which would make many more things undefined.
> :
> :   a = b = c; // accesses modified b

> Per issue 222, this expression has undefined behavior when a, b, and c
> have built-in types.

NO.  Andy said, "One could argue".  That is much different from a
statement that it is undefined.  The goal of issue 222 is to assure
that it is well defined.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 18 Aug 2004 16:52:16 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Wed, 18 Aug 2004 05:14:36 GMT, thp@cs.ucr.edu wrote:
:
:> John Potter <jpotter@falcon.lhup.edu> wrote:
:
:> : Very deterministic code for a single sequential processor is allowed.
:> :
:> :   mov r1,a+0
:> :   mov r1,[r1]
:> :   inc a+0
:
:> According to some postings a few years ago by Nick MacLaren on
:> comp.std.c, the model is that in some aggressive architectures one
:> must wait until its new value stabilizes before accessing a recently
:> modified object.
:
: So what?

IIUC, your sample code would yield unspecified behavior on such processors.

:> :>     ... Furthermore, the object shall be accessed only to ...
:> :
:> : Which would make many more things undefined.
:> :
:> :   a = b = c; // accesses modified b
:
:> Per issue 222, this expression has undefined behavior when a, b, and c
:> have built-in types.
:
: NO.  Andy said, "One could argue".  That is much different from a
: statement that it is undefined.  The goal of issue 222 is to assure
: that it is well defined.

Then, perr the Standard "a=b=c" has undefined behavior.  Issue 222
doesn't change that fact.

Tom Payne






















---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 18 Aug 2004 16:52:48 GMT
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
[...]
: It seems that you do not place any value on replacing undefined
: behaviour with unspecified behaviour. I, OYOH, think that undefined
: behaviour should be limited to cases where the Standard really cannot
: place any requirements on the result.

Visibly 5p4 and its relatives in the C standards were introduced to
permit conforming compilers to make certain optimizations default.
Are there other such instances of performance-motivated undefined
behavior in the standards?

: Of course, I would also prefer a deterministic order of evaluation and
: leave it to compilers to provide out of order evaluation as an
: optimisation but that is a different issue though I am surprised by the
: vehemence with which some advocate that the higher risk rules that we
: currently have should not be changed.

That vehemence seems to be based on the unsupported conventional
wisdom that violations of 5p4 are the province solely of the ignorant.

: What both these have in common is that they move code up the spectrum
: away from less defined behaviour towards more the predictable. IMO, if
: software development is to aspire to being an engineering discipline it
: must take risk potential seriously.

IMHO, software development is an engineering discipline too often
practiced badly.  In the case at hand, we are discussing a risk vs
performance tradeoff.  Such "trade studies" abound in engineering,
most notably in aeornautical engineering and systems engineering.  In
an appropriately mature engineering environment the discussion would
be based on empirical evidence regarding both the incremental risk and
the incremental performance associated with the design decision under
discussion.  If anyone knows of empirical evidence relative this
particular discussion, most especially evidence of significant
performance degredation to important real-world programs that would
result from specifying order of evaluation and dropping 5p4, I'd
very much appreciate knowing about it.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Wed, 18 Aug 2004 16:53:26 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cfisom$aqg$2@glue.ucr.edu...

> Unspecified order of evaluation involves a performance vs. risk
> tradeoff.

Very good take. So we shall use the well-known threat analysis to see the
benefits. Just stating 'that is less risky' is not enough.    Like vearing
bulletproof vest on street is more secure than not wearing one.  The
question is whether the difference is relevant in practice.

> One estimate is that having a specified order of evaluation
> would cost about 2% in terms of performance.

Possibly. From theoretical point of view we know that
A) cost is not avoidable on some platforms compared to free choice.
B) the cost is low in "linear" terms, IOW if we just execute all the
functions once, the extra will not be high.
C) the cost can be pretty high on micro level, in individual functions. It
may have high impact on the real execution.

On the bright side we also know that:
D) a compiler switch may allow the free order as option.
E) hardware gets faster as we talk, and in many situations the processor
runs the idle task in 99% of the time

My conclusion here: if I had a magic wand that could change all the
compilers out there to use fixed order, and give the switch, I used it.
But still I would predict we soon get the same situation as today, people
adjust the build configs to use the mentioned switch and forget about it,
the same bugs creep around with similar surprise factors (we carefully
tested the debug build, then sfipped the release and some users report
strange errors...)  Okey we have the scrapegoat elsewhere now, the guy who
pust /O in the release build. Without carefully learning the 30 suboptions
to finetune.

In this real world I better admit the train is gone, and look for other ways
to reach the destination. What would help more:

1. compiler switch that fixes the eval order.    [for those unsure their
code is not dependent]
2. compiler help/analysers that warn about 'code outcome seriously dependent
on eval order'

Especially having the second would catch much more bugs than a fixed order
could have.

> On the hand
> foo(arg1,arg2,arg3) could give six different results depending on
> which of 3! orders of evaluation are applied to the arguments.
> Presumably only one of those six results is correct.

That is the point our views differ.  I consider all the results incorrect
should they possibly differ.

> So the tradeoff is
>   - the wrong result in five out of six cases vs.
>   - waiting an additional 2% for the right result.
> ;-)

What is a good rethoric but IMHO far from reality.

Could you please show a few real-world examples where you stumbled on such
an order-dependent expression, considered it good, and the only thing to
make it really correct was a fixed eval order?

Those I saw were just broken, or certain order didn't fix it.   Others were
way misleading.

In a current discussion we loked after temporaryless swap. one came with a
really compact solution:

a ^= b ^= a;

it's certainly broken in C++, but it was on a java forum, and everyone said
WOW.
Until someone tried it with the compiler where the result did not swap the
values. And digging deep in the rules (which are pretty simple and
straightforward) we concluded, the compiler is right indeed.

And the order is not one that even an expert eye would think it is.

And however you fix one order, you'll always have expressions misleading,
shall they have order-dependent parts.

The only gain having the order fixed is not getting the _right_ result, but
getting the _same_ result all the time, so giving more chance some test case
will catch the bug in source.
What undoubtedly has great value.  The question is whether that value is
good *enough* or running after it worth the resources.  Possibly we could
buy more security using less resources.

Paul


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu (Tom Payne)
Date: Wed, 18 Aug 2004 18:16:09 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
[...]
> My conclusion here: if I had a magic wand that could change all the
> compilers out there to use fixed order, and give the switch, I used it.
> But still I would predict we soon get the same situation as today, people
> adjust the build configs to use the mentioned switch and forget about it,
> the same bugs creep around with similar surprise factors (we carefully
> tested the debug build, then sfipped the release and some users report
> strange errors...)  Okey we have the scrapegoat elsewhere now, the guy who
> pust /O in the release build. Without carefully learning the 30 suboptions
> to finetune.
>
> In this real world I better admit the train is gone, and look for other ways
> to reach the destination. What would help more:
>
> 1. compiler switch that fixes the eval order.    [for those unsure their
> code is not dependent]
> 2. compiler help/analysers that warn about 'code outcome seriously dependent
> on eval order'
>
> Especially having the second would catch much more bugs than a fixed order
> could have.

The status quo mandates the weird a semantics that permits particular
optimizations.  I'm suggesting mandating straightforward semantics and
treating the optimization-semantics as an optional mode.  Perhaps
conforming implementation should be required to provide that mode as
an option.

Tom Payne


















---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Fri, 13 Aug 2004 19:56:30 GMT
Raw View
On Thu, 12 Aug 2004 18:54:29 GMT, hyrosen@mail.com (Hyman Rosen)
wrote:

>Bob Hairgrove wrote:
>> IIUC, the parentheses (having highest precedence of all) will preclude
>> D being executed before A, B, or C.
>
>No, your understanding is incorrect.
>
>That's why this has got to be changed. The number of people who
>actually understand seems to be vanishingly small, even among
>very experienced people here on this newsgroup.

Well, it's nice to know that I am in good company! :-)

>Parentheses control the association of operands with operators.
>They have absolutely nothing to do with when attached pre- or
>post-increments are applied.

Please bear with me a bit, since I'm not a C++ expert ... in school,
we were (are) taught "When in doubt (abt. operator precedence), use
parentheses!"

What other operators (except for --, of course) would behave similarly
with regard to UB (i.e. would execute possibly outside of the
parentheses in the above situation)? All the unary operators? Or only
a subset of these?

Thanks.

PS - In view of the current confusion on this issue, I would strongly
support your suggestion, as stated in a different post in this thread,
to force a sequence point after execution of all statements within
parentheses.

--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 20:12:54 GMT
Raw View
Balog Pal wrote:
> Reading forums and newsgroups I don't see it improved too much.  To be more
> precise, it works well for simple function calls     foo(arg1, arg2, arg3).
> Generally not, for expressions with symbolic operators. Absolutely not for
> expresions with operators and parentheses.

To be more precise, the big improvement is that even in an
absence of perfect understanding, the expression won't have
accidental undefined behavior, and will not depend on machine,
operating system, or compiler for its meaning. That's a mighty
big improvement to me.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 20:27:14 GMT
Raw View
Bob Hairgrove wrote:
> What other operators (except for --, of course) would behave similarly
> with regard to UB (i.e. would execute possibly outside of the
> parentheses in the above situation)? All the unary operators? Or only
> a subset of these?

Well, only ++ and -- mutate their operands.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 13 Aug 2004 20:27:21 GMT
Raw View
Bob Hairgrove <invalid@bigfoot.com> wrote:
[...]
: What other operators (except for --, of course) would behave similarly
: with regard to UB (i.e. would execute possibly outside of the
: parentheses in the above situation)? All the unary operators? Or only
: a subset of these?
:
: Thanks.
:
: PS - In view of the current confusion on this issue, I would strongly
: support your suggestion, as stated in a different post in this thread,
: to force a sequence point after execution of all statements within
: parentheses.

Prefix ++ and -- have a problem similar to assignment operators since
they return the lvalue of the updated object.  But postfix ++ and --
also give problems.  Suppose that a[0] is 0.  Consider a[a[0]++].  the
outer subscripting operation reads a[0] after a modifying operation
without the benefit of an intervening sequence point.  Note also that
this expression does not necessarily violate 5p4 since the read of
a[0] by the outer subscripting operation does not necesssarily see the
old value.

Tom Payne
















---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 20:27:27 GMT
Raw View
Bob Hairgrove wrote:
 > and it seems a logical thing to do, since it is probably
 > an easy thing for the compiler to parse parentheses.

The logical thing to do is to emulate Java's order of
evaluation rules. They're pretty simple. Operands of
an operator or function call are fully evaluated left-
to-right, and then the operation is evaluated.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 21:05:58 GMT
Raw View
thp@cs.ucr.edu wrote:
 > On the hand foo(arg1,arg2,arg3) could give six different results depending on
> which of 3! orders of evaluation are applied to the arguments.

The compiler is still free to pick the most efficient order
except in the case where the operands have order dependencies.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Fri, 13 Aug 2004 21:53:06 GMT
Raw View
In article <1092428193.856648@master.nyc.kbcfp.com>, Hyman Rosen
<hyrosen@mail.com> writes
>Bob Hairgrove wrote:
>> What other operators (except for --, of course) would behave similarly
>> with regard to UB (i.e. would execute possibly outside of the
>> parentheses in the above situation)? All the unary operators? Or only
>> a subset of these?
>
>Well, only ++ and -- mutate their operands.

And all the assignment operators :-) However note that there are no
undefined behaviour problems with any of these if at least one of the
operands is of a user defined type. The problem we do have is
unspecified behaviour. Here is an example I posted earlier to day to
comp.std.c

#include <stdio.h>
int i = 4;
int foo(){i = 2; return i;}
int bar(){++i; return i;}

int main(){
  int value = 0;
  value = i + foo() + bar();
  printf("%d", value);
}

AFAIK the above program has no undefined behaviour however the output
may be any of:

order of evaluation result
i, foo(), bar()     9
i, bar(), foo()     11
foo(), i, bar()     7
foo(), bar(), i     8
bar(), i, foo()     12
bar(), foo(), i     9

Five different results with only strict left-right and right-left (pure
coincidence) giving the same one.

Now a strict order of evaluation would provide a reproducible, portable
result. Any internal side effects from the function calls happen in a
guaranteed order. However parallel evaluation of the sub-expressions
would result in undefined behaviour.




--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 22:09:10 GMT
Raw View
Francis Glassborow wrote:
 > However parallel evaluation of the sub-expressions
> would result in undefined behaviour.

That's not legal now anyway.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 14 Aug 2004 21:16:23 GMT
Raw View
Hyman Rosen <hyrosen@mail.com> wrote:
: thp@cs.ucr.edu wrote:
: > On the hand foo(arg1,arg2,arg3) could give six different results depending on
:> which of 3! orders of evaluation are applied to the arguments.
:
: The compiler is still free to pick the most efficient order
: except in the case where the operands have order dependencies.

The compiler is free to pick any of the 3! orders and is not bound to
pick the same order each time.  AFAIK, it can do so regardless of
dependencies.

Tom Payne













---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sat, 14 Aug 2004 21:16:32 GMT
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
[...]
: Now a strict order of evaluation would provide a reproducible, portable
: result. Any internal side effects from the function calls happen in a
: guaranteed order. However parallel evaluation of the sub-expressions
: would result in undefined behaviour.

Huh?  parallel evaluation is of function bodies is now allowed.  Did I
misunderstand?

Tom Payne




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Sun, 15 Aug 2004 05:21:08 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cfhdie$6cu$2@glue.ucr.edu...

> : Little benefit: if in your example, or any other you use Int instead of
in,
> : that is just a wrapper to int, the behavior is no longer indefined. 'Cos
> : overloaded operators are functions and insert the missing seq points.
But
> : the catch is the defined behavior till has the unspecified part, the
> : expression can have different results legally. What is hardly acceptable
in
> : a program.
>
> It sounds like fixing that "catch" would be a big benefit.

I see it as a patch that would cure a few percent of problematic cases
leaving the rest uncured.  I wouldn't impose it on the language.  I'd think
static-anal tools can flag the cases of obvious violation even now, and any
implemeter is free to define any UB, or specify anything unspecified.
Making it a QoI issue.

> : Cost: it may prevent theuse of some assy instructions or optimisations
as
> : now you have more seq points in the old code -- all in places they were
not
> : necessary.
>
> What empirical studies do we have showing that this cost is
> significant in terms of performance degradation to important
> real-world programs?

I can't pont you to a real empirical study, but you can think about the
issue from the compiler implemeter's view.  Note we have multiple issues in
this conversation.

One is regarding the unspecified order of argument evaluation.  Having that
allowed, implemetatoin passing params on stack will use an order compatible
with the order the called function will see the parameters.   If there's an
external order, and it is different from the one the compiler would use --
subresults must be put somewhere.  That means more code and worse resource
management.  As long as C++ is intended as a general purpose tool for
multitude of different platforms I'm sure without studies that someone will
get hurt. (Especially as long as I see recurring discussions on 'how to
avoid virtual calls' -- do you think one extra indirection is a big deal?)

The other issue, fixing UB on aliasing is a really big one. Pick a simple
function that receives pointers or refs, and create the code. Then recreate
it to make sure it works for any possible case of aliasing. You'll see
tremendous proliferation, either in form of checking the pointer values
against each other and addresses of other objects around -- or you suppress
all forms of item caching and register usage; everything must be immediately
written to memory, and reread from there.  The difference will be around
what you see now comparing your debug and release builds.

As I mentioned, C and C++ way here is to put the burden on programmer to
sort out the in real life very rare cases when aliasing is expected.  (look
around, how many memmove-s you see compared to memcpy-s?)

> : Expressions both modifying and reading the same object in the middle
just
> : shall be avoided.
>
> But they do occur often inadvertently as a result of unnoticed
> aliasing.  Undefined behavior can be a very harsh penalty for
> such a slip.

Life is full of harsh penalties for all kinds of slips -- but we can't
afford to carry or mom around to look after them, can we.

Jokes aside, IMO that is a case we shall educate people to be aware of the
issue. That can cover most of the cases.   If instead we replace UB with
some specified behavior that is still wrong for quite many cases are we much
ahead?
And shall we all pay to make some ignorant people releived?


Paul


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 15 Aug 2004 05:21:45 GMT
Raw View
In article <1092434586.363488@master.nyc.kbcfp.com>, Hyman Rosen
<hyrosen@mail.com> writes
>Francis Glassborow wrote:
>> However parallel evaluation of the sub-expressions
>> would result in undefined behaviour.
>
>That's not legal now anyway.

Yes, I know. However it is something we should give some thought to as
multicore CPUs come on line.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Sun, 15 Aug 2004 06:03:51 GMT
Raw View
thp@cs.ucr.edu wrote:
> The compiler is free to pick any of the 3! orders and is not bound to
> pick the same order each time.  AFAIK, it can do so regardless of
> dependencies.

I meant even if order of evaluation is firmly specified by the language,
the compiler can still use any order it wants, as long as the as-if rules
are satisfied.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Sun, 15 Aug 2004 17:57:22 GMT
Raw View
Francis Glassborow wrote:
> Yes, I know. However it is something we should give some thought to as
> multicore CPUs come on line.

About two seconds worth, and then it should be dismissed forever.
Adding more non-deterministic semantics to C++ is a horrible idea.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 15 Aug 2004 17:57:29 GMT
Raw View
On Fri, 13 Aug 2004 20:27:21 GMT, thp@cs.ucr.edu wrote:

> Prefix ++ and -- have a problem similar to assignment operators since
> they return the lvalue of the updated object.  But postfix ++ and --
> also give problems.  Suppose that a[0] is 0.  Consider a[a[0]++].  the
> outer subscripting operation reads a[0] after a modifying operation
> without the benefit of an intervening sequence point.  Note also that
> this expression does not necessarily violate 5p4 since the read of
> a[0] by the outer subscripting operation does not necesssarily see the
> old value.

I think you failed to read the last sentence.  If any allowed sequence
sees the old value, the expression has undefined behavior.  Not sure
what you mean by violate 5p4.  The expression is well-formed with UB.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 15 Aug 2004 20:32:48 GMT
Raw View
On Fri, 13 Aug 2004 13:54:27 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:

> Bob Hairgrove wrote:

> > On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
> >>(  &  ++  x[0]  )  [0]
> >>   A   B    C       D

> > IIUC, the parentheses (having highest precedence of all) will preclude
> > D being executed before A, B, or C.

> No, because the actual incrementing is a side effect, and side effects
> can occur at any time between sequence points.

That is the point of the thread is it not?

> Parentheses do not
> introduce a sequence point (maybe they should?).

I don't think they should.  It would make (a*b)+c*d different from
a*b+c*d.

> A valid sequence of machine code could be:
> - Load the current value of x[0] into a register (C)
> - increment the register (B)
> - load the current value of x[0] into a different register (A and D)
> - write the value of the first register to x[0] (finish off B)

This is questionable using the standard and not allowed using the WP.

Operation D ([]) is applied to the result of operation A (&) which is
applied to the result of operation B (++) which returns the value of
its operand after it has been modified as an lvalue.

The WP makes it clear that the assignment has taken place prior to
production of the result.  Note that ++ is defined in terms of +=.
It does not make it a sequence point, but it does demand sequencing.
There is a difference.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Sun, 15 Aug 2004 20:33:29 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Fri, 13 Aug 2004 20:27:21 GMT, thp@cs.ucr.edu wrote:
:
:> Prefix ++ and -- have a problem similar to assignment operators since
:> they return the lvalue of the updated object.  But postfix ++ and --
:> also give problems.  Suppose that a[0] is 0.  Consider a[a[0]++].  the
:> outer subscripting operation reads a[0] after a modifying operation
:> without the benefit of an intervening sequence point.  Note also that
:> this expression does not necessarily violate 5p4 since the read of
:> a[0] by the outer subscripting operation does not necesssarily see the
:> old value.
:
: I think you failed to read the last sentence.  If any allowed sequence
: sees the old value, the expression has undefined behavior.  Not sure
: what you mean by violate 5p4.

A good point.  That sentence reads:

   The requirements of this paragraph shall be met for each allowable
   ordering of the subexpressions of a full expression; otherwise
   the behavior is undefined.

Technically there are four allowable orderings of the subexpressions
of this expression and they are all equivalent with respect to the
matter under discussion, so let's consider just one:

     0
     a
     a[0]
     a[0]++
     a
     a[a[0]++]

At this point the object is being read while it is undergoing
modification, but the behavior appears to be defined if the new value
is returned.

: The expression is well-formed with UB.

IIUC, it appears that the standard is ambiguous on this matter is:
  - When a[a[0]++] happens to retrieve the prior value, the behavior
    is undefined.
  - When a[a[0]++] happens to retrieve the new value, the behavior
    is well defined.
  - When a[a[0]++] happens to retrieve some indeterminate intermediate
    value, the implementation is non-conforming.
Obviously, that's not the intent of 5p4.  IMHO that particular defect
could be fixed by the following revision to 5p4:

   ... Furthermore, the object shall be accessed only to ...

becomes

   ... Furthermore, the object shall be accessed only to ...

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 15 Aug 2004 20:33:48 GMT
Raw View
In article <xrFTc.4590$Zh3.818@trndny02>, Hyman Rosen <hyrosen@mail.com>
writes
>Francis Glassborow wrote:
>> Yes, I know. However it is something we should give some thought to
>>as  multicore CPUs come on line.
>
>About two seconds worth, and then it should be dismissed forever.
>Adding more non-deterministic semantics to C++ is a horrible idea.

Why do you think that with correct specifications would result in
non-deterministic semantics? There is prior art on using multiple
processors such as Occam. Of course it would require more than just
allowing parallel execution of sub-expressions but do not jump to the
conclusion that I was advocating that.



--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 16 Aug 2004 00:42:40 GMT
Raw View
Hyman Rosen <hyrosen@mail.com> wrote:
: Francis Glassborow wrote:
:> Yes, I know. However it is something we should give some thought to as
:> multicore CPUs come on line.
:
: About two seconds worth, and then it should be dismissed forever.
: Adding more non-deterministic semantics to C++ is a horrible idea.

Agreed.  Non-deterministic semantics should be relegated to
non-default optimization options.  Within the realm of deterministic
semantics, the as-if rule allows a lot of parallelization.  Modern X86
architectures do a lot of it at the hardware level.

Tom Payne









---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 16 Aug 2004 00:43:18 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
: <thp@cs.ucr.edu> wrote in message news:cfhdie$6cu$2@glue.ucr.edu...
:
:> : Little benefit: if in your example, or any other you use Int instead of
: in,
:> : that is just a wrapper to int, the behavior is no longer indefined. 'Cos
:> : overloaded operators are functions and insert the missing seq points.
: But
:> : the catch is the defined behavior till has the unspecified part, the
:> : expression can have different results legally. What is hardly acceptable
: in
:> : a program.
:>
:> It sounds like fixing that "catch" would be a big benefit.
:
: I see it as a patch that would cure a few percent of problematic cases
: leaving the rest uncured.

Why must this be an all-or-nothing matter.  Fixing a serious problem
is a step in the right direction, even if it doesn't cure world
hunger.

: I wouldn't impose it on the language.

Where's the imposition?  Currently the language carries the burder of
ill-defined semantics in order to accomodate (what some say is) a 2%
optimization.  What I propose imposing on the language is to relieve
it of that burdern.

: I'd think static-anal tools can flag the cases of obvious violation
: even now,

The obvious cases are at worst an nuisance.  The real problem is the
non-obvious cases.

: and any implemeter is free to define any UB, or specify anything
: unspecified.  Making it a QoI issue.

And I'm suggesting that the optimization options enabled by the
current semantic chaos become the QoI issue --- any implementor is
free to have optimization options that introduce non-conforming
behavior.

[...]
: As I mentioned, C and C++ way here is to put the burden on programmer

That exactly the problem.

: to sort out the in real life very rare cases when aliasing is expected.

In my experience, such cases are not rare.

:> : Expressions both modifying and reading the same object in the middle
:> : just shall be avoided.
:>
:> But they do occur often inadvertently as a result of unnoticed
:> aliasing.  Undefined behavior can be a very harsh penalty for
:> such a slip.
:
: Life is full of harsh penalties for all kinds of slips -- but we can't
: afford to carry or mom around to look after them, can we.

I've heard that same argument used against mandatory seatbelts and every
other safety device.  I don't buy it.

: Jokes aside, IMO that is a case we shall educate people to be aware of the
: issue. That can cover most of the cases.   If instead we replace UB with
: some specified behavior that is still wrong for quite many cases are we much
: ahead?
: And shall we all pay to make some ignorant people releived?
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What evidence do you have that invoking undefined behavior is a problem of
ignorance and/or ignorant people.  Consider the fact that since the
ARM, every time a C++ luminary wrote i=++j, he/she invoked undefined
behavior.  IMHO, you are simply blaming and demeaning the victims.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Mon, 16 Aug 2004 06:41:29 GMT
Raw View
jpotter@falcon.lhup.edu (John Potter) writes:

>> > On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>> >>(  &  ++  x[0]  )  [0]
>> >>   A   B    C       D
>

> Operation D ([]) is applied to the result of operation A (&) which is

I'm pretty sure that's backwards.  This compiles:

  struct X
  {
    X operator++() const;
    X operator[](int) const;
    int operator&() const;
  } x;

  int a = &++x[0];

This does not:

  int b = (&++x)[0];

Am I missing something?

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 16 Aug 2004 16:34:49 GMT
Raw View
On Sun, 15 Aug 2004 20:33:29 GMT, thp@cs.ucr.edu wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> A good point.  That sentence reads:

>    The requirements of this paragraph shall be met for each allowable
>    ordering of the subexpressions of a full expression; otherwise
>    the behavior is undefined.

> Technically there are four allowable orderings of the subexpressions
> of this expression and they are all equivalent with respect to the
> matter under discussion, so let's consider just one:

>      0
>      a
>      a[0]
>      a[0]++
>      a
>      a[a[0]++]

> At this point the object is being read while it is undergoing
> modification, but the behavior appears to be defined if the new value
> is returned.

An interesting deviation from the usual interpretation.  Since we are
talking about sequence points, the usual question is when the store
takes place.  Since it is valid to do the store after the second
access and that is UB, the implementation may generate any code it
likes for that expression.  You are defining UB based on the code which
happens to be generated, but the usual is to define it based on the
worst code which could be generated.

> : The expression is well-formed with UB.

> IIUC, it appears that the standard is ambiguous on this matter is:
>   - When a[a[0]++] happens to retrieve the prior value, the behavior
>     is undefined.

Since it could, the expression has undefined behavior.

>   - When a[a[0]++] happens to retrieve the new value, the behavior
>     is well defined.

Nope, just an accident of one possible UB.

>   - When a[a[0]++] happens to retrieve some indeterminate intermediate
>     value, the implementation is non-conforming.

Nope.  The store may be performed in parallel with the load.  These
cases are found when considering a type which requires multiple loads
such as a long on a 16 bit machine.

> Obviously, that's not the intent of 5p4.

The intent is to allow the store at any time.  The form of the
expression determines UB.

> IMHO that particular defect
> could be fixed by the following revision to 5p4:

>    ... Furthermore, the object shall be accessed only to ...
> becomes
>    ... Furthermore, the object shall be accessed only to ...

???

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Mon, 16 Aug 2004 16:37:49 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cfou1n$m0a$1@glue.ucr.edu...

> What evidence do you have that invoking undefined behavior is a problem of
> ignorance and/or ignorant people.  Consider the fact that since the
> ARM, every time a C++ luminary wrote i=++j, he/she invoked undefined
> behavior.

Come again?  As I read the rules i = ++j has well defined behavior. Provided
i and j are distinct objects.

UB you have if they happen to be the same object of a builtin type. IOW when
that programmer  writes

i = ++i;

>  IMHO, you are simply blaming and demeaning the victims.

Not really my intention, nut I umst confess that I fail to understand why
anyone would like that later form of expression. And why would he expect any
sane behavior from the former in the accidental case.    I consider that
case as wrong, as a bug, as a no-no. Even it it happens to produce what is
expected for the moment in the special case.

Writing a C++ progrtam we must be aware of the possible aliasing, and deal
with the case. By either arranging the code to deal with it, or specifying
requirement of forbidding overlaps.  Just like most morality guides teach to
expect self-assignment in op=.

Whoever didn't grasp the concept in general is IMHO a danger factor.
You may fix the language to give you more defined behavior, the issue still
remains.  Likely in its fulness.  Do you expect the unaware environment
write the relevant test cases to make the problem surface?   I see it as a
tied issue.

To me such code is just broken whatever behavior is carved in stone.

Good code is one that can be read and reading makes it obvious what will
happen. And makes the _same_ abvious reading.    As a parallel, see
guidelines to insert ().  For expressions that are well formed, all the
behavior defined, just depend on arbitrary language rules that only a few
people know, and even them claim that knowledge as being an accident and
better not rely upon.  Like the operator precedence.

if ( a & b == c)   // that's good as is, I'm a master guru knowing == comes
before &, and eager to show off...

turning back, is

a = i + ++i;

really a sane expression in java code, where it has no problems with the
compiler and language?  How about this one:

a = i + (++i + 3);

Try a few programmers, how many will guess the result correctly. Would you
pass such code as a reviewer?

OTOH, don't let you be offended by stubborn people in this newsgroup, the
committee is open to everyone.   You can write a proposal to the desired
changes.  A simple one that just insterts seq points around ++ and --
operators would hopefully not consume mush of the WG time, and could be just
voted upon. With a chance on positive vote too.

For something fatter like fixing argument eval order, I'd expect Ambassador
Kosh'  "The avalanche is already rolling. There's no point for the pebbles
to vote now."  Suppose that change just made it into the next standard, and
it comes out in 2010. What year do you start writing code that wold rely and
build upon the newly defined feature? And if the answer is 'well, you'd
better not bulid apon it after all, it's just a safety measure for the
case', consider the row of features people eagerly want to have and use.

[As a side note, some years ago I was asking for adding labeled
break/continue to C++ the same way it exists in java. after the negative
discussion I thought to file the proposal. In the time between I
reconsidered it, not for i'm lazy or think it less valueable, just I was
unaware of a resource: committee time. And looking at the mass of issues I
don't consider it a worthy ENOUGH one.]

I hoped someone from the committee would tell us some stories on the issue
here -- hard to believe there wasn't pretty much discussion around it, and
would be interesting to hear.

Paul




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Mon, 16 Aug 2004 16:37:58 GMT
Raw View
On Mon, 16 Aug 2004 06:41:29 GMT, dave@boost-consulting.com (David
Abrahams) wrote:

> jpotter@falcon.lhup.edu (John Potter) writes:

> >> > On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
> >> >>(  &  ++  x[0]  )  [0]
> >> >>   A   B    C       D

> > Operation D ([]) is applied to the result of operation A (&) which is

> I'm pretty sure that's backwards.  This compiles:

>   struct X
>   {
>     X operator++() const;
>     X operator[](int) const;
>     int operator&() const;
>   } x;

In this thread, x is an array.  That struct is meaningless.

>   int a = &++x[0];

> This does not:

>   int b = (&++x)[0];

> Am I missing something?

The discussion is about UB for the subject expression.  If the operators
are functions, there is no UB.  We are talking about the builtin
operators where [] is applied to pointers and & gives a pointer.

   int x[20] = { 0 };

Now neither compiles, but the subject, (&++x[0])[0], does.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gfpng@paradise.net.nz (Graeme Prentice)
Date: Mon, 16 Aug 2004 16:41:13 GMT
Raw View
On Mon, 16 Aug 2004 06:41:29 GMT, David Abrahams wrote:

>jpotter@falcon.lhup.edu (John Potter) writes:
>
>>> > On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>>> >>(  &  ++  x[0]  )  [0]
>>> >>   A   B    C       D
>>
>
>> Operation D ([]) is applied to the result of operation A (&) which is
>
>I'm pretty sure that's backwards.  This compiles:
>
>  struct X
>  {
>    X operator++() const;
>    X operator[](int) const;
>    int operator&() const;
>  } x;
>
>  int a = &++x[0];

It compiles without the const's as well, because you can call a non
const member function on an rvalue.  Subscript has highest precedence so
is applied first, returning rvalue of type X, then member function
operator++ also returning rvalue of type X, then member operator&,
returning int.


>
>This does not:
>
>  int b = (&++x)[0];

operator& returns an int and applying the subscript operator without one
of the operands being a pointer or the left hand operand being a class
type is illegal.

>
>Am I missing something?

Probably the fact that x was specified originally as being an array of
int and not a class type.  Even so, operation D is still applied last in
the case that doesn't compile (due to the parentheses) so I'm not sure
why you think it's backwards.

Graeme

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 16 Aug 2004 16:58:50 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Sun, 15 Aug 2004 20:33:29 GMT, thp@cs.ucr.edu wrote:
:
:> John Potter <jpotter@falcon.lhup.edu> wrote:
:
:> A good point.  That sentence reads:
:
:>    The requirements of this paragraph shall be met for each allowable
:>    ordering of the subexpressions of a full expression; otherwise
:>    the behavior is undefined.
:
:> Technically there are four allowable orderings of the subexpressions
:> of this expression and they are all equivalent with respect to the
:> matter under discussion, so let's consider just one:
:
:>      0
:>      a
:>      a[0]
:>      a[0]++
:>      a
:>      a[a[0]++]
:
:> At this point the object is being read while it is undergoing
:> modification, but the behavior appears to be defined if the new value
:> is returned.
:
: An interesting deviation from the usual interpretation.  Since we are
: talking about sequence points, the usual question is when the store
: takes place.  Since it is valid to do the store after the second
: access and that is UB, the implementation may generate any code it
: likes for that expression.  You are defining UB based on the code which
: happens to be generated, but the usual is to define it based on the
: worst code which could be generated.

But the actual words refer to the worst allowable ordering, not the
worst sequence of nondeterministic events that could occur.  Also,
there is such a thing as behavior that is undefined by omission.  But
in this case the behavior is explicitly defined in one of the
non-deterministic possibilities.

[...]
:> Obviously, that's not the intent of 5p4.
:
: The intent is to allow the store at any time.  The form of the
: expression determines UB.
:
:> IMHO that particular defect
:> could be fixed by the following revision to 5p4:
:
:>    ... Furthermore, the object shall be accessed only to ...
:> becomes
:>    ... Furthermore, the object shall be accessed only to ...
:
: ???

Oops!  That should have read:
    ... Furthermore, the prior value shall be accessed only to ...
becomes
    ... Furthermore, the object shall be accessed only to ...

Tom Payne



































---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Mon, 16 Aug 2004 19:20:44 GMT
Raw View
In article <41209f62@andromeda.datanet.hu>, Balog Pal <pasa@lib.hu>
writes
><thp@cs.ucr.edu> wrote in message news:cfou1n$m0a$1@glue.ucr.edu...
>
>> What evidence do you have that invoking undefined behavior is a problem of
>> ignorance and/or ignorant people.  Consider the fact that since the
>> ARM, every time a C++ luminary wrote i=++j, he/she invoked undefined
>> behavior.
>
>Come again?  As I read the rules i = ++j has well defined behavior. Provided
>i and j are distinct objects.

Absolutely true in C but in C++ ++j returns an lvalue which means that
you now get an lvalue to rvalue conversion in order to make the
assignment to i. Which technically means that j is accessed to obtain a
value other than for the purposes of evaluating the value that is
written to it. According to a strict interpretation of the rules,
without any intervening sequence point that is UB. I would be amazed if
any compiler actually does anything dubious but we are being language
lawyers here.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Mon, 16 Aug 2004 19:21:15 GMT
Raw View
jpotter@falcon.lhup.edu (John Potter) writes:

> On Mon, 16 Aug 2004 06:41:29 GMT, dave@boost-consulting.com (David
> Abrahams) wrote:
>
>> jpotter@falcon.lhup.edu (John Potter) writes:
>
>> >> > On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>> >> >>(  &  ++  x[0]  )  [0]
>> >> >>   A   B    C       D
>
>> > Operation D ([]) is applied to the result of operation A (&) which is
>
>> I'm pretty sure that's backwards.  This compiles:
>
>>   struct X
>>   {
>>     X operator++() const;
>>     X operator[](int) const;
>>     int operator&() const;
>>   } x;
>
> In this thread, x is an array.  That struct is meaningless.

Isn't evaluation order and associativity the same regardless of the
type of x?  It's the same parse tree whether x is an array or a
struct.

Oh, what I was missing was that you said operation D, not operation
C.  Nevermind! </relurk>

--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jhyslop@ieee.org (Jim Hyslop)
Date: Tue, 17 Aug 2004 03:43:14 GMT
Raw View
John Potter wrote:

> On Fri, 13 Aug 2004 13:54:27 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>>Parentheses do not
>>introduce a sequence point (maybe they should?).
>
>
> I don't think they should.  It would make (a*b)+c*d different from
> a*b+c*d.
How so? If a, b, c and d are all built-in types, I don't see any side
effects that would be written out early. If there's an 'operator *()'
involved which produces side effects, then the compiler would have to
evaluate a*b first anyway.

What have I missed?

--
Jim



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 17 Aug 2004 16:22:17 GMT
Raw View
Jim Hyslop <jhyslop@ieee.org> wrote:
: Bob Hairgrove wrote:
:> On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
:>>(  &  ++  x[0]  )  [0]
:>>   A   B    C       D
:> IIUC, the parentheses (having highest precedence of all) will preclude
:> D being executed before A, B, or C.
: No, because the actual incrementing is a side effect, and side effects
: can occur at any time between sequence points.

IIUC, the subscripting operator has unspecified order of execution, so
it is up to the implementation to decide whether evaluate D or the
parenthesized expression first.

: Parentheses do not introduce a sequence point (maybe they should?).

IMHO we should put a sequence point immediately after each modifying
experession, i.e., expressions rooted and an assignment, increment or
decrement operator.

: A valid sequence of machine code could be:
: - Load the current value of x[0] into a register (C)
: - increment the register (B)
: - load the current value of x[0] into a different register (A and D)
: - write the value of the first register to x[0] (finish off B)

Right.  But I'd reverse the second and third steps, in which case the
second load can be replaced by a simple copy.

The point here is that read operations that are ancestors of write
operations can obtain the new value of the object written to with out
actually reading --- the new value can simply be kept in a register.

The basic principle is that a given write operation does not interfer
with a given read operations if and only if one of them is an ancestor
of the other or they are separated by a sequence point.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Tue, 17 Aug 2004 16:23:17 GMT
Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:OpNMEIB6QPIBFwNS@robinton.demon.co.uk...

> >Come again?  As I read the rules i = ++j has well defined behavior.
Provided
> >i and j are distinct objects.
>
> Absolutely true in C but in C++ ++j returns an lvalue which means that
> you now get an lvalue to rvalue conversion in order to make the
> assignment to i.

I finally located DR#222 applying to the issue.

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#222

I see it's pretty old, and discusses most of the points written here (and I
see also in other currently runnoing threads too).

It's kept in 'drafting' status,what IUC means there's a consensus on how
things are supposed to work yet no-one yet presented a good set of words
describing it.

However by the end I see  the solution sidestepping the special issues just
adding a seq point, and two meetings seeing that as the right soulution.

I wonder why then it didn't get confirmed and made it into TC1.  And what
shall happen to move the issue further, out of the limbo?

- ---------
My own thinking on the problem got the same results I read at the cited
page.  I think it is possible to find words to make lvalue to rvalue
conversion involved here to have special and defined behavior not
conflicting 5.4. What is close to two-face semantics. But I don;t think it
worth it, the extra seqence point is way more elegant, and easy.  Also I
fail to see any way the implementation could do the right thing without
having one seq point at he location inderted on its own accord.   So the
change would just fixed the existing practice, and relieve everyone from
further debate.

Two and a half years of looking for counterexamples (hope no more notes
implies none found) isn't enough to fix the thing?

Paul



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 17 Aug 2004 18:31:25 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
[...]
: I finally located DR#222 applying to the issue.
:
: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#222
[...]
: My own thinking on the problem got the same results I read at the cited
: page.  I think it is possible to find words to make lvalue to rvalue
: conversion involved here to have special and defined behavior not
: conflicting 5.4. What is close to two-face semantics. But I don;t think it
: worth it, the extra seqence point is way more elegant, and easy.  Also I
: fail to see any way the implementation could do the right thing without
: having one seq point at he location inderted on its own accord.   So the
: change would just fixed the existing practice, and relieve everyone from
: further debate.

Unfortunately, there myriad other problems associated with unspecified
order of evaluation and with omitted sequence points.  They'd all be
solved nicely if there were a sequence point immediately after each
modifying experession and the order of evaluation were specified.
There is, however, the matter of the performance tradeoff, and I'm
having difficulty getting real empirical information on that.

Tom Payne

















---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Tue, 17 Aug 2004 22:59:28 GMT
Raw View
On Mon, 16 Aug 2004 16:58:50 GMT, thp@cs.ucr.edu wrote:

> John Potter <jpotter@falcon.lhup.edu> wrote:

> : On Sun, 15 Aug 2004 20:33:29 GMT, thp@cs.ucr.edu wrote:

> :> Technically there are four allowable orderings of the subexpressions
> :> of this expression and they are all equivalent with respect to the
> :> matter under discussion, so let's consider just one:

> :>      0
> :>      a
> :>      a[0]
> :>      a[0]++

I think the problem is in considering this subexpression as an atomic
operation.  It is not and the store may be delayed until the next
sequence point.

> :>      a
> :>      a[a[0]++]

> :> At this point the object is being read while it is undergoing
> :> modification, but the behavior appears to be defined if the new value
> :> is returned.

> : An interesting deviation from the usual interpretation.  Since we are
> : talking about sequence points, the usual question is when the store
> : takes place.  Since it is valid to do the store after the second
> : access and that is UB, the implementation may generate any code it
> : likes for that expression.  You are defining UB based on the code which
> : happens to be generated, but the usual is to define it based on the
> : worst code which could be generated.

> But the actual words refer to the worst allowable ordering, not the
> worst sequence of nondeterministic events that could occur.

Very deterministic code for a single sequential processor is allowed.

   mov r1,a+0
   mov r1,[r1]
   inc a+0

> Also,
> there is such a thing as behavior that is undefined by omission.  But
> in this case the behavior is explicitly defined in one of the
> non-deterministic possibilities.

My read is that if allowed generated code (read delayed store) would
cause access of the old value, the expression has UB.  We will need to
let someone who knows the intent tell us.

> Oops!  That should have read:
>     ... Furthermore, the prior value shall be accessed only to ...
> becomes
>     ... Furthermore, the object shall be accessed only to ...

Which would make many more things undefined.

   a = b = c; // accesses modified b
   a = ++ b;  // accesses modified b
   a = *((q = (p = & ++ b) + 1) - 1); // accesses modified b, p, q

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 18 Aug 2004 05:14:36 GMT
Raw View
John Potter <jpotter@falcon.lhup.edu> wrote:
: On Mon, 16 Aug 2004 16:58:50 GMT, thp@cs.ucr.edu wrote:
:
:> John Potter <jpotter@falcon.lhup.edu> wrote:
:
:> : On Sun, 15 Aug 2004 20:33:29 GMT, thp@cs.ucr.edu wrote:
:
:> :> Technically there are four allowable orderings of the subexpressions
:> :> of this expression and they are all equivalent with respect to the
:> :> matter under discussion, so let's consider just one:
:
:> :>      0
:> :>      a
:> :>      a[0]
:> :>      a[0]++
:
: I think the problem is in considering this subexpression as an atomic
: operation.  It is not and the store may be delayed until the next
: sequence point.

The Standard refers to "ordering" which is a discrete notion rather
than "timing", which would be the term that would capture the
continuum of possible points at which one might access an object
undergoing modification.

:> :>      a
:> :>      a[a[0]++]
:
:> :> At this point the object is being read while it is undergoing
:> :> modification, but the behavior appears to be defined if the new value
:> :> is returned.
:
:> : An interesting deviation from the usual interpretation.  Since we are
:> : talking about sequence points, the usual question is when the store
:> : takes place.  Since it is valid to do the store after the second
:> : access and that is UB, the implementation may generate any code it
:> : likes for that expression.  You are defining UB based on the code which
:> : happens to be generated, but the usual is to define it based on the
:> : worst code which could be generated.
:
:> But the actual words refer to the worst allowable ordering, not the
:> worst sequence of nondeterministic events that could occur.
:
: Very deterministic code for a single sequential processor is allowed.
:
:   mov r1,a+0
:   mov r1,[r1]
:   inc a+0

According to some postings a few years ago by Nick MacLaren on
comp.std.c, the model is that in some aggressive architectures one
must wait until its new value stabilizes before accessing a recently
modified object.

:> Also,
:> there is such a thing as behavior that is undefined by omission.  But
:> in this case the behavior is explicitly defined in one of the
:> non-deterministic possibilities.
:
: My read is that if allowed generated code (read delayed store) would
: cause access of the old value, the expression has UB.  We will need to
: let someone who knows the intent tell us.
:
:> Oops!  That should have read:
:>     ... Furthermore, the prior value shall be accessed only to ...
:> becomes
:>     ... Furthermore, the object shall be accessed only to ...
:
: Which would make many more things undefined.
:
:   a = b = c; // accesses modified b

Per issue 222, this expression has undefined behavior when a, b, and c
have built-in types.

:   a = ++ b;  // accesses modified b

Same problem as issue 222.

:   a = *((q = (p = & ++ b) + 1) - 1); // accesses modified b, p, q

Same problem yet again.

Tom Payne








































---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Wed, 18 Aug 2004 05:25:36 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
: <thp@cs.ucr.edu> wrote in message news:cfou1n$m0a$1@glue.ucr.edu...
:
:> What evidence do you have that invoking undefined behavior is a problem of
:> ignorance and/or ignorant people.  Consider the fact that since the
:> ARM, every time a C++ luminary wrote i=++j, he/she invoked undefined
:> behavior.
:
: Come again?  As I read the rules i = ++j has well defined behavior. Provided
: i and j are distinct objects.

I'm assuming that i and j are distinct ints.  When "i=++j" gets
evaluated, j gets incremented by ++, which returns the lvalue of j,
which gets read via lvalue-to-rvalue conversion without the benefit of
an intervening sequence point.  Inadvertent UB!!  And, not the product
of ignorance.

These rules are too complex even for experts.

For another example, note that the C89 and C99 committees inadvertently
assigned undefined behavior to

           a[0] = 0;
        a[a[0]] = 0;  // a[0] get read but not to determine the new value.

Obviously a[0] must be read before the modifying assignment, so there's
no real problem here.

Again, experts didn't fully understand and appreciate the implications
of their own specifications.

Give that both committees have had difficulty with these notions, I
think that accusations of "ignorance" and "incompetence" against
programmers who get them wrong are unwarranted.

Tom Payne

















---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 10 Aug 2004 17:19:03 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
: <thp@cs.ucr.edu> wrote in message news:cf8a82$6so$1@glue.ucr.edu...
:
:> Suppose that x is an array of integers, and conider the expression
:> "(&++x[0])[0]".  AFAIK, it is well formed, but I'm uncertain whether
:> the behavior is defined.  Obviously, the object x[0] gets updated and
:> then gets read by the second subscripting operation without the
:> benefit of an intervening sequence point.
:
: Exactly. Thus you have UB.
:
:> IIRC, the behavior is
:> undefined if the prior value of the object gets accessed (for a
:> purpose other than computing the new value), but it is entirely
:> possible that it will be the new value of the object that gets read.
:
: Why do you think this rest part is relevant?

It seems that 5#4 explicitly attaches undefined behavior to
"(&++x[0])[0]" in the case where it evaluates to the old value of
x[0].  But I suspect that somewhere/somehow the Standard says that
the value of this expression is the new value of x[0] in which case
the expression is defined.

Come to think of it, "i=j=0" presents the same difficulty.  IIUC,
"j=0" evaluates to the lvalue of j, which gets lvalue-to-rvalue
converted without benefit of an intervening sequence point.  Obviously
the only C compatible behavior and the only behavior that doesn't
become undefined by running afoul of 5#4 is that the lvalue-to-rvalue
conversion yields the new rvalue of j (which can be kept in a register
following the assignment so that no real access to j is required).
So, somewhere/somehow the Standard probably say so.  But I've not been
able to find it.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gfpng@paradise.net.nz (Graeme Prentice)
Date: Wed, 11 Aug 2004 21:36:15 GMT
Raw View
On Tue, 10 Aug 2004 17:19:03 GMT, thp@cs.ucr.edu wrote:

>
>It seems that 5#4 explicitly attaches undefined behavior to
>"(&++x[0])[0]" in the case where it evaluates to the old value of
>x[0].  But I suspect that somewhere/somehow the Standard says that
>the value of this expression is the new value of x[0] in which case
>the expression is defined.


No.  The wording in the standard is a little misleading with its use of
the word "prior".   5.4 says "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."

When the std says "prior" - it really means any read of the object.
Since the value isn't guaranteed to actually change in memory until the
next sequence point, a read of the value could produce either the prior
or updated value, so the word prior is pretty much misleading because it
suggests that the coder is reading the object to get at the old value
when she could be reading it to get the new value.  There's an example
in the C standard that makes it clearer  - it states the following
expression produces UB
a[i++] = i;
because it accesses the value of i for reasons other than to determine
the new value of i.



>
>Come to think of it, "i=j=0" presents the same difficulty.  IIUC,
>"j=0" evaluates to the lvalue of j, which gets lvalue-to-rvalue
>converted without benefit of an intervening sequence point.

Correct.

>Obviously
>the only C compatible behavior and the only behavior that doesn't
>become undefined by running afoul of 5#4 is that the lvalue-to-rvalue
>conversion yields the new rvalue of j (which can be kept in a register
>following the assignment so that no real access to j is required).
>So, somewhere/somehow the Standard probably say so.  But I've not been
>able to find it.

No, it doesn't say so.  There's active issue 222 by Andrew Koenig
pointing this out.

<quote Andrew Koenig>
One could argue that as the C++ standard currently stands, the effect of
x = y = 0; is undefined. The reason is that it both fetches and stores
the value of y, and does not fetch the value of y in order to compute
its new value.
<end quote>

The proposed solution is
<quote>
There is a sequence point between assigning the new value to the left
operand and yielding the result of the assignment expression.
<end quote>

Issue 222 has "drafting status" which means there is consensus on this
resolution.

Graeme

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Thu, 12 Aug 2004 04:46:34 GMT
Raw View
Graeme Prentice <gfpng@paradise.net.nz> wrote:
[...]
:>Obviously
:>the only C compatible behavior and the only behavior that doesn't
:>become undefined by running afoul of 5#4 is that the lvalue-to-rvalue
:>conversion yields the new rvalue of j (which can be kept in a register
:>following the assignment so that no real access to j is required).
:>So, somewhere/somehow the Standard probably say so.  But I've not been
:>able to find it.
:
: No, it doesn't say so.  There's active issue 222 by Andrew Koenig
: pointing this out.
:
: <quote Andrew Koenig>
: One could argue that as the C++ standard currently stands, the effect of
: x = y = 0; is undefined. The reason is that it both fetches and stores
: the value of y, and does not fetch the value of y in order to compute
: its new value.
: <end quote>
:
: The proposed solution is
: <quote>
: There is a sequence point between assigning the new value to the left
: operand and yielding the result of the assignment expression.
: <end quote>
:
: Issue 222 has "drafting status" which means there is consensus on this
: resolution.

Thanks.

So, if I understand correctly, issue 222 and its proposed solution
only address the problems with assignment operators, but leaves
unresolved similar problems with prefix++ and prefix--.  It could, of
course, also be decreed that there is also a sequence point
immediately after each prefix++ and prefix-- instruction,

A possible alternative would be to decree that whenever the rvalue of
a modified object is read by an operation (e.g., lvalue-to-rvalue
conversion) that is higher in the syntax tree, the object's new rvalue
is obtained -- the implementation can simply keep the new value in a
register, thus eliminating the need for any real access to the object
to obtain that value.  (I don't see what difference it makes.)

Tom Payne











---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jhyslop@ieee.org (Jim Hyslop)
Date: Thu, 12 Aug 2004 05:31:39 GMT
Raw View
thp@cs.ucr.edu wrote:
> It seems that 5#4 explicitly attaches undefined behavior to
> "(&++x[0])[0]" in the case where it evaluates to the old value of
> x[0].  But I suspect that somewhere/somehow the Standard says that
> the value of this expression is the new value of x[0] in which case
> the expression is defined.
No, I'm afraid not. You're looking at the right section of the standard,
but drawing the wrong conclusion. If we work through this expression one
sub-expression at a time, then the undefined behaviour will stand out.

There are four sub-expressions at work here; from left to right, let's
label them A through D:

(  &  ++  x[0]  )  [0]
    A   B    C       D

The compiler will generate code to:

1) access x[0] (C)
2) Take its address, yielding x again (A)
3) access x[0] again (D)
4) Increment x[0] (B)

Sub-expression B can actually be evaluated as early as step 2 - that's
the "unspecified" part of 5p4.

Now, here's the undefined part - 5p4 requires that "the prior value
shall be accessed only to determine the value to be stored." Oops - step
3 tries to access the prior value a second time to retrieve its value,
not to determine the value to be stored. The rule is violated, therefore
the behaviour is undefined.

> Come to think of it, "i=j=0" presents the same difficulty.
Not at all. Each scalar value is modified exactly once, and is accessed
only to determine the value to be stored. Well-defined. It had better
be, otherwise there's one HELL of a lot of code out there that's broken!

--
Jim




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Bob Hairgrove <invalid@bigfoot.com>
Date: 12 Aug 2004 17:25:04 GMT
Raw View
On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:

[snip]
>There are four sub-expressions at work here; from left to right, let's
>label them A through D:
>
>(  &  ++  x[0]  )  [0]
>    A   B    C       D
>
>The compiler will generate code to:
>
>1) access x[0] (C)
>2) Take its address, yielding x again (A)
>3) access x[0] again (D)
>4) Increment x[0] (B)
>
>Sub-expression B can actually be evaluated as early as step 2 - that's
>the "unspecified" part of 5p4.

IIUC, the parentheses (having highest precedence of all) will preclude
D being executed before A, B, or C.

>Now, here's the undefined part - 5p4 requires that "the prior value
>shall be accessed only to determine the value to be stored." Oops - step
>3 tries to access the prior value a second time to retrieve its value,
>not to determine the value to be stored. The rule is violated, therefore
>the behaviour is undefined.

If the "parentheses rule" is effective, its not UB.


--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 12 Aug 2004 18:51:54 GMT
Raw View
Jim Hyslop wrote:
 > If we work through this expression one sub-expression at a time,
 > then the undefined behaviour will stand out.

As usual, I claim that it's high time to amend C++ to require
a specific order of evaluation for all expressions and get rid
of this stupid morass.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Thu, 12 Aug 2004 18:52:51 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cferi5$1df$2@glue.ucr.edu...
> So, if I understand correctly, issue 222 and its proposed solution
> only address the problems with assignment operators, but leaves
> unresolved similar problems with prefix++ and prefix--.  It could, of
> course, also be decreed that there is also a sequence point
> immediately after each prefix++ and prefix-- instruction,

It could.  It isn't because there's little benefit. And there is cost.

Little benefit: if in your example, or any other you use Int instead of in,
that is just a wrapper to int, the behavior is no longer indefined. 'Cos
overloaded operators are functions and insert the missing seq points.  But
the catch is the defined behavior till has the unspecified part, the
expression can have different results legally. What is hardly acceptable in
a program.

Cost: it may prevent theuse of some assy instructions or optimisations as
now you have more seq points in the old code -- all in places they were not
necessary.

It is interesting to mention that even with fixed param evaluation order
(like it is in java) the results of many instructions modifying items in the
middle would surprise a plenty of programmers.    As we tend to read the
code coupled with precedence and parentheses, and think that will be the
order.  And for op= many would think the right is evaluated before left,
even knowing the rule...

Expressions both modifying and reading the same object in the middle just
shall be avoided.

Paul


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 12 Aug 2004 18:54:29 GMT
Raw View
Bob Hairgrove wrote:
> IIUC, the parentheses (having highest precedence of all) will preclude
> D being executed before A, B, or C.

No, your understanding is incorrect.

That's why this has got to be changed. The number of people who
actually understand seems to be vanishingly small, even among
very experienced people here on this newsgroup.

Parentheses control the association of operands with operators.
They have absolutely nothing to do with when attached pre- or
post-increments are applied.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 12 Aug 2004 22:32:44 GMT
Raw View
In article <1092310795.707281@master.nyc.kbcfp.com>, Hyman Rosen
<hyrosen@mail.com> writes
>Jim Hyslop wrote:
>> If we work through this expression one sub-expression at a time,
>> then the undefined behaviour will stand out.
>
>As usual, I claim that it's high time to amend C++ to require
>a specific order of evaluation for all expressions and get rid
>of this stupid morass.

I provisionally agree. Currently there is a fairly substantial thread on
comp.std.c on this subject.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 13 Aug 2004 02:47:12 GMT
Raw View
Hyman Rosen <hyrosen@mail.com> wrote:
: Jim Hyslop wrote:
: > If we work through this expression one sub-expression at a time,
: > then the undefined behaviour will stand out.
:
: As usual, I claim that it's high time to amend C++ to require
: a specific order of evaluation for all expressions and get rid
: of this stupid morass.

I'm of the opinion that it's time to revisit the decisions to revisit
the performance reasons for introducing the following
pitfalls/loopholes into the language:
  - unspecified order of evaluation for most binary operators
  - 5p4.
I've been asking (to no avail) on comp.std.c for empirical evidence of
the performance benefits of the corresponding features of C99.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 13 Aug 2004 13:54:16 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
: <thp@cs.ucr.edu> wrote in message news:cferi5$1df$2@glue.ucr.edu...
:> So, if I understand correctly, issue 222 and its proposed solution
:> only address the problems with assignment operators, but leaves
:> unresolved similar problems with prefix++ and prefix--.  It could, of
:> course, also be decreed that there is also a sequence point
:> immediately after each prefix++ and prefix-- instruction,
:
: It could.  It isn't because there's little benefit. And there is cost.
:
: Little benefit: if in your example, or any other you use Int instead of in,
: that is just a wrapper to int, the behavior is no longer indefined. 'Cos
: overloaded operators are functions and insert the missing seq points.  But
: the catch is the defined behavior till has the unspecified part, the
: expression can have different results legally. What is hardly acceptable in
: a program.

It sounds like fixing that "catch" would be a big benefit.

: Cost: it may prevent theuse of some assy instructions or optimisations as
: now you have more seq points in the old code -- all in places they were not
: necessary.

What empirical studies do we have showing that this cost is
significant in terms of performance degradation to important
real-world programs?

: It is interesting to mention that even with fixed param evaluation order
: (like it is in java) the results of many instructions modifying items in the
: middle would surprise a plenty of programmers.    As we tend to read the
: code coupled with precedence and parentheses, and think that will be the
: order.  And for op= many would think the right is evaluated before left,
: even knowing the rule...
:
: Expressions both modifying and reading the same object in the middle just
: shall be avoided.

But they do occur often inadvertently as a result of unnoticed
aliasing.  Undefined behavior can be a very harsh penalty for
such a slip.

Tom Payne
























---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jhyslop@ieee.org (Jim Hyslop)
Date: Fri, 13 Aug 2004 13:54:27 GMT
Raw View
Bob Hairgrove wrote:
> On Thu, 12 Aug 2004 05:31:39 GMT, jhyslop@ieee.org (Jim Hyslop) wrote:
>>(  &  ++  x[0]  )  [0]
>>   A   B    C       D
> IIUC, the parentheses (having highest precedence of all) will preclude
> D being executed before A, B, or C.
No, because the actual incrementing is a side effect, and side effects
can occur at any time between sequence points. Parentheses do not
introduce a sequence point (maybe they should?).

A valid sequence of machine code could be:
- Load the current value of x[0] into a register (C)
- increment the register (B)
- load the current value of x[0] into a different register (A and D)
- write the value of the first register to x[0] (finish off B)

--
Jim


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Fri, 13 Aug 2004 13:55:03 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cfh7lv$5ts$7@glue.ucr.edu...

> : As usual, I claim that it's high time to amend C++ to require
> : a specific order of evaluation for all expressions and get rid
> : of this stupid morass.
>
> I'm of the opinion that it's time to revisit the decisions to revisit
> the performance reasons for introducing the following
> pitfalls/loopholes into the language:
>   - unspecified order of evaluation for most binary operators
>   - 5p4.
> I've been asking (to no avail) on comp.std.c for empirical evidence of
> the performance benefits of the corresponding features of C99.

I'd better suggest to take a look at java experience. That language DID
introduce a strict and easy to remember order of argument evaluation, and
the langspec fixes all the interesting cases (eg. how op= works).

Now, did that remove all the confusion in programmers, and do they see
correctly how expressions get evaluated?

Reading forums and newsgroups I don't see it improved too much.  To be more
precise, it works well for simple function calls     foo(arg1, arg2, arg3).
Generally not, for expressions with symbolic operators. Absolutely not for
expresions with operators and parentheses.

Paul


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Fri, 13 Aug 2004 19:10:51 GMT
Raw View
"Balog Pal" <pasa@lib.hu> wrote:
: <thp@cs.ucr.edu> wrote in message news:cfh7lv$5ts$7@glue.ucr.edu...
:
:> : As usual, I claim that it's high time to amend C++ to require
:> : a specific order of evaluation for all expressions and get rid
:> : of this stupid morass.
:>
:> I'm of the opinion that it's time to revisit the decisions to revisit
:> the performance reasons for introducing the following
:> pitfalls/loopholes into the language:
:>   - unspecified order of evaluation for most binary operators
:>   - 5p4.
:> I've been asking (to no avail) on comp.std.c for empirical evidence of
:> the performance benefits of the corresponding features of C99.
:
: I'd better suggest to take a look at java experience. That language DID
: introduce a strict and easy to remember order of argument evaluation, and
: the langspec fixes all the interesting cases (eg. how op= works).
:
: Now, did that remove all the confusion in programmers, and do they see
: correctly how expressions get evaluated?
:
: Reading forums and newsgroups I don't see it improved too much.  To be more
: precise, it works well for simple function calls     foo(arg1, arg2, arg3).
: Generally not, for expressions with symbolic operators. Absolutely not for
: expresions with operators and parentheses.

Unspecified order of evaluation involves a performance vs. risk
tradeoff.  One estimate is that having a specified order of evaluation
would cost about 2% in terms of performance.  On the hand
foo(arg1,arg2,arg3) could give six different results depending on
which of 3! orders of evaluation are applied to the arguments.
Presumably only one of those six results is correct.  So the tradeoff is
  - the wrong result in five out of six cases vs.
  - waiting an additional 2% for the right result.
;-)

Tom Payne




























---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Fri, 13 Aug 2004 19:53:00 GMT
Raw View
On Thu, 12 Aug 2004 18:54:29 GMT, hyrosen@mail.com (Hyman Rosen)
wrote:

>Parentheses control the association of operands with operators.
>They have absolutely nothing to do with when attached pre- or
>post-increments are applied.

Oops ... I think it was Jim Hyslop, not you, who suggested that
sequence points might be introduced after parentheses. But you did
agree that something has to be changed to clear this up ... and it
seems a logical thing to do, since it is probably an easy thing for
the compiler to parse parentheses.

--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Mon, 9 Aug 2004 17:09:05 GMT
Raw View
Suppose that x is an array of integers, and conider the expression
"(&++x[0])[0]".  AFAIK, it is well formed, but I'm uncertain whether
the behavior is defined.  Obviously, the object x[0] gets updated and
then gets read by the second subscripting operation without the
benefit of an intervening sequence point.  IIRC, the behavior is
undefined if the prior value of the object gets accessed (for a
purpose other than computing the new value), but it is entirely
possible that it will be the new value of the object that gets read.

Tom Payne

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rhairgrove@bigfoot.com (Bob Hairgrove)
Date: Mon, 9 Aug 2004 21:24:54 GMT
Raw View
On Mon,  9 Aug 2004 17:09:05 GMT, thp@cs.ucr.edu wrote:

>Suppose that x is an array of integers, and conider the expression
>"(&++x[0])[0]".  AFAIK, it is well formed, but I'm uncertain whether
>the behavior is defined.  Obviously, the object x[0] gets updated and
>then gets read by the second subscripting operation without the
>benefit of an intervening sequence point.  IIRC, the behavior is
>undefined if the prior value of the object gets accessed (for a
>purpose other than computing the new value), but it is entirely
>possible that it will be the new value of the object that gets read.
>

Who in their right mind would write code like this??

And why is it so hard to find anything about operator precedence in
the printed C++ Standard book (publ. by John Wiley & Sons Ltd. in
2003)? I had to dig out my old beginners' C++ books to discover that
"&" (address-of) and "++" have equal operator precedence (or am I
wrong?)

Since "++" and "&" are evaluated right-to-left, I surmise that "++"
comes first (but after [] which has higher precedence). Since the
parentheses force evaluation of these three operators before anything
else, I would assume that the expression is well-defined for
single-threaded programs.

But it sounds like you are worried about another thread reading or
modifying x[0] ... unfortunately, threads and multi-threaded
programming are not yet covered by standard C++ (AFAIK). You might
want to read more about the "volatile" keyword.

--
Bob Hairgrove
NoSpamPlease@Home.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Mon, 9 Aug 2004 23:38:56 GMT
Raw View
In article <dnnfh0l0ocm0p9np65lvp8gk3r55kqf19m@4ax.com>, Bob Hairgrove
<rhairgrove@bigfoot.com> writes
>And why is it so hard to find anything about operator precedence in
>the printed C++ Standard book (publ. by John Wiley & Sons Ltd. in
>2003)? I had to dig out my old beginners' C++ books to discover that
>"&" (address-of) and "++" have equal operator precedence (or am I
>wrong?)

Because precedence is an artefact of the grammar and actually there is
not a strict precedence that can be derived from the grammar (there are
problems with the ternary operator)


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: thp@cs.ucr.edu
Date: Tue, 10 Aug 2004 06:14:38 GMT
Raw View
Bob Hairgrove <rhairgrove@bigfoot.com> wrote:
: On Mon,  9 Aug 2004 17:09:05 GMT, thp@cs.ucr.edu wrote:
:
:>Suppose that x is an array of integers, and conider the expression
:>"(&++x[0])[0]".  AFAIK, it is well formed, but I'm uncertain whether
:>the behavior is defined.  Obviously, the object x[0] gets updated and
:>then gets read by the second subscripting operation without the
:>benefit of an intervening sequence point.  IIRC, the behavior is
:>undefined if the prior value of the object gets accessed (for a
:>purpose other than computing the new value), but it is entirely
:>possible that it will be the new value of the object that gets read.
:>
:
: Who in their right mind would write code like this??
:
: And why is it so hard to find anything about operator precedence in
: the printed C++ Standard book (publ. by John Wiley & Sons Ltd. in
: 2003)? I had to dig out my old beginners' C++ books to discover that
: "&" (address-of) and "++" have equal operator precedence (or am I
: wrong?)
:
: Since "++" and "&" are evaluated right-to-left, I surmise that "++"
: comes first (but after [] which has higher precedence). Since the
: parentheses force evaluation of these three operators before anything
: else, I would assume that the expression is well-defined for
: single-threaded programs.

So far as I can tell, the expression is syntactically correct.  But
per my understanding, if an object is modified and the prior value is
read for any purpose other than computing the new value, then the
behavior is undefined.  So where does that leave "(&++x[0])[0]"?  Does
this expression access the prior value, or the new value?  If it
accesses the old value, then presumably the behavior is undefined.
But what if it accesses the new value?

: But it sounds like you are worried about another thread reading or
: modifying x[0] ... unfortunately, threads and multi-threaded
: programming are not yet covered by standard C++ (AFAIK). You might
: want to read more about the "volatile" keyword.

My concern here has absolutely nothing to do with multithreading.

Tom Payne




























---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Tue, 10 Aug 2004 15:34:38 GMT
Raw View
<thp@cs.ucr.edu> wrote in message news:cf8a82$6so$1@glue.ucr.edu...

> Suppose that x is an array of integers, and conider the expression
> "(&++x[0])[0]".  AFAIK, it is well formed, but I'm uncertain whether
> the behavior is defined.  Obviously, the object x[0] gets updated and
> then gets read by the second subscripting operation without the
> benefit of an intervening sequence point.

Exactly. Thus you have UB.

> IIRC, the behavior is
> undefined if the prior value of the object gets accessed (for a
> purpose other than computing the new value), but it is entirely
> possible that it will be the new value of the object that gets read.

Why do you think this rest part is relevant?  It is merely a manifestation
of UB, where you have a chance that you'll get the original value or the
incremented value instead of a core dump or a nuke explosion.

Looking your other post -- the problem lies in accessing the object,
regardless of speculation whether it has the old/new value.

C++ relieves the implementation of looking deep into aliassing issues and
check every pointer value in an expression whether they happen to access the
same memory area. The implemetation is allowed to think they all go to
distinct locations, and the programmer has the responsbility to separate
modifying a location and its further reading/writing by sequence points.
Failing that you face UB.

Sure a real compiler will just emit code that works well is locations were
distinct, and it will happen to work for the majority of real-life cases.
But a programmer shall better not rely on some observed manifestation of UB.

Paul




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]