----- Original Message ----- 
From: "Nicholas Clark" <[EMAIL PROTECTED]>
To: "Brian Lee Ray" <[EMAIL PROTECTED]>
Cc: "Josh Wilmes" <[EMAIL PROTECTED]>; <[EMAIL PROTECTED]>
Sent: Saturday, February 23, 2002 5:32 AM
Subject: Re: [PATCH] Bowing to necessity (was Re: [PATCH]Macro bulletproofing )


> On Sat, Feb 23, 2002 at 03:21:08AM -0600, Brian Lee Ray wrote:
> > 
> > From: "Josh Wilmes" <[EMAIL PROTECTED]>
> 
> > > Using NULL where a function pointer is expected is considered an error by
> > > tcc, and a mandatory warning by lcc.  It is my understanding that
> > conversion
> > > between data pointers and function pointers is forbidden under ANSI C89.
> 
> > The relevant excerpt:
> >     Using NULL in this way is perfectly conforming, as it is
> >     expressly allowed by the standard in 6.2.2.3:
> > 
> >     ===================
> >        An integral constant expression with the value 0, or such an
> >     expression cast to type void *, is called a null pointer
> >     constant.  If a null pointer constant is assigned to or compared
> >     for equality to a pointer, the constant is converted to a
> >     pointer of that type.  Such a pointer, called a null pointer, is
> >     guaranteed to compare unequal to a pointer to any object or
> >     function.
> > 
> >        Two null pointers, converted through possibly different
> >     sequences of casts to pointer types, shall compare equal.
> >     ====================
> > Still, if tcc won't take it, there's no sense in whining about it. This
> > should fix it:
> 
> Function pointers are not data pointers.
> 
> [And thinking about it, that excerpt doesn't say that. I hope its context did,
> else I'd accuse the standard of being unclear]
I don't see the words "data pointer" anywhere in the excerpt, and I didn't mean
to imply that object pointers were compatible with function pointers. They aren't.
However, a null pointer constant, expressed as either 0 or (void*)0 (and the
definition of NULL must be one of the above), can be safely compared with 
or assigned to either a function pointer or a data pointer. Consider the following:

void *v=NULL;
typedef void(*fptr)(void);
fptr f;


1:f=v; /*invalid: assignment of a void pointer to a function pointer*/
2:f=0;f=NULL;f=(void*)0; /*all valid: assignment of a null pointer
                          *constant to a function pointer*/
3:v=f; /*invalid: assignment of a function pointer to a void pointer*/
4:f==0;/*valid:comparison of a function pointer to a null pointer constant*/
5:f==(void*)0;/*valid:comparison of a function pointer to a null pointer constant*/
6:f==NULL;/*valid:comparison of a function pointer to a null pointer constant*/
7:f==(fptr)v;/*must compile, however, unless both f and v are null pointers,
              *the result is undefined. I would expect a warning for this, as
              *it is a really stupid thing to do. after all, if you know that
              *f and v are both null pointers, the result will hardly be surprising*/


> There is some-or-other rather old Cray architecture where they are
> sufficiently different that casting a function pointer to (void *) and then
> back to a function pointer was enough to garble the function pointer.
> [This was a perl5 bug report from 2 or 3 years ago. It was something to do
> with how source filters were stashing a function pointer in an unused bit of
> an IO structure, IIRC. It got fixed, with a union, IIRC]
that's a case of 1: and 3: above. that's a valid argument for the definition
of funcptr_t. however, since 2: and 6: are both valid, the following:
#define NULLfunc NULL
will perforce produce correct code on any conforming implementation.

> Function pointers are not data pointers, compilers are allowed to warn.
Yes, a compiler can warn about anything at any time according to the
ANSI standard. However, for a strictly conforming program, it must produce
an executable image which produces the expected output, therefore it is my
contention that if the following program:

-----begin test.c------
#include <stdio.h>
int main(void)
{
    void(*f)(void);
    f=NULL;
    if(f==NULL)
        puts("skippy");
    return 0;
}
------end test.c-------
does not both compile and place the string "skippy" on stdout (followed by a
newline) on tcc, then tcc is not a conforming C implementation.

> [Actually, shouldn't conformant compilers always issue a diagnostic, as
> you're doing something not allowed by the standard]
There are surprisingly few cases where a diagnostic is required, mainly
syntax errors. not of the above require a diagnostic, but nice compilers
give diagnostics for things which aren't requried to produce them but
which are still wrong.

thus, lcc is well within it's rights to output a warning, but in my opinion,
outputing a diagnostic for well defined and innocuous code (such as 2,4,5 and
6 above) is a mistake. it might just as well complain about "warning: value 0
returned from main" or "warning: integer initialized to 666. you're going to hell"
> 
> 
> It seems that your mailer or something on the way has "helpfully" wrapped all
> the lines in your patch. Don't you just love them?
yeah, i've reprimanded it :). should I resend my first patch with the part in question
removed since there's disagreement about it?

brian.


Reply via email to