GCC aliasing rules: more aggressive than C99?

Patrick Horgan phorgan1@yahoo.com
Wed Jan 6 06:45:00 GMT 2010


Erik Trulsson wrote:
> Moreover I think you are misinterpreting 6.5 clause 7 (which I concede is
> fairly easy since it is not quite as unambiguous as one could wish).
> I believe that paragraph should not be interpreted as automatically allowing
> all accesses that correspond to one of the sorts listed.  Rather it should
> be interpreted as saying that if an access is not included in that list then
> it is not allowed, but even if it is included in that list there could be
> other reasons why it is not allowed.  (I.e.  just as the attached footnote
> suggests it is a list of what types of aliasing are allowed, not of which
> pointers may be dereferenced.)
>   
Good point, they're saying that something other than this list is 
undefined for sure.

While the C Standard says in this section:

7 An object shall have its stored value accessed only by an lvalue 
expression that has one of the following types:78)
with footnote 78 saying:
78) The intent of this list is to specify those circumstances in which 
an object may or may not be aliased.

The same section of the C++ standard says:
15 If a program attempts to access the stored value of an object through 
an lvalue of other than one of the following types the behavior is 
undefined:49)
with footnote 49 saying:
49) The intent of this list is to specify those circumstances in which 
an object may or may not be aliased.

The content of the section is almost identical, and both say identically 
word for word:
— an aggregate or union type that includes one of the aforementioned 
types among its members (including, recursively, a member of a 
subaggregate or contained union),

and I think that the intent of the C version is the same as the C++ 
clearly states. This is a list of all the ways to access a stored value 
through an lvalue. Anything else is undefined behavior. So constructing 
code to bypass the pointer issues, gcc does allow accessing an int value 
through a lvalue that is a union that contains an int like this:

int i;
union u{ int x; };
printf("%d\n",(*((union u*)&i)).x);

although it's perverse, it doesn't seem to break any aliasing rules and 
neither gcc (nor g++ with an equivalent std::cout line), complain about 
it with maximum aliasing bitching turned on. And indeed, the problems 
with aliasing are more like the cool part about the structs I elided 
above. -fstrict-aliasing is a promise to the compiler that you aren't 
going to do weird things like:

void foo(int, float);

union u{
int a;
float b;
}

foo(u.a, u.b);

so that it can do some types of optimizations it couldn't otherwise do. 
-Wstrict-aliasing tries to warn you if you break the promise, although 
if the definition and call are in different compilation units gcc won't 
know.

A funnier example of something that seems not to break the above 
aliasing rules, (really equivalent to the printf above), the following 
when compiled with -fstrict-aliasing -Wstrict-aliasing=3 doesn't get 
complained about by 4.4.1 or 4.5.0 at least.

#include <stdio.h>
union u { int x; };

void
foo(union u theu)
{
printf("%d\n",theu.x);
}

int main()
{
int i=7;
foo(*((union u*)&i));
return 0;
}

Patrick




More information about the Gcc mailing list