https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92152
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- In particular this testcase seems to be exactly what is tested in gcc.dg/tree-ssa/alias-access-path-4.c: struct a {int v1; int v2;}; struct b {struct a a[0];}; union c {struct b b;}; int test2 (struct b *bptr1, union c *cptr, int i, int j) { bptr1->a[i].v1=124; cptr->b.a[j].v1=1; return bptr1->a[i].v1; } /* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */ and with my fix which looks like the following, this case breaks somehow... diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 670676f20c3..55c28514d0b 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1043,7 +1043,9 @@ aliasing_component_refs_p (tree ref1, end_struct_ref1 = base1; } if (TREE_CODE (base1) == VIEW_CONVERT_EXPR - || TREE_CODE (base1) == BIT_FIELD_REF) + || TREE_CODE (base1) == BIT_FIELD_REF + || (TREE_CODE (base1) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (base1, 0))) == UNION_TYPE)) ref1 = TREE_OPERAND (base1, 0); base1 = TREE_OPERAND (base1, 0); } @@ -1057,7 +1059,9 @@ aliasing_component_refs_p (tree ref1, end_struct_ref2 = base2; } if (TREE_CODE (base2) == VIEW_CONVERT_EXPR - || TREE_CODE (base2) == BIT_FIELD_REF) + || TREE_CODE (base2) == BIT_FIELD_REF + || (TREE_CODE (base2) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (base2, 0))) == UNION_TYPE)) ref2 = TREE_OPERAND (base2, 0); base2 = TREE_OPERAND (base2, 0); } this is because we later check if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0 && (!end_struct_ref1 || compare_type_sizes (TREE_TYPE (ref2), TREE_TYPE (end_struct_ref1)) >= 0) and the union type is of size zero while the size of the array decays to the size of struct a. That looks like another latent issue to me. Guess we may not really strip access paths this way if we rely on sizes being those of the actual access (and the appearant size _shrinking_ when dropping part of the access path...). IIRC we need to use the original ref for type size compares. Even then we end up comparing an integer against an aggregate and never enter this check. The code is really somewhat weird given the zero type sizes involved here (both bases have zero size). Honza?