From ee8a6a3ee5d35c2e188225c2bbb58c2cca69a2ab Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 26 Aug 2004 17:37:48 -0700 Subject: [PATCH] c-typeck.c (build_offsetof): Remove. * 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. From-SVN: r86651 --- gcc/ChangeLog | 11 +++++++++ gcc/c-common.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/c-common.h | 2 ++ gcc/c-parse.in | 24 ++++++++++++------- gcc/c-tree.h | 1 - gcc/c-typeck.c | 28 ---------------------- 6 files changed, 94 insertions(+), 37 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cf1dc09c719..84af91f9e9e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2004-08-26 Richard Henderson + + * 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. + 2004-08-26 Richard Henderson * tree.c (staticp): Return the static object. 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" diff --git a/gcc/c-common.h b/gcc/c-common.h index 94f3249b21b..e9a91d50fdd 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -870,6 +870,8 @@ extern void c_warn_unused_result (tree *); extern void verify_sequence_points (tree); +extern tree fold_offsetof (tree); + /* In c-gimplify.c */ extern void c_genericize (tree); extern int c_gimplify_expr (tree *, tree *, tree *); diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 85927d4f359..c28b1565c84 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -275,6 +275,9 @@ static GTY(()) tree all_prefix_attributes; all_prefix_attributes. */ static GTY(()) tree declspec_stack; +/* INDIRECT_REF with a TREE_TYPE of the type being queried for offsetof. */ +static tree offsetof_base; + /* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK should be called from the productions making use of setspecs. */ #define PUSH_DECLSPEC_STACK \ @@ -681,8 +684,15 @@ primary: { $$.value = build_va_arg ($3.value, groktypename ($5)); $$.original_code = ERROR_MARK; } - | OFFSETOF '(' typename ',' offsetof_member_designator ')' - { $$.value = build_offsetof (groktypename ($3), $5); + | OFFSETOF '(' typename ',' + { tree type = groktypename ($3); + if (type == error_mark_node) + offsetof_base = error_mark_node; + else + offsetof_base = build1 (INDIRECT_REF, type, NULL); + } + offsetof_member_designator ')' + { $$.value = fold_offsetof ($6); $$.original_code = ERROR_MARK; } | OFFSETOF '(' error ')' { $$.value = error_mark_node; $$.original_code = ERROR_MARK; } @@ -753,17 +763,15 @@ primary: /* This is the second argument to __builtin_offsetof. We must have one identifier, and beyond that we want to accept sub structure and sub - array references. We return tree list where each element has - PURPOSE set for component refs or VALUE set for array refs. We'll - turn this into something real inside build_offsetof. */ + array references. */ offsetof_member_designator: identifier - { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); } + { $$ = build_component_ref (offsetof_base, $1); } | offsetof_member_designator '.' identifier - { $$ = tree_cons ($3, NULL_TREE, $1); } + { $$ = build_component_ref ($1, $3); } | offsetof_member_designator '[' expr ']' - { $$ = tree_cons (NULL_TREE, $3.value, $1); } + { $$ = build_array_ref ($1, $3.value); } ; old_style_parm_decls: diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 5c99f47aa0e..f9f06eb517c 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -277,7 +277,6 @@ extern tree c_finish_return (tree); extern tree c_finish_bc_stmt (tree *, bool); extern tree c_finish_goto_label (tree); extern tree c_finish_goto_ptr (tree); -extern tree build_offsetof (tree, tree); /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ca6e9f372a7..aa04ac0d24a 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -7583,31 +7583,3 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return result; } } - -/* Build the result of __builtin_offsetof. TYPE is the first argument to - offsetof, i.e. a type. LIST is a tree_list that encodes component and - array references; PURPOSE is set for the former and VALUE is set for - the later. */ - -tree -build_offsetof (tree type, tree list) -{ - tree t; - - /* Build "*(type *)0". */ - t = convert (build_pointer_type (type), null_pointer_node); - t = build_indirect_ref (t, ""); - - /* Build COMPONENT and ARRAY_REF expressions as needed. */ - for (list = nreverse (list); list ; list = TREE_CHAIN (list)) - if (TREE_PURPOSE (list)) - t = build_component_ref (t, TREE_PURPOSE (list)); - else - t = build_array_ref (t, TREE_VALUE (list)); - - /* Finalize the offsetof expression. For now all we need to do is take - the address of the expression we created, and cast that to an integer - type; this mirrors the traditional macro implementation of offsetof. */ - t = build_unary_op (ADDR_EXPR, t, 0); - return convert (size_type_node, t); -} -- 2.30.2