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
This commit is contained in:
Richard Henderson 2004-08-26 17:37:48 -07:00 committed by Richard Henderson
parent 525c6bf5a6
commit ee8a6a3ee5
6 changed files with 94 additions and 37 deletions

View File

@ -1,3 +1,14 @@
2004-08-26 Richard Henderson <rth@redhat.com>
* 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 <rth@redhat.com>
* tree.c (staticp): Return the static object.

View File

@ -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"

View File

@ -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 *);

View File

@ -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:

View File

@ -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. */

View File

@ -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);
}