Commit f1dedc31 by Mark Mitchell Committed by Mark Mitchell

cp-tree.def (SUBOBJECT): New tree node.

	* cp-tree.def (SUBOBJECT): New tree node.
	* cp-tree.h (CLEANUP_P): New macro.
	(SUBOBJECT_CLEANUP): Likewise.
	(keep_next_level): Add parameter.
	(get_temp_regvar): Don't declare.
	(emit_base_init): Remove parameter.
	(expand_aggr_init): Rename to build_aggr_init.
	(expand_vec_init): Rename to build_vec_init.
	(do_pushlevel): Remove.
	(do_poplevel): Likewise.
	(finish_cleanup): New function.
	(finish_subobject): Likewise.
	(stmts_are_full_exprs_p): New variable.
	* decl.c (keep_next_level): Add parameter.
	(cp_finish_decl): Use build_aggr_init, not
	expand_aggr_init.  Use finish_expr_stmt to expand the code.
	(expand_static_init): Use tree-generating, not RTL-generating,
	functions to handle the initialization.
	(start_function): Remove dead code.  Always have a momentary
	obstack inside the function, even before hitting the first curly
	brace.
	(cplus_expand_expr_stmt): Move calls to
	expand_{start,end}_target_temps into semantics.c.
	(cp_function): Add stmts_are_full_exprs_p.
	(push_cp_function_context): Save it.
	(pop_cp_function_context): Restore it.
	* decl2.c (get_temp_regvar): Move to init.c.
	(do_static_initialization): Use build_{aggr,vec}_init.
	(do_static_destruction): Fix typo in comment.
	* dump.c (dequeue_and_dump): Handle INIT_EXPR.
	* except.c (expand_throw): Use create_temporary_var.
	* expr.c (cplus_expand_expr): Use build_{aggr,vec}_init.
	* init.c (expand_vec_init_try_block): Remove.
	(expand_vec_init_catch_clause): Likewise.
	(get_temp_regvar): New function.
	(begin_init_stmts): Likewise.
	(finish_init_stmts): Likewise.
	(perform_member_init): Use build_{aggr,vec}_init.  Build up tree
	structure here.
	(emit_base_init): Likewise.  Remove unused parameter.
	(expand_virtual_init): Likewise.
	(expand_cleanup_for_base): Use finish_subobject.
	(expand_aggr_vbase_init_1): Simplify.
	(construct_virtual_bases): Use tree-generating functions to build
	up initialization.
	(expand_aggr_init): Likewise.  Rename to build_aggr_init.
	(expand_default_init): Likewise.
	(expand_aggr_init_1): Likewise.
	(expand_vec_init): Rename to build_vec_init.
	* method.c (do_build_copy_constructor): Use tree-generating
	functions.  Don't call clear_last_expr.
	(do_build_assign_ref): Likewise.
	(synthesize_method): Call clear_last_expr here.
	* parse.y (base_init): Don't call clear_last_expr here.
	(nodecls): Likewise.
	* pt.c (tsubst_expr): Handle a TRY_BLOCK with CLEANUP_P set.
	* semantics.c (do_pushlevel): Move to here.
	(do_poplevel): Likewise.
	(stmts_are_full_exprs_p): New variable.
	(finish_expr_stmt): Handle logic for temoprary cleanup here.
	(finish_for_stmt): Use finish_expr_stmt.
	(finish_cleanup): New function.
	(finish_function_try_block): Fix indentation.
	(finish_subobject): New function.
	(setup_vtbl_ptr): Call keep_next_level here.
	(finish_stmt_expr): Handle a block with no scope inside the
	statement-expression.
	(expand_stmt): Handle a TRY_BLOCK with CLEANUP_P set.  Handle
	SUBOBJECT.
	* tree.c (search_tree): Handle INIT_EXPR.
	(mapcar): Likewise.
	* typeck.c (build_modify_expr): Don't build an RTL_EXPR.
	* typeck2.c (store_init_value): Change expand_aggr_init to
	build_aggr_init in comment.

From-SVN: r28878
parent 1d0e51ba
1999-08-25 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (SUBOBJECT): New tree node.
* cp-tree.h (CLEANUP_P): New macro.
(SUBOBJECT_CLEANUP): Likewise.
(keep_next_level): Add parameter.
(get_temp_regvar): Don't declare.
(emit_base_init): Remove parameter.
(expand_aggr_init): Rename to build_aggr_init.
(expand_vec_init): Rename to build_vec_init.
(do_pushlevel): Remove.
(do_poplevel): Likewise.
(finish_cleanup): New function.
(finish_subobject): Likewise.
(stmts_are_full_exprs_p): New variable.
* decl.c (keep_next_level): Add parameter.
(cp_finish_decl): Use build_aggr_init, not
expand_aggr_init. Use finish_expr_stmt to expand the code.
(expand_static_init): Use tree-generating, not RTL-generating,
functions to handle the initialization.
(start_function): Remove dead code. Always have a momentary
obstack inside the function, even before hitting the first curly
brace.
(cplus_expand_expr_stmt): Move calls to
expand_{start,end}_target_temps into semantics.c.
(cp_function): Add stmts_are_full_exprs_p.
(push_cp_function_context): Save it.
(pop_cp_function_context): Restore it.
* decl2.c (get_temp_regvar): Move to init.c.
(do_static_initialization): Use build_{aggr,vec}_init.
(do_static_destruction): Fix typo in comment.
* dump.c (dequeue_and_dump): Handle INIT_EXPR.
* except.c (expand_throw): Use create_temporary_var.
* expr.c (cplus_expand_expr): Use build_{aggr,vec}_init.
* init.c (expand_vec_init_try_block): Remove.
(expand_vec_init_catch_clause): Likewise.
(get_temp_regvar): New function.
(begin_init_stmts): Likewise.
(finish_init_stmts): Likewise.
(perform_member_init): Use build_{aggr,vec}_init. Build up tree
structure here.
(emit_base_init): Likewise. Remove unused parameter.
(expand_virtual_init): Likewise.
(expand_cleanup_for_base): Use finish_subobject.
(expand_aggr_vbase_init_1): Simplify.
(construct_virtual_bases): Use tree-generating functions to build
up initialization.
(expand_aggr_init): Likewise. Rename to build_aggr_init.
(expand_default_init): Likewise.
(expand_aggr_init_1): Likewise.
(expand_vec_init): Rename to build_vec_init.
* method.c (do_build_copy_constructor): Use tree-generating
functions. Don't call clear_last_expr.
(do_build_assign_ref): Likewise.
(synthesize_method): Call clear_last_expr here.
* parse.y (base_init): Don't call clear_last_expr here.
(nodecls): Likewise.
* pt.c (tsubst_expr): Handle a TRY_BLOCK with CLEANUP_P set.
* semantics.c (do_pushlevel): Move to here.
(do_poplevel): Likewise.
(stmts_are_full_exprs_p): New variable.
(finish_expr_stmt): Handle logic for temoprary cleanup here.
(finish_for_stmt): Use finish_expr_stmt.
(finish_cleanup): New function.
(finish_function_try_block): Fix indentation.
(finish_subobject): New function.
(setup_vtbl_ptr): Call keep_next_level here.
(finish_stmt_expr): Handle a block with no scope inside the
statement-expression.
(expand_stmt): Handle a TRY_BLOCK with CLEANUP_P set. Handle
SUBOBJECT.
* tree.c (search_tree): Handle INIT_EXPR.
(mapcar): Likewise.
* typeck.c (build_modify_expr): Don't build an RTL_EXPR.
* typeck2.c (store_init_value): Change expand_aggr_init to
build_aggr_init in comment.
1999-08-25 Mark Mitchell <mark@codesourcery.com>
* dump.c (dequeue_and_dump): Dump TARGET_EXPRs.
1999-08-25 Nathan Sidwell <nathan@acm.org>
......
......@@ -229,7 +229,11 @@ DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
/* A SUBOBJECT statement marks the point at which a sub-object is
fully constructed. After this point, the SUBOBJECT_CLEANUP must be
run if an exception is thrown before the end of the enclosing
function. */
DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
......
......@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
IDENTIFIER_MARKED (used by search routines).
LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
......@@ -2141,6 +2142,7 @@ extern int flag_new_for_scope;
#define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0)
#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1)
#define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (NODE)
#define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0)
#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1)
#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
......@@ -2151,6 +2153,7 @@ extern int flag_new_for_scope;
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \
......@@ -2841,7 +2844,7 @@ extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void));
extern int namespace_bindings_p PROTO((void));
extern void keep_next_level PROTO((void));
extern void keep_next_level PROTO((int));
extern int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void));
extern void declare_pseudo_global_level PROTO((void));
......@@ -3009,7 +3012,6 @@ extern void setup_vtbl_ptr PROTO((void));
extern void mark_inline_for_output PROTO((tree));
extern void clear_temp_name PROTO((void));
extern tree get_temp_name PROTO((tree, int));
extern tree get_temp_regvar PROTO((tree, tree));
extern void finish_anon_union PROTO((tree));
extern tree finish_table PROTO((tree, tree, tree, int));
extern void finish_builtin_type PROTO((tree, const char *,
......@@ -3105,10 +3107,10 @@ extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flag
/* in init.c */
extern void init_init_processing PROTO((void));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void emit_base_init PROTO((tree, int));
extern void emit_base_init PROTO((tree));
extern void check_base_init PROTO((tree));
extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int));
extern tree build_aggr_init PROTO((tree, tree, int));
extern int is_aggr_typedef PROTO((tree, int));
extern int is_aggr_type PROTO((tree, int));
extern tree get_aggr_from_typedef PROTO((tree, int));
......@@ -3119,11 +3121,12 @@ extern tree resolve_offset_ref PROTO((tree));
extern tree decl_constant_value PROTO((tree));
extern tree build_new PROTO((tree, tree, tree, int));
extern tree build_new_1 PROTO((tree));
extern tree expand_vec_init PROTO((tree, tree, tree, tree, int));
extern tree build_vec_init PROTO((tree, tree, tree, tree, int));
extern tree build_x_delete PROTO((tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
extern tree create_temporary_var PROTO((tree));
/* in input.c */
......@@ -3234,7 +3237,6 @@ extern void mark_class_instantiated PROTO((tree, int));
extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree));
extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void));
......@@ -3242,7 +3244,6 @@ extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
extern int template_parms_equal PROTO((tree, tree));
extern int comp_template_parms PROTO((tree, tree));
......@@ -3349,10 +3350,12 @@ extern void finish_function_handler_sequence PROTO((tree));
extern tree begin_handler PROTO((void));
extern void finish_handler_parms PROTO((tree));
extern void finish_handler PROTO((tree));
extern void finish_cleanup PROTO((tree, tree));
extern tree begin_compound_stmt PROTO((int));
extern tree finish_compound_stmt PROTO((int, tree));
extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree));
extern void finish_label_stmt PROTO((tree));
extern void finish_subobject PROTO((tree));
extern tree finish_parenthesized_expr PROTO((tree));
extern tree begin_stmt_expr PROTO((void));
extern tree finish_stmt_expr PROTO((tree, tree));
......@@ -3395,6 +3398,7 @@ extern void expand_body PROTO((tree));
extern void begin_stmt_tree PROTO((tree));
extern void finish_stmt_tree PROTO((tree));
extern int expanding_p;
extern int stmts_are_full_exprs_p;
extern tree last_expr_type;
/* Non-zero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */
......
......@@ -882,10 +882,15 @@ namespace_bindings_p ()
return b->namespace_p;
}
/* If KEEP is non-zero, make a BLOCK node for the next binding level,
unconditionally. Otherwise, use the normal logic to decide whether
or not to create a BLOCK. */
void
keep_next_level ()
keep_next_level (keep)
int keep;
{
keep_next_level_flag = 1;
keep_next_level_flag = keep;
}
/* Nonzero if the current level needs to have a BLOCK made. */
......@@ -7908,7 +7913,16 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
expand_aggr_init (decl, init, flags);
/* We call push_momentary here so that when
finish_expr_stmt clears the momentary obstack it
doesn't destory any momentary expressions we may
have lying around. Although cp_finish_decl is
usually called at the end of a declaration
statement, it may also be called for a temporary
object in the middle of an expression. */
push_momentary ();
finish_expr_stmt (build_aggr_init (decl, init, flags));
pop_momentary ();
}
/* Set this to 0 so we can tell whether an aggregate which
......@@ -8024,6 +8038,8 @@ expand_static_init (decl, init)
{
/* Emit code to perform this initialization but once. */
tree temp;
tree assignment;
tree temp_init;
/* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack);
......@@ -8058,26 +8074,35 @@ expand_static_init (decl, init)
/* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node), 0);
expand_start_target_temps ();
/* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
{
expand_aggr_init (decl, init, 0);
do_pending_stack_adjust ();
}
assignment = build_aggr_init (decl, init, 0);
else if (init)
expand_assignment (decl, init, 0, 0);
/* Set TEMP to 1. */
expand_assignment (temp, integer_one_node, 0, 0);
/* Cleanup any temporaries needed for the initial value. If
destroying one of the temporaries causes an exception to be
thrown, then the object itself has still been fully
constructed. */
expand_end_target_temps ();
assignment = build_modify_expr (decl, NOP_EXPR, init);
else
assignment = NULL_TREE;
/* Once the assignment is complete, set TEMP to 1. Since the
construction of the static object is complete at this point,
we want to make sure TEMP is set to 1 even if a temporary
constructed during the initialization throws an exception
when it is destroyed. So, we combine the initialization and
the assignment to TEMP into a single expression, ensuring
that when we call finish_expr_stmt the cleanups will not be
run until after TEMP is set to 1. */
temp_init = build_modify_expr (temp, NOP_EXPR, integer_one_node);
if (assignment)
{
assignment = tree_cons (NULL_TREE, assignment,
build_tree_list (NULL_TREE,
temp_init));
assignment = build_compound_expr (assignment);
}
else
assignment = temp_init;
finish_expr_stmt (assignment);
/* Use atexit to register a function for destroying this static
variable. */
......@@ -12813,25 +12838,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
{
decl1 = declarator;
#if 0
/* What was this testing for, exactly? */
if (! DECL_ARGUMENTS (decl1)
&& !DECL_STATIC_FUNCTION_P (decl1)
&& !DECL_ARTIFICIAL (decl1)
&& DECL_CLASS_SCOPE_P (decl1)
&& TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
tree binding = binding_for_name (DECL_NAME (decl1),
current_namespace);
cp_error ("redeclaration of `%#D'", decl1);
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)))
cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)));
else if (BINDING_VALUE (binding))
cp_error_at ("previous declaration here", BINDING_VALUE (binding));
}
#endif
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
......@@ -13161,6 +13167,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
on the permanent obstack in case we need to inline it later. */
if (! hack_decl_function_context (decl1))
temporary_allocation ();
/* Make sure that we always have a momntary obstack while we're in a
function body. */
push_momentary ();
if (building_stmt_tree ())
begin_stmt_tree (decl1);
......@@ -13856,6 +13866,9 @@ finish_function (lineno, flags, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
/* Undo the call to push_momentary in start_function. */
pop_momentary ();
if (expand_p)
{
int saved_flag_keep_inline_functions =
......@@ -14261,9 +14274,6 @@ void
cplus_expand_expr_stmt (exp)
tree exp;
{
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
exp = require_complete_type_in_void (exp);
if (TREE_CODE (exp) == FUNCTION_DECL)
......@@ -14288,10 +14298,6 @@ cplus_expand_expr_stmt (exp)
go outside the bounds of the type. */
if (exp != error_mark_node)
expand_expr_stmt (break_out_cleanups (exp));
/* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */
expand_end_target_temps ();
}
/* When a stmt has been parsed, this function is called. */
......@@ -14381,6 +14387,7 @@ struct cp_function
int static_labelno;
int in_function_try_handler;
int expanding_p;
int stmts_are_full_exprs_p;
tree last_tree;
tree last_expr_type;
};
......@@ -14429,10 +14436,15 @@ push_cp_function_context (context)
p->last_tree = last_tree;
p->last_expr_type = last_expr_type;
p->expanding_p = expanding_p;
p->stmts_are_full_exprs_p = stmts_are_full_exprs_p;
/* For now, we always assume we're expanding all the way to RTL
unless we're explicitly doing otherwise. */
expanding_p = 1;
/* Whenever we start a new function, we destroy temporaries in the
usual way. */
stmts_are_full_exprs_p = 1;
}
/* Restore the variables used during compilation of a C++ function. */
......@@ -14479,6 +14491,7 @@ pop_cp_function_context (context)
last_tree = p->last_tree;
last_expr_type = p->last_expr_type;
expanding_p = p->expanding_p;
stmts_are_full_exprs_p = p->stmts_are_full_exprs_p;
free (p);
}
......
......@@ -2077,31 +2077,6 @@ get_temp_name (type, staticp)
return decl;
}
/* Get a variable which we can use for multiple assignments.
It is not entered into current_binding_level, because
that breaks things when it comes time to do final cleanups
(which take place "outside" the binding contour of the function). */
tree
get_temp_regvar (type, init)
tree type, init;
{
tree decl;
decl = build_decl (VAR_DECL, NULL_TREE, type);
TREE_USED (decl) = 1;
DECL_REGISTER (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
/* We can expand these without fear, since they cannot need
constructors or destructors. */
expand_expr (build_modify_expr (decl, INIT_EXPR, init),
NULL_RTX, VOIDmode, 0);
return decl;
}
/* Hunts through the global anonymous union ANON_DECL, building
appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and
returns a VAR_DECL whose size is the same as the size of the
......@@ -3219,11 +3194,12 @@ do_static_initialization (decl, init, sentry, priority)
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0);
expand_expr (build_aggr_init (decl, init, 0),
const0_rtx, VOIDmode, EXPAND_NORMAL);
else if (TREE_CODE (init) == TREE_VEC)
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0),
expand_expr (build_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0),
const0_rtx, VOIDmode, EXPAND_NORMAL);
else
expand_assignment (decl, init, 0, 0);
......@@ -3290,7 +3266,7 @@ do_static_destruction (decl, sentry, priority)
integer_zero_node),
/*exit_flag=*/0);
/* Actually to the destruction. */
/* Actually do the destruction. */
expand_expr_stmt (build_cleanup (decl));
/* Cleanup any deferred pops from function calls. This would be done
......
......@@ -768,6 +768,13 @@ dequeue_and_dump (di)
dump_next_stmt (di, t);
break;
case SUBOBJECT:
dump_stmt (di, t);
if (dump_children_p)
dump_child ("clnp", TREE_OPERAND (t, 0));
dump_next_stmt (di, t);
break;
case INTEGER_CST:
if (TREE_INT_CST_HIGH (t))
dump_int (di, "high", TREE_INT_CST_HIGH (t));
......@@ -798,6 +805,7 @@ dequeue_and_dump (di)
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case INIT_EXPR:
case MODIFY_EXPR:
case COMPONENT_REF:
case COMPOUND_EXPR:
......
......@@ -965,9 +965,7 @@ expand_throw (exp)
ourselves into expand_call. */
if (TREE_SIDE_EFFECTS (exp))
{
tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
DECL_ARTIFICIAL (temp) = 1;
DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
tree temp = create_temporary_var (TREE_TYPE (exp));
DECL_INITIAL (temp) = exp;
cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
exp = temp;
......
......@@ -204,7 +204,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = convert_from_reference (init);
flag_access_control = 0;
expand_aggr_init (slot, init, 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))
......@@ -237,7 +239,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
case VEC_INIT_EXPR:
return expand_expr
(expand_vec_init
(build_vec_init
(NULL_TREE, TREE_OPERAND (exp, 0),
build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
integer_one_node),
......
......@@ -2177,11 +2177,9 @@ do_build_copy_constructor (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
tree t;
clear_last_expr ();
push_momentary ();
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm);
......@@ -2194,7 +2192,7 @@ do_build_copy_constructor (fndecl)
{
t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
finish_expr_stmt (t);
}
else
{
......@@ -2257,7 +2255,8 @@ do_build_copy_constructor (fndecl)
setup_vtbl_ptr ();
}
pop_momentary ();
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
}
static void
......@@ -2265,10 +2264,9 @@ do_build_assign_ref (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
clear_last_expr ();
push_momentary ();
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
parm = convert_from_reference (parm);
if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
......@@ -2279,7 +2277,7 @@ do_build_assign_ref (fndecl)
{
tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t);
finish_expr_stmt (t);
}
else
{
......@@ -2353,7 +2351,7 @@ do_build_assign_ref (fndecl)
}
}
c_expand_return (current_class_ref);
pop_momentary ();
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
}
void
......@@ -2374,6 +2372,7 @@ synthesize_method (fndecl)
interface_unknown = 1;
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
clear_last_expr ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
do_build_assign_ref (fndecl);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
typedef union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; } YYSTYPE;
#define IDENTIFIER 258
#define TYPENAME 259
#define SELFNAME 260
#define PFUNCNAME 261
#define SCSPEC 262
#define TYPESPEC 263
#define CV_QUALIFIER 264
#define CONSTANT 265
#define STRING 266
#define ELLIPSIS 267
#define SIZEOF 268
#define ENUM 269
#define IF 270
#define ELSE 271
#define WHILE 272
#define DO 273
#define FOR 274
#define SWITCH 275
#define CASE 276
#define DEFAULT 277
#define BREAK 278
#define CONTINUE 279
#define RETURN_KEYWORD 280
#define GOTO 281
#define ASM_KEYWORD 282
#define TYPEOF 283
#define ALIGNOF 284
#define SIGOF 285
#define ATTRIBUTE 286
#define EXTENSION 287
#define LABEL 288
#define REALPART 289
#define IMAGPART 290
#define VA_ARG 291
#define AGGR 292
#define VISSPEC 293
#define DELETE 294
#define NEW 295
#define THIS 296
#define OPERATOR 297
#define CXX_TRUE 298
#define CXX_FALSE 299
#define NAMESPACE 300
#define TYPENAME_KEYWORD 301
#define USING 302
#define LEFT_RIGHT 303
#define TEMPLATE 304
#define TYPEID 305
#define DYNAMIC_CAST 306
#define STATIC_CAST 307
#define REINTERPRET_CAST 308
#define CONST_CAST 309
#define SCOPE 310
#define EMPTY 311
#define PTYPENAME 312
#define NSNAME 313
#define THROW 314
#define ASSIGN 315
#define OROR 316
#define ANDAND 317
#define MIN_MAX 318
#define EQCOMPARE 319
#define ARITHCOMPARE 320
#define LSHIFT 321
#define RSHIFT 322
#define POINTSAT_STAR 323
#define DOT_STAR 324
#define UNARY 325
#define PLUSPLUS 326
#define MINUSMINUS 327
#define HYPERUNARY 328
#define POINTSAT 329
#define TRY 330
#define CATCH 331
#define PRE_PARSED_FUNCTION_DECL 332
#define EXTERN_LANG_STRING 333
#define ALL 334
#define PRE_PARSED_CLASS_DECL 335
#define DEFARG 336
#define DEFARG_MARKER 337
#define TYPENAME_DEFN 338
#define IDENTIFIER_DEFN 339
#define PTYPENAME_DEFN 340
#define END_OF_LINE 341
#define END_OF_SAVED_INPUT 342
#define IDENTIFIER 257
#define TYPENAME 258
#define SELFNAME 259
#define PFUNCNAME 260
#define SCSPEC 261
#define TYPESPEC 262
#define CV_QUALIFIER 263
#define CONSTANT 264
#define STRING 265
#define ELLIPSIS 266
#define SIZEOF 267
#define ENUM 268
#define IF 269
#define ELSE 270
#define WHILE 271
#define DO 272
#define FOR 273
#define SWITCH 274
#define CASE 275
#define DEFAULT 276
#define BREAK 277
#define CONTINUE 278
#define RETURN_KEYWORD 279
#define GOTO 280
#define ASM_KEYWORD 281
#define TYPEOF 282
#define ALIGNOF 283
#define SIGOF 284
#define ATTRIBUTE 285
#define EXTENSION 286
#define LABEL 287
#define REALPART 288
#define IMAGPART 289
#define VA_ARG 290
#define AGGR 291
#define VISSPEC 292
#define DELETE 293
#define NEW 294
#define THIS 295
#define OPERATOR 296
#define CXX_TRUE 297
#define CXX_FALSE 298
#define NAMESPACE 299
#define TYPENAME_KEYWORD 300
#define USING 301
#define LEFT_RIGHT 302
#define TEMPLATE 303
#define TYPEID 304
#define DYNAMIC_CAST 305
#define STATIC_CAST 306
#define REINTERPRET_CAST 307
#define CONST_CAST 308
#define SCOPE 309
#define EMPTY 310
#define PTYPENAME 311
#define NSNAME 312
#define THROW 313
#define ASSIGN 314
#define OROR 315
#define ANDAND 316
#define MIN_MAX 317
#define EQCOMPARE 318
#define ARITHCOMPARE 319
#define LSHIFT 320
#define RSHIFT 321
#define POINTSAT_STAR 322
#define DOT_STAR 323
#define UNARY 324
#define PLUSPLUS 325
#define MINUSMINUS 326
#define HYPERUNARY 327
#define POINTSAT 328
#define TRY 329
#define CATCH 330
#define PRE_PARSED_FUNCTION_DECL 331
#define EXTERN_LANG_STRING 332
#define ALL 333
#define PRE_PARSED_CLASS_DECL 334
#define DEFARG 335
#define DEFARG_MARKER 336
#define TYPENAME_DEFN 337
#define IDENTIFIER_DEFN 338
#define PTYPENAME_DEFN 339
#define END_OF_LINE 340
#define END_OF_SAVED_INPUT 341
extern YYSTYPE yylval;
......
......@@ -780,10 +780,6 @@ base_init:
if ($3 == 0)
error ("no base initializers given following ':'");
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost
pair of curley braces of a function. These are needed
for correct operation of dwarfout.c. */
keep_next_level ();
}
;
......@@ -1623,10 +1619,6 @@ nodecls:
if (! current_function_parms_stored)
store_parm_decls ();
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost
pair of curley braces of a function. These are needed
for correct operation of dwarfout.c. */
keep_next_level ();
}
;
......
......@@ -7424,12 +7424,17 @@ tsubst_expr (t, args, complain, in_decl)
stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (stmt);
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl);
}
finish_handler_sequence (stmt);
if (CLEANUP_P (t))
finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
complain, in_decl),
stmt);
else
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl);
finish_handler_sequence (stmt);
}
break;
case HANDLER:
......
......@@ -42,12 +42,27 @@
much easier since it will be able to make use of these routines. */
static void expand_stmts PROTO((tree));
static void do_pushlevel PROTO((void));
static tree do_poplevel PROTO((void));
/* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */
int expanding_p = 1;
/* Non-zero if we should treat statements as full expressions. In
particular, this variable is no-zero if at the end of a statement
we should destroy any temporaries created during that statement.
Similarly, if, at the end of a block, we should destroy any local
variables in this block. Normally, this variable is non-zero,
since those are the normal semantics of C++.
However, in order to represent aggregate initialization code as
tree structure, we use statement-expressions. The statements
within the statement expression should not result in cleanups being
run until the entire enclosing statement is complete. */
int stmts_are_full_exprs_p = 1;
/* The type of the last expression-statement we have seen. This is
required because the type of a statement-expression is the type of
the last expression statement. */
......@@ -91,10 +106,18 @@ finish_expr_stmt (expr)
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr);
if (stmts_are_full_exprs_p)
expand_start_target_temps ();
cplus_expand_expr_stmt (expr);
}
clear_momentary ();
if (stmts_are_full_exprs_p)
{
expand_end_target_temps ();
clear_momentary ();
}
}
}
finish_stmt ();
......@@ -455,7 +478,7 @@ finish_for_stmt (expr, for_stmt)
emit_line_note (input_filename, lineno);
expand_loop_continue_here ();
if (expr)
cplus_expand_expr_stmt (expr);
finish_expr_stmt (expr);
expand_end_loop ();
}
......@@ -647,11 +670,28 @@ finish_try_block (try_block)
expand_start_all_catch ();
}
/* Finish an implicitly generated try-block, with a cleanup is given
by CLEANUP. */
void
finish_cleanup (cleanup, try_block)
tree cleanup;
tree try_block;
{
if (building_stmt_tree ())
{
TRY_HANDLERS (try_block) = copy_to_permanent (cleanup);
CLEANUP_P (try_block) = 1;
}
else
expand_eh_region_end (protect_with_terminate (cleanup));
}
/* Likewise, for a function-try-block. */
void
finish_function_try_block (try_block)
tree try_block;
tree try_block;
{
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
......@@ -673,9 +713,7 @@ finish_handler_sequence (try_block)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
expand_end_all_catch ();
}
expand_end_all_catch ();
}
/* Likewise, for a function-try-block. */
......@@ -762,6 +800,12 @@ begin_compound_stmt (has_no_scope)
if (!has_no_scope)
do_pushlevel ();
else
/* Normally, we try hard to keep the BLOCK for a
statement-expression. But, if it's a statement-expression with
a scopeless block, there's nothing to keep, and we don't want
to accidentally keep a block *inside* the scopeless block. */
keep_next_level (0);
return r;
}
......@@ -904,6 +948,23 @@ add_decl_stmt (decl)
add_tree (decl_stmt);
}
/* We're in a constructor, and have just constructed a a subobject of
*THIS. CLEANUP is code to run if an exception is thrown before the
end of the current function is reached. */
void
finish_subobject (cleanup)
tree cleanup;
{
if (building_stmt_tree ())
{
tree r = build_min_nt (SUBOBJECT, cleanup);
add_tree (r);
}
else
add_partial_entry (cleanup);
}
/* Bind a name and initialization to the return value of
the current function. */
......@@ -975,13 +1036,18 @@ setup_vtbl_ptr ()
(CTOR_INITIALIZER,
current_member_init_list, current_base_init_list));
else
emit_base_init (current_class_type, 0);
emit_base_init (current_class_type);
}
/* Always keep the BLOCK node associated with the outermost pair of
curley braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level (1);
}
/* Begin a new scope. */
void
static void
do_pushlevel ()
{
if (!building_stmt_tree ())
......@@ -989,22 +1055,24 @@ do_pushlevel ()
emit_line_note (input_filename, lineno);
clear_last_expr ();
}
pushlevel (0);
push_momentary ();
if (!building_stmt_tree ())
if (stmts_are_full_exprs_p)
pushlevel (0);
if (!building_stmt_tree () && stmts_are_full_exprs_p)
expand_start_bindings (0);
}
}
/* Finish a scope. */
tree
static tree
do_poplevel ()
{
tree t;
if (!building_stmt_tree ())
if (!building_stmt_tree () && stmts_are_full_exprs_p)
expand_end_bindings (getdecls (), kept_level_p (), 0);
t = poplevel (kept_level_p (), 1, 0);
if (stmts_are_full_exprs_p)
t = poplevel (kept_level_p (), 1, 0);
pop_momentary ();
return t;
}
......@@ -1028,7 +1096,7 @@ finish_parenthesized_expr (expr)
tree
begin_stmt_expr ()
{
keep_next_level ();
keep_next_level (1);
/* If we're building a statement tree, then the upcoming compound
statement will be chained onto the tree structure, starting at
last_tree. We return last_tree so that we can later unhook the
......@@ -1055,39 +1123,35 @@ finish_stmt_expr (rtl_expr, expr)
TREE_SIDE_EFFECTS (rtl_expr) = 1;
}
if (TREE_CODE (expr) == BLOCK)
{
/* Make a BIND_EXPR for the BLOCK already made. */
if (building_stmt_tree ())
{
/* If the last thing in the statement-expression was not an
expression-statement, then it has type `void'. */
if (!last_expr_type)
last_expr_type = void_type_node;
result = build_min (STMT_EXPR, last_expr_type, last_tree);
/* FIXME: Do we need this? */
TREE_SIDE_EFFECTS (result) = 1;
}
else
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
/* Remove the block from the tree at this point. It gets put
back at the proper place when the STMT_EXPR or BIND_EXPR is
expanded. */
delete_block (expr);
}
else
result = expr;
if (building_stmt_tree ())
{
/* If the last thing in the statement-expression was not an
expression-statement, then it has type `void'. */
if (!last_expr_type)
last_expr_type = void_type_node;
result = build_min (STMT_EXPR, last_expr_type, last_tree);
TREE_SIDE_EFFECTS (result) = 1;
/* Remove the compound statement from the tree structure; it is
now saved in the STMT_EXPR. */
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
}
else if (expr && TREE_CODE (expr) == BLOCK)
{
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
delete_block (expr);
}
else
result = rtl_expr;
if (expr && TREE_CODE (expr) == BLOCK)
/* Remove the block from the tree at this point. It gets put back
at the proper place when the STMT_EXPR or BIND_EXPR is
expanded. */
delete_block (expr);
return result;
}
......@@ -2082,11 +2146,20 @@ expand_stmt (t)
case TRY_BLOCK:
lineno = STMT_LINENO (t);
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
if (CLEANUP_P (t))
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
finish_cleanup (TRY_HANDLERS (t), NULL_TREE);
}
else
{
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
}
break;
case HANDLER:
......@@ -2105,6 +2178,11 @@ expand_stmt (t)
finish_handler (NULL_TREE);
break;
case SUBOBJECT:
lineno = STMT_LINENO (t);
finish_subobject (SUBOBJECT_CLEANUP (t));
break;
default:
my_friendly_abort (19990810);
break;
......@@ -2168,11 +2246,6 @@ expand_body (fn)
base-classes. */
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost pair of
curly braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level ();
/* Expand the body. */
expand_stmt (t);
......
......@@ -1656,6 +1656,7 @@ search_tree (t, func)
case CALL_EXPR:
case COMPOUND_EXPR:
case MODIFY_EXPR:
case INIT_EXPR:
TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1));
break;
......@@ -1920,6 +1921,7 @@ mapcar (t, func)
case WITH_CLEANUP_EXPR:
case COMPOUND_EXPR:
case MODIFY_EXPR:
case INIT_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
......
......@@ -5989,32 +5989,11 @@ build_modify_expr (lhs, modifycode, rhs)
if (pedantic && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment of arrays");
/* Have to wrap this in RTL_EXPR for two cases:
in base or member initialization and if we
are a branch of a ?: operator. Since we
can't easily know the latter, just do it always. */
result = make_node (RTL_EXPR);
TREE_TYPE (result) = void_type_node;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (result);
/* As a matter of principle, `start_sequence' should do this. */
emit_note (0, -1);
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs,
from_array);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (result) = 1;
RTL_EXPR_SEQUENCE (result) = get_insns ();
RTL_EXPR_RTL (result) = const0_rtx;
end_sequence ();
return result;
return (build_vec_init
(lhs, lhs, array_type_nelts (lhstype), newrhs,
from_array));
}
if (modifycode == INIT_EXPR)
......
......@@ -465,7 +465,7 @@ store_init_value (decl, init)
;
/* Other code expects that initializers for objects of types that need
constructing never make it into DECL_INITIAL, and passes 'init' to
expand_aggr_init without checking DECL_INITIAL. So just return. */
build_aggr_init without checking DECL_INITIAL. So just return. */
else if (TYPE_NEEDS_CONSTRUCTING (type))
return value;
else if (TREE_STATIC (decl)
......
// Build don't link:
// Special g++ Options: -fno-const-strings
// Origin: Mark Mitchell <mark@codesourcery.com>
char foo[26];
template <class T>
void f ()
{
foo = "0123456789012345678901234";
}
template void f<int>();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment