This is the mail archive of the gcc-patches@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]

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


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!

Richard.

2009-01-11  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38806
	* tree-ssa-structalias.c (may_alias_p): Do not do false pruning
	on pointer-to-union points-to sets.

	* gcc.c-torture/execute/20090111-1.c: New testcase.
	* gcc.dg/tree-ssa/20030807-7.c: XFAIL again.

Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c	(revision 143251)
--- gcc/tree-ssa-structalias.c	(working copy)
*************** may_alias_p (tree ptr, alias_set_type me
*** 4743,4749 ****
  
    /* If the alias sets don't conflict then MEM cannot alias VAR.  */
    if (mem_alias_set != var_alias_set
!       && !alias_set_subset_of (mem_alias_set, var_alias_set))
      return false;
  
    return true;
--- 4743,4754 ----
  
    /* If the alias sets don't conflict then MEM cannot alias VAR.  */
    if (mem_alias_set != var_alias_set
!       && !alias_set_subset_of (mem_alias_set, var_alias_set)
!       /* If the pointer points to a union then we have to allow
!          GCCs union type-punning extension.  */
!       && ((TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) != UNION_TYPE
! 	   && TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) != QUAL_UNION_TYPE)
! 	  || !alias_set_subset_of (var_alias_set, mem_alias_set)))
      return false;
  
    return true;
Index: gcc/testsuite/gcc.c-torture/execute/20090111-1.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/20090111-1.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/20090111-1.c	(revision 0)
***************
*** 0 ****
--- 1,19 ----
+ union U { float f; int i; };
+ 
+ /* GCC says the access through the union does alias the bare variable.  */
+ int foo(union U *u, int *i)
+ {
+   *i = 1;
+   u->f = 0.0;
+   return *i;
+ }
+ 
+ extern void abort (void);
+ int main()
+ {
+   int i;
+   if (foo ((union U *)&i, &i) != 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c	(revision 143273)
--- gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c	(working copy)
*************** simplify_condition (cond_p)
*** 33,37 ****
  }
  
  /* There should be exactly one IF conditional.  */
! /* { dg-final { scan-tree-dump-times "if " 1 "vrp1" } } */
  /* { dg-final { cleanup-tree-dump "vrp1" } } */
--- 33,37 ----
  }
  
  /* There should be exactly one IF conditional.  */
! /* { dg-final { scan-tree-dump-times "if " 1 "vrp1" { xfail *-*-* } } } */
  /* { dg-final { cleanup-tree-dump "vrp1" } } */


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