This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GCC aliasing rules: more aggressive than C99?


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]