Topic: *p++ *= 2 /* Bug in Symantec C++ 7.0.3 */


Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Wed, 27 Jul 1994 14:16:47 GMT
Raw View
In article <1994Jul26.190810.27702@sal.wisc.edu>, alan@sal.wisc.edu (Alan Watson) writes:

>>They do result in undefined behaviour, but not because the order of
>>evaluation is unspecified (this is irrelevant here). They're breaking
>>one of the following "shall"s from 6.3:
>>
>>#  Between the previous and the next sequence point an object shall
>>#  have its stored value modified at most once by the evaluation of
>>#  an expression.  Furthermore, the prior value shall be accessed
>>#  only to determine the value to be stored.
>
>
>On consideration, I think the status of the code is a more complex
>question.
>
>Neither statement violates the first sentence of that paragraph as p is
>modified exactly once and *p, whatever that happens to be, is modified
>exactly once; this is not `i = i++'.
>
>If the implementation applies the side-effect in the expression `*p++'
>after evaluating the expression `*p', then it is accessing the PRIOR
>value of p other than to determine the value to be stored and the
>behaviour is undefined.  However, if it applies the side-effect in
>`*p++' before evaluating `*p', then when `*p' is evaluated it is not
>the PRIOR value of p that is being accessed, so the second sentence
>does not apply.
>
>The code invokes unspecified behaviour, but one of the consequences of
>that unspecified behaviour is undefined behaviour.

Yeah. The poor wording in the Standard is the reason for this unnecessarily
complicated analysis. I never liked that "accesses the prior value" phrase.

--

Chris Volpe    Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D   Fax:   (518) 387-6560
PO Box 8, Schenectady, NY 12301  Email: volpecr@crd.ge.com





Author: rang@winternet.com (Anton Rang)
Date: 26 Jul 1994 02:51:00 GMT
Raw View
In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>
> [ we're discussing the statement '*p++ *= 2' ]
>
> What is not defined is the order of the ++. For instance, this
> expression can equally be treated as:
>
> (*p) = *p++ * 2;
>
> or
>
> (*p++) = *p * 2;

  Can somebody more familiar with the standards than I am clarify
whether this should actually be treated as equivalent to the sequence:

 temp = p;
 *temp *= 2;
 p++;

or whether it's valid for the compiler to produce a variant more like

 temp = *p;
 p++;
 *p = temp * 2;

(where p was incremented before the result was assigned)?
--
Anton Rang (rang@winternet.com)




Author: alan@sal.wisc.edu (Alan Watson)
Date: Tue, 26 Jul 1994 05:28:38 GMT
Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>
rang@winternet.com (Anton Rang) wrote:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:
>>
>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;
>
>  Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
>
> temp = p;
> *temp *= 2;
> p++;
>
>or whether it's valid for the compiler to produce a variant more like
>
> temp = *p;
> p++;
> *p = temp * 2;
>
>(where p was incremented before the result was assigned)?

The ++ operator increments a variable and yields a value; in the case
of ++p it is the value of the variable after the increment and in the
case of p++ it is the value of the variable prior to the increment.
So, in `*p++ *= 2;' the address that is dereferenced first to load and
then store a value is the same -- it is the original value of p.  The
statement is equivalent to

> temp = p;
> *temp *= 2;
> p++;

It is not equivalent to

> temp = *p;
> p++;
> *p = temp * 2;

The two statements:

   *p++ = *p * 2;
   *p = *p++ * 2;

result in undefined behaviour as they depend on an unspecified order of
evaluation; neither of them are equivalent to `*p++ *= 2;'.

--
Alan Watson                        | B can be thought of as C without types;
alan@oldp.astro.wisc.edu           | more accurately, it is BCPL squeezed into
Department of Astronomy            | 8K bytes of memory and filtered through
University of Wisconsin -- Madison | Thompson's brain. -- Dennis Ritchie




Author: blm@chinook.halcyon.com (Brian L. Matthews)
Date: 26 Jul 1994 07:29:43 GMT
Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>,
Anton Rang <rang@winternet.com> wrote:
|> [ we're discussing the statement '*p++ *= 2' ]
|  Can somebody more familiar with the standards than I am clarify
|whether this should actually be treated as equivalent to the sequence:
| temp = p;
| *temp *= 2;
| p++;

l op= e

is equivalent to

l = l op e

with any side-effects of l evaluated once.

Now,

*l++ = e

is equivalent to

*l = e
l++

So,

*l++ op= e

is equivalent to

*l++ = *l++ op e

with the side-effects of *l++ happening only once, which is equivalent
to

*l = *l op e
l++

which is basically what Anton suggests, except with post-increment
the temp variable isn't necessary.  With pre-increment, it is:

*++l

is equivalent to

temp = l
l++
*temp

Anyway, to drag this all back to the original example, the following:

short *p = array;

*p++ *= 2;
*p++ *= 2;

should double the first two elements of array and leave p pointing to
the third element (having been incremented twice).  So it is a Symantec
bug, which Symantec has acknowledged.

Brian




Author: baynes@ukpsshp1.serigate.philips.nl (Stephen Baynes)
Date: Tue, 26 Jul 1994 07:07:52 GMT
Raw View
Anton Rang (rang@winternet.com) wrote:
: In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
: >
: > [ we're discussing the statement '*p++ *= 2' ]
: >
: > What is not defined is the order of the ++. For instance, this
: > expression can equally be treated as:
: >
: > (*p) = *p++ * 2;
: >
: > or
: >
: > (*p++) = *p * 2;

:   Can somebody more familiar with the standards than I am clarify
: whether this should actually be treated as equivalent to the sequence:

:  temp = p;
:  *temp *= 2;
:  p++;
That is OK
: or whether it's valid for the compiler to produce a variant more like

:  temp = *p;
:  p++;
:  *p = temp * 2;

: (where p was incremented before the result was assigned)?
I don't think that is. But the following would be OK:
  temp = p;
  p++;
  *temp *= 2;
--
Stephen Baynes                              baynes@mulsoc2.serigate.philips.nl
Philips Semicondutors Ltd
Southampton                                 My views are my own.
United Kingdom




Author: danpop@cernapo.cern.ch (Dan Pop)
Date: Tue, 26 Jul 1994 10:27:50 GMT
Raw View
In <1994Jul26.052838.15652@sal.wisc.edu> alan@sal.wisc.edu (Alan Watson) writes:

>The two statements:
>
>   *p++ = *p * 2;
>   *p = *p++ * 2;
>
>result in undefined behaviour as they depend on an unspecified order of
>evaluation; neither of them are equivalent to `*p++ *= 2;'.

They do result in undefined behaviour, but not because the order of
evaluation is unspecified (this is irrelevant here). They're breaking
one of the following "shall"s from 6.3:

#  Between the previous and the next sequence point an object shall
#  have its stored value modified at most once by the evaluation of
#  an expression.  Furthermore, the prior value shall be accessed
#  only to determine the value to be stored.

Dan
--
Dan Pop
CERN, CN Division
Email: danpop@cernapo.cern.ch
Mail:  CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Tue, 26 Jul 1994 13:41:43 GMT
Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>, rang@winternet.com (Anton Rang) writes:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:
>>
>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;

 or as

 (*p++) = system("rm -rf *");

>
>  Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
[...]
>
>or whether it's valid for the compiler to produce a variant more like
[...]

Between the same pair of sequence points, the object denoted by "p" is
modified (by the ++ operator) and used (as part of the right operand of "=")
in a way not used to compute its new value. The behavior is therefore
undefined.

--

Chris Volpe    Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D   Fax:   (518) 387-6560
PO Box 8, Schenectady, NY 12301  Email: volpecr@crd.ge.com





Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Tue, 26 Jul 1994 16:21:45 GMT
Raw View
In article <CtJvDJ.CGI@crdnns.crd.ge.com>, volpe@bart.crd.ge.com (Christopher R. Volpe) writes:
>In article <RANG.94Jul25215100@icicle.winternet.com>, rang@winternet.com (Anton Rang) writes:
>>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>>
>>> [ we're discussing the statement '*p++ *= 2' ]
>>>
>>> What is not defined is the order of the ++. For instance, this
>>> expression can equally be treated as:
>>>
>>> (*p) = *p++ * 2;
>>>
>>> or
>>>
>>> (*p++) = *p * 2;
>
> or as
>
> (*p++) = system("rm -rf *");

Oops, I didn't read carefully. The original expression is just fine. It is
merely the non-equivalent ones above (that attempt to expand "*=") that
invoke undefined behavior.

--

Chris Volpe    Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D   Fax:   (518) 387-6560
PO Box 8, Schenectady, NY 12301  Email: volpecr@crd.ge.com





Author: alan@sal.wisc.edu (Alan Watson)
Date: Tue, 26 Jul 1994 19:08:10 GMT
Raw View
In article <CtJMEE.1CK@news.cern.ch>
danpop@cernapo.cern.ch (Dan Pop) wrote:
>In <1994Jul26.052838.15652@sal.wisc.edu> alan@sal.wisc.edu (Alan Watson) writes:
>
>>The two statements:
>>
>>   *p++ = *p * 2;
>>   *p = *p++ * 2;
>>
>>result in undefined behaviour as they depend on an unspecified order of
>>evaluation; neither of them are equivalent to `*p++ *= 2;'.
>
>They do result in undefined behaviour, but not because the order of
>evaluation is unspecified (this is irrelevant here). They're breaking
>one of the following "shall"s from 6.3:
>
>#  Between the previous and the next sequence point an object shall
>#  have its stored value modified at most once by the evaluation of
>#  an expression.  Furthermore, the prior value shall be accessed
>#  only to determine the value to be stored.


On consideration, I think the status of the code is a more complex
question.

Neither statement violates the first sentence of that paragraph as p is
modified exactly once and *p, whatever that happens to be, is modified
exactly once; this is not `i = i++'.

If the implementation applies the side-effect in the expression `*p++'
after evaluating the expression `*p', then it is accessing the PRIOR
value of p other than to determine the value to be stored and the
behaviour is undefined.  However, if it applies the side-effect in
`*p++' before evaluating `*p', then when `*p' is evaluated it is not
the PRIOR value of p that is being accessed, so the second sentence
does not apply.

The code invokes unspecified behaviour, but one of the consequences of
that unspecified behaviour is undefined behaviour.

--
Alan Watson                        | Where in the Bible does it say that
alan@oldp.astro.wisc.edu           | i = i++ is a bad idea? -- Alan Morgan
Department of Astronomy            |
University of Wisconsin -- Madison |




Author: jqb@netcom.com (Jim Balter)
Date: Wed, 27 Jul 1994 02:52:42 GMT
Raw View
In article <RANG.94Jul25215100@icicle.winternet.com>,
Anton Rang <rang@winternet.com> wrote:
>In article <310slaINN7tv@symiserver.symantec.com> John T. Micco <johnm@bedford.symantec.com> writes:
>>
>> [ we're discussing the statement '*p++ *= 2' ]
>>
>> What is not defined is the order of the ++. For instance, this
>> expression can equally be treated as:

It is important when discussing such things to do so in terms of the actual
concepts and contents of the Standard.  "the order of the ++" is meaningless,
certainly in terms of the language of the Standard.  "*p++ *= 2" is conforming;
it doesn't matter whether p is incremented before or after *p is accessed
and/or modified; the value of p by which the access and the modification is done
is unambiguously defined by the definition of the postincrement operator as the
value before the increment.

>> (*p) = *p++ * 2;
>>
>> or
>>
>> (*p++) = *p * 2;

Neither of these is conforming, because, while the value of p in p++
is unambiguous, the value of p in "*p" is ambiguous, since the an
evaluation of the expression "p" and the side effect of incrementing p
(via p++) occur between the same sequence points.

>  Can somebody more familiar with the standards than I am clarify
>whether this should actually be treated as equivalent to the sequence:
>
> temp = p;
> *temp *= 2;
> p++;

Yes, that is equivalent.  As is

 temp = p;
 p++;
 *temp *= 2;

(which perhaps is what John Micco was thinking of).

>or whether it's valid for the compiler to produce a variant more like
>
> temp = *p;
> p++;
> *p = temp * 2;

No, that is not equivalent.  It would mean "p" has two different values in
the expression "*p++", one for access and one for modification, which of
course is absurd.
--
<J Q B>