Email List: Xaustin-group-lX
[All Lists]

RE: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem

To: "Schwarz, Konrad" <konrad.schwarz@xxxxxxxxxxx>
Subject: RE: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem
From: "Wojtek Lerch" <Wojtek@xxxxxxx>
Date: Fri, 3 Jul 2009 12:09:44 -0400
Cc: <austin-group-l@xxxxxxxxxxxxx>
References: <e26e5335cda9d0dfe49395e6115066fe@austingroupbugs.net> <1730938080F74546ACC51CB65BA00565@ott.qnx.com> <20090702094404.GA28393@squonk.masqnet> <4A4CC239.2040603@qnx.com> <5030E566C603DA449D6B4C060CE529B73A8F37@MCHP7RDA.ww002.siemens.net> <4A4D2366.9090904@qnx.com> <5030E566C603DA449D6B4C060CE529B73A8FF1@MCHP7RDA.ww002.siemens.net>
Thread-index: Acn7WujWGeMqB9+ARVOvty8p0UGcfwAS+nFQAAzQ9yA=
Thread-topic: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem
 
> From: Schwarz, Konrad [mailto:konrad.schwarz@siemens.com] 
> > From: Wojtek Lerch [mailto:wojtek@qnx.com] 
> > >   A pointer to <b>void</b> may be converted to or from a pointer
> > > to any function type.
> > 
> > You would want to allow converting *any* void pointers to function 
> > pointers?

Sorry about that one.  You just copied that sentence from the C
standard.  I don't know if it's just me, but I think it doesn't really
need to be there and the standard would be clearer without it.  With
that text in, you need to separately say that not all void* pointers can
be safely converted to pointers to function.  (For conversions of data
pointers, the C standard says that when it talks about alignment
requirements.)

> > >>I don't think it's a good idea to introduce unusual 
> > >>restrictions on what 
> > >>the void* pointer can be converted to.  Can I convert it 
> to a "void 
> > >>const*"?  What about a "void *const"?  Why would it need to 
> > >>be undefined 
> > >>behaviour to convert it to a char*, even though standard C 
> > intends to 
> > >>allow converting any valid void* pointer to char*?
...
> I think POSIX should continue to allow all these conversions.  Thus,
> it can remain silent on the issue.

Silent would be fine.  My objection is against saying that it's
undefined behaviour to convert the pointer to any type other than a
function pointer, or to use it for any purpose other than a conversion
to a function pointer, without meaning exactly that.

>  The only important things are that
> pointers to objects have the same size as pointers to functions and
> that NULL pointers are mapped to NULL pointers.

Don't you mean *at least* the same size?  (BTW Pedantically speaking,
it's not the size that matters: a type could have a big size but be full
of padding bits not used to represent the value.  I don't think there's
a need to talk specifically about the size -- the real requirement that
a conversion must be reversible, and the fact that it can't be satisfied
without having enough bits in a void* doesn't need to be mentioned
separately.)
 
> > OK, but still, it's not obvious to me that this necessarily 
> > applies to 
> > conversions that have undefined behaviour in standard C.
> 
> According to 3.4.3, in ANSI C, undefined behavior is "behavior,
> upon use of a nonportable or erroneous program construct [...]
> for which this International Standard imposes no requirements."
> 
> What POSIX is doing here is making one instance of undefinded behavior
> defined.  Everything else continues to apply as usual.

I don't think it's that simple.  POSIX it making the result of certain
undefined conversions defined, by introducing a new category of pointer
values.  There's no such thing as "as usual", because the C standard was
not originally meant to describe the behaviour of those new values; its
wording may rely on the assumption that such values do not exist, and it
may break in surprising ways if they do.

> > Normally a void* pointer can be compared to another void* 
> pointer; if 
> > you make it undefined behaviour for some valid pointers, you'll be 
> > introducing an inconsistency that people will tend to forget 
> > about.  My 
> > feeling is that it would be better to allow comparing but 
> > discourage it 
> > by saying that the result is unspecified.
> 
> Section 6.3.2.3 only defines the equality of pointers
> to non-void type.

No, it talks in a few places about the equality of pointers to an object
or incomplete type.  Void is an incomplete type.

>   However, 6.5.9, Equality Operators,
> specifies that comparison of an object pointer with a
> void pointer converts the void pointer to the type of
> the object pointer.

No, it's the other pointer that's converted to a void pointer: "If one
operand is a pointer to an object or incomplete type and the other is a
pointer to a qualified or unqualified version of void, the former is
converted to the type of the latter."
 
> So POSIX would have to specify that the analogous
> conversion would need to be done for function pointers,
> if it wanted to allow arbitrary comparisons of (uncasted)
> void pointers with function pointers.

No, I wasn't talking about comparing a pointer to function with a
pointer to void.  That's a constraint violation in standard C, and I
would prefer POSIX to keep it that way.

I was talking about comparing two pointers to void, if one or both
pointers are converted function pointers:

  void *ptr1 = (void*) malloc, *ptr2 = (void*) free, *ptr3 = (void*)
free;
  if ( ptr1 == "hi" ) ... // Defined?  Guaranteed to be false?
  if ( ptr1 == ptr2 ) ... // Defined?  Guaranteed to be false?
  if ( ptr2 == ptr3 ) ... // Defined?  Guaranteed to be true?
 
> However, I suspect that at least
> some compilers emit a warning here---changing this
> would require changes to those compilers.  This is
> probably not warranted.

Some compilers have really bizzare ideas about what deserves a warning.
I don't think POSIX has the authority (or should have the ambition) to
change that.
 
> > >   If a pointer to any function type, converted to a pointer to
> > > <b>void</b>,
> > >   is used for any purpose other than conversion back to a pointer
> > > to a
> > >   function or comparison with a null pointer, the behavior is
> > > undefined.
> > 
> > Comparison with a null pointer, or specifically with a null pointer 
> > cstant?
> 
> For consistency with the rest of the C standard, which alows
> comparing function pointers with null pointers, not just
> null pointer constants, a null pointer.  (See paragraph 3).

I don't think that paragraph means to override the constraints on the
pointer types that can be compared with each other.  It's just trying to
say that when you compare a pointer that points to a function or an
object with a null pointer *of a type that you're allowed to compare it
to*, then the result is false.

> On the other hand, paragraph 4 says that conversion of a null pointer
> to another pointer type yields a null pointer of that type.  Any
> two null pointers shall compare equal.  So null pointers are covered
> already.

Interesting.  It does seem to say that converting between a data pointer
and a function pointer is defined, as long as the value being converted
is a null pointer.  I wonder if that's intentional.  My suspicion is
that it's not, and that the problem is that 6.3.2.3 is unclear about
when it intends to describe constraints, and when it's talking about
behaviour.  It would definitely help to have Clive D.W. Feather's
insight on this.

> > Can't it be used in an assignment?  In a compound literal?  
> > Passed to a 
> > function?  Returned from a function?  Used to initialize a 
> variable? 
> > Converted to void?  To _Bool?  To another function pointer 
> > stored in a 
> > void*?
> 
> You are right, my second paragraph is too limiting.  Perhaps it
> would suffice to say that the result of converting a function
> designator to a void pointer results in an invalid object pointer,
> similarly, the result of converting the address of an object to a
> function pointer results in an invalid function pointer.

I don't like the idea of calling it an "invalid" pointer -- that sounds
too much like how the C standard sometimes refers to an "indeterminate
value".  I think it needs to be considered a valid value.  But if you
don't promise that it points to an object or to past the end of an array
(or that it does not), I think it will follow that it can't be safely
incremented, decremented, or dereferenced.
 
> Additionally, it might be worth stating that conversion of a function
> pointer
> to an intptr_t or uintptr_t and back will result in a value 
> equal to the
> original pointer.

That would be an additional requirement, not strictly necessary for
dlsym() to work.

<Prev in Thread] Current Thread [Next in Thread>