[comp.lang.c] Can analysis detect undefined expressions?

ckp@grebyn.com (Checkpoint Technologies) (06/13/91)

The subject line is not very good.  Let me explain what I want.

Some expressions in C are undefined, because of expression reordering and
side effects. A recent (ongoing?) thread discussed the possible different
interpretations of if ((i=1) == (i=2)), and there are other examples like
i = i++ + i++, and so on.

I'd like to know if there has been any attempt to diagnose such undefined
expressions.  It seems like an exceedingly difficult thing to do,
especially considering aliasing and possible side effects of functions.

I have two reasons for asking. One is that I'm sure everyone would love
to have the compiler (or lint) point out these errors, and so we'd all
create bug-free code.  :-)

Another reason is that I have a similar problem in another language,
which I'm trying to re-implement. This language is supposed to be
a specification language which is insensitive to the order in which it's
primitives are evaluated. Well, 95% of the time is is, but we have to
explain to users how to avoid problems in those last 5% of cases.
So I'm exploring the idea of providing diagnostics for these exceptional
cases. I figure if someone's done it for C expressions then the same
concepts should apply to this other language.

Any ideas? Has it been proven impossible? Thanks all.
-- 
Richard Krehbiel, private citizen      ckp@grebyn.com
(Who needs a fancy .signature?)

willcr@bud.sos.ivy.isc.com (Will Crowder) (06/14/91)

In article <1991Jun13.015548.24724@grebyn.com>, ckp@grebyn.com
(Checkpoint Technologies) writes:

|> The subject line is not very good.  Let me explain what I want.
|> 
|> Some expressions in C are undefined, because of expression reordering and
|> side effects. A recent (ongoing?) thread discussed the possible different
|> interpretations of if ((i=1) == (i=2)), and there are other examples like
|> i = i++ + i++, and so on.

|> I'd like to know if there has been any attempt to diagnose such undefined
|> expressions.  It seems like an exceedingly difficult thing to do,
|> especially considering aliasing and possible side effects of functions.

I'm not sure if it has been proven impossible, and indeed, trivial and
obvious violations like "i = i++ + i++" are easy to spot.  However,
how would you deal with the case of:

   i = (*p)++ + (*q)++;

I mean, this statement is perfectly legal and its value defined if
p != q.  However, if p == q, then you're once again in deep yogurt as you're
modifying the same object twice without an intervening sequence point.

I don't know statistics well enough to put this as eloquently as I'd like,
but:

Determining at compile time of p could ever be equal to q would require
exhaustive code path analysis, and this analysis has been shown to take
longer than the estimated remaining lifespan of the galaxy for anything
over a few lines.  (I can't remember that great quote I heard about it,
or I'd put it in my .sig.)

Will

--------------------------------------------------------------------------------
Will Crowder, MTS            | "Any airplane you can't roll ain't no
(willcr@ivy.isc.com)         |  damn good!"
INTERACTIVE Systems Corp.    |		-- Tex Johnson

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

In article <1991Jun13.231924.3711@ism.isc.com>,
willcr@bud.sos.ivy.isc.com (Will Crowder) writes:
|>I'm not sure if it has been proven impossible, and indeed, trivial and
|>obvious violations like "i = i++ + i++" are easy to spot.  However,
|>how would you deal with the case of:
|>
|>   i = (*p)++ + (*q)++;
|>
|>I mean, this statement is perfectly legal and its value defined if
|>p != q.  However, if p == q, then you're once again in deep yogurt as you're
|>modifying the same object twice without an intervening sequence point.
|>
|>I don't know statistics well enough to put this as eloquently as I'd like,
|>but:
|>
|>Determining at compile time of p could ever be equal to q would require
|>exhaustive code path analysis, and this analysis has been shown to take
|>longer than the estimated remaining lifespan of the galaxy for anything
|>over a few lines.  (I can't remember that great quote I heard about it,
|>or I'd put it in my .sig.)

It's not just time consuming, it's theoretically impossible for an
arbitrary program. It's trivial to reduce the halting problem to
this problem, thus showing its undecidability. 
                                       
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

worley@compass.com (Dale Worley) (06/14/91)

In article <1991Jun13.231924.3711@ism.isc.com> willcr@bud.sos.ivy.isc.com (Will Crowder) writes:
   Determining at compile time of p could ever be equal to q would require
   exhaustive code path analysis, and this analysis has been shown to take
   longer than the estimated remaining lifespan of the galaxy for anything
   over a few lines.  (I can't remember that great quote I heard about it,
   or I'd put it in my .sig.)

Even worse, there is *no* algorithm which can do the job for all
programs, no matter *how* much time it is given.

Dale Worley		Compass, Inc.			worley@compass.com
--
It's one thing to burn down the shithouse, it's quite another to
install plumbing.	-- P.J. O'Rourke, on revolution

Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/16/91)

 >From: ckp@grebyn.com (Checkpoint Technologies)
 >The subject line is not very good.  Let me explain what I want.

 >Some expressions in C are undefined, because of expression reordering and
 >side effects. A recent (ongoing?) thread discussed the possible different
 >interpretations of if ((i=1) == (i=2)), and there are other examples like
 >i = i++ + i++, and so on.

 >I'd like to know if there has been any attempt to diagnose such undefined
 >expressions.  It seems like an exceedingly difficult thing to do,
 >especially considering aliasing and possible side effects of functions.

To say the least.  It can PROBABLY be done on local variables using operators 
the compiler understands (ie the primitives).  As soon as you throw 
subroutines in where the compiler really doesn't know all possible sources of 
the parameters when compiling the subroutine or what the subroutine itself 
does to the variables (assuming you pass them as addresses) at the expression 
containing the call.  

For the easy case, it should not be unthinkable hard see if the same address 
is being modified in more than one sub-expression in a group of 
sub-expressions who's order of evaluation does not matter.  So in C we have 
what... the comparison operators (== <= >= !=), the math operators (+ - * / % 
| & etc) and the , "operator".  There might be more, I don't recall.  

An extended example so that I can think clearly here:

     (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))

Assumedly, i can end up as 1,2,3, or 4.  j should be 0.  The grouping is such 
that i=4, i=2, i=3, i=1 won't happen without breaking any laws.  right?

So the idea here is to scan for the problem operators such as the ==, 
determine the subexpression for both sides, then determine if a same address 
(not variable) is modified in both.  Easier said than done, and something you 
don't want to do at compile time very badly, but it should be doable.  Once 
again, this would only be good for the simpler cases.  I would hate to 
estimate what percentage of the programmer mistakes fall under this type of 
example, its been a long time since I've made one this blantant.

On the whole, I would say it is NOT possible to contend with every case.  For 
examples.

int func(x,y,t)
{
    int *z;
    
    if (t);
       z = &x;
    else
       z = &y;

    t = (*x)++ == (*z)++;
}

This one much harder to contend with.  Its being defined depends on the value 
of t being passed in.  And it only gets worse..

Dave Harris.
 


 

--  
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris
Internet: Dave.Harris@f14.n15.z1.fidonet.org

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/17/91)

In article <14206.285B7688@stjhmc.fidonet.org>, Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
> An extended example so that I can think clearly here:
> 
>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
> 
> Assumedly, i can end up as 1,2,3, or 4.  j should be 0.  The grouping is such 
> that i=4, i=2, i=3, i=1 won't happen without breaking any laws.  right?

Wrong.  Think of the assignments as going into a bag.  By the time you
reach a "sequence point" all of the assignments must have been pulled
out of the bag and been done, but they can be pulled out of the bag in
any order.  So
	((i=1) == (i=2))	=>	put <i=2> into bag
					put <i=1> into bag
	(j = ...)		=>	put <j=0> into bag
	((i=3) == (i=4))	=>	put <i=4> into bag
					put <i=1> into bag
	(j = ...)		=>	put <j=0> into bag					
So now we can pull the assignments out in any order we please;
4 -> i, 2 -> i, 3 -> i, 1 -> i, 0 -> j, 0 -> j
is perfectly possible.  This can be optimised if i, j are not volatile.

-- 
Q:  What should I know about quicksort?   A:  That it is *slow*.
Q:  When should I use it?  A:  When you have only 256 words of main storage.

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

In article <6371@goanna.cs.rmit.oz.au>, ok@goanna.cs.rmit.oz.au (Richard
A. O'Keefe) writes:
|>Wrong.  Think of the assignments as going into a bag.  By the time you
|>reach a "sequence point" all of the assignments must have been pulled
|>out of the bag and been done, but they can be pulled out of the bag in
|>any order.  So
|>	((i=1) == (i=2))	=>	put <i=2> into bag
|>					put <i=1> into bag
|>	(j = ...)		=>	put <j=0> into bag
                                             ^^^
This is not necessarily true. J could very well be 1 here, if it reads the
value of i twice before comparing them.

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

torek@elf.ee.lbl.gov (Chris Torek) (06/18/91)

(I realized shortly after posting article <14392@dog.ee.lbl.gov> that its
example was incorrect.  Those of you whose news systems do not understand
the "Supersedes" header may see it anyway.  Sorry about that.)

>>From: ckp@grebyn.com (Checkpoint Technologies)
>>I'd like to know if there has been any attempt to diagnose such undefined
>>expressions.  It seems like an exceedingly difficult thing to do ...

In article <14206.285B7688@stjhmc.fidonet.org>
Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
>On the whole, I would say it is NOT possible to contend with every case.

Indeed, it is fairly easy to show that no compiler can diagnose all
misuses correctly.  On the other hand, diagnosing obvious misuses is
easy, and most `lint's, for instance, will note that:

	i = i++ + i++;

is undefined.  The interesting part comes in trying to catch the less
obvious misuses without catching non-obvious non-misuses.  For instance,

	if (use_j)
		p = &j;
	else
		p = &a[j];
	*p += foo;
	if (something)
		*p *= 2;
	if (anotherthing)
		*p /= 3;
	use(*p);
	if (use_j)
		done_j();
	else
		j += (*p)++;

may be correct (if use() modifies use_j, it may be incorrect as well),
but deciding for certain whether it is or is not is a hard problem.  I
believe that a global-analysis system would be able to decide `correct'
or `incorrect' (rather than `don't know') in most real code, and that
it could do so in a sufficiently small amount of time to make it worth
running on `high stakes' code such as that found in embedded medical
systems.  That is, I think that a decent analysis program could point
out a minimum number of questionable cases after running on a powerful
system for only a few months or even weeks.  As we learn more, and the
system becomes more effective, I think such analysis will become
commonplace, but this seems to be a number of years away.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

worley@compass.com (Dale Worley) (06/18/91)

In article <14206.285B7688@stjhmc.fidonet.org>, Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
> An extended example so that I can think clearly here:
>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
> Assumedly, i can end up as 1,2,3, or 4.  j should be 0.  The grouping is such 
> that i=4, i=2, i=3, i=1 won't happen without breaking any laws.  right?

Sorry to belabor this yet again, but there is no requirement in Ansi C
that i have one of the values 1, 2, 3, or 4.  The effect of this
statement is "undefined", which means that the implementation can do
*anything*, including giving i the value 100, core dumping, or
starting World War III.  Ditto for j.  The mere fact that none of
these actions are mentioned in the statement is irrelevant.

Dale Worley		Compass, Inc.			worley@compass.com
--
I'd sign on for the War on Drugs if they'd include alcohol and
nicotine on the official hit list.

tmb@ai.mit.edu (Thomas M. Breuel) (06/19/91)

In article <14394@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes:
   >>From: ckp@grebyn.com (Checkpoint Technologies)
   >>I'd like to know if there has been any attempt to diagnose such undefined
   >>expressions.  It seems like an exceedingly difficult thing to do ...

   In article <14206.285B7688@stjhmc.fidonet.org>
   Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
   >On the whole, I would say it is NOT possible to contend with every case.

   Indeed, it is fairly easy to show that no compiler can diagnose all
   misuses correctly.

However, a compiler can do better than just detecting problems
with builtins:

(1) it can warn about all potential dependencies on order of
    evaluation. To be useful it requires that all functions
    without side effects are declared as such (see GNU CC/C++):

Thus, this fragment should not generate a warning:

    const double sin(double);

	sin(x)+sin(x)*sin(x)

On the other hand, this fragment should:

    double sin(double);
    ...
	sin(x)+sin(x)*sin(x)

    >>> Warning: potential dependency on order of evaluation

(2) it can generate code to run several versions of the program
    with different orders of evaluation in parallel and detect
    differences in their execution

					Thomas.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/21/91)

In article <WORLEY.91Jun18095521@sn1987a.compass.com> worley@compass.com (Dale Worley) writes:
  [ on statements like (i = 1) == (i = 2) ]
> The effect of this
> statement is "undefined", which means that the implementation can do
> *anything*, including giving i the value 100, core dumping, or
> starting World War III.

More realistically, there do exist architectures where parts of the
first assignment can overlap parts of the second. Think about core
memories: to read a bit you have to flip a bit, and the operations don't
commute. You just can't access the same word twice in one cycle.
Otherwise both the word and the value you read from it can be corrupted.
Vector machines, such as the Convex, continue this fine tradition.

---Dan

Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/21/91)

In a message of <Jun 18 20:31>, Dale Worley (1:114/15) writes: 
> An extended example so that I can think clearly here:
>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
> Assumedly, i can end up as 1,2,3, or 4.  j should be 0.  The grouping is 
such 
> that i=4, i=2, i=3, i=1 won't happen without breaking any laws.  right?

 >Sorry to belabor this yet again, but there is no requirement in Ansi C
 >that i have one of the values 1, 2, 3, or 4.  The effect of this
 >statement is "undefined", which means that the implementation can do
 >*anything*, including giving i the value 100, core dumping, or
 >starting World War III.  Ditto for j.  The mere fact that none of
 >these actions are mentioned in the statement is irrelevant.

Not arguing that the result is undefined as you say.  But....
I for one would quickly scrap any compiler that went to the additional work of 
embedding code to yield a value of anything other than 1,2,3 or 4 for i.  It 
would mean the compiler would have to detect the undefined statement first 
before it could even do this.  Its one thing for a compiler to give you a 
warning, but quite another for it to go out of its way to make mince meat out 
of your code.  It would be just one more thing that could go accidently wrong 
on perfectly good code.  The authors have a bad enough time with optimizer 
options ruining good code as it is.  Now, maybe there is a way of writing 
compilers such that undefined statemets yield completely unexpected results as 
a built in property of the algorithm.  The only thing that even remotely comes 
to mind might be some type of optimization that relies heavily on the 
assumption that nobody will write undefined expressions, but even that doesn't 
seem like a logical reason.

I would really like to see an example of code accomplishing completely 
unexpected behavior as in setting i equal to 5.  There probably isn't a 
compiler around that would do it because it would be extraneous work and risky 
to boot.

 


 

--  
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris
Internet: Dave.Harris@f14.n15.z1.fidonet.org

geels@cs.vu.nl (Arnold Geels) (06/21/91)

In comp.lang.c you write:
>>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))

>Not arguing that the result is undefined as you say.  But....
>I for one would quickly scrap any compiler that went to the additional work of 
>embedding code to yield a value of anything other than 1,2,3 or 4 for i.  It 
>would mean the compiler would have to detect the undefined statement first 
>before it could even do this. 

You're missing the point.  The "undefined" rule was not invented to
tease the users of C, but to please the compiler writers!  Of course
nobody is going to write a compiler that deliberately starts up a game
of rogue if compiling this expression.  But if on some future computer
the {natural, fastest, best, only} way to code expressions leads to i
getting set to something unequal to 1,2,3, or 4, then surely this is
the way this expression will be coded!

>It would be just one more thing that could go accidently wrong 
>on perfectly good code.

"perfectly good code" is NOT equal to "code that works now and that I would
very much like to continue working in the future"...  

>I would really like to see an example of code accomplishing completely 
>unexpected behavior as in setting i equal to 5. 

("Unexpected" by whom?)

-- fantasy mode ON --

Suppose we have, in the future, a massively parallel computer that
works with one processor for each variable.  Whenever an assignment is
made to a variable, you send a message to the appropriate processor.
When building this computer, the engineers found out that sometimes two
or more assignment messages would arrive at the same node at the same
time.  They found out that the fastest solution was to ignore BOTH
messages, i.e. no assignment is done at all.  In the above statement,
objects "1", "2", "3", and "4" all send a message to i at the same
time...  All messages cancel out,  and i keeps its old value.  Voila.

-- fantasy mode OFF --

>There probably isn't a 
>compiler around that would do it because it would be extraneous work and risky 
>to boot.

It probably isn't around NOW, but it could be around in the future...  Do
YOU know what the future architectures are like?  And do you want your
programs to work on them?

Arno1d.

kers@hplb.hpl.hp.com (Chris Dollin) (06/21/91)

Dave Harris says:

   Not arguing that the result is undefined as you say.  But....
   I for one would quickly scrap any compiler that went to the additional work
   of embedding code to yield a value of anything other than 1,2,3 or 4 for i.
   It would mean the compiler would have to detect the undefined statement
   first before it could even do this.  Its one thing for a compiler to give 
   you a warning, but quite another for it to go out of its way to make mince
   meat out of your code.  It would be just one more thing that could go 
   accidently wrong .

True, if the compiler ``went out of its way'' to do so. But consider the
smaller (indeed, the original) example:

    (i = 1) == (i = 2)

and suppose that the compiler compiles it as

    Ri = 1 || Ri = 2; Ranswer = (Ri == Ri)

where Ri is the register allocated to i, "||" denotes parallel execution, ";"
sequential execution, Ranswer is where the answer goes. Perhaps we're on some
machine (VLIW ?) where instructions can be executed in parallel, and maybe
parallel stores to the same register interfere - perhaps the bitwise OR of the
two operands gets written, perhaps you get junk, perhaps the machine traps,
perhaps it scrambles the PC, perhaps it turns into a butterfly and flies to
Berkeley.

With the first of these choices, the conditional delivers TRUE, but i becomes
3. The compiler has done no ``additional work'' - it has just exploited
knowledge about the semantics of C. (It's a pretty idiot savant of a compiler,
of course, because it should probably have an internal check to ensure it never
generates such a rubbish instruction. Then again, if it *did* check, you might
get a compiler message as well:

    Mishap - internal error or source code exploits undefined behaviour
    Somewhere near: (probably a garbled location)

What fun.)

The moral of the story is: there are more architectures in Heaven and Earth,
Horatio, then are dreamed of in your philosophy.



--

Regards, Chris ``GC's should take less than 0.1 second'' Dollin.

worley@compass.com (Dale Worley) (06/21/91)

In article <6622.Jun2023.40.0891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
   In article <WORLEY.91Jun18095521@sn1987a.compass.com> worley@compass.com (Dale Worley) writes:
     [ on statements like (i = 1) == (i = 2) ]
   > The effect of this statement is "undefined", [...]

   More realistically, there do exist architectures where parts of the
   first assignment can overlap parts of the second. 

Or consider this:  Suppose the statement is

	(i = 100000) == (i = 1)

And suppose that the two assignments are performed by two parallel
processors.  And suppose that assignment to a (4-byte) int is *not*
atomic -- each processor has to perform it as two 2-byte stores.  The
result left in 'i' may have the high-order part from one assignment
and the low-order part from the other, giving the possible values:

	100000
	65537
	34464
	1

Dale Worley		Compass, Inc.			worley@compass.com
--
Managing computer programmers is like herding cats.

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

In article <14489.2861906B@stjhmc.fidonet.org> Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
>In a message of <Jun 18 20:31>, Dale Worley (1:114/15) writes: 
>> An extended example so that I can think clearly here:
>>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
>> Assumedly, i can end up as 1,2,3, or 4.  j should be 0.  The grouping is 
>such 
>> that i=4, i=2, i=3, i=1 won't happen without breaking any laws.  right?
> >Sorry to belabor this yet again, but there is no requirement in Ansi C
> >that i have one of the values 1, 2, 3, or 4.  The effect of this
> >statement is "undefined", which means that the implementation can do
> >*anything*, including giving i the value 100, core dumping, or
> >starting World War III.  Ditto for j.  The mere fact that none of
> >these actions are mentioned in the statement is irrelevant.
>Not arguing that the result is undefined as you say.  But....
>I for one would quickly scrap any compiler that went to the additional work of 
>embedding code to yield a value of anything other than 1,2,3 or 4 for i.  It 
>would mean the compiler would have to detect the undefined statement first 
>before it could even do this.  ...
Not if it were setting i on 4 CPUs run in parallel!                    Jon.

msb@sq.sq.com (Mark Brader) (06/23/91)

> >      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
> Not arguing that the result is undefined as you say.  But....  I for one
> would quickly scrap any compiler that went to the additional work of 
> embedding code to yield a value of anything other than 1,2,3 or 4 for i.

On the other hand, I for one would welcome with open arms a compiler
that made those checks at compile time and exercised its right to
*refuse to compile it* in the first place.

(As has been pointed out, this becomes arbitrarily difficult if the
expression involves things like indirection.  I don't care.  I just
want the compiler to reject a[i++] = i, x = a[i++]+b[i++], the above
expression, and other such cases that *are* easily diagnosed.  Even
Saber-C (3.0.1) misses these, unless maybe I have some option set wrong.)
-- 
Mark Brader		     "It is impractical for the standard to attempt to
SoftQuad Inc., Toronto	      constrain the behavior of code that does not obey
utzoo!sq!msb, msb@sq.com      the constraints of the standard."  -- Doug Gwyn

This article is in the public domain.

Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/25/91)

In a message of <Jun 21 17:44>, Jonathan Gingerich (1:114/15) writes: 
>Not arguing that the result is undefined as you say.  But....
>I for one would quickly scrap any compiler that went to the additional work 
of 
>embedding code to yield a value of anything other than 1,2,3 or 4 for i.  It 
 
>would mean the compiler would have to detect the undefined statement first 
>before it could even do this.  ...
 >Not if it were setting i on 4 CPUs run in parallel!                    
 >Jon.

Are the electronics such that the same memory address can really be written to 
similtaneously?  If so would you expect a completely random result or 
something in the range of 1 to 7?

Dave Harris
 


 

--  
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris
Internet: Dave.Harris@f14.n15.z1.fidonet.org

Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/25/91)

In a message of <Jun 21 17:44>, Arnold Geels (1:114/15) writes: 
 >In comp.lang.c you write:
>>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))

>Not arguing that the result is undefined as you say.  But....
>I for one would quickly scrap any compiler that went to the additional work 
of 
>embedding code to yield a value of anything other than 1,2,3 or 4 for i.  It 
 
>would mean the compiler would have to detect the undefined statement first 
>before it could even do this. 

 >You're missing the point.  The "undefined" rule was not invented to
 >tease the users of C, but to please the compiler writers!  Of course
 >nobody is going to write a compiler that deliberately starts up a game
 >of rogue if compiling this expression.  But if on some future computer
 >the {natural, fastest, best, only} way to code expressions leads to i
 >getting set to something unequal to 1,2,3, or 4, then surely this is
 >the way this expression will be coded!

I am not questioning that undefined statements should not be used.  They most 
definately should NOT be used.  I am just rambling about what I would do with 
a compiler that would have *ADDITIONAL* logic to make your code yield an 
unexpected result or some type of debug value like -9999.  I should narrow the 
term "unexpeceted" down to any given machine as its evidently different on 
multi-processor machines (learn something new every day).  Pretty moot to talk 
about since only the worst fool would make their compiler this way instead of 
printing out a warning.

Dave Harris.
 


 

--  
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris
Internet: Dave.Harris@f14.n15.z1.fidonet.org

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/26/91)

In article <14489.2861906B@stjhmc.fidonet.org>, Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
> In a message of <Jun 18 20:31>, Dale Worley (1:114/15) writes: 
>>      (j = ((i=1) == (i=2))) == (j = ((i=3) == (i=4)))
>> Sorry to belabor this yet again, but there is no requirement in Ansi
>> C that i have one of the values 1, 2, 3, or 4.
> I for one would quickly scrap any compiler that went to the
> additional work of embedding code to yield a value of anything other
> than 1,2,3 or 4 for i.

Let's rephrase that...I too would quickly scrap any compiler that went
to the additional work of embedding unnecessary code.  Period.

However, if the architecture is such that assignments can happen in
parallel, i could wind up holding 1|2|3|4, which happens to be 7.  Or
perhaps 1&2&3&4, which is 0.  Or maybe i doesn't get changed at all.
Or perhaps something else, including a run-time assignment collision
fault from the parallel assignment hardware.

> I would really like to see an example of code accomplishing
> completely unexpected behavior as in setting i equal to 5.

	ON * RENDEZVOUS	; rendezvous (end of last statement)
	ON 0 MOV $1,i	; i=1
	ON 1 MOV $2,i	; i=2
	ON 2 MOV $3,i	; i=3
	ON 3 MOV $4,i	; i=4
	ON 4 MOV $0,j	; j = ((i=1) == (i=2))
	ON 5 MOV $0,j	; j = ((i=3) == (i=4))
	ON * RENDEZVOUS	; rendezvous again

Or the optimizer might save code space by doing

	ON * RENDEZVOUS
	ON 0 MOV $0,j			; j = ((i=1) == (i=2))
	ON 5 MOV $0,j			; j = ((i=3) == (i=4))
	ON 1,2,3,4 MOV %PROCID,i	; i=1 / i=2 / i=3 / i=4
	ON * RENDEZVOUS

Of course, the hardware to execute that code probably doesn't exist at
the moment, but that's beside the point.  It's hardly a far-fetched
architecture.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

worley@compass.com (Dale Worley) (06/26/91)

In article <14816.28673F12@stjhmc.fidonet.org> Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) writes:
   Are the electronics such that the same memory address can really be
   written to similtaneously?  If so would you expect a completely
   random result or something in the range of 1 to 7?

On the Connection Machine, if you are using the message-passing system
to perform the store, stores that collide will be merged by (1) adding,
(2) or-ing, (3) and-ing, (4) max-ing, (5) min-ing, or (6) picking a
random one.  It all depends on how you set some flag in the
message-passing system.  It is quite conceivable that there are
parallel processors where colliding writes produce completely random
results, if it saves a few nanoseconds somewhere...

Dale Worley		Compass, Inc.			worley@compass.com
--
Our informal mission is to improve the love life of operators worldwide.
-- Peter Behrendt, president of Exabyte.  Quoted in Digital Review, Feb 4, 1991.