Keith Thompson <
ks...@mib.org> writes:
> Consider the following toy program:
>
> int main(void) {
> void *void_ptr = 0;
> void (*func_ptr)(void) = (void(*)(void))void_ptr;
> return 0;
> }
>
> (Note that void_ptr is *not* a null pointer constant, it's merely a
> pointer object that happens to contain a null pointer.)
>
> Is the conversion of void_ptr to void(*)(void) (a pointer-to-function
> type) permitted?
>
> N1570 6.5.4 lists three constraints for the cast operator. This code
> doesn't violate any of them.
>
> N1570 6.3.2.3 describes the semantics of conversions involving pointers.
> It mentions conversions from void* to and from pointer-to-object types,
> conversions from one pointer-to-object type to another, and conversions
> from one pointer-to-function type to another. Conversions from void* to
> a pointer-to-function type simply aren't mentioned.
>
> My conclusion is that the conversion is permitted (it doesn't violate
> any constraint or syntax rule), but its behavior is undefined by
> omission.
I agree with this conclusion.
> Note that the authors of gcc seem to have a different interpretation;
> on the above code, gcc-4.7 with "-std=c99 -pedantic" produces the
> following warning:
>
> warning: ISO C forbids conversion of object pointer to function pointer type [-pedantic]
I interpret gcc's message differently, especially since it is a
warning. Since there is at least potential confusion about
whether the ISO standard allows such conversions, they feel
obliged to give a diagnostic (but without preventing compilation)
to be on the safe side for being a conforming implementation.
When in doubt, issue a diagnostic - no harm for being wrong
on that side of the fence.
> Frankly I think it would make more sense if the conversion *were*
> a constraint violation, or else if its behavior were explicitly
> stated to be undefined (or the result to be implementation-defined
> or unspecified).
The problem is, for this particular case none of those categories
are really quite right. One implementation might think it's okay
and sensible and perfectly acceptable, whereas another might
choose to treat it as an unrecoverable translation failure. It
isn't just executing such a conversion, but even writing an
expression (ie, a cast) that specifies such a conversion, crosses
over into undefined behavior. And, apparently the Standard wants
to give all of that latitude, in both directions (including not
having to issue any diagnostics), for implementations to use as
they see fit. I don't know offhand of any other construct that
falls into exactly this category.