Topic: Order of evaluation (was Difference between reference vs. pointer)


Author: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/05/04
Raw View
In article <D7o1Lv.M2D@ucc.su.OZ.AU>,
John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>In article <3nic72$qdv@hustle.rahul.net>,
>Ronald F. Guilmette <rfg@rahul.net> wrote:
>>In article <3n68ef$3il@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>>>In article <D746Gt.DCn@ucc.su.OZ.AU>,
>>>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>>>>...
>>>Can you elaborate on what exactly is buggy about C sequence points? ...
>>
>>Don't worry Jamshid.  This is yet another classic example of John Max
>>Skaller speaking without benefit of the facts (and without having done
>>any research).  Sadly, not only does he often speak from a truly notable
>>ignorance, he also often speaks when he should instead listen.
>
> Thank you Ron, who seems even more in ignorance of
>the facts. Try reading the paper written by Jerry Schwarz,
>or listening to the comments of Tom Plum.

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.

It is the second part that I have contested.  Perhaps there _is_ some
flaw in the C definition of sequence points.  Who knows?  Maybe there
is, and maybe Jerry Schwarz (who is not a member of the C committee)
and Tom Plum (who is) know about this alleged flaw.  Does that imply
that the committee as a whole is aware of this alleged flaw?  I don't
think so.

> Sorry, it is silly of me to attribute knowledge to
>a committee. Only humans have knowledge.

The committee is made up of humans.  If all, or a majority of them knew
about thing X, then it might be appropriate to say that ``the committee
knows about thing X''.  But you were simply wrong to assert that the C
committee knows about this supposed flaw with C sequence points which you
allege exists.  I am a member of the committee and I don't have the
vaguest idea what the hell you are talking about.  Neither do I remember
any discussions of any such alleged flaw at either of the prior two
meetings.

> Ron is not aware of the flaw. Plauger and Plum are.

Correction.  _You_ believe that _Plauger and Plum_ believe that they have
uncovered a flaw in the C definition of sequence points.

That's fine.  As long as the three of you keep this information to your-
selves, you folks are free to believe anything you want.

Once you start making public claims in a newgroup however, the burden of
proof becomes a bit higher.  Now, rather than just making unsubstantiated
claims, or relying on second-hand reports of uninvestigated (and unreported)
claims of other third parties, I would like to see you do some homework
for a change and find out why no report has ever been filed on this alleged
sequence point flaw (in C) with the C committee.

Could it perhaps be because there is no such 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.

Remember, individuals are free to believe whatever they want, but only
the C standardization committee as a whole has the power to say when the
C standard contains a defect, or when it doesn't.  Bill Plauger, Tom Plum,
and Jerry Schwartz are all well noted and respected experts, but no one
has vested any of them with the unilateral power to decide when the standard
is flawed or when it isn't.  Such questions must be reviewed and adjudicated
by the committee as a whole, and we have formal, elaborate, and official
procedures in place for doing just that.

If Plum, Plauger, or Scahwrtz have already submitted an official Defect
Report with the C committee covering this alleged problem with sequence
points, then please cite its number John.

P.S.  It is in fact that case that (since John's original post) Jutta
Degener has noted (on the C committee's official mailing list) that there
appears to be a serious discrepancy between the committee's interm re-
sponse to official Defect Report #087 (Part A) and the committee's interm
response to official Defect Report #117, both of which relate to a subtle
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.
--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- E-mail: rfg@segfault.us.com ----------- Purveyors of Compiler Test ----
---- finger: rfg@rahul.net ----------------- Suites and Bullet-Proof Shoes -





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/04/26
Raw View
In article <3nic72$qdv@hustle.rahul.net>,
Ronald F. Guilmette <rfg@rahul.net> wrote:
>In article <3n68ef$3il@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>>In article <D746Gt.DCn@ucc.su.OZ.AU>,
>>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>>>...
>>Can you elaborate on what exactly is buggy about C sequence points? ...
>
>Don't worry Jamshid.  This is yet another classic example of John Max
>Skaller speaking without benefit of the facts (and without having done
>any research).  Sadly, not only does he often speak from a truly notable
>ignorance, he also often speaks when he should instead listen.

 Thank you Ron, who seems even more in ignorance of
the facts. Try reading the paper written by Jerry Schwarz,
or listening to the comments of Tom Plum.

>Contrary to the statement made by J.M.S, I, as a dues paying member of
>X3J11, can categorically state that his assertion that the C committee
>knows of some fundamental flaw in the C concept of sequence points is
>simply false.

 Sorry, it is silly of me to attribute knowledge to
a committee. Only humans have knowledge. Ron is not aware
of the flaw. Plauger and Plum are. It arises in a few
circumstances and, being known, is not considered serious
enough to warrant a complete rebuilding of the C execution model.
(The flaw is not in the rules in the C Standard, but in the very notion
of sequence points. They simply don't work. They cannot be
"fixed" no matter how many Defect reports are submitted.)

 As a matter of interest the _concept_ of sequence points was
added to C++ due to a motion by Tom Plum, and the ISO C sequence
points in particular were added due to a friendly amendment move by ME.

 I accepted Tom's argument that it was better to
adopt the C sequence point model, which is flawed but
works most of the time, than have no execution model
in the Working Paper at all, or spend a whole lot of time
developing a new model.

 I am not particularly happy with this state of
affairs, as the model Jerry outlined was clearly superior.
However, he did not provide a complete normative text
of an execution model, and the ISO C Standard does,
even if it is flawed.

 A "dirty" summary of the problem is that
the notion doesn't nest -- it isn't recursive.

--
        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: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/04/25
Raw View
In article <3n68ef$3il@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>In article <D746Gt.DCn@ucc.su.OZ.AU>,
>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>>...
>> I confirm you are correct for ISO C. I also note there
>>is a serious BUG in the whole notion of sequence points which
>>leaves open to interpretation a few scenarios. This bug is
>>known to the C committee...

>What's the bug -- the reply I got in comp.std.c clearly stated the
>code results in undefined behavior.  Was their analysis faulty?
>
>Can you elaborate on what exactly is buggy about C sequence points? ...

Don't worry Jamshid.  This is yet another classic example of John Max
Skaller speaking without benefit of the facts (and without having done
any research).  Sadly, not only does he often speak from a truly notable
ignorance, he also often speaks when he should instead listen.

>haven't read comp.std.c much recently but I don't remember ever seeing
>a discussion about holes in the C Standard wrt sequence points.  Has a
>defect report been filed?

A couple of defect reports were filed quite a long time ago which asked
the committee to provide further clarity regarding its intent with respect
to certain sequence point questions (such as the one that began this thread).
These defect reports were answered quite some time ago, although publication
of the answers in officially released records of responses is probably
still pending (just due to bureaucratic time overhead).  Still, it is
easy enough for anyone who wishes to do so to learn what the committee's
current draft responses to these questions are, e.g. simply by asking some
of the knowledgable people who hang out in comp.std.c.

Contrary to the statement made by J.M.S, I, as a dues paying member of
X3J11, can categorically state that his assertion that the C committee
knows of some fundamental flaw in the C concept of sequence points is
simply false.

What distresses me more that this latest example of J.M.S's tendency to
confuse opinion with fact is the general tendency I have seen over time
of many of those involved with the standardization of C++ to display an
abundant ignorance of the actual details of ISO Standard C while simul-
taneously making the claim that C is all messed up, and that (therefore)
the C++ committee should go forth and reinvent many fundamental wheels
from scratch (e.g. sequence points, and the approach to specifying
conformance, just to name two).

--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- E-mail: rfg@segfault.us.com ----------- Purveyors of Compiler Test ----
---- finger: rfg@rahul.net ----------------- Suites and Bullet-Proof Shoes -





Author: jamshid@ses.com (Jamshid Afshar)
Date: 1995/04/20
Raw View
In article <D746Gt.DCn@ucc.su.OZ.AU>,
John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>In article <3m27na$f68@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>>> cout << func (++i, ++i);
>>>
>>>however the result has to be 2+3. Either the left or right [...]
>>
>>Stop right there, John.  Modifying an object twice between two
>>sequence points results in undefined behavior, period.
>
> I confirm you are correct for ISO C. I also note there
>is a serious BUG in the whole notion of sequence points which
>leaves open to interpretation a few scenarios. This bug is
>known to the C committee. A outline of a proposal for a better system
>for C++ got nowhere, so unfortunately we are stuck with the bugged
>ISO C sequence point idea :-( [It works in many cases and is better
>than not having any execution model at all]
>
>>[see comp.std.c reply to "write( write( stdout, ++i ), ++i );"]
>>There is a sequence point at the point a
>>function is called, but not between the evaluation of function
>>arguments.
>
> Yep, thats the bug. Sequence points don't nest.
>Jerry Schwarz invented "actions" which did nest. Actions are
>a much better idea I think.

What's the bug -- the reply I got in comp.std.c clearly stated the
code results in undefined behavior.  Was their analysis faulty?

Can you elaborate on what exactly is buggy about C sequence points?  I
haven't read comp.std.c much recently but I don't remember ever seeing
a discussion about holes in the C Standard wrt sequence points.  Has a
defect report been filed?

It is very disturbing to hear that ANSI/ISO C++ is considering redoing
the large amount of work already completed in one of its base
documents at this late stage.  This is especially disturbing because
the reworking means that all C++ compiler writers will have to rewrite
(or at least thoroughly inspect) their low-level backends or jump
through hoops when compiling to C in order for code that is undefined
under C to be safe (though unspecified) under C++.

>>In any case, the evaluation order of function arguments is
>>unspecified.  Modifying and using an object twice between two sequence
>>points results in undefined behavior.  There is a sequence point at
>>the call to a function after all its arguments have been evaluated.
>>If there exists a possible order of evaluation of function arguments
>>in which the same object will be modified and used between two
>>sequence points, the expression results in undefined behavior.
>
>I think you have mis-stated the condition,
>you mean "not separated by at least one sequence point":
>
> The reason is that in C++ objects have constructors
>and destructors and may have static members.

I don't understand why C++ has special needs when it comes to sequence
points.  Constructors and destructors are just special kinds of
functions.

> Evaluating two function arguments which are constructible
>objects must occur in one of two orders: a then b, or b then a.
>Parallel invocation is NOT permitted. It would break reams
>of code in cases such as those in which a global count
>of an object is maintained.
>For example:
>
> class X { static int x; X() { ++x; } ~X() { --x; } }
> f( X(), X() );

That's just as true for C if a regular function call and global int is
used instead of a constructor and static data member.  Why are
Standard C sequence points inadequate in C++?  Note: I'm not saying
that C allows parallel evaluation of function arguments involving
function calls -- I used to think it did but stuff I've read in
comp.std.c implies that Standard C does not allow it.

Jamshid Afshar
jamshid@ses.com





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/04/15
Raw View
jamshid@ses.com (Jamshid Afshar) writes:

>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>> cout << func (++i, ++i);
>>
>>however the result has to be 2+3. Either the left or right [...]
>
>Stop right there, John.  Modifying an object twice between two
>sequence points results in undefined behavior, period.

Nope, I think you had better eat that period.
Modifying an object twice between two sequence points
results in undefined behaviour _in C_.  But C++ is another matter.

If you think otherwise, please quote chapter and verse -
but remember this is comp.std._c++_, not comp.std.c!
As best I can tell, the C++ draft does not contain
any such prohibition, and nor does the ARM.
In fact the commentary on page 50 of the ARM contains the following example

 int i = 1;
 extern f(int, int);

 void g()
 {
  f(i++,i++);
 }

and specifically states that "Here, f() is called with the arguments
(1,2) or (2,1) or even (1,1) depending on the order of evaluation of
the arguments".

Of course, the C++ draft is not yet a standard, and the committee
may decide to add such a prohibition.  But in C++ as it
currently stands, I think John Skaller is right.

--
Fergus Henderson            | As practiced by computer science, the study of
fjh@cs.mu.oz.au             | programming is an unholy mixture of mathematics,
http://www.cs.mu.oz.au/~fjh | literary criticism, and folklore. - B. A. Sheil





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/04/16
Raw View
In article <3m27na$f68@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>In article <D6HHAM.74H@ucc.su.OZ.AU>,
>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>>In article <3lfb4d$1ki@hermes.synopsys.com>,
>>Joe Buck <jbuck@synopsys.com> wrote:
>>>> int func(int a, int b) { return a+b; }
>>>> int i = 1;
>>>> cout << func(i++,i++);
>>>>
>>>>Its well defined result is 3.
>>>
>>>This is wrong, John.
>>
>> Consider:
>>
>> cout << func (++i, ++i);
>>
>>however the result has to be 2+3. Either the left or right [...]
>
>Stop right there, John.  Modifying an object twice between two
>sequence points results in undefined behavior, period.

 I confirm you are correct for ISO C. I also note there
is a serious BUG in the whole notion of sequence points which
leaves open to interpretation a few scenarios. This bug is
known to the C committee. A outline of a proposal for a better system
for C++ got nowhere, so unfortunately we are stuck with the bugged
ISO C sequence point idea :-( [It works in many cases and is better
than not having any execution model at all]

>See the first
>appended article -- I raised a bit more complicated question in
>comp.std.c a few months ago.  There is a sequence point at the point a
>function is called, but not between the evaluation of function
>arguments.

 Yep, thats the bug. Sequence points don't nest.
Jerry Schwarz invented "actions" which did nest. Actions are
a much better idea I think.

>In any case, the evaluation order of function arguments is
>unspecified.  Modifying and using an object twice between two sequence
>points results in undefined behavior.  There is a sequence point at
>the call to a function after all its arguments have been evaluated.
>If there exists a possible order of evaluation of function arguments
>in which the same object will be modified and used between two
>sequence points, the expression results in undefined behavior.

I think you have mis-stated the condition,
you mean "not separated by at least one sequence point":

 The reason is that in C++ objects have constructors
and destructors and may have static members.

 Evaluating two function arguments which are constructible
objects must occur in one of two orders: a then b, or b then a.
Parallel invocation is NOT permitted. It would break reams
of code in cases such as those in which a global count
of an object is maintained.

For example:

 class X { static int x; X() { ++x; } ~X() { --x; } }
 f( X(), X() );

In this example "x" is modified twice during evaluation of the
function arguments and I feel confident asserting there
is no unspecified or undefined behaviour here at all.
The results are well defined and completely deterministic,
no matter which "X()" is evaluated first.

Merely invoking the constructor introduces sequence points
between them. We don't know which constructor is
on which side of which sequence point, but the sequence
points between the evaluation of the two arguments
are still there.

--
        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: jamshid@ses.com (Jamshid Afshar)
Date: 1995/04/07
Raw View
In article <D6HHAM.74H@ucc.su.OZ.AU>,
John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>In article <3lfb4d$1ki@hermes.synopsys.com>,
>Joe Buck <jbuck@synopsys.com> wrote:
>>> int func(int a, int b) { return a+b; }
>>> int i = 1;
>>> cout << func(i++,i++);
>>>
>>>Its well defined result is 3.
>>
>>This is wrong, John.
>
> Consider:
>
> cout << func (++i, ++i);
>
>however the result has to be 2+3. Either the left or right [...]

Stop right there, John.  Modifying an object twice between two
sequence points results in undefined behavior, period.  See the first
appended article -- I raised a bit more complicated question in
comp.std.c a few months ago.  There is a sequence point at the point a
function is called, but not between the evaluation of function
arguments.

>>There's no rule preventing the compiler from
>>implementing the operations in an order that would yield 2 as a
>>value.  It's not merely that we can process the arguments right
>>to left or left to right; we can also interleave the processing
>>(something that might happen in cases like this to avoid pipeline
>>bubbles, perhaps).
>
> Are you sure? I'm not sure interleaving is permitted.
>That was the whole point of the UK objections.

See the second appended article I saved from comp.std.c.  It's about
interleaving the evaluation of function arguments.  Chris Torek seems
to believe that the standard doesn't rule out such an implementation
but such an implementation would be unreleastic.

In any case, the evaluation order of function arguments is
unspecified.  Modifying and using an object twice between two sequence
points results in undefined behavior.  There is a sequence point at
the call to a function after all its arguments have been evaluated.
If there exists a possible order of evaluation of function arguments
in which the same object will be modified and used between two
sequence points, the expression results in undefined behavior.

 int modify( int& r ) { r = 7; return r; }

 int i = 1;

 int modify_i() { i = 5; return i; }

 int foo( int x, int y );

 int main() {
    foo( i, modify(i) ); // okay but unspecified: foo(1,7) or foo(7,7)
    foo( i++, i );       // undefined: can't modify and use same object
    foo( modify_i(), i ); // not sure
 }

Jamshid Afshar
jamshid@ses.com

------------------------------------------------------------------------------

Newsgroups: comp.lang.c++,comp.std.c
From: msb@sq.sq.com (Mark Brader)
Subject: Re: Order of evaluation (was Re: Ambiguity problem)
Message-ID: <1995Jan15.104554.5185@sq.sq.com>
Organization: SoftQuad Inc., Toronto, Canada
Date: Sun, 15 Jan 95 10:45:54 GMT

Chris Volpe (volpe@ausable.crd.ge.com) writes:
> > > write( write( stdout, ++i ), ++i );
>
> ... There are three sequence points involved here, and they occur
> in this order:
>
>  1) Start of expression
>  2) Just before inner function call
>  3) Just before outer function call
>
> The first occurrence of i++ [%] must occur between points 1 and 2. The second
> occurrence of i++ may either occur between points 1 and 2, or between points 2
> and 3, and it is unspecified which of these occurs. THE CASE IN WHICH
> UNDEFINED BEHAVIOR RESULTS is the former, i.e. when the second (and hence
> both) occurrences of i++ occur between points 1 and 2.
>
> [%] Actually, I mean "the side effect of i++ must occur..."

There are two small errors here.

First, there is a sequence point at the END of a full expression, not at
the start.  We can correct this as follows:

    1) End of the previous full expression if any.  If none, then this
       must be the first expression evaluated in the program, so there
       can't have been any previous side effects; in the discussion
       below, substitute "start of execution" for "sequence point 1".
    ...
    4) End of full expression.

In general there could be additional sequence points in the called
functions, but neither these (if present) nor sequence point 4 are
relevant to the discussion.

Second, Chris's words that I have block-capitalized in the quotation above
should read "The case in which section 6.3/3.3 of the standard specifies
undefined behavior".

If it is unspecified whether or not a situation occurs that causes
undefined behavior, then THIS situation causes undefined behavior;
this rule follows from the explanation of undefined behavior in section
3.16/1.6.  Thus we can ALWAYS conclude that there is undefined behavior
here.  (A particular implementation might, of course, choose to define it.)
--
Mark Brader                  "Could you please continue the petty bickering?
msb@sq.com                    I find it most intriguing."
SoftQuad Inc., Toronto               -- Data ("Haven", ST:TNG, Tracy Torme)

This article is in the public domain.

------------------------------------------------------------------------------

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: jamshid@ses.com (Jamshid Afshar)
Date: 1995/04/07
Raw View
In article <3m27na$f68@giga.bga.com>, Jamshid Afshar <jamshid@ses.com> wrote:
>In article <D6HHAM.74H@ucc.su.OZ.AU>,
>John Max Skaller <maxtal@Physics.usyd.edu.au> wrote:
>> cout << func (++i, ++i);
>>
>>however the result has to be 2+3. Either the left or right [...]
>
>Stop right there, John.  Modifying an object twice between two
>sequence points results in undefined behavior, period.  See [...]

Whoops, scratch that.  I didn't read your other followups in this
thread.  You seem to already know that analogous C code results in
undefined behavior, but the ANSI/ISO C++ committee may be
(gratuitously?) changing this part of the language from ANSI/ISO C,
resulting in code like the above having unspecified, as opposed to
undefined, results.

Jamshid Afshar
jamshid@ses.com