/* 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.
#include "flags.h"
#include "expr.h"
#include "cp-tree.h"
+#include "toplev.h"
+#include "except.h"
+#include "tm_p.h"
#if 0
static tree extract_aggr_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. */
+
+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
initialization. It is left here to show the choices that
exist for C++. */
- if (TREE_CODE (func) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
- && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
+ if (AGGR_INIT_VIA_CTOR_P (exp))
{
type = build_pointer_type (type);
- /* Don't clobber a value that might be part of a default
- parameter value. */
mark_addressable (slot);
- if (TREE_PERMANENT (args))
- args = expr_tree_cons (0, build1 (ADDR_EXPR, type, slot),
- TREE_CHAIN (args));
- else
- TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
+ args = tree_cons (NULL_TREE,
+ build1 (ADDR_EXPR, type, slot),
+ TREE_CHAIN (args));
call_target = 0;
}
else
init = convert_from_reference (init);
flag_access_control = 0;
- expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
+ expand_expr (build_aggr_init (slot, init,
+ LOOKUP_ONLYCONVERTING),
+ target, tmode, EXPAND_NORMAL);
flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type))
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:
return DECL_RTL (exp);
case THROW_EXPR:
- expand_throw (TREE_OPERAND (exp, 0));
+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
+ expand_internal_throw ();
return NULL;
- case VEC_INIT_EXPR:
- return expand_expr
- (expand_vec_init
- (NULL_TREE, TREE_OPERAND (exp, 0),
- build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
- integer_one_node, 1),
- TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
+ case EMPTY_CLASS_EXPR:
+ /* We don't need to generate any code for an empty class. */
+ return const0_rtx;
- case NEW_EXPR:
- return expand_expr (build_new_1 (exp), target, tmode, modifier);
+ case STMT_EXPR:
+ {
+ tree rtl_expr = begin_stmt_expr ();
+ expand_stmt (STMT_EXPR_STMT (exp));
+ finish_stmt_expr (rtl_expr);
+ return expand_expr (rtl_expr, target, tmode, modifier);
+ }
+ break;
default:
break;
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
extern struct obstack temporary_obstack;
tree t = NULL_TREE;
- push_obstacks (&temporary_obstack, &temporary_obstack);
start_sequence ();
value = expand_expr (init, NULL_RTX, VOIDmode, 0);
insns = get_insns ();
end_sequence ();
reg_scan (insns, max_reg_num (), 0);
jump_optimize (insns, 0, 0, 1);
- pop_obstacks ();
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
int
extract_init (decl, init)
- tree decl, init;
+ tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
{
return 0;
if (end && pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement");
- if (processing_template_decl)
- {
- add_tree (build_min_nt (CASE_LABEL, start, end));
- return;
- }
-
if (start)
value1 = check_cp_case_value (start);
if (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);
+
+ current_function_return_value = NULL_TREE;
}