[comp.std.c] More Re: Function Argument Evaluation argument

bhoughto@pima.intel.com (Blair P. Houghton) (03/29/91)

In article <17983@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>But the only reason you were able to produce an order of evaluation that
>resulted in "200 200" is because the program did something it should never
>have done in the first place, which was to modify p twice between sequence
>points.

He's got a definite point, here [1].  Neither of the
expressions in this list of function arguments is a
full-expression [2], and neither contains any of the
operators that define sequence points [3], so the
only sequence-point around is the one before the
function-call [4].  Thus, using p twice in an lvalue
context renders the behavior undefined [5].

[1] ANSI X3.159-1989, sec. 3.3, p. 39, ll. 5-7.
[2] Ibid., Appendix B, p. 189.
[3] Ibid.
[4] Ibid (dangit! no line numbers! <grouse>).
[5] See also p. 39, footnote 34.

Maybe this also answers John Gingerich's question (and if I
still didn't understand it then I really don't understand
it) about "is it undefined?"  I was wrong.  The arguments'
behavior is undefined, so the statement's is undefined, so the
program's is undefined, and the compiler can tune up its
pipes and start tooting "Daaaaaii-seeeee, Daaai-seee, give
me your an-swer true..." [6]

>I would be very interested in seeing a program whose behavior
>was *not* undefined, yet could arbitrarily produce either of two
>drastically different outputs depending solely on the unspecified
>order of evaluation.

Insert a sequence-point:

	char *x = "foo", *y = "bar";

	printf("\t%s %s\n", (p = x)?p:"(nil)", (p = y) );

Now the behavior is defined, since there's a sequence point
after the first assignment to p, but no way to tell
which of the p's is returned after either question mark.

It is certain, however, that the second argument
must return "bar", since the first assignment was
before the sequence point at the `?', and everything else
is after that sequence point and before the function-call
sequence point.

This will print either

	foo bar

or

	bar bar

Depending on the order in which the placing of the first
argument on the stack and the assignment of y to p are
performed.  It seems to me, though, that since I asked
for "p" and not "the result of p only due to the first
argument", then the value should have to wait for the
side-effects (the actual storage is a side-effect
of assignment (sec. 3.3.16, p. 54, ll. 14-16)) of
other argument-expressions before it is placed on the
stack.

I didn't need the obfuscation of the `?:', either.

	f(p,p=y);

faces a similar nonspecificity of the values of the arguments
at the sequence point.

There's no rule against changing a stack value multiple
times between sequence points, either, so the stack could
get the first p, then the compiler could say "oops, p changed
due to an assignment, better fix the first one" and the new
value could be put on the stack.  If a compiler does this,
I'd like to have it.  It probably gets the rest of the standard
right, too.  But I can't count on it, since the standard
moots this interpretation.

				--Blair
				  "[6]  I get it.  '2001: A Space Odyssey'
				   is all about the perils of nonconformance.
				   :-) :-)  Kubrick, what a visionary!"

volpe@camelback.crd.ge.com (Christopher R Volpe) (03/29/91)

In article <3547@inews.intel.com>, bhoughto@pima.intel.com (Blair P.
Houghton) writes:
|>Insert a sequence-point:
|>
|>	char *x = "foo", *y = "bar";
|>
|>	printf("\t%s %s\n", (p = x)?p:"(nil)", (p = y) );
|>
|>Now the behavior is defined, since there's a sequence point
|>after the first assignment to p, but no way to tell
|>which of the p's is returned after either question mark.

I don't think that's necessarily true. The order of evaluation of
arguments to the function call is unspecified, so it could evaluate
(p=y) first and then (p=x)?p:"(nil)", with no sequence point between
the two assignments. It's true that there's a sequence point after
the evaluateion of (p=x) and before the evaluation of either p or "(nil)",
but I don't think that's sufficient.

|>
|>Depending on the order in which the placing of the first
|>argument on the stack and the assignment of y to p are
|>performed.  It seems to me, though, that since I asked
|>for "p" and not "the result of p only due to the first

You asked for the value of p immediately following the sequence point
that follows the evaluation of (p=x).

|>argument", then the value should have to wait for the
|>side-effects (the actual storage is a side-effect
|>of assignment (sec. 3.3.16, p. 54, ll. 14-16)) of
|>other argument-expressions before it is placed on the
|>stack.
|>
|>I didn't need the obfuscation of the `?:', either.
|>
|>	f(p,p=y);

Section 3.3: "Furthermore, the prior value [of an object] shall be accessed
only to determine the value to be stored."  Between sequence points, 
you are modifying p, and referencing p in a way that is not used to determine
the new value of p (i.e. the first argument to f). The behavior of
your example is undefined.

|>				--Blair
|>				  "[6]  I get it.  '2001: A Space Odyssey'
|>				   is all about the perils of nonconformance.
|>				   :-) :-)  Kubrick, what a visionary!"
                                                                        
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

rjohnson@shell.com (Roy Johnson) (04/02/91)

I understand that the comma operator is a sequence point.
If we use the comma operator as a sequence point between evaluations:

   int v=1;
   printf("%d %d\n", (1, v), (1,v++));

This can print
	1 1
or
	2 1
if I understand it right, which I very well may not.

Similarly,

   char *x="foo", *y="bar", *p;
   p=x;
   printf("%s %s\n", (1, (p=y)), (1, p));

can print

	foo bar
or

	bar bar

Do I win?  8^)
--
======= !{sun,psuvax1,bcm,rice,decwrl,cs.utexas.edu}!shell!rjohnson =======
Feel free to correct me, but don't preface your correction with "BZZT!"
Roy Johnson, Shell Development Company

volpe@camelback.crd.ge.com (Christopher R Volpe) (04/02/91)

In article <RJOHNSON.91Apr1142143@olorin.shell.com>, rjohnson@shell.com
(Roy Johnson) writes:
|>I understand that the comma operator is a sequence point.
|>If we use the comma operator as a sequence point between evaluations:
|>
|>   int v=1;
|>   printf("%d %d\n", (1, v), (1,v++));
|>
|>This can print
|>	1 1
|>or
|>	2 1
|>
|>Do I win?  8^)

Hey, that looks pretty good. No matter what the order of evaluation of
the function arguments is, there's always a sequence point separating the
references to v. So the behavior is not undefined, yet order of evaluation
definitely has a drastic effect on the output. 

Anybody see a problem with that?
                              
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

grogers@convex.com (Geoffrey Rogers) (04/02/91)

In article <18140@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>In article <RJOHNSON.91Apr1142143@olorin.shell.com>, rjohnson@shell.com
>(Roy Johnson) writes:
+|>I understand that the comma operator is a sequence point.
+|>If we use the comma operator as a sequence point between evaluations:
+|>
+|>   int v=1;
+|>   printf("%d %d\n", (1, v), (1,v++));
+|>
+|>This can print
+|>	1 1
+|>or
+|>	2 1
+|>
+|>Do I win?  8^)
+
+Hey, that looks pretty good. No matter what the order of evaluation of
+the function arguments is, there's always a sequence point separating the
+references to v. So the behavior is not undefined, yet order of evaluation
+definitely has a drastic effect on the output. 
+
+Anybody see a problem with that?

No. 

In this case the compiler must evaluate 1 before it evaluate v or v++
in the subexpressions '(1,v)' and '(1,v++)'. But the order of
evaluation of these two subexpressions are still undefined.

+------------------------------------+---------------------------------+
| Geoffrey C. Rogers   		     | "Whose brain did you get?"      |
| grogers@convex.com                 | "Abbie Normal!"                 |
| {sun,uunet,uiucdcs}!convex!grogers |                                 |
+------------------------------------+---------------------------------+

gwyn@smoke.brl.mil (Doug Gwyn) (04/03/91)

In article <18140@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>|>   printf("%d %d\n", (1, v), (1,v++));
>Hey, that looks pretty good. No matter what the order of evaluation of
>the function arguments is, there's always a sequence point separating the
>references to v. So the behavior is not undefined, yet order of evaluation
>definitely has a drastic effect on the output. 
>Anybody see a problem with that?

Yes, perhaps the order of evaluation of the subexpressions is still
unspecified even though one might think that there are sequence points
involved.  The question is whether the sequence-point constraints bind
more tightly than the unspecified-order specification or more loosely.
A similar issue arose with regard to the first formal request for
interpretation of X3.159, only in that case the sloppy-order specification
was the one permitted for assignment expressions.  In the case of that
interpretation, X3J11 finally (at the March 1991 meeting) decided that
the 3.3.16.1 license did NOT override the expectation that the function
value had to be "copied" out.  If that is taken as a precedent, then a
consistent interpretation for the above example ought to be that the
sequence point ordering is more important than the argument subexpression
evaluation ordering license.  However, without a formal interpretation
ruling I would hesitate to promise that it "must" be that way.

Certainly, nobody should write code like that!

pds@lemming.webo.dg.com (Paul D. Smith) (04/03/91)

  [ Hopefully I understand what you're saying here; if not please correct
    me... ]

[] On 2 Apr 91 13:24:16 GMT, volpe@camelback.crd.ge.com (Christopher R Volpe) said:

CRV> In article <RJOHNSON.91Apr1142143@olorin.shell.com>, rjohnson@shell.com
CRV> (Roy Johnson) writes:
CRV> |>
CRV> |>   int v=1;
CRV> |>   printf("%d %d\n", (1, v), (1,v++));
CRV> |>
CRV> |>This can print
CRV> |>	1 1
CRV> |>or
CRV> |>	2 1

CRV> Hey, that looks pretty good. No matter what the order of
CRV> evaluation of the function arguments is, there's always a
CRV> sequence point separating the references to v. So the behavior is
CRV> not undefined, yet order of evaluation definitely has a drastic
     ^^^^^^^^^^^^^
CRV> effect on the output.

The behavior *is* indeed undefined in this case:

Reference 1: ANSI X3.159-1989 Section 2.1.2.3, p. 8, lines 33-35:

   "At certain specified 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."

Reference 2: Ibid, Section 3.3.2.2, p. 42, lines 20-21:

   "The order of evaluation of the function designator, the arguments,
        ^^^^^^^^^^^^^^^^^^^
    and subexpressions within the arguments is unspecified, ... "
                                               ^^^^^^^^^^^

So given the following statement:

    printf("%d %d\n", (1, v), (1, v++));
                      ^^^^^^  ^^^^^^^^
                      exp. 1   exp.2

The compiler is free to choose whether to evaluate exp.1 first, or
whether to evaluate exp.2 first.  Once it chooses it must indeed
evaluate the "1" first, before the "v" or "v++".

So it's still undefined whether this prints "1 1" or "2 1".  And
rightly so, IMHO!

                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds@lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Services Development Division  |   "Pretty Damn S..."    |
| Open Network Systems Development       |                         |
 ------------------------------------------------------------------

volpe@camelback.crd.ge.com (Christopher R Volpe) (04/05/91)

In article <PDS.91Apr2203927@lemming.webo.dg.com>,
pds@lemming.webo.dg.com (Paul D. Smith) writes:
|>Reference 2: Ibid, Section 3.3.2.2, p. 42, lines 20-21:
|>
|>   "The order of evaluation of the function designator, the arguments,
|>        ^^^^^^^^^^^^^^^^^^^
|>    and subexpressions within the arguments is unspecified, ... "
|>                                               ^^^^^^^^^^^
|>
|>So given the following statement:
|>
|>    printf("%d %d\n", (1, v), (1, v++));
|>                      ^^^^^^  ^^^^^^^^
|>                      exp. 1   exp.2
|>
|>The compiler is free to choose whether to evaluate exp.1 first, or
|>whether to evaluate exp.2 first.  Once it chooses it must indeed
|>evaluate the "1" first, before the "v" or "v++".
|>
|>So it's still undefined whether this prints "1 1" or "2 1".  And
|>rightly so, IMHO!

Paul-
  You are misusing the term "undefined". It has a very specific
meaning in the Standard, and doesn't simply mean "it can print this or
it can print that". You are correct that the program can print
"1 1" or "2 1", but that was also exactly my point. The point of this
recent discussion was to find a program whose behavior is not
undefined (according to the proper definition) yet still produces
indeterminate (for lack of a better word) output. Notice that nowhere
in that example is a violation of any "shall" rule outside of a 
constraint. Regardless of whether exp1 or exp2 is evaluated first, there
is a sequence point immediately before each reference to "v". Note that
if the behavior of this program were undefined, it would be allowed
to core dump, or even print "Happy Birthday", or the compiler need not
have even generated code in the first place! But here the output *must*
be *either* "1 1" or "2 1".

This is all subject to the comment Doug made about the possibility
of the "unspecified order of subexpressions" overriding the
"specified order and sequence point locations" of the comma operator.
A formal interpretation would be needed on this, it seems, but I
would suspect that the Committee would rule that the semantics of
the comma operator hold, even when used as an argument to a function.
But that's just my guess. If the semantics of the comma operator
are maintained, then the evaluations of "v" and "v++" are always
separated by a sequence point, regarless of the order of evaluation of
exp1 and exp2. 
 
|> ------------------------------------------------------------------
|>| Paul D. Smith                          | pds@lemming.webo.dg.com |
|>| Data General Corp.                     |                         |
|>| Network Services Development Division  |   "Pretty Damn S..."    |
|>| Open Network Systems Development       |                         |
|> ------------------------------------------------------------------
                                                              
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

jon@maui.cs.ucla.edu (Jonathan Gingerich) (04/06/91)

In article <18272@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>|>
>|>    printf("%d %d\n", (1, v), (1, v++));
>|>                      ^^^^^^  ^^^^^^^^
>This is all subject to the comment Doug made about the possibility
>of the "unspecified order of subexpressions" overriding the
>"specified order and sequence point locations" of the comma operator.
>A formal interpretation would be needed on this, it seems, but I
>would suspect that the Committee would rule that the semantics of
>the comma operator hold, even when used as an argument to a function.
>But that's just my guess. If the semantics of the comma operator
>are maintained, then the evaluations of "v" and "v++" are always
>separated by a sequence point, regarless of the order of evaluation of
>exp1 and exp2. 

Where are the sequence points on the comma operator?  I would guess there
is only one between the first and second expression in which case the
evaluation order 1 - 1 - (sequence point) - (sequence point) - v - v++
would make the result undefined.  The output of:

	printf("%d %d\n", f(...v...), f(...v++...)) 

is unspecified and not undefined because the sequence point before f(), but
since the subexpressions ...v... and ...v++... cannot be interleaved (unless
this is a case of the ambiguity Doug was talking about), it is not as
interesting.

Jon.

volpe@camelback.crd.ge.com (Christopher R Volpe) (04/06/91)

In article <1991Apr5.182945.15789@cs.ucla.edu>, jon@maui.cs.ucla.edu
(Jonathan Gingerich) writes:
|>Where are the sequence points on the comma operator? 

After the evaluation of the left operand.

|> I would guess there
|>is only one between the first and second expression in which case the
|>evaluation order 1 - 1 - (sequence point) - (sequence point) - v - v++
|>would make the result undefined.

That order of evaluation would seem to be inconsistent with the Semantics
part of 3.3.17 (Comma Operator). "The left operand of a comma operator
is evaluated as a void expression; there is a sequence point after its
evaluation. THEN THE RIGHT OPERAND IS EVALUATED [emphasis mine]; the
result has its type and value."


|>Jon.
                            
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

gwyn@smoke.brl.mil (Doug Gwyn) (04/06/91)

In article <PDS.91Apr2203927@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
>So it's still undefined whether this prints "1 1" or "2 1".  And
>rightly so, IMHO!

Unspecified != undefined.

jmaynard@thesis1.med.uth.tmc.edu (Jay Maynard) (04/06/91)

In article <15730@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <PDS.91Apr2203927@lemming.webo.dg.com> pds@lemming.webo.dg.com (Paul D. Smith) writes:
>>So it's still undefined whether this prints "1 1" or "2 1".  And
>>rightly so, IMHO!
>Unspecified != undefined.

Just to make sure I understand the distinction: It is legal for a conforming
implementation to print either "1 1" or "2 1", but not "Four score and seven
years ago...", right?


-- 
Jay Maynard, EMT-P, K5ZC, PP-ASEL | Never ascribe to malice that which can
jmaynard@thesis1.med.uth.tmc.edu  | adequately be explained by stupidity.
     "Religious flames over judgement calls are contraindicated."
                         -- Peter da Silva

bhoughto@nevin.intel.com (Blair P. Houghton) (04/06/91)

In article <18286@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>In article <1991Apr5.182945.15789@cs.ucla.edu>, jon@maui.cs.ucla.edu
>(Jonathan Gingerich) writes:
>|> I would guess there
>|>is only one between the first and second expression in which case the
>|>evaluation order 1 - 1 - (sequence point) - (sequence point) - v - v++
>|>would make the result undefined.
>
>That order of evaluation would seem to be inconsistent with the Semantics
>part of 3.3.17 (Comma Operator). "The left operand of a comma operator
>is evaluated as a void expression; there is a sequence point after its
>evaluation. THEN THE RIGHT OPERAND IS EVALUATED [emphasis mine]; the
>result has its type and value."

The line read (essentially):

	f ( ( 1 , v) , ( 1 , v++ ) ) ;

I expect you're not confusing the two comma operators with the
comma separator in this function call.  The sequence point
after the left operand of each comma-operator serves only
to define the end of operations on the left operand and the
beginning of operations on the right operand; it does not
affect the order in which the two arguments to the function
are evaluated.  However, what you may be saying is that the
sequence of abstract events

        1 - 1 - ( seq. pt. ) - ( seq. pt. ) - v - v++

is incorrect, and would be

        1 - ( seq. pt. ) - 1 - ( seq. pt. ) - v - v++

or

        	                       ...  - v++ - v

implying that the sequence point must be applied to the
end of evaluation of one of the left operands before
the other can be evaluated.

It would seem so, or else

	f ( ( a=b, 1 ), ( a=c, 1 ) );

Would have undefined behavior (assigning to `a' twice
before the next sequence point), while it should have
only unspecified order of evaluation of the two arguments.

				--Blair
				  "Hey!  This stuff's *recursive*!"

eggert@twinsun.com (Paul Eggert) (04/06/91)

In commenting on

	printf("%d %d\n", (1, v), (1,v++));

volpe@camelback.crd.ge.com (Christopher R Volpe) writes:

	No matter what the order of evaluation of the function
	arguments is, there's always a sequence point separating the
	references to v.

While the ANSI standard does not clearly address this point, Jim Brodie
has reported [Journal of C Language Translation 2, 3 (Dec. 1990), 207-215]
that the general opinion of X3J11 seems to be that the sequence point
in an expression X=F(Y) prior to the call to F causes only a partial
ordering on the subexpressions F and Y; it does not control the
ordering of other subexpressions like X.  From this, I would expect
that the sequence point between A and B in the comma expression (A,B)
establishes only a partial order on A and B, and does not place
constraints on the ordering of expressions outside (A,B).  Therefore,

	printf("%d %d\n", (1, v), (1,v++));

isn't conforming, because an implementation can evaluate the two `1's
first, and then evaluate `v' and `v++' in parallel, so to speak.

volpe@camelback.crd.ge.com (Christopher R Volpe) (04/08/91)

In article <3693@inews.intel.com>, bhoughto@nevin.intel.com (Blair P.
Houghton) writes:
|>
|>The line read (essentially):
|>
|>	f ( ( 1 , v) , ( 1 , v++ ) ) ;
|>
|>I expect you're not confusing the two comma operators with the
|>comma separator in this function call.  

Nope, I'm not, but thanks for pointing it out. 

|>The sequence point
|>after the left operand of each comma-operator serves only
|>to define the end of operations on the left operand and the
|>beginning of operations on the right operand; it does not
|>affect the order in which the two arguments to the function
|>are evaluated.  However, what you may be saying is that the
|>sequence of abstract events
|>
|>        1 - 1 - ( seq. pt. ) - ( seq. pt. ) - v - v++
|>
|>is incorrect, and would be
|>
|>        1 - ( seq. pt. ) - 1 - ( seq. pt. ) - v - v++

I'd say it would at least have to be that. I would have also expected that
the right operand of the first comma-operator evaluated had to be evaluated
before the left operand of the second comman-operator evaluated, until
someone mentioned that bit about only specifying a partial ordering.
So perhaps the above function call is not an example of one whose behavior
is not undefined.

                                                   
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

jon@maui.cs.ucla.edu (Jonathan Gingerich) (04/09/91)

In article <1991Apr6.022220.6449@twinsun.com> eggert@twinsun.com (Paul Eggert) writes:
>
>While the ANSI standard does not clearly address this point, Jim Brodie
>has reported [Journal of C Language Translation 2, 3 (Dec. 1990), 207-215]
>that the general opinion of X3J11 seems to be that the sequence point
>in an expression X=F(Y) prior to the call to F causes only a partial
>ordering on the subexpressions F and Y; it does not control the
>ordering of other subexpressions like X.  From this, I would expect

Earlier I claimed:

	printf("%d %d\n", f(...v...), f(...v++...))

was unspecified not undefined based on a misapprehension of where the sequence
point in a function calls is.  Looking at K&RII it appears that the s.p. is 
between the evaluation of the arguments (and function name) and the application
of the functions.  I.e.

	x = double_it(x++);

would always leave x even.  In my previous example however, I believe that v
and v++ could be evaluated before either s.p. thus it is undefined.

So what about:

	 (*fp)(fp = &g)

???

Jon.

diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/09/91)

In article <1991Apr8.191009.24897@cs.ucla.edu> jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:

>So what about:
>	 (*fp)(fp = &g)

Intuitively, either the function previously pointed to, or g, could be called,
though the argument would have to be a pointer to g.  (But this is not what
the standard says.)

Pedantically, the net.random_marauders could be called, because the expression
fetches the old value of fp for a purpose other than determining the new value
to be stored.
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.

bhoughto@nevin.intel.com (Blair P. Houghton) (04/09/91)

In article <1991Apr8.191009.24897@cs.ucla.edu> jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>In article <1991Apr6.022220.6449@twinsun.com> eggert@twinsun.com (Paul Eggert) writes:
>>
>>While the ANSI standard does not clearly address this point, Jim Brodie
>>has reported [Journal of C Language Translation 2, 3 (Dec. 1990), 207-215]
>>that the general opinion of X3J11 seems to be that the sequence point
>>in an expression X=F(Y) prior to the call to F causes only a partial
>>ordering on the subexpressions F and Y; it does not control the
>>ordering of other subexpressions like X.  From this, I would expect

Huh?  F and Y both must be evaluated prior to that sequence point.
If this is what is meant by "partial ordering" (the common
beforeness is defined, but not the actual order of the two
wrt each other), then no problem.

>Earlier I claimed:
>
>	printf("%d %d\n", f(...v...), f(...v++...))
[...]
>would always leave x even.  In my previous example however, I believe that v
>and v++ could be evaluated before either s.p. thus it is undefined.

Again, it's confused.  There are two sequence points
among the arguments to printf(); they are the calls
to the function f().  Sequence points are defined
in terms of their proscriptions on side effects.
Since `v++' has a side effect (the assignment of
v+1 to v), it must be evaluated after the preceding
sequence point and prior to the sequence point
defined by the rightward call to f().  It is unspecified
whether the preceding sequence point comes from some
earlier statement or from the leftward call to f().
However, the first usage of `v' has no side effects.
It can be evaluated regardless of sequence points
other than the one for the leftward call to f().
The value for `v' in the leftward call is indeterminate.

				--Blair
				  "I gotta start bringing the
				   standard home with me?"

jon@maui.cs.ucla.edu (Jonathan Gingerich) (04/11/91)

In article <3731@inews.intel.com> bhoughto@nevin.intel.com (Blair P. Houghton) writes:
>In article <1991Apr8.191009.24897@cs.ucla.edu> jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>>Earlier I claimed:
>>
>>	printf("%d %d\n", f(...v...), f(...v++...))
>[was unspecified not undefined]
>> In my previous example however, I believe that v
>>and v++ could be evaluated before either s.p. thus it is undefined.
>
>Again, it's confused.  There are two sequence points
>among the arguments to printf(); they are the calls
>to the function f().  Sequence points are defined
>in terms of their proscriptions on side effects.
>Since `v++' has a side effect (the assignment of
>v+1 to v), it must be evaluated after the preceding
>sequence point and prior to the sequence point
>defined by the rightward call to f().  It is unspecified
>whether the preceding sequence point comes from some
>earlier statement or from the leftward call to f().
>However, the first usage of `v' has no side effects.
>It can be evaluated regardless of sequence points
>other than the one for the leftward call to f().
>The value for `v' in the leftward call is indeterminate.

You are correct as far as you go.  But v and v++ can both be evaluated before
either s.p. associated with the application of f()'s and because v is both
read and written in separate actions it's undefined.

Jon.

bhoughto@bishop.intel.com (Blair P. Houghton) (04/11/91)

In article <1991Apr10.191853.4604@cs.ucla.edu> jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>In article <3731@inews.intel.com> bhoughto@nevin.intel.com (Blair P. Houghton) writes:
>>In article <1991Apr8.191009.24897@cs.ucla.edu> jon@maui.cs.ucla.edu (Jonathan Gingerich) writes:
>>>Earlier I claimed:
>>>	printf("%d %d\n", f(...v...), f(...v++...))
>>[was unspecified not undefined]
>>
>>However, the first usage of `v' has no side effects.
>>It can be evaluated regardless of sequence points
>>other than the one for the leftward call to f().
>>The value for `v' in the leftward call is indeterminate.
>
>You are correct as far as you go.  But v and v++ can both be evaluated before
>either s.p. associated with the application of f()'s and because v is both
>read and written in separate actions it's undefined.

Okay, make them both v++.  Now it's definite that the
sequence must be:

	v++, corresponding s.p., v++, corresponding s.p.

though which v++ and corresponding s.p. come first is
still unspecified.

Doug (or was it Guy?) once made the point about parsing of
tokens that maximal munch doesn't hold, rather it is the
parsing that is true to the syntax that holds.  I think
that here a similar situation exists.  It's possible to
create only two orderings of the evaluations and sequence
points in

	f( g(v), h(v++) )

SUCH THAT the statement is NOT "undefined", and they are

	v, s.p.(g), v++, s.p.(h)
	v++, s.p.(h), v, s.p.(g)

and the compiler should produce one of these orderings.

I.e., if it's possible to avoid undefined behavior by
application of sequence points that are defined to
exist, then they should be so applied.

(Note that the side effects don't force placement
of the sequence points, here.  The same thing would
happen if `v++' were replaced by `v' in both arguments.)

I believe that this is what the standard mandates; but it
may be the opposite:  that if there is ANY way to produce
undefined behavior by pushing around the unanchored
sequence points, then the behavior should be undefined.

				--Blair
				  "But then, I go through red
				   lights at 3 a.m. if there's
				   no cross-traffic, too..."