Hi, this is a regression present on the mainline and 4.6 branch caused by the constructor uniquization patch. The tree_output_constant_def routine rejects offsetof-like computations that can be written in the C family of languages. While the C compiler folds most of them early, it doesn't if an intermediate folding step is required.
The proposed fix is to make c_fully_fold also do the offsetof folding. Tested on x86_64-suse-linux, OK for mainline and 4.6 branch? 2011-09-06 Eric Botcazou <ebotca...@adacore.com> PR middle-end/50266 * c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Fold offsetof-like computations. 2011-09-06 Eric Botcazou <ebotca...@adacore.com> * gcc.dg/init-offsetof-1.c: New test. -- Eric Botcazou
Index: c-common.c =================================================================== --- c-common.c (revision 178488) +++ c-common.c (working copy) @@ -1264,7 +1264,18 @@ c_fully_fold_internal (tree expr, bool i STRIP_TYPE_NOPS (op0); if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR) op0 = decl_constant_value_for_optimization (op0); - if (op0 != orig_op0 || in_init) + if (op0 != orig_op0 + && code == ADDR_EXPR + && (op1 = get_base_address (op0)) != NULL_TREE + && TREE_CODE (op1) == INDIRECT_REF + && TREE_CONSTANT (TREE_OPERAND (op1, 0))) + { + tree offset = fold_offsetof (op0, op1); + op1 + = fold_convert_loc (loc, TREE_TYPE (expr), TREE_OPERAND (op1, 0)); + ret = fold_build_pointer_plus_loc (loc, op1, offset); + } + else if (op0 != orig_op0 || in_init) ret = in_init ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0) : fold_build1_loc (loc, code, TREE_TYPE (expr), op0);
/* PR middle-end/50266 */ /* Testcase by <b...@arklinux.org> */ /* { dg-do compile } */ /* { dg-options "-Os" } */ struct a { unsigned int a; unsigned int b; }; struct a *const p = (struct a *)0x4A004100; void foo(void) { unsigned int i = 0; unsigned int *const x[] = { &p->a, &p->b, 0 }; (*(volatile unsigned int *)((x[i])) = (unsigned int)((unsigned int)((*(volatile unsigned int *)(x[i]))))); }