expr?(void):(void) (I was wrong. I've seen the light.)

Ray Butterworth rbutterworth at watmath.UUCP
Sat Aug 2 07:31:13 AEST 1986


I've received mail or news from the following people, all strongly
protesting that my fix for void functions and the ?: operator was
invalid and that the current behaviour of most compilers is correct,
and that the proposed ANSI standard is as mixed up as I am.

>  From: aka at cbrma.UUCP (Andy Kashyap)
>  From: allbery at ncoast.UUCP (Brandon Allbery)
>  From: ark at alice.UucP (Andrew Koenig)
>  From: hamilton at uxc.CSO.UIUC.EDU (Wayne Hamilton)
>  From: jsdy at hadron.UUCP (Joseph S. D. Yao)
>  From: <utzoo!dciem!msb>
>  From: seismo!ll-xn!mit-amt!mit-eddie!ci-dandelion!jim (Jim Fulton)
>  From: whp at cbnap.UUCP (W. H. Pollock x4575 3S235)

First I'd like to clear up some confusion.  We seem to be arguing about
slightly different things.  In a statement such as
    i = e1 ? e2 : e3;
there are actually three distinct points where the compiler can make
checks.  At the "=", it must make sure that the types of "i" and
the result of the "?:" expression are the same or at least compatible
for an assignment.  At the "?" it must make sure that e1 is in fact
something that can be tested against 0.  At the ":" it must make sure
that the types of e2 and e3 are the same or are at least compatible.

Now, my "fix" was to the check at the ":".  Rather than allowing that
the two types may both be void perhaps it would have been better to
have done a simple test that any type is allowed as long as they are
both the same.  After all, the error message at this point does
say that the two operands of the ":" are incompatible with each other,
when in fact they are not.  For instance this fix solves the problem
of using "?:" with pointers to void functions that was reported earlier.

Even this shouldn't cause people to get upset.  The complaints were
actually about what happens (or rather doesn't happen) at the "?".
This is where the check that people want should go.  At this point
the compiler could check that the right operand (in the parse tree)
is in fact a valid expression and not void.  This is the point at
which a message such as "'?' operator returns void expression" could
be produced.  If we added that (see below) as well as leaving in
the earlier fix, it would get rid of the misleading "incompatible"
message and still produce an error that will keep these people
happy.


>  From: aka at cbrma.UUCP (Andy Kashyap)
>  A function call is an expression and can, therefore, be used anywhere an
>  expression can be used. When you declare a function (void), you state that
>  you intend to use that function as a statement instead, that you do not 
>  intend to use it in any operations. It can now only be used where a statement
>  can. Keep in mind that an expression is a statement, but NOT vice-versa.
>  
>  If you look up the reference section of K&R, somewhere it says something
>  like this (I don't have my K&R with me):
>      expression -> expression ? expression : expression
>  Thus you can not use a statement (ie (void) f1()) where an expression is
>  expected.

That did it.  You've finally convinced me of the error of my ways.
The "?:" expression has the same value and type as the two expressions
around the ":".  This type cannot be void.

I'm converted.  I've seen the light.  I'm studing the Bible much more
closely.  And look what I've found:

    comma-expression -> expression , expression
    The type and value of the result are the type and value
    of the right operand.
                                  DMR, Chapter 7, Verse 15.

But, isn't that what it says about the "?:" expression too?
Hallelujah!  I've found a sin in our compiler.  It actually
allows those evil "void expressions" on the right of a comma.
Why, this means we'll have to go back through the last few
weeks of news, take all those articles talking about void
functions and "?:" and repost them, this time changing the
"?:" to ",", since all the arguments in them hold equally
well.

In the meantime, I urge everyone (well, those mentioned above anyway),
to put the follwing fix into their compilers.  I'm sure it will find
many occurrences of this sin that may have crept into their code over
the years.


void f3(which)
{
    extern void f1(),f2();
    which?f1():f2();
}
cc(1) gives an "incompatible types" error.


In /usr/src/lib/mip/trees.c add the lines indicated by "->>".

    ...
    opact( p )  NODE *p; {
    ...
        switch( optype(o=p->in.op) ){
    ...
            case QUEST:          /* Look, the two cases are already common. */
            case COMOP:          /* This must prove the devine intent. */
->> #ifdef I_HAVE_BEEN_SAVED
->>             if (!mt2) uerror("'%s' returns void expression", opts[o]);
->> #endif
    ...
            case COLON:
                if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
                else if( mt12 & MDBI ) return( TYMATCH );
    ...
                else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
->>             else if ( mt1==mt2 ) return TYPL;
                break;
            case ASSIGN:



More information about the Comp.lang.c mailing list