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
PR middle-end/50266
* c-common.c (c_fully_fold_internal) : Fold offsetof-like
computations.
2011-09-06 Eric Botcazou
* 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 */
/* { 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]);
}