diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-09-06 21:17:46 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-09-06 21:17:46 +0000 |
commit | 737a23cc661aa8cd152f7bb381efa432354f4e8f (patch) | |
tree | f8ec4e3a49cb94b3bcb4c9ae1b5f59900b37958c /gcc/c-family/c-common.c | |
parent | a9d7b961d748341cba0c86dfcf78dcec643735da (diff) | |
download | gcc-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.c | 15 |
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); |