From: guenther on
On May 6, 8:28 am, William Ahern <will...(a)wilbur.25thandClement.com>
wrote:
> Geoff Clare <ge...(a)clare.see-my-signature.invalid> wrote:
....
> > The dlsym() example in POSIX that uses similar code is a bug in POSIX,
> > and is being corrected by this interpretation:
> >    http://austingroupbugs.net/view.php?id=74#c205
> > which (among many other things) changes the relevant line in the
> > example from
> >     *(void **)(&fptr) = dlsym(handle, "my_function");
> > back to
> >     fptr = (int (*)(int))dlsym(handle, "my_function");
> > (which is how it was in SUSv2).  This might also produce a warning
> > in some compilers, but implementations are required to accept it
> > and "do the right thing".
>
> Required by which standard? All conversions from a void pointer to a
> function pointer are undefined behavior in C, and all implementations are
> required to emit a diagnostic, and allowed to bail.

Can you please cite the relevant parts of the C standard that require
a diagnostic for that case? When this was most recently discussed on
the austin-group mailing list, no one could find such a requirement,
while there were agreed to be issues for the *(void **)&fptr from. To
pick an apropos message from the archive:

https://www.opengroup.org/sophocles/show_mail.tpl?CALLER=show_archive.tpl&source=L&listname=austin-group-l&id=12755

....though you should examine the entire thread for context. Visit
http://www.opengroup.org/austin/mailarchives/ag/

and do a subject search for "0000074".


Philip Guenther
From: Ersek, Laszlo on
On Thu, 6 May 2010, guenther(a)gmail.com wrote:

> On May 6, 8:28�am, William Ahern <will...(a)wilbur.25thandClement.com>
> wrote:

>> [snip] All conversions from a void pointer to a function pointer are
>> undefined behavior in C, and all implementations are required to emit a
>> diagnostic, and allowed to bail.

> Can you please cite the relevant parts of the C standard that require a
> diagnostic for that case?

I looked at C99 5.1.1.3 "Diagnostics" and 6.3.2.3 "Pointers". While
converting a pointer-to-void to a pointer-to-function is certainly
undefined behavior "by the omission of any explicit definition of
behavior" (C99 4. "Conformance" p2), I must admit that 6.3.2.3 doesn't
contain an explicit "Constraints" part -- like many other sections do
(most notably, the descriptions of operators). Therefore, 5.1.1.3 doesn't
seem to apply.

----v----
5.1.1.3 Diagnostics

1 A conforming implementation shall produce at least one diagnostic message
(identified in an implementation-defined manner) if a preprocessing
translation unit or translation unit contains a violation of any syntax
rule or constraint, even if the behavior is also explicitly specified as
undefined or implementation-defined. Diagnostic messages need not be
produced in other circumstances. [...]
----^----

In short, the explicit conversion (the cast operation) in question is
"only" undefined behavior, but (so it seems) not a syntax rule or
constraint violation, thus a diagnostic message need not be produced.

The current wording of SUSv4 XSH 2.12.3 "Pointer Types" defines the
conversion. It likely permits the type-punned pointer access too, by
fixing the representation. (Though I'm not sure if an additional note on
alignment is not missing.)

Cheers,
lacos
From: William Ahern on
Ersek, Laszlo <lacos(a)caesar.elte.hu> wrote:
> On Thu, 6 May 2010, guenther(a)gmail.com wrote:
> > On May 6, 8:28?am, William Ahern <will...(a)wilbur.25thandClement.com>
> > wrote:
>
> >> [snip] All conversions from a void pointer to a function pointer are
> >> undefined behavior in C, and all implementations are required to emit a
> >> diagnostic, and allowed to bail.
>
> > Can you please cite the relevant parts of the C standard that require a
> > diagnostic for that case?
>
> I looked at C99 5.1.1.3 "Diagnostics" and 6.3.2.3 "Pointers". While
> converting a pointer-to-void to a pointer-to-function is certainly
> undefined behavior "by the omission of any explicit definition of
> behavior" (C99 4. "Conformance" p2), I must admit that 6.3.2.3 doesn't
> contain an explicit "Constraints" part -- like many other sections do
> (most notably, the descriptions of operators). Therefore, 5.1.1.3 doesn't
> seem to apply.
<snip>
> In short, the explicit conversion (the cast operation) in question is
> "only" undefined behavior, but (so it seems) not a syntax rule or
> constraint violation, thus a diagnostic message need not be produced.

Perhaps. But my take on it was that since the conversion is undefined, what
exactly are you assigning? The pointer types in an assignment must be
compatible, otherwise it's an express constraint violation. See 6.5.16.1,
C99:TC3 draft n1256. If you can't write an expression which is assignable
under the constraints of 6.5.16.1, then presumably that requires a
diagnostic.

6.5.4, concerning the cast operator, on it's face seems to support the idea
that a cast is a declaration of the type, end of story, and any cast to a
proper type would be sufficient to meet the contraints of 6.5.16.1, no
matter whether the conversion is defined. And I agree this is the intuitive
interpretation.

But section 6.3 on conversions says that there's nothing special about a
cast. Casts can't obtain by _explicit_ conversion what isn't fundamentally
convertible; they can only obtain what _implicit_ conversion cannot, and of
course there are no implicit conversions between non-void pointers. Without
a conversion the type of the expression cannot change, and so you cannot
meet the 6.5.16.1 contraints.

In support of this latter interpretation, I should note that GCC in pedantic
mode does emit a diagnostic. At least according to my local man page, the
sole effect of `-pedantic' is to "issue all the warnings demanded by strict
ISO C". Though, the diagnostic description concerns the conversion, not the
assignment. But if we're concerned with _practical_ interpretations of the
standard, rather than _intuitive_, then GCC is persuasive authority.

> The current wording of SUSv4 XSH 2.12.3 "Pointer Types" defines the
> conversion. It likely permits the type-punned pointer access too, by
> fixing the representation. (Though I'm not sure if an additional note on
> alignment is not missing.)

True. There doesn't seem to be anything else which guarantees that a void
pointer doesn't have stricter alignment than a function pointer.

From: Ersek, Laszlo on
On Thu, 6 May 2010, William Ahern wrote:

> Ersek, Laszlo <lacos(a)caesar.elte.hu> wrote:
>> On Thu, 6 May 2010, guenther(a)gmail.com wrote:
>>> On May 6, 8:28?am, William Ahern <will...(a)wilbur.25thandClement.com>
>>> wrote:
>>
>>>> [snip] All conversions from a void pointer to a function pointer are
>>>> undefined behavior in C, and all implementations are required to emit a
>>>> diagnostic, and allowed to bail.
>>
>>> Can you please cite the relevant parts of the C standard that require a
>>> diagnostic for that case?
>>
>> I looked at C99 5.1.1.3 "Diagnostics" and 6.3.2.3 "Pointers". While
>> converting a pointer-to-void to a pointer-to-function is certainly
>> undefined behavior "by the omission of any explicit definition of
>> behavior" (C99 4. "Conformance" p2), I must admit that 6.3.2.3 doesn't
>> contain an explicit "Constraints" part -- like many other sections do
>> (most notably, the descriptions of operators). Therefore, 5.1.1.3 doesn't
>> seem to apply.
> <snip>
>> In short, the explicit conversion (the cast operation) in question is
>> "only" undefined behavior, but (so it seems) not a syntax rule or
>> constraint violation, thus a diagnostic message need not be produced.
>
> Perhaps. But my take on it was that since the conversion is undefined,

I've probably lost the thread of your reasoning, but I believe the point
is, the POSIX (SUSv4) XSH 2.12.3 "Pointer Types" section defines both the
representation and the conversion (separately). Thus if you take the C99
standard and fill in this single (intentional) white spot, and change
nothing else, the resultant specification "fixes" the *only* problem with
the expressions in question.


> what exactly are you assigning? The pointer types in an assignment must
> be compatible, otherwise it's an express constraint violation.

The

*(void **)&funptr = dlsym(...)

assignment has no problems with type compatibility (both sides are of type
pointer-to-void), it has problems with representation and alignment (even
before funptr is accessed in its own right). They are (or at least,
representation is) fixed by POSIX.

The

funptr = (funptr_type)dlsym(...)

assignment has no problem with type compatibility (both sides have type
funptr_type), it has problems with undefined conversion. That's also fixed
(defined) by POSIX.

I believe neither expression violates the constrains of simple assignment.

[snip]

Cheers,
lacos
From: William Ahern on
Ersek, Laszlo <lacos(a)caesar.elte.hu> wrote:
> On Thu, 6 May 2010, William Ahern wrote:
<snip>
> > Perhaps. But my take on it was that since the conversion is undefined,
>
> I've probably lost the thread of your reasoning, but I believe the point
> is, the POSIX (SUSv4) XSH 2.12.3 "Pointer Types" section defines both the
> representation and the conversion (separately). Thus if you take the C99
> standard and fill in this single (intentional) white spot, and change
> nothing else, the resultant specification "fixes" the *only* problem with
> the expressions in question.
>
> > what exactly are you assigning? The pointer types in an assignment must
> > be compatible, otherwise it's an express constraint violation.
<snip>
> funptr = (funptr_type)dlsym(...)
>
> assignment has no problem with type compatibility (both sides have type
> funptr_type), it has problems with undefined conversion. That's also fixed
> (defined) by POSIX.

> I believe neither expression violates the constrains of simple assignment.

My thread of reasoning is that simple assignment of pointers requires
compatible _types_, without which a diagnostic is required. In order to get
compatible types you need to have a conversion. There's no implicit
conversion allowed here, thus you need an explicit conversion--a cast. But a
cast can't convert what isn't covertible. There can be no conversion from a
void or object pointer to a function pointer. (Note that 6.3.2.3p7 allows
conversion between object pointers, so a typical object pointer cast is
making a well-defined conversion.) Therefore, there can't be a compatible
type to the right operand of the assignment no matter how emphatic the cast,
and the assignment constraint can be met.

Query: does the following require a diagnostic?

struct s { int a; } s;
int i;

i = (int)s; /* pretty please! */

I propose that the above is indistinguishable in this context from
attempting to cast a void pointer to a function pointer. I'm not sure it
improves my argument about requiring a diagnostic, but it does a better job
of showing what kind of distinctions I'm making.
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: How to find out the default gateway on Mac OSX?
Next: ack