Possible gcc bug in strict type aliasing

Vincent Lefevre vincent+gcc@vinc17.org
Tue Sep 27 13:39:00 GMT 2016


On 2016-09-27 14:10:13 +0100, Andrew Haley wrote:
> On 27/09/16 13:49, Vincent Lefevre wrote:
> > On 2016-09-26 10:32:14 +0100, Andrew Haley wrote:
> >> On 25/09/16 22:46, David Brown wrote:
> >>
> >> I think the bug is here:
> >>
> >>>        temp = *t2p;      // Read as T2
> >>>        t1p2 = (T1*)t2p;  // Visible T2 to T1 pointer conversion
> >>>        *t1p2 = temp;     // Write as T1
> >>
> >> 6.3.2.3 Pointers
> >>
> >> 7 A pointer to an object type may be converted to a pointer to a
> >>   different object type. If the resulting pointer is not correctly
> >>   aligned for the referenced type, the behavior is undefined.
> >>   Otherwise, when converted back again, the result shall compare equal
> >>   to the original pointer.
> >>
> >> Note that you have permission only to convert the pointer back to the
> >> original type and compare it.  You don't have permission to
> >> dereference it as a different type.  IMO your program is undefined.
> > 
> > I disagree. The above paragraph says nothing about dereferencing the
> > pointer; in particular, it does not disallow one to dereference it
> > as a different type.
> 
> Perhaps you are right with regard to original intent, but if so it's
> very oddly worded.

Hmm... I think I see your point. If I understand correctly you meant
that the standard does not define how the pointer is converted, and
it may magically point to some completely different place (address),
the only requirement being that when doing the reverse conversion,
one would get the original address.

I'm thinking of an example like the following one. Assume that you
have two different types T1 and T2 (not character types, otherwise
the conversion is well-defined by the standard) with the same size
and alignment requirements.

  T1 t;
  T1 *p1;
  T2 *p2;

  p1 = &t;
  p2 = (T2 *) p1;

I suppose that the compiler may choose as conversion rules:
  * When converting T1 * to T2 *, sizeof(T1) is added to the address.
  * When converting T2 * to T1 *, sizeof(T2) is subtracted from the
    address.

I suppose that such an implementation could be conforming. But David's
example would no longer work.

A solution could be:

  p2 = (T2 *) (void *) p1;

> AIUI without any explicit description of what should happen in any
> situation, all bets are off.  This is the usual way of writing
> language specifications, and indeed standards in general.  6.3.2.3
> does not say that the converted pointer may be used for anything other
> than an equality comparison; if there was the intention that anything
> else was possible, why only mention equality comparisons?

No, with the above point, one cannot even use this in a useful way
for comparisons (but one could use void * for comparisons).

But it might be a defect in the standard (or something I haven't
seen).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)



More information about the Gcc-help mailing list