Topic: Sequence points


Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/24
Raw View
In article <D8u1GE.DtB@tigadmin.ml.com> mansionj@gstldn9.merrill
(James Mansion LADS LDN X4923) writes:

|> In article 4f6@giga.bga.com, jamshid@ses.com (Jamshid Afshar) writes:

|> > (A, B) + (C, D);
|> >
|> >There's a sequence point after evaluating A.  There's also a sequence
|> >point after evaluating C.  But, that does NOT mean there's a sequence
|> >point between A and C.  Here's an article from Chris Torek in
|> >comp.std.c I quoted in an earlier article.  Maybe it can shed some
|> >light.
|> >
|> >Apparently Standard C does not forbid a compiler from evaluating the
|> >two calls to inc() in parallel.  I don't know if this is considered to
|> >be a hole in Standard C, but as Chris says such an implementation
|> >would be unmanageable.  But, it would be interesting to know if the
|> >vast majority of all expressions in C and C++ code are technically
|> >undefined by a strict reading of the standards.  Anyone know if this
|> >is true, and if so, if the Standard C committee is planning on fixing
|> >it?
|> >
|> >Jamshid Afshar
|> >jamshid@ses.com
|> >

|> I understand the point that Torek makes, but I disagree with his statement
|> this will have a deleterious effect on many programs.

|> The only ones that will be badly effected are ones which make calls to
|> multiple functions with side effects within an expression.  In my experience,
|> most code which does a lot with side effects uses statements to sequence them.
|> And even to put comments between them, sometimes.

|> I would have thought that while code like this does exist, it is most likely
|> unmaintainable and undefined in other ways too.

In sum, typical C code.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/19
Raw View
In article <3ph9hl$4f6@giga.bga.com> jamshid@ses.com (Jamshid Afshar)
writes:

|> In article <KANZE.95May18112915@slsvhdt.lts.sel.alcatel.de>,
|> James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> wrote:
|> >In article <D8qK5H.HD3@ucc.su.OZ.AU> maxtal@Physics.usyd.edu.au (John
|> >Max Skaller) writes:
|> >> In article <JASON.95May11131923@phydeaux.cygnus.com>,
|> >> Jason Merrill <jason@cygnus.com> wrote:
|> >> >John Max Skaller writes:
|> C or C++ code like:
|>   int inc(int* x) { ++*x; return *x; }
|>   inc(&i) + inc(&i)
|> >> >> is _well defined_ because there IS a sequence point between the
|> >> >> increments.
|> >> >
|> >> >No, there isn't.  There is a sequence point after each of the increments,
|> >> >but neither one is necessarily between the increments.  This example is
|> >> >also undefined.
|> >>
|> >>  Ah. Thats CLEARLY a flaw if what you say is right.
|> >
|> >There is a flaw in what Jason says, and the above is well defined.  It
|> >would not be well defined if you actually accessed i anywhere in the
|> >expression.  (Passing a reference to i does not require an access.)
|> >There is a sequence point (in C, at least) after all of the parameters
|> >of a function are evaluated, but before the function is called.

|> Yes, but no ordering is imposed on those sequence points.

Correct.  But it is not needed.  The important point is that i is not
accessed in the expression, so the fact that there are no sequence
points in the expression (which would impose an order) is not relevant
to this particular case.

Note that

 inc( &i ) + i

would *not* be defined, despite the (in C implicit) sequence point on
returning from the expression.

|> It's
|> analogous to code like:

|>  (A, B) + (C, D);

|> There's a sequence point after evaluating A.  There's also a sequence
|> point after evaluating C.  But, that does NOT mean there's a sequence
|> point between A and C.  Here's an article from Chris Torek in
|> comp.std.c I quoted in an earlier article.  Maybe it can shed some
|> light.

|> Apparently Standard C does not forbid a compiler from evaluating the
|> two calls to inc() in parallel.

Then the C++ standard differs from C in this regard.  See section 1.8.
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: jamshid@ses.com (Jamshid Afshar)
Date: 1995/05/19
Raw View
In article <KANZE.95May18112915@slsvhdt.lts.sel.alcatel.de>,
James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> wrote:
>In article <D8qK5H.HD3@ucc.su.OZ.AU> maxtal@Physics.usyd.edu.au (John
>Max Skaller) writes:
>> In article <JASON.95May11131923@phydeaux.cygnus.com>,
>> Jason Merrill <jason@cygnus.com> wrote:
>> >John Max Skaller writes:
C or C++ code like:
  int inc(int* x) { ++*x; return *x; }
  inc(&i) + inc(&i)
>> >> is _well defined_ because there IS a sequence point between the
>> >> increments.
>> >
>> >No, there isn't.  There is a sequence point after each of the increments,
>> >but neither one is necessarily between the increments.  This example is
>> >also undefined.
>>
>>  Ah. Thats CLEARLY a flaw if what you say is right.
>
>There is a flaw in what Jason says, and the above is well defined.  It
>would not be well defined if you actually accessed i anywhere in the
>expression.  (Passing a reference to i does not require an access.)
>There is a sequence point (in C, at least) after all of the parameters
>of a function are evaluated, but before the function is called.

Yes, but no ordering is imposed on those sequence points.  It's
analogous to code like:

 (A, B) + (C, D);

There's a sequence point after evaluating A.  There's also a sequence
point after evaluating C.  But, that does NOT mean there's a sequence
point between A and C.  Here's an article from Chris Torek in
comp.std.c I quoted in an earlier article.  Maybe it can shed some
light.

Apparently Standard C does not forbid a compiler from evaluating the
two calls to inc() in parallel.  I don't know if this is considered to
be a hole in Standard C, but as Chris says such an implementation
would be unmanageable.  But, it would be interesting to know if the
vast majority of all expressions in C and C++ code are technically
undefined by a strict reading of the standards.  Anyone know if this
is true, and if so, if the Standard C committee is planning on fixing
it?

Jamshid Afshar
jamshid@ses.com

-----------------
From: torek@bsdi.com (Chris Torek)
Subject: Re: Puzzle involving the ?: opperator. HELP!!!
Date: 19 Aug 1994 04:54:14 -0700
Newsgroups: comp.lang.c,comp.lang.c++
Message-ID: <3326h6$5jm@elf.bsdi.com>

[Given:
 int f(void) { puts("f"); return 0; }
 int g(void) { puts("g"); return 1; }
 int h(void) { puts("h"); return 2; }
 int i(void) { puts("i"); return 3; }

 x = (f(), g()) + (h(), i());
]

The variable `x' will definitely be set to 4, because g() returns 1
and i() returns 3 and the expression `(f(), g()) + (h(), i())' adds
the values returned from g() and i().  The order of the four lines
of output, however, is unspecified[%], except that we know that `f'
must print before `g', and `h' must print before `i'.  This gives us
six possible orders of evaluation:

 f, g, h, i [do everything left to right]
 h, i, f, g [do right to left except as forced]
 f, h, g, i [do f and h, then add g+i]
 h, f, i, g [etc]
 f, h, i, g
 h, f, g, i

-----
[%] There was some nonsense about interleaving the statements in f
    and h---on a multiprocessor, we might fork and do them both in
    parallel---which the Standard does not literally prohibit.  Such
    an implementation would prove unmanageable, however, if the
    compiler did not first guarantee that this sort of parallel
    evaluation still *appeared* sequential.  A trivial example
    occurs if we make f and h each print two identical characters
    with putchar(): if the output is not `ffhh' or `hhff', but
    rather is `fhfh' or `hfhf', we could predict that most nontrivial
    programs would behave erratically in this system.
-----





Author: mansionj@gstldn9.merrill (James Mansion LADS LDN X4923)
Date: 1995/05/19
Raw View
In article 4f6@giga.bga.com, jamshid@ses.com (Jamshid Afshar) writes:

> (A, B) + (C, D);
>
>There's a sequence point after evaluating A.  There's also a sequence
>point after evaluating C.  But, that does NOT mean there's a sequence
>point between A and C.  Here's an article from Chris Torek in
>comp.std.c I quoted in an earlier article.  Maybe it can shed some
>light.
>
>Apparently Standard C does not forbid a compiler from evaluating the
>two calls to inc() in parallel.  I don't know if this is considered to
>be a hole in Standard C, but as Chris says such an implementation
>would be unmanageable.  But, it would be interesting to know if the
>vast majority of all expressions in C and C++ code are technically
>undefined by a strict reading of the standards.  Anyone know if this
>is true, and if so, if the Standard C committee is planning on fixing
>it?
>
>Jamshid Afshar
>jamshid@ses.com
>

I understand the point that Torek makes, but I disagree with his statement
this will have a deleterious effect on many programs.

The only ones that will be badly effected are ones which make calls to
multiple functions with side effects within an expression.  In my experience,
most code which does a lot with side effects uses statements to sequence them.
And even to put comments between them, sometimes.

I would have thought that while code like this does exist, it is most likely
unmaintainable and undefined in other ways too.

James







Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/17
Raw View
In article <JASON.95May11131923@phydeaux.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
>>>>>> John Max Skaller <maxtal@Physics.usyd.edu.au> writes:
>
>>  No, my point is exactly the opposite. While the expression
>
>>  ++i + ++i
>
>> is undefined (I previously said unspecified but I withdraw that after
>> finding a rule hidden in Clause 5), the expression
>
>>  int inc(int x&) { ++x; return x; }
>
>>  inc(i) + inc(i)
>
>> is _well defined_ because there IS a sequence point between the
>> increments.
>
>No, there isn't.  There is a sequence point after each of the increments,
>but neither one is necessarily between the increments.  This example is
>also undefined.

 Ah. Thats CLEARLY a flaw if what you say is right.
It would prevent code like

 string(..) + string(..);

which incremented some static variable. I believe there is
meant to be a sequence point at the _start_ of a function
as well. But that isn't the point. Consider:

 int inc(int x&) { g(); ++x; return x; }

Here there's definitely a sequence point on either side of '++x'.
Now, according to your logic there isn't a sequence point between
the two ++x either -- despite there being one on either side.

Sequence points allow register optimisations (like pipelining).
They're not intended to make two function calls like this
undefined. If you cannot _see_ lexically a conflict, there
had better not be one or it wouldn't be safe to call
functions in expressions.

In fact, this might make sense in a more functional language;
but it surely can't in C.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/18
Raw View
In article <D8qK5H.HD3@ucc.su.OZ.AU> maxtal@Physics.usyd.edu.au (John
Max Skaller) writes:

|> In article <JASON.95May11131923@phydeaux.cygnus.com>,
|> Jason Merrill <jason@cygnus.com> wrote:
|> >>>>>> John Max Skaller <maxtal@Physics.usyd.edu.au> writes:
|> >
|> >>  No, my point is exactly the opposite. While the expression
|> >
|> >>  ++i + ++i
|> >
|> >> is undefined (I previously said unspecified but I withdraw that after
|> >> finding a rule hidden in Clause 5), the expression
|> >
|> >>  int inc(int x&) { ++x; return x; }
|> >
|> >>  inc(i) + inc(i)
|> >
|> >> is _well defined_ because there IS a sequence point between the
|> >> increments.
|> >
|> >No, there isn't.  There is a sequence point after each of the increments,
|> >but neither one is necessarily between the increments.  This example is
|> >also undefined.

|>  Ah. Thats CLEARLY a flaw if what you say is right.

There is a flaw in what Jason says, and the above is well defined.  It
would not be well defined if you actually accessed i anywhere in the
expression.  (Passing a reference to i does not require an access.)

There is a sequence point (in C, at least) after all of the parameters
of a function are evaluated, but before the function is called.

Note that this sequence point doesn't buy you anything in the
expression calling the function; the compiler is still authorized to
rearrange this expression.  *All* the sequence point guarantees is
that any side effects *of* *the* *function* *arguments* have taken
place before the function is called.  (This seems to be a common
theme, which constantly reoccurs on comp.std.c.)
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/11
Raw View
In article <3olfvs$bch@engnews2.Eng.Sun.COM>,
Steve Clamage <clamage@Eng.Sun.COM> wrote:
>In article E44@ucc.su.OZ.AU, maxtal@Physics.usyd.edu.au (John Max Skaller) writes:
>>
>>Now consider:
>>
>> (0, ++i) + (0, ++i);
>>
>>is well defined and deterministic because there IS a sequence
>>point between the evaluation of the two  expressions ++i,
>
>I disagree. In order to provide labels, consider the more general example
> (w, x) + (y, z)
>I don't believe it is required to completely evaluate the left or the right
>side of the + before beginning evaluation of the other side. That is, I
>believe it would be valid to compute in the order "w,y,x,z" or "w,y,z,x"
>(among other possibilities), leaving no sequence point between x and z.

 You're right.  Its worse that I thought. I was trying
to give a well defined example.

>>The flaw then is the failure of the sequence point execution
>>model to specify a deterministic result of evaluating
>>an expression which is well defined.
>
>I don't think you have proved your case. If I have understood your argument,
>it rests on claiming that a source-code expression which might be
>well-defined IS well-defined. I don't believe you can support such an
>interpetation. I believe the only interpretation of the standard is that
>if an expession might be ill-defined, it IS ill-defined.

 No, my point is exactly the opposite. While the expression

 ++i + ++i

is undefined (I previously said unspecified but I withdraw that after
finding a rule hidden in Clause 5), the expression

 int inc(int x&) { ++x; return x; }

 inc(i) + inc(i)

is _well defined_ because there IS a sequence point between the
increments. But that sequence point is hidden inside the
function body.

So my point is that some expressions have unspecified results
depending on ordering, such as

 int &inc(int &x) {++x; return x; }
 inc(i) = inc(i);

whereas the matching

 ++i = ++i;

is undefined. I find that inconsistent: the well definedness
does not depend on order independence, as it should, but on
notation.

Put another way, sequence points violate the notion
of substitutability.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/05/11
Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
: In article <D89DxC.8qK@online.tmx.com.au>,
: Tony Cook <tony@online.tmx.com.au> wrote:
: >John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
: >: Now consider the following code:
: >
: >:  int i = 0;
: >:  int *f() { return &i; }
: >:  ++ *f() +  ++ *f();
: >
: >: Here, there IS a sequence point in between the first
: >: and second increment of i. Although the order of
: >: evaluation of the arguments of "+" are unspecified
: >: there are only two possible orderings, one must be
: >: chosen, they happen to be equivalent, and the result
: >: is a completely deterministic well defined C program (fragment).
: >: Agree?
: >
: >What about possible orderings on when * occurs:
: > int *t1, *t2;
: > t1 = f(); t2 = f(); ++*t1 + ++*t2;

:  You seem to be right, I didn't think of that :-)

:  In this case, in C the results are undefined and in C++
: they're the same as before (namely 1 + 2 = 3). (Again AFAIK)

I'm not too sure of that - I don't think there's a sequence point
between the two increments, so possibly:

 int *t1, *t2;
 t1 = f();
 t2 = f();
 ++*t1;
 ++*t2;
 result = *t1 + *t2;
?
--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/05/11
Raw View
>>>>> John Max Skaller <maxtal@Physics.usyd.edu.au> writes:

>  No, my point is exactly the opposite. While the expression

>  ++i + ++i

> is undefined (I previously said unspecified but I withdraw that after
> finding a rule hidden in Clause 5), the expression

>  int inc(int x&) { ++x; return x; }

>  inc(i) + inc(i)

> is _well defined_ because there IS a sequence point between the
> increments.

No, there isn't.  There is a sequence point after each of the increments,
but neither one is necessarily between the increments.  This example is
also undefined.

Jason





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/10
Raw View
In article <D89DxC.8qK@online.tmx.com.au>,
Tony Cook <tony@online.tmx.com.au> wrote:
>John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
>: Now consider the following code:
>
>:  int i = 0;
>:  int *f() { return &i; }
>:  ++ *f() +  ++ *f();
>
>: Here, there IS a sequence point in between the first
>: and second increment of i. Although the order of
>: evaluation of the arguments of "+" are unspecified
>: there are only two possible orderings, one must be
>: chosen, they happen to be equivalent, and the result
>: is a completely deterministic well defined C program (fragment).
>: Agree?
>
>What about possible orderings on when * occurs:
> int *t1, *t2;
> t1 = f(); t2 = f(); ++*t1 + ++*t2;

 You seem to be right, I didn't think of that :-)

 In this case, in C the results are undefined and in C++
they're the same as before (namely 1 + 2 = 3). (Again AFAIK)

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/06
Raw View
In article <3oa63j$gvv@hustle.rahul.net>,
Ronald F. Guilmette <rfg@rahul.net> wrote:
>
>John, you made two very specific assertions; i.e. (a) that there is a flaw
>in the definition of sequence points in C, and that ``the C committee''
>knows about this flaw.

>All I'm asking is that (for once) you present the facts, the whole facts,
>and nothing but the facts, rather than just repeating things you heard
>over coffee.

 OK. I withdraw any claim the C committe knows about
the purported flaw.

>point regarding sequence points, however I doubt that this relates in any
>way whatsoever to this alleged ``nesting'' problem that John keeps rambling
>on about.  In any case it is impossible for me to know, because I still
>haven't the faintest idea what he's talking about.

 Then let me explain. First, the ISO C Standard says:

 5.1.2.3 Program Execution ...

 "At certain points in the execution sequence called
 sequence points all side effects of previous evaluations
 shall be complete and no side effects of subsequent
 evaluations shall have taken place."

Second, the sequence points are listed in Annex C --while
not normative I'll assume if you don't mind this Annex
is in fact a faithful description of where the sequence
points are to be found. These are:

 1) After [all] the arguments to a function have been
 evaluated

 2) After LHS of && or || or comma operator or ?

 3) After a full expression is evaluated

Third 6.3 provides the normative rule:

 "Between the previous and next sequence point an
 object shall have its store 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"

So for example (I hope you agree)  in the code

 int i=0;
 ++i + ++i;

there is NO sequence point until after the full expression would
be evaluated. But the "object" is modified twice between the
previous sequence point (whatever that was) and the one
ending the expression evaluation -- so the behaviour is
undefined (in C, in C++ it is merely unspecified).

Agree with the example?

Now consider the following code:

 int i = 0;
 int *f() { return &i; }
 ++ *f() +  ++ *f();

Here, there IS a sequence point in between the first
and second increment of i. Although the order of
evaluation of the arguments of "+" are unspecified
there are only two possible orderings, one must be
chosen, they happen to be equivalent, and the result
is a completely deterministic well defined C program (fragment).
Agree?

Now consider:

 (0, ++i) + (0, ++i);

is well defined and deterministic because there IS a sequence
point between the evaluation of the two  expressions ++i,
and, even though the ordering is not specified, there are only
two possible orderings which compute the same answer and have
the same overall side effects.

Now consider:

 (0, ++i) + ++i;

It is unspecified whether the behaviour is well defined or not!

You can see, if the RHS is evaluated first, then the LHS, there is
a sequence point BETWEEN the two ++i evaluations and so the
results are well defined. On the other hand if the LHS is evaluated
first, there is no sequence point after the evaluation of
the LHS ++i expression and therefore none between it and the evaluation
of the RHS - so behaviour is undefined.

I guess the correct interpretation is that behaviour is undefined.

It gets worse with conditionals, where the possible
flows of control bifurcate depending on the value of the LHS
of the expressions a||b, a&&b or a? b1: b2.

The problem here becomes that whether or not the expression
is well defined may depend on the value of the LHS of
the conditional. Which may depend on side effects.

For example:

 ( i ? b: i++) + (i ? b i++);

If i==0, whichever of the two subexressions is evaluated first
evaluates to 0 and i is incremented,  there's no sequence point
prior to accessing the second conditional i, so the behaviour
is undefined. But it is well defined (the answer is "b")
if I rewrite it:

 ( (0||i) ? b: i++) + ( (0||i) ? b: i++);

because a sequence point is _injected_ before the plain "i"
by the || operator. This is also true if I write:

 ( i ? b: (i++,i-1)) + (i ? b : (i++, i-1));

A nasty case is:

 int i = 0;
 x[i] = x[i++];

which may mean:

 x[0] = x[0]; // ERROR: "Prior value" of i used (LHS first)
 x[1] = x[0]; // OK, subsequent value of i used (RHS first)

so I think this another case of "it is unspecified is the result
is well defined or undefined" :-) Note as usual

 x[i] = (0,x[i++]);

is well defined but still has unspecified (non-deterministic)
results. In this case if the LHS is evaluated first, a sequence
point is injected before the RHS i++ is evaluated, so the
"prior value" clause does not apply. If the RHS is evaluated
first, only the value _after_ i is modified is used evaluating
the LHS so no rules are broken. It is clear that the
RHS MUST store the value into i immediately before the
LHS is evaluated -- DESPITE the fact there is no
intervening sequence point. So while

 i = ++i + 1; // is undefined, see ISO C Standard note (34)

we have

 x[i] = x[++i] +1; // undefined (see above)
 x[i] = x[0,i++]+1; // well defined!  Results indeterminate

The flaw then is the failure of the sequence point execution
model to specify a deterministic result of evaluating
an expression which is well defined.

This is desirable and can be achieved with a model based on
"actions". Actions are composed of other actions which
are either performed sequentially or in unspecified order
(in parallel).

One can then say that behaviour is undefined if two actions
might overlap, and if the one modifies some object, then
the other may not access or modify the same object.

If for example in the code:

 a + b

a modifies i and b access it, then the behaviour is undefined
because addition is composed of two actions -- evaluation
of the arguments. This formulation support _genuine_
parallelism and interleaved processing.

Alternatively one can simply say the results are well
defined but unspecified. _Some_ ordering must be used.
This formulation is far less
optimial but it does allow more code to operate with risk
that your hard disk will be scrubbed.

AFAIK, in C++ this approach is taken -- in C++ there
is no undefined behaviour associated with side effects
and order of evaluation. The results are merely unspecified --
a change from ISO C.

[The "action" model was discussed by Jerry Shwarz]

A slightly more sophisticated model could handle
BOTH unspecified order as well as parallel evaluations.

In any case in C++ sequence points are "good enough".
--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/05/08
Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
: Now consider the following code:

:  int i = 0;
:  int *f() { return &i; }
:  ++ *f() +  ++ *f();

: Here, there IS a sequence point in between the first
: and second increment of i. Although the order of
: evaluation of the arguments of "+" are unspecified
: there are only two possible orderings, one must be
: chosen, they happen to be equivalent, and the result
: is a completely deterministic well defined C program (fragment).
: Agree?

What about possible orderings on when * occurs:
 int *t1, *t2;
 t1 = f(); t2 = f(); ++*t1 + ++*t2;
?

--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/08
Raw View
In article E44@ucc.su.OZ.AU, maxtal@Physics.usyd.edu.au (John Max Skaller) writes:
>
>Now consider:
>
> (0, ++i) + (0, ++i);
>
>is well defined and deterministic because there IS a sequence
>point between the evaluation of the two  expressions ++i,

I disagree. In order to provide labels, consider the more general example
 (w, x) + (y, z)
I don't believe it is required to completely evaluate the left or the right
side of the + before beginning evaluation of the other side. That is, I
believe it would be valid to compute in the order "w,y,x,z" or "w,y,z,x"
(among other possibilities), leaving no sequence point between x and z.
Depending on how the compiler implements the increments, you could get
different results for your example above.


>Now consider:
>
> (0, ++i) + ++i;
>
>It is unspecified whether the behaviour is well defined or not!

Which means that the effect of this code is not well-defined.


>It gets worse with conditionals, where the possible
>flows of control bifurcate depending on the value of the LHS
>of the expressions a||b, a&&b or a? b1: b2.
>
>The problem here becomes that whether or not the expression
>is well defined may depend on the value of the LHS of
>the conditional. Which may depend on side effects.
>
>For example:
>
> ( i ? b: i++) + (i ? b i++);

You can analyze the code to death, but I think the short answer is that
if the meaning of the code is sometimes ill-defined, you must either
prove that those circumstances never arise, or conclude that the code
is ill-defined.

For example, "a/(b-c)" is ill-defined unless we know that the magnitude
of (b-c) is such that the division doesn't overflow. You have the same
situation with "a+b": Can the sum overflow?

>A nasty case is:
>
> int i = 0;
> x[i] = x[i++];

This case is already covered by the C standard. The value of 'i' is
accessed other than to determine the value to be incremented, with no
intervening sequence point. The results (in C) are undefined.

> Note as usual
>
> x[i] = (0,x[i++]);
>
>is well defined

I disagree. The sequence point need not intervene, thus the results are
not well-defined.

>
>The flaw then is the failure of the sequence point execution
>model to specify a deterministic result of evaluating
>an expression which is well defined.

I don't think you have proved your case. If I have understood your argument,
it rests on claiming that a source-code expression which might be
well-defined IS well-defined. I don't believe you can support such an
interpetation. I believe the only interpretation of the standard is that
if an expession might be ill-defined, it IS ill-defined.

By "ill-defined", I mean depending on a particular result that the
standard does not require. I don't care to argue here about whether it is
unspecified or undefined.

---
Steve Clamage, stephen.clamage@eng.sun.com