[PATCH][RFC] Fix PR38806, wrong TBAA pruning with unions

Richard Guenther rguenther@suse.de
Sun Jan 11 18:25:00 GMT 2009


On Sun, 11 Jan 2009, Richard Guenther wrote:

> 
> I believe that GCC specifies that
> 
> union U { float f; int i; };
> 
> int main()
> {
>   int i;
>   union U *u = (union U *)&i;
>   i = 1;
>   u->f = 0.0;
>   if (i != 0)
>     abort ();
>   return 0;
> }
> 
> does not abort (at least that is what comments throughout
> the GCC source suggest.  For example:
> 
>   /* If strict aliasing applies the only way to access a scalar variable
>      is through a pointer dereference or through a union (gcc extension).  */
> 
> invoke.texi specifies
> 
> "
> Similarly, access by taking the address, casting the resulting pointer
> and dereferencing the result has undefined behavior, even if the cast
> uses a union type, e.g.:
> @smallexample
> int f() @{
>   double d = 3.0;
>   return ((union a_union *) &d)->i;
> @}
> "
> 
> as a recent addition.  Does this cover the case above?  Is the only
> type-punning we allow really
> 
>   union.a = x;
>   y = union.b;
> 
> ?  In this case c_common_get_alias_set should not need to return 0
> for unions either:
> 
>   /* Permit type-punning when accessing a union, provided the access
>      is directly through the union.  For example, this code does not
>      permit taking the address of a union member and then storing
>      through it.  Even the type-punning allowed here is a GCC
>      extension, albeit a common and useful one; the C standard says
>      that such accesses have implementation-defined behavior.  */
>   for (u = t;
>        TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
>        u = TREE_OPERAND (u, 0))
>     if (TREE_CODE (u) == COMPONENT_REF
>         && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
>       return 0;
> 
> Sigh, this exception always confuses me!

If it's really only accesses through unions that conflict the above
should return get_alias_set (TREE_OPERAND (u, 0)) instead of 0.
Thus, pretend to be an access of the whole union.  That will cause
all proper conflicts to happen (of course still also with non-union
accesses).  If we want to exclude all non-union-access conflicts
we would have to drop all alias subset recordings that do not end up
in another union (which might be sightly complicated to do).
And I wonder how much code we break there then?

Richard.



More information about the Gcc-patches mailing list