This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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