summaryrefslogtreecommitdiff
path: root/gcc/c-family/c-common.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2011-09-06 21:17:46 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2011-09-06 21:17:46 +0000
commit737a23cc661aa8cd152f7bb381efa432354f4e8f (patch)
treef8ec4e3a49cb94b3bcb4c9ae1b5f59900b37958c /gcc/c-family/c-common.c
parenta9d7b961d748341cba0c86dfcf78dcec643735da (diff)
downloadgcc-737a23cc661aa8cd152f7bb381efa432354f4e8f.tar.gz
PR middle-end/50266
* c-common.c (c_fully_fold_internal) <ADDR_EXPR>: Fold offsetof-like computations. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178611 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-family/c-common.c')
-rw-r--r--gcc/c-family/c-common.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 9c42d5944da..d8028d34878 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1264,7 +1264,20 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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)
+ /* ??? Cope with user tricks that amount to offsetof. The middle-end is
+ not prepared to deal with them if they occur in initializers. */
+ 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);