diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-08-27 00:37:48 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-08-27 00:37:48 +0000 |
commit | af28855bc1af90aa53b5de0a91ef843dce967545 (patch) | |
tree | dac64a782e7964b7582fea44120f93c164d43398 /gcc/c-common.c | |
parent | 82e3f297ce223cec0a87865f7ea87f03586979b1 (diff) | |
download | gcc-af28855bc1af90aa53b5de0a91ef843dce967545.tar.gz |
* c-typeck.c (build_offsetof): Remove.
* c-tree.h (build_offsetof): Remove.
* c-common.c (fold_offsetof_1, fold_offsetof): New.
* c-common.h (fold_offsetof): Declare.
* c-parse.in (offsetof_base): New.
(offsetof_member_designator): Use it. Build references, not just
a tree list.
(primary): Use fold_offsetof, not build_offsetof.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86651 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index 8b7ee2c94ea..03531d3ca03 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5436,4 +5436,69 @@ c_warn_unused_result (tree *top_p) } } +/* Build the result of __builtin_offsetof. EXPR is a nested sequence of + component references, with an INDIRECT_REF at the bottom; much like + the traditional rendering of offsetof as a macro. Returns the folded + and properly cast result. */ + +static tree +fold_offsetof_1 (tree expr) +{ + enum tree_code code = PLUS_EXPR; + tree base, off, t; + + switch (TREE_CODE (expr)) + { + case ERROR_MARK: + return expr; + + case INDIRECT_REF: + return size_zero_node; + + case COMPONENT_REF: + base = fold_offsetof_1 (TREE_OPERAND (expr, 0)); + if (base == error_mark_node) + return base; + + t = TREE_OPERAND (expr, 1); + if (DECL_C_BIT_FIELD (t)) + { + error ("attempt to take address of bit-field structure " + "member `%s'", IDENTIFIER_POINTER (DECL_NAME (t))); + return error_mark_node; + } + off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t), + size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1) + / BITS_PER_UNIT)); + break; + + case ARRAY_REF: + base = fold_offsetof_1 (TREE_OPERAND (expr, 0)); + if (base == error_mark_node) + return base; + + t = TREE_OPERAND (expr, 1); + if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0) + { + code = MINUS_EXPR; + t = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t)); + } + t = convert (sizetype, t); + off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); + break; + + default: + abort (); + } + + return size_binop (code, base, off); +} + +tree +fold_offsetof (tree expr) +{ + /* Convert back from the internal sizetype to size_t. */ + return convert (size_type_node, fold_offsetof_1 (expr)); +} + #include "gt-c-common.h" |