diff options
Diffstat (limited to 'contrib/gcc/cp/expr.c')
-rw-r--r-- | contrib/gcc/cp/expr.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c index 4c3d8b6..83bdff9 100644 --- a/contrib/gcc/cp/expr.c +++ b/contrib/gcc/cp/expr.c @@ -1,6 +1,6 @@ /* Convert language-specific tree expression to rtl instructions, for GNU compiler. - Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -36,6 +36,62 @@ static tree extract_scalar_init PROTO((tree, tree)); static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode, enum expand_modifier)); +/* Hook used by output_constant to expand language-specific + constants. */ + +static tree +cplus_expand_constant (cst) + tree cst; +{ + switch (TREE_CODE (cst)) + { + case PTRMEM_CST: + { + tree type = TREE_TYPE (cst); + tree member; + tree offset; + + /* Find the member. */ + member = PTRMEM_CST_MEMBER (cst); + + if (TREE_CODE (member) == FIELD_DECL) + { + /* Find the offset for the field. */ + offset = convert (sizetype, + size_binop (EASY_DIV_EXPR, + DECL_FIELD_BITPOS (member), + size_int (BITS_PER_UNIT))); + + /* We offset all pointer to data members by 1 so that we + can distinguish between a null pointer to data member + and the first data member of a structure. */ + offset = size_binop (PLUS_EXPR, offset, size_int (1)); + + cst = cp_convert (type, offset); + } + else + { + tree delta; + tree idx; + tree pfn; + tree delta2; + + expand_ptrmemfunc_cst (cst, &delta, &idx, &pfn, &delta2); + + cst = build_ptrmemfunc1 (type, delta, idx, + pfn, delta2); + } + } + break; + + default: + /* There's nothing to do. */ + break; + } + + return cst; +} + /* Hook used by expand_expr to expand language-specific tree codes. */ static rtx @@ -148,7 +204,7 @@ cplus_expand_expr (exp, target, tmode, modifier) init = convert_from_reference (init); flag_access_control = 0; - expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING); + expand_aggr_init (slot, init, LOOKUP_ONLYCONVERTING); flag_access_control = old_ac; if (TYPE_NEEDS_DESTRUCTOR (type)) @@ -162,19 +218,14 @@ cplus_expand_expr (exp, target, tmode, modifier) return DECL_RTL (slot); } + case PTRMEM_CST: + return expand_expr (cplus_expand_constant (exp), + target, tmode, modifier); + case OFFSET_REF: { -#if 1 return expand_expr (default_conversion (resolve_offset_ref (exp)), target, tmode, EXPAND_NORMAL); -#else - /* This is old crusty code, and does not handle all that the - resolve_offset_ref function does. (mrs) */ - tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0); - tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0); - return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset), - target, tmode, EXPAND_NORMAL); -#endif } case THUNK_DECL: @@ -189,7 +240,7 @@ cplus_expand_expr (exp, target, tmode, modifier) (expand_vec_init (NULL_TREE, TREE_OPERAND (exp, 0), build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2), - integer_one_node, 1), + integer_one_node), TREE_OPERAND (exp, 1), 0), target, tmode, modifier); case NEW_EXPR: @@ -207,6 +258,7 @@ void init_cplus_expand () { lang_expand_expr = cplus_expand_expr; + lang_expand_constant = cplus_expand_constant; } /* If DECL had its rtl moved from where callers expect it @@ -304,7 +356,7 @@ extract_scalar_init (decl, init) int extract_init (decl, init) - tree decl, init; + tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED; { return 0; @@ -405,8 +457,5 @@ do_case (start, end) cp_error ("case label `%E' within scope of cleanup or variable array", start); } } - if (start) - define_case_label (label); - else - define_case_label (NULL_TREE); + define_case_label (); } |