Clarification on Gcc's strict aliasing rules

Patrick Horgan phorgan1@yahoo.com
Fri Nov 12 23:04:00 GMT 2010


On 11/12/2010 11:45 AM, Francis Moreau wrote:
... elision by patrick
> No.
>     t.d = 3.0;
>     i = t.i;
>
> is well defined in C.
>
> Again, what's ambiguous is the example given by the GCC man:
>
>     int *ip;
>     t.d = 3.0;
>     ip =&t.i;
>     return *ip;
>
> which produces code that might or not work.
>
> 6.5p7 lists this as a possible alias case and I can't find any rule in
> the standard that could invalidate it.
Well, 6.2.5 Types
21 Arithmetic types and pointer types are collectively 
called scalar types. Array and
   structure types are collectively called aggregate 
types.46)
     46) Note that aggregate type does not include 
union type because an object with union type can only 
contain one member at a time.

So technically accessing a different member is 
undefined behavior, but realistically you'll get 
"something", and this is how people do things like deal 
with endian issues without running afoul of strict 
aliasing issues.  int vs double is a bit of a stretch, 
allow though you might imagine a struct with bit fields 
that let you look at the different parts of the 
double.  (Again, I know, accessing in this way is 
undefined behavior.  But see 6.2.6

In general, you're looking at 6.5 differently than the 
people that wrote it.  6.5 is a set of rules for 
compiler writers to know when things might alias so 
that they don't do optimizations that don't make 
sense.  For example if lvalues t1 and t2 can alias, 
then you can't reorder accesses if the value of the 
object referred to by one of them is changed.  You 
can't pull an apparently loop invariant assignment to 
one of them out of a loop if an assignment to another 
is also in a loop.  You can't replace the use of one by 
a constant assigned to it if intervening assignments 
are made to the other.  6.5p7 is meant for things like:

union u{
    int i;
    double p;
} thisistheunion.

void foo(u& theunion, int & theint)
{
    // inside here theunion.i and theint have to be 
considered as potentially aliasing
    // since we could have been called like  
foo(thisistheunion, thisistheunion.i)
    // don't do any optimizations that might break if 
this is true.
    ... lots of most excellent code ...
}

What you're really looking at is type punning not 
aliasing.  Footnote 94 is interesting:

94) If the member used to access the contents of a 
union object is not the same as the member last used to 
store a value in the object, the appropriate part of 
the object representation of the value is reinterpreted 
as an object representation in the new type as 
described in 6.2.6 (a process sometimes called ‘‘type 
punning’’). This might be a trap representation.

In general though, if you want to access something as 
other than it's lvalue type, the ONLY supported way 
according to the standard is through access as chars.

> So either GCC is not conformant in this regard or I'm missing something.
>
> Thanks



More information about the Gcc-help mailing list