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> 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. * dump.c (dequeue_and_dump): Dump TARGET_EXPRs.
1999-08-25 Nathan Sidwell <nathan@acm.org> 1999-08-25 Nathan Sidwell <nathan@acm.org>
......
...@@ -229,7 +229,11 @@ DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0) ...@@ -229,7 +229,11 @@ DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2) DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1) DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5) 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 (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2) DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
......
...@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
IDENTIFIER_MARKED (used by search routines). IDENTIFIER_MARKED (used by search routines).
LOCAL_BINDING_P (in CPLUS_BINDING) LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV) ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
1: IDENTIFIER_VIRTUAL_P. 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -2141,6 +2142,7 @@ extern int flag_new_for_scope; ...@@ -2141,6 +2142,7 @@ extern int flag_new_for_scope;
#define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0) #define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0)
#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0) #define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1) #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_PARMS(NODE) TREE_OPERAND (NODE, 0)
#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1) #define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1)
#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0) #define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
...@@ -2151,6 +2153,7 @@ extern int flag_new_for_scope; ...@@ -2151,6 +2153,7 @@ extern int flag_new_for_scope;
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4) #define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0) #define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(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. */ /* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \ #define ASM_VOLATILE_P(NODE) \
...@@ -2841,7 +2844,7 @@ extern void set_identifier_local_value PROTO((tree, tree)); ...@@ -2841,7 +2844,7 @@ extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void)); extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void)); extern int toplevel_bindings_p PROTO((void));
extern int namespace_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 int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void)); extern void declare_parm_level PROTO((void));
extern void declare_pseudo_global_level PROTO((void)); extern void declare_pseudo_global_level PROTO((void));
...@@ -3009,7 +3012,6 @@ extern void setup_vtbl_ptr PROTO((void)); ...@@ -3009,7 +3012,6 @@ extern void setup_vtbl_ptr PROTO((void));
extern void mark_inline_for_output PROTO((tree)); extern void mark_inline_for_output PROTO((tree));
extern void clear_temp_name PROTO((void)); extern void clear_temp_name PROTO((void));
extern tree get_temp_name PROTO((tree, int)); extern tree get_temp_name PROTO((tree, int));
extern tree get_temp_regvar PROTO((tree, tree));
extern void finish_anon_union PROTO((tree)); extern void finish_anon_union PROTO((tree));
extern tree finish_table PROTO((tree, tree, tree, int)); extern tree finish_table PROTO((tree, tree, tree, int));
extern void finish_builtin_type PROTO((tree, const char *, 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 ...@@ -3105,10 +3107,10 @@ extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flag
/* in init.c */ /* in init.c */
extern void init_init_processing PROTO((void)); extern void init_init_processing PROTO((void));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree)); 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 check_base_init PROTO((tree));
extern void expand_member_init PROTO((tree, tree, 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_typedef PROTO((tree, int));
extern int is_aggr_type PROTO((tree, int)); extern int is_aggr_type PROTO((tree, int));
extern tree get_aggr_from_typedef PROTO((tree, int)); extern tree get_aggr_from_typedef PROTO((tree, int));
...@@ -3119,11 +3121,12 @@ extern tree resolve_offset_ref PROTO((tree)); ...@@ -3119,11 +3121,12 @@ extern tree resolve_offset_ref PROTO((tree));
extern tree decl_constant_value PROTO((tree)); extern tree decl_constant_value PROTO((tree));
extern tree build_new PROTO((tree, tree, tree, int)); extern tree build_new PROTO((tree, tree, tree, int));
extern tree build_new_1 PROTO((tree)); 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_x_delete PROTO((tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int)); extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree)); extern tree build_vbase_delete PROTO((tree, tree));
extern tree build_vec_delete PROTO((tree, tree, tree, tree, int)); extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
extern tree create_temporary_var PROTO((tree));
/* in input.c */ /* in input.c */
...@@ -3234,7 +3237,6 @@ extern void mark_class_instantiated PROTO((tree, int)); ...@@ -3234,7 +3237,6 @@ extern void mark_class_instantiated PROTO((tree, int));
extern void do_decl_instantiation PROTO((tree, tree, tree)); extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree)); extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree)); extern tree instantiate_decl PROTO((tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree)); extern tree get_bindings PROTO((tree, tree, tree));
extern void add_tree PROTO((tree)); extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void)); extern void begin_tree PROTO((void));
...@@ -3242,7 +3244,6 @@ extern void end_tree PROTO((void)); ...@@ -3242,7 +3244,6 @@ extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree)); extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void)); extern void pop_tinst_level PROTO((void));
extern int more_specialized_class PROTO((tree, tree)); extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree)); extern int is_member_template PROTO((tree));
extern int template_parms_equal PROTO((tree, tree)); extern int template_parms_equal PROTO((tree, tree));
extern int comp_template_parms PROTO((tree, tree)); extern int comp_template_parms PROTO((tree, tree));
...@@ -3349,10 +3350,12 @@ extern void finish_function_handler_sequence PROTO((tree)); ...@@ -3349,10 +3350,12 @@ extern void finish_function_handler_sequence PROTO((tree));
extern tree begin_handler PROTO((void)); extern tree begin_handler PROTO((void));
extern void finish_handler_parms PROTO((tree)); extern void finish_handler_parms PROTO((tree));
extern void finish_handler PROTO((tree)); extern void finish_handler PROTO((tree));
extern void finish_cleanup PROTO((tree, tree));
extern tree begin_compound_stmt PROTO((int)); extern tree begin_compound_stmt PROTO((int));
extern tree finish_compound_stmt PROTO((int, tree)); extern tree finish_compound_stmt PROTO((int, tree));
extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree)); extern void finish_asm_stmt PROTO((tree, tree, tree, tree, tree));
extern void finish_label_stmt PROTO((tree)); extern void finish_label_stmt PROTO((tree));
extern void finish_subobject PROTO((tree));
extern tree finish_parenthesized_expr PROTO((tree)); extern tree finish_parenthesized_expr PROTO((tree));
extern tree begin_stmt_expr PROTO((void)); extern tree begin_stmt_expr PROTO((void));
extern tree finish_stmt_expr PROTO((tree, tree)); extern tree finish_stmt_expr PROTO((tree, tree));
...@@ -3395,6 +3398,7 @@ extern void expand_body PROTO((tree)); ...@@ -3395,6 +3398,7 @@ extern void expand_body PROTO((tree));
extern void begin_stmt_tree PROTO((tree)); extern void begin_stmt_tree PROTO((tree));
extern void finish_stmt_tree PROTO((tree)); extern void finish_stmt_tree PROTO((tree));
extern int expanding_p; extern int expanding_p;
extern int stmts_are_full_exprs_p;
extern tree last_expr_type; extern tree last_expr_type;
/* Non-zero if we are presently building a statement tree, rather /* Non-zero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */ than expanding each statement as we encounter it. */
......
...@@ -882,10 +882,15 @@ namespace_bindings_p () ...@@ -882,10 +882,15 @@ namespace_bindings_p ()
return b->namespace_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 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. */ /* 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) ...@@ -7908,7 +7913,16 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{ {
emit_line_note (DECL_SOURCE_FILE (decl), emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (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 /* Set this to 0 so we can tell whether an aggregate which
...@@ -8024,6 +8038,8 @@ expand_static_init (decl, init) ...@@ -8024,6 +8038,8 @@ expand_static_init (decl, init)
{ {
/* Emit code to perform this initialization but once. */ /* Emit code to perform this initialization but once. */
tree temp; tree temp;
tree assignment;
tree temp_init;
/* Remember this information until end of file. */ /* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack); push_obstacks (&permanent_obstack, &permanent_obstack);
...@@ -8058,26 +8074,35 @@ expand_static_init (decl, init) ...@@ -8058,26 +8074,35 @@ expand_static_init (decl, init)
/* Begin the conditional initialization. */ /* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp, expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node), 0); integer_zero_node), 0);
expand_start_target_temps ();
/* Do the initialization itself. */ /* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST)) || (init && TREE_CODE (init) == TREE_LIST))
{ assignment = build_aggr_init (decl, init, 0);
expand_aggr_init (decl, init, 0);
do_pending_stack_adjust ();
}
else if (init) else if (init)
expand_assignment (decl, init, 0, 0); assignment = build_modify_expr (decl, NOP_EXPR, init);
else
/* Set TEMP to 1. */ assignment = NULL_TREE;
expand_assignment (temp, integer_one_node, 0, 0);
/* Once the assignment is complete, set TEMP to 1. Since the
/* Cleanup any temporaries needed for the initial value. If construction of the static object is complete at this point,
destroying one of the temporaries causes an exception to be we want to make sure TEMP is set to 1 even if a temporary
thrown, then the object itself has still been fully constructed during the initialization throws an exception
constructed. */ when it is destroyed. So, we combine the initialization and
expand_end_target_temps (); 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 /* Use atexit to register a function for destroying this static
variable. */ variable. */
...@@ -12813,25 +12838,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12813,25 +12838,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
{ {
decl1 = declarator; 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); fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE) if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype); ctype = TYPE_METHOD_BASETYPE (fntype);
...@@ -13161,6 +13167,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -13161,6 +13167,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
on the permanent obstack in case we need to inline it later. */ on the permanent obstack in case we need to inline it later. */
if (! hack_decl_function_context (decl1)) if (! hack_decl_function_context (decl1))
temporary_allocation (); temporary_allocation ();
/* Make sure that we always have a momntary obstack while we're in a
function body. */
push_momentary ();
if (building_stmt_tree ()) if (building_stmt_tree ())
begin_stmt_tree (decl1); begin_stmt_tree (decl1);
...@@ -13856,6 +13866,9 @@ finish_function (lineno, flags, nested) ...@@ -13856,6 +13866,9 @@ finish_function (lineno, flags, nested)
to the FUNCTION_DECL node itself. */ to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
/* Undo the call to push_momentary in start_function. */
pop_momentary ();
if (expand_p) if (expand_p)
{ {
int saved_flag_keep_inline_functions = int saved_flag_keep_inline_functions =
...@@ -14261,9 +14274,6 @@ void ...@@ -14261,9 +14274,6 @@ void
cplus_expand_expr_stmt (exp) cplus_expand_expr_stmt (exp)
tree exp; tree exp;
{ {
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
exp = require_complete_type_in_void (exp); exp = require_complete_type_in_void (exp);
if (TREE_CODE (exp) == FUNCTION_DECL) if (TREE_CODE (exp) == FUNCTION_DECL)
...@@ -14288,10 +14298,6 @@ cplus_expand_expr_stmt (exp) ...@@ -14288,10 +14298,6 @@ cplus_expand_expr_stmt (exp)
go outside the bounds of the type. */ go outside the bounds of the type. */
if (exp != error_mark_node) if (exp != error_mark_node)
expand_expr_stmt (break_out_cleanups (exp)); 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. */ /* When a stmt has been parsed, this function is called. */
...@@ -14381,6 +14387,7 @@ struct cp_function ...@@ -14381,6 +14387,7 @@ struct cp_function
int static_labelno; int static_labelno;
int in_function_try_handler; int in_function_try_handler;
int expanding_p; int expanding_p;
int stmts_are_full_exprs_p;
tree last_tree; tree last_tree;
tree last_expr_type; tree last_expr_type;
}; };
...@@ -14429,10 +14436,15 @@ push_cp_function_context (context) ...@@ -14429,10 +14436,15 @@ push_cp_function_context (context)
p->last_tree = last_tree; p->last_tree = last_tree;
p->last_expr_type = last_expr_type; p->last_expr_type = last_expr_type;
p->expanding_p = expanding_p; 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 /* For now, we always assume we're expanding all the way to RTL
unless we're explicitly doing otherwise. */ unless we're explicitly doing otherwise. */
expanding_p = 1; 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. */ /* Restore the variables used during compilation of a C++ function. */
...@@ -14479,6 +14491,7 @@ pop_cp_function_context (context) ...@@ -14479,6 +14491,7 @@ pop_cp_function_context (context)
last_tree = p->last_tree; last_tree = p->last_tree;
last_expr_type = p->last_expr_type; last_expr_type = p->last_expr_type;
expanding_p = p->expanding_p; expanding_p = p->expanding_p;
stmts_are_full_exprs_p = p->stmts_are_full_exprs_p;
free (p); free (p);
} }
......
...@@ -2077,31 +2077,6 @@ get_temp_name (type, staticp) ...@@ -2077,31 +2077,6 @@ get_temp_name (type, staticp)
return decl; 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 /* Hunts through the global anonymous union ANON_DECL, building
appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and 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 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) ...@@ -3219,11 +3194,12 @@ do_static_initialization (decl, init, sentry, priority)
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || 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) else if (TREE_CODE (init) == TREE_VEC)
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0), expand_expr (build_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1), TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0), TREE_VEC_ELT (init, 2), 0),
const0_rtx, VOIDmode, EXPAND_NORMAL); const0_rtx, VOIDmode, EXPAND_NORMAL);
else else
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
...@@ -3290,7 +3266,7 @@ do_static_destruction (decl, sentry, priority) ...@@ -3290,7 +3266,7 @@ do_static_destruction (decl, sentry, priority)
integer_zero_node), integer_zero_node),
/*exit_flag=*/0); /*exit_flag=*/0);
/* Actually to the destruction. */ /* Actually do the destruction. */
expand_expr_stmt (build_cleanup (decl)); expand_expr_stmt (build_cleanup (decl));
/* Cleanup any deferred pops from function calls. This would be done /* Cleanup any deferred pops from function calls. This would be done
......
...@@ -768,6 +768,13 @@ dequeue_and_dump (di) ...@@ -768,6 +768,13 @@ dequeue_and_dump (di)
dump_next_stmt (di, t); dump_next_stmt (di, t);
break; 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: case INTEGER_CST:
if (TREE_INT_CST_HIGH (t)) if (TREE_INT_CST_HIGH (t))
dump_int (di, "high", TREE_INT_CST_HIGH (t)); dump_int (di, "high", TREE_INT_CST_HIGH (t));
...@@ -798,6 +805,7 @@ dequeue_and_dump (di) ...@@ -798,6 +805,7 @@ dequeue_and_dump (di)
case TRUTH_ANDIF_EXPR: case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR: case TRUTH_ORIF_EXPR:
case INIT_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
case COMPONENT_REF: case COMPONENT_REF:
case COMPOUND_EXPR: case COMPOUND_EXPR:
......
...@@ -965,9 +965,7 @@ expand_throw (exp) ...@@ -965,9 +965,7 @@ expand_throw (exp)
ourselves into expand_call. */ ourselves into expand_call. */
if (TREE_SIDE_EFFECTS (exp)) if (TREE_SIDE_EFFECTS (exp))
{ {
tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp)); tree temp = create_temporary_var (TREE_TYPE (exp));
DECL_ARTIFICIAL (temp) = 1;
DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
DECL_INITIAL (temp) = exp; DECL_INITIAL (temp) = exp;
cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
exp = temp; exp = temp;
......
...@@ -204,7 +204,9 @@ cplus_expand_expr (exp, target, tmode, modifier) ...@@ -204,7 +204,9 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = convert_from_reference (init); init = convert_from_reference (init);
flag_access_control = 0; 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; flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
...@@ -237,7 +239,7 @@ cplus_expand_expr (exp, target, tmode, modifier) ...@@ -237,7 +239,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
case VEC_INIT_EXPR: case VEC_INIT_EXPR:
return expand_expr return expand_expr
(expand_vec_init (build_vec_init
(NULL_TREE, TREE_OPERAND (exp, 0), (NULL_TREE, TREE_OPERAND (exp, 0),
build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2), build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
integer_one_node), integer_one_node),
......
...@@ -57,10 +57,11 @@ static int member_init_ok_or_else PROTO((tree, tree, const char *)); ...@@ -57,10 +57,11 @@ static int member_init_ok_or_else PROTO((tree, tree, const char *));
static void expand_virtual_init PROTO((tree, tree)); static void expand_virtual_init PROTO((tree, tree));
static tree sort_member_init PROTO((tree)); static tree sort_member_init PROTO((tree));
static tree initializing_context PROTO((tree)); static tree initializing_context PROTO((tree));
static void expand_vec_init_try_block PROTO((tree));
static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree));
static tree build_java_class_ref PROTO((tree)); static tree build_java_class_ref PROTO((tree));
static void expand_cleanup_for_base PROTO((tree, tree)); static void expand_cleanup_for_base PROTO((tree, tree));
static tree get_temp_regvar PROTO((tree, tree));
static void begin_init_stmts PROTO((tree *, tree *));
static tree finish_init_stmts PROTO((tree, tree));
/* Cache the identifier nodes for the magic field of a new cookie. */ /* Cache the identifier nodes for the magic field of a new cookie. */
static tree nc_nelts_field_id; static tree nc_nelts_field_id;
...@@ -119,6 +120,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -119,6 +120,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree binfos = BINFO_BASETYPES (binfo); tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0; int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
push_momentary ();
for (i = 0; i < n_baselinks; i++) for (i = 0; i < n_baselinks; i++)
{ {
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i); tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
...@@ -140,6 +142,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -140,6 +142,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree base_ptr = convert_pointer_to_real (binfo, addr); tree base_ptr = convert_pointer_to_real (binfo, addr);
expand_virtual_init (real_binfo, base_ptr); expand_virtual_init (real_binfo, base_ptr);
} }
pop_momentary ();
} }
/* 348 - 351 */ /* 348 - 351 */
...@@ -153,8 +156,6 @@ perform_member_init (member, name, init, explicit) ...@@ -153,8 +156,6 @@ perform_member_init (member, name, init, explicit)
tree decl; tree decl;
tree type = TREE_TYPE (member); tree type = TREE_TYPE (member);
expand_start_target_temps ();
decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit); decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
/* Deal with this here, as we will get confused if we try to call the /* Deal with this here, as we will get confused if we try to call the
...@@ -164,7 +165,7 @@ perform_member_init (member, name, init, explicit) ...@@ -164,7 +165,7 @@ perform_member_init (member, name, init, explicit)
{ {
init = build (INIT_EXPR, type, decl, TREE_VALUE (init)); init = build (INIT_EXPR, type, decl, TREE_VALUE (init));
TREE_SIDE_EFFECTS (init) = 1; TREE_SIDE_EFFECTS (init) = 1;
expand_expr_stmt (init); finish_expr_stmt (init);
} }
else if (TYPE_NEEDS_CONSTRUCTING (type) else if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type))) || (init && TYPE_HAS_CONSTRUCTOR (type)))
...@@ -181,11 +182,12 @@ perform_member_init (member, name, init, explicit) ...@@ -181,11 +182,12 @@ perform_member_init (member, name, init, explicit)
&& TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
{ {
/* Initialization of one array from another. */ /* Initialization of one array from another. */
expand_vec_init (TREE_OPERAND (decl, 1), decl, finish_expr_stmt
array_type_nelts (type), TREE_VALUE (init), 1); (build_vec_init (TREE_OPERAND (decl, 1), decl,
array_type_nelts (type), TREE_VALUE (init), 1));
} }
else else
expand_aggr_init (decl, init, 0); finish_expr_stmt (build_aggr_init (decl, init, 0));
} }
else else
{ {
...@@ -205,7 +207,7 @@ perform_member_init (member, name, init, explicit) ...@@ -205,7 +207,7 @@ perform_member_init (member, name, init, explicit)
for constructors and such. */ for constructors and such. */
tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (e) = 1; TREE_SIDE_EFFECTS (e) = 1;
expand_expr_stmt (build (INIT_EXPR, type, decl, e)); finish_expr_stmt (build (INIT_EXPR, type, decl, e));
} }
else if (TREE_CODE (type) == REFERENCE_TYPE) else if (TREE_CODE (type) == REFERENCE_TYPE)
cp_error ("default-initialization of `%#D', which has reference type", cp_error ("default-initialization of `%#D', which has reference type",
...@@ -231,12 +233,9 @@ perform_member_init (member, name, init, explicit) ...@@ -231,12 +233,9 @@ perform_member_init (member, name, init, explicit)
} }
if (init) if (init)
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
} }
expand_end_target_temps ();
free_temp_slots ();
if (TYPE_NEEDS_DESTRUCTOR (type)) if (TYPE_NEEDS_DESTRUCTOR (type))
{ {
tree expr; tree expr;
...@@ -251,7 +250,7 @@ perform_member_init (member, name, init, explicit) ...@@ -251,7 +250,7 @@ perform_member_init (member, name, init, explicit)
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node) if (expr != error_mark_node)
add_partial_entry (expr); finish_subobject (expr);
pop_obstacks (); pop_obstacks ();
} }
...@@ -508,9 +507,8 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -508,9 +507,8 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
extern tree base_init_expr; extern tree base_init_expr;
void void
emit_base_init (t, immediately) emit_base_init (t)
tree t; tree t;
int immediately;
{ {
tree member; tree member;
tree mem_init_list; tree mem_init_list;
...@@ -518,27 +516,8 @@ emit_base_init (t, immediately) ...@@ -518,27 +516,8 @@ emit_base_init (t, immediately)
tree t_binfo = TYPE_BINFO (t); tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo); tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree expr = NULL_TREE; tree stmt_expr;
tree compound_stmt;
if (! immediately)
{
int momentary;
do_pending_stack_adjust ();
/* Make the RTL_EXPR node temporary, not momentary,
so that rtl_expr_chain doesn't become garbage. */
momentary = suspend_momentary ();
expr = make_node (RTL_EXPR);
resume_momentary (momentary);
start_sequence_for_rtl_expr (expr);
}
if (write_symbols == NO_DEBUG)
/* As a matter of principle, `start_sequence' should do this. */
emit_note (0, -1);
else
/* Always emit a line number note so we can step into constructors. */
emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl));
mem_init_list = sort_member_init (t); mem_init_list = sort_member_init (t);
current_member_init_list = NULL_TREE; current_member_init_list = NULL_TREE;
...@@ -546,6 +525,8 @@ emit_base_init (t, immediately) ...@@ -546,6 +525,8 @@ emit_base_init (t, immediately)
sort_base_init (t, &rbase_init_list, &vbase_init_list); sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE; current_base_init_list = NULL_TREE;
begin_init_stmts (&stmt_expr, &compound_stmt);
/* First, initialize the virtual base classes, if we are /* First, initialize the virtual base classes, if we are
constructing the most-derived object. */ constructing the most-derived object. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
...@@ -579,15 +560,10 @@ emit_base_init (t, immediately) ...@@ -579,15 +560,10 @@ emit_base_init (t, immediately)
if (init != void_list_node) if (init != void_list_node)
{ {
expand_start_target_temps ();
member = convert_pointer_to_real (base_binfo, current_class_ptr); member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE, expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init, build_indirect_ref (member, NULL_PTR), init,
LOOKUP_NORMAL); LOOKUP_NORMAL);
expand_end_target_temps ();
free_temp_slots ();
} }
expand_cleanup_for_base (base_binfo, NULL_TREE); expand_cleanup_for_base (base_binfo, NULL_TREE);
...@@ -665,36 +641,12 @@ emit_base_init (t, immediately) ...@@ -665,36 +641,12 @@ emit_base_init (t, immediately)
cp_error ("field `%D' not in immediate context", field); cp_error ("field `%D' not in immediate context", field);
} }
#if 0
/* It turns out if you have an anonymous union in the
class, a member from it can end up not being on the
list of fields (rather, the type is), and therefore
won't be seen by the for loop above. */
/* The code in this for loop is derived from a general loop
which had this check in it. Theoretically, we've hit
every initialization for the list of members in T, so
we shouldn't have anything but these left in this list. */
my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);
#endif
perform_member_init (field, name, init, 1); perform_member_init (field, name, init, 1);
} }
mem_init_list = TREE_CHAIN (mem_init_list); mem_init_list = TREE_CHAIN (mem_init_list);
} }
if (! immediately) base_init_expr = finish_init_stmts (stmt_expr, compound_stmt);
{
do_pending_stack_adjust ();
my_friendly_assert (base_init_expr == 0, 207);
base_init_expr = expr;
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
RTL_EXPR_SEQUENCE (expr) = get_insns ();
rtl_expr_chain = tree_cons (NULL_TREE, expr, rtl_expr_chain);
end_sequence ();
TREE_SIDE_EFFECTS (expr) = 1;
}
/* All the implicit try blocks we built up will be zapped /* All the implicit try blocks we built up will be zapped
when we come to a real binding contour boundary. */ when we come to a real binding contour boundary. */
...@@ -745,7 +697,7 @@ expand_virtual_init (binfo, decl) ...@@ -745,7 +697,7 @@ expand_virtual_init (binfo, decl)
/* Have to convert VTBL since array sizes may be different. */ /* Have to convert VTBL since array sizes may be different. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl)); finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
} }
/* If an exception is thrown in a constructor, those base classes already /* If an exception is thrown in a constructor, those base classes already
...@@ -778,7 +730,7 @@ expand_cleanup_for_base (binfo, flag) ...@@ -778,7 +730,7 @@ expand_cleanup_for_base (binfo, flag)
expr, integer_zero_node)); expr, integer_zero_node));
pop_obstacks (); pop_obstacks ();
add_partial_entry (expr); finish_subobject (expr);
} }
/* Subroutine of `expand_aggr_vbase_init'. /* Subroutine of `expand_aggr_vbase_init'.
...@@ -792,15 +744,10 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) ...@@ -792,15 +744,10 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree init = purpose_member (binfo, init_list); tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR); tree ref = build_indirect_ref (addr, NULL_PTR);
expand_start_target_temps ();
if (init) if (init)
init = TREE_VALUE (init); init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN); expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
expand_end_target_temps ();
free_temp_slots ();
} }
/* Construct the virtual base-classes of THIS_REF (whose address is /* Construct the virtual base-classes of THIS_REF (whose address is
...@@ -818,24 +765,33 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag) ...@@ -818,24 +765,33 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
{ {
tree vbases; tree vbases;
tree result; tree result;
tree if_stmt;
/* If there are no virtual baseclasses, we shouldn't even be here. */ /* If there are no virtual baseclasses, we shouldn't even be here. */
my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621); my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
/* First set the pointers in our object that tell us where to find /* First set the pointers in our object that tell us where to find
our virtual baseclasses. */ our virtual baseclasses. */
expand_start_cond (flag, 0); if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr); result = init_vbase_pointers (type, this_ptr);
/* The RESULT will contain entries on the momentary obstack. They
must live until the end of this function; we use them in the loop
below. */
push_momentary ();
if (result) if (result)
expand_expr_stmt (build_compound_expr (result)); finish_expr_stmt (build_compound_expr (result));
expand_end_cond (); finish_then_clause (if_stmt);
finish_if_stmt ();
/* Now, run through the baseclasses, initializing each. */ /* Now, run through the baseclasses, initializing each. */
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
vbases = TREE_CHAIN (vbases)) vbases = TREE_CHAIN (vbases))
{ {
tree tmp = purpose_member (vbases, result); tree tmp = purpose_member (vbases, result);
tree inner_if_stmt;
tree compound_stmt;
/* If there are virtual base classes with destructors, we need to /* If there are virtual base classes with destructors, we need to
emit cleanups to destroy them if an exception is thrown during emit cleanups to destroy them if an exception is thrown during
the construction process. These exception regions (i.e., the the construction process. These exception regions (i.e., the
...@@ -850,14 +806,21 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag) ...@@ -850,14 +806,21 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
in the outer block.) We trust the back-end to figure out in the outer block.) We trust the back-end to figure out
that the FLAG will not change across initializations, and that the FLAG will not change across initializations, and
avoid doing multiple tests. */ avoid doing multiple tests. */
expand_start_cond (flag, 0); inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, inner_if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
expand_aggr_vbase_init_1 (vbases, this_ref, expand_aggr_vbase_init_1 (vbases, this_ref,
TREE_OPERAND (TREE_VALUE (tmp), 0), TREE_OPERAND (TREE_VALUE (tmp), 0),
init_list); init_list);
expand_end_cond (); finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
expand_cleanup_for_base (vbases, flag); expand_cleanup_for_base (vbases, flag);
} }
/* Undo the call to push_momentary above. */
pop_momentary ();
} }
/* Find the context in which this FIELD can be initialized. */ /* Find the context in which this FIELD can be initialized. */
...@@ -1035,6 +998,39 @@ expand_member_init (exp, name, init) ...@@ -1035,6 +998,39 @@ expand_member_init (exp, name, init)
} }
} }
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
to include conditionals, loops, and other such statement-level
constructs. Therefore, we build the initialization code inside a
statement-expression. This function starts such an expression.
STMT_EXPR_P and COMPOUND_STMT_P are filled in by this function;
pass them back to finish_init_stmts when the expression is
complete. */
static void
begin_init_stmts (stmt_expr_p, compound_stmt_p)
tree *stmt_expr_p;
tree *compound_stmt_p;
{
push_momentary ();
*stmt_expr_p = begin_stmt_expr ();
*compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
}
/* Finish out the statement-expression begun by the previous call to
begin_init_stmts. Returns the statement-expression itself. */
static tree
finish_init_stmts (stmt_expr, compound_stmt)
tree stmt_expr;
tree compound_stmt;
{
pop_momentary ();
return finish_stmt_expr (stmt_expr,
finish_compound_stmt (/*has_no_scope=*/1,
compound_stmt));
}
/* This is like `expand_member_init', only it stores one aggregate /* This is like `expand_member_init', only it stores one aggregate
value into another. value into another.
...@@ -1073,17 +1069,20 @@ expand_member_init (exp, name, init) ...@@ -1073,17 +1069,20 @@ expand_member_init (exp, name, init)
A constructor or a conversion operator may have to be used to A constructor or a conversion operator may have to be used to
perform the initialization, but not both, as it would be ambiguous. */ perform the initialization, but not both, as it would be ambiguous. */
void tree
expand_aggr_init (exp, init, flags) build_aggr_init (exp, init, flags)
tree exp, init; tree exp, init;
int flags; int flags;
{ {
tree stmt_expr;
tree compound_stmt;
int destroy_temps;
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
int was_const = TREE_READONLY (exp); int was_const = TREE_READONLY (exp);
int was_volatile = TREE_THIS_VOLATILE (exp); int was_volatile = TREE_THIS_VOLATILE (exp);
if (init == error_mark_node) if (init == error_mark_node)
return; return error_mark_node;
TREE_READONLY (exp) = 0; TREE_READONLY (exp) = 0;
TREE_THIS_VOLATILE (exp) = 0; TREE_THIS_VOLATILE (exp) = 0;
...@@ -1117,38 +1116,36 @@ expand_aggr_init (exp, init, flags) ...@@ -1117,38 +1116,36 @@ expand_aggr_init (exp, init, flags)
} }
*/ */
error ("bad array initializer"); error ("bad array initializer");
return; return error_mark_node;
} }
expand_vec_init (exp, exp, array_type_nelts (type), init, stmt_expr = build_vec_init (exp, exp, array_type_nelts (type), init,
init && same_type_p (TREE_TYPE (init), init && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp))); TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile; TREE_THIS_VOLATILE (exp) = was_volatile;
TREE_TYPE (exp) = type; TREE_TYPE (exp) = type;
if (init) if (init)
TREE_TYPE (init) = itype; TREE_TYPE (init) = itype;
return; return stmt_expr;
} }
if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL) if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
/* just know that we've seen something for this node */ /* just know that we've seen something for this node */
TREE_USED (exp) = 1; TREE_USED (exp) = 1;
#if 0
/* If initializing from a GNU C CONSTRUCTOR, consider the elts in the
constructor as parameters to an implicit GNU C++ constructor. */
if (init && TREE_CODE (init) == CONSTRUCTOR
&& TYPE_HAS_CONSTRUCTOR (type)
&& TREE_TYPE (init) == type)
init = CONSTRUCTOR_ELTS (init);
#endif
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p;
stmts_are_full_exprs_p = 0;
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
init, LOOKUP_NORMAL|flags); init, LOOKUP_NORMAL|flags);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
stmts_are_full_exprs_p = destroy_temps;
TREE_TYPE (exp) = type; TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile; TREE_THIS_VOLATILE (exp) = was_volatile;
return stmt_expr;
} }
static void static void
...@@ -1199,7 +1196,7 @@ expand_default_init (binfo, true_exp, exp, init, flags) ...@@ -1199,7 +1196,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
else else
init = build (INIT_EXPR, TREE_TYPE (exp), exp, init); init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
TREE_SIDE_EFFECTS (init) = 1; TREE_SIDE_EFFECTS (init) = 1;
expand_expr_stmt (init); finish_expr_stmt (init);
return; return;
} }
...@@ -1225,7 +1222,7 @@ expand_default_init (binfo, true_exp, exp, init, flags) ...@@ -1225,7 +1222,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
rval = build_method_call (exp, ctor_identifier, rval = build_method_call (exp, ctor_identifier,
parms, binfo, flags); parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval)) if (TREE_SIDE_EFFECTS (rval))
expand_expr_stmt (rval); finish_expr_stmt (rval);
} }
/* This function is responsible for initializing EXP with INIT /* This function is responsible for initializing EXP with INIT
...@@ -1271,15 +1268,20 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags) ...@@ -1271,15 +1268,20 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
&& TREE_CODE (init) == CONSTRUCTOR && TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init)) && TREE_HAS_CONSTRUCTOR (init))
{ {
tree t = store_init_value (exp, init); /* If store_init_value returns NULL_TREE, the INIT has been
if (!t) record in the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
if (!store_init_value (exp, init))
{ {
expand_decl_init (exp); if (!building_stmt_tree ())
return; expand_decl_init (exp);
}
else
{
tree t = build (INIT_EXPR, type, exp, init);
TREE_SIDE_EFFECTS (t) = 1;
finish_expr_stmt (t);
} }
t = build (INIT_EXPR, type, exp, init);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr_stmt (t);
return; return;
} }
...@@ -2689,88 +2691,54 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete, ...@@ -2689,88 +2691,54 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
return cp_convert (void_type_node, body); return cp_convert (void_type_node, body);
} }
/* Protect the vector initialization with a try-block so that we can tree
destroy the first few elements if constructing a later element create_temporary_var (type)
causes an exception to be thrown. TYPE is the type of the array
elements. */
static void
expand_vec_init_try_block (type)
tree type; tree type;
{ {
if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions) tree decl;
return;
decl = build_decl (VAR_DECL, NULL_TREE, type);
/* The code we generate looks like: TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
try { DECL_SOURCE_FILE (decl) = input_filename;
// Initialize the vector. DECL_SOURCE_LINE (decl) = lineno;
} catch (...) { DECL_IGNORED_P (decl) = 1;
// Destory the elements that need destroying.
throw; if (building_stmt_tree ())
} add_decl_stmt (decl);
else
Here we're just beginning the `try'. */ DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
expand_eh_region_start (); return decl;
} }
/* Add code to destroy the array elements constructed so far if the /* Create a new temporary variable of the indicated TYPE, initialized
construction of some element in the array causes an exception to be to INIT.
thrown. RVAL is the address of the last element in the array.
TYPE is the type of the array elements. MAXINDEX is the maximum
allowable index into the array. ITERATOR is an integer variable
indicating how many elements remain to be constructed. */
static void It is not entered into current_binding_level, because that breaks
expand_vec_init_catch_clause (rval, type, maxindex, iterator) things when it comes time to do final cleanups (which take place
tree rval; "outside" the binding contour of the function). */
tree type;
tree maxindex; static tree
tree iterator; get_temp_regvar (type, init)
tree type, init;
{ {
tree e; tree decl;
tree cleanup;
if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions) decl = create_temporary_var (type);
return; DECL_REGISTER (decl) = 1;
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
/* We have to ensure that this can live to the cleanup expansion
time, since we know it is only ever needed once, generate code
now. */
push_obstacks_nochange ();
resume_temporary_allocation ();
cleanup = make_node (RTL_EXPR); return decl;
TREE_TYPE (cleanup) = void_type_node;
RTL_EXPR_RTL (cleanup) = const0_rtx;
TREE_SIDE_EFFECTS (cleanup) = 1;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (cleanup);
e = build_vec_delete_1 (rval,
build_binary_op (MINUS_EXPR, maxindex,
iterator),
type,
/*auto_delete_vec=*/integer_zero_node,
/*auto_delete=*/integer_zero_node,
/*use_global_delete=*/0);
expand_expr (e, const0_rtx, VOIDmode, EXPAND_NORMAL);
do_pending_stack_adjust ();
RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
end_sequence ();
cleanup = protect_with_terminate (cleanup);
expand_eh_region_end (cleanup);
pop_obstacks ();
} }
/* `expand_vec_init' performs initialization of a vector of aggregate /* `build_vec_init' returns tree structure that performs
types. initialization of a vector of aggregate types.
DECL is passed only for error reporting, and provides line number DECL is passed only for error reporting, and provides line number
and source file name information. and source file name information.
BASE is the space where the vector will be. BASE is the space where the vector will be. For a vector of Ts,
the type of BASE is `T*'.
MAXINDEX is the maximum index of the array (one less than the MAXINDEX is the maximum index of the array (one less than the
number of elements). number of elements).
INIT is the (possibly NULL) initializer. INIT is the (possibly NULL) initializer.
...@@ -2783,16 +2751,23 @@ expand_vec_init_catch_clause (rval, type, maxindex, iterator) ...@@ -2783,16 +2751,23 @@ expand_vec_init_catch_clause (rval, type, maxindex, iterator)
but use assignment instead of initialization. */ but use assignment instead of initialization. */
tree tree
expand_vec_init (decl, base, maxindex, init, from_array) build_vec_init (decl, base, maxindex, init, from_array)
tree decl, base, maxindex, init; tree decl, base, maxindex, init;
int from_array; int from_array;
{ {
tree rval; tree rval;
tree base2 = NULL_TREE; tree base2 = NULL_TREE;
tree type = TREE_TYPE (TREE_TYPE (base));
tree size; tree size;
tree itype = NULL_TREE; tree itype = NULL_TREE;
tree iterator; tree iterator;
/* The type of an element in the array. */
tree type;
/* The type of a pointer to an element in the array. */
tree ptype;
tree stmt_expr;
tree compound_stmt;
int destroy_temps;
tree try_block;
int num_initialized_elts = 0; int num_initialized_elts = 0;
maxindex = cp_convert (ptrdiff_type_node, maxindex); maxindex = cp_convert (ptrdiff_type_node, maxindex);
...@@ -2808,17 +2783,56 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -2808,17 +2783,56 @@ expand_vec_init (decl, base, maxindex, init, from_array)
return rval; return rval;
} }
type = TREE_TYPE (TREE_TYPE (base));
ptype = build_pointer_type (type);
size = size_in_bytes (type); size = size_in_bytes (type);
base = default_conversion (base); /* The code we are generating looks like:
base = cp_convert (build_pointer_type (type), base);
rval = get_temp_regvar (build_pointer_type (type), base); T* t1 = (T*) base;
base = get_temp_regvar (build_pointer_type (type), base); T* rval = base;
ptrdiff_t iterator = maxindex;
try {
... initializations from CONSTRUCTOR ...
if (iterator != -1) {
do {
... initialize *base ...
++base;
} while (--iterator != -1);
}
} catch (...) {
... destroy elements that were constructed ...
}
We can omit the try and catch blocks if we know that the
initialization will never throw an exception, or if the array
elements do not have destructors. If we have a CONSTRUCTOR to
give us initialization information, we emit code to initialize
each of the elements before the loop in the try block, and then
iterate over fewer elements. We can omit the loop completely if
the elements of the array do not have constructors.
We actually wrap the entire body of the above in a STMT_EXPR, for
tidiness.
When copying from array to another, when the array elements have
only trivial copy constructors, we should use __builtin_memcpy
rather than generating a loop. That way, we could take advantage
of whatever cleverness the back-end has for dealing with copies
of blocks of memory. */
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p;
stmts_are_full_exprs_p = 0;
rval = get_temp_regvar (ptype,
cp_convert (ptype, default_conversion (base)));
base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex); iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
/* Protect the entire array initialization so that we can destroy /* Protect the entire array initialization so that we can destroy
the partially constructed array if an exception is thrown. */ the partially constructed array if an exception is thrown. */
expand_vec_init_try_block (type); if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
try_block = begin_try_block ();
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR
&& (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl)))) && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
...@@ -2827,35 +2841,37 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -2827,35 +2841,37 @@ expand_vec_init (decl, base, maxindex, init, from_array)
initializers. */ initializers. */
tree elts; tree elts;
tree baseref = build1 (INDIRECT_REF, type, base);
from_array = 0; from_array = 0;
for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts)) for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts))
{ {
tree elt = TREE_VALUE (elts); tree elt = TREE_VALUE (elts);
tree baseref = build1 (INDIRECT_REF, type, base);
num_initialized_elts++; num_initialized_elts++;
if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE) if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
expand_aggr_init (baseref, elt, 0); finish_expr_stmt (build_aggr_init (baseref, elt, 0));
else else
expand_assignment (baseref, elt, 0, 0); finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR,
elt));
expand_assignment (base, finish_expr_stmt (build_modify_expr
(base,
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type), build (PLUS_EXPR, build_pointer_type (type),
base, size), base, size)));
0, 0); finish_expr_stmt (build_modify_expr
expand_assignment (iterator, (iterator,
NOP_EXPR,
build (MINUS_EXPR, ptrdiff_type_node, build (MINUS_EXPR, ptrdiff_type_node,
iterator, integer_one_node), iterator, integer_one_node)));
0, 0);
} }
/* Clear out INIT so that we don't get confused below. */ /* Clear out INIT so that we don't get confused below. */
init = NULL_TREE; init = NULL_TREE;
if (obey_regdecls) if (obey_regdecls && !building_stmt_tree ())
use_variable (DECL_RTL (base)); use_variable (DECL_RTL (base));
} }
else if (from_array) else if (from_array)
...@@ -2897,15 +2913,33 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -2897,15 +2913,33 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{ {
/* If the ITERATOR is equal to -1, then we don't have to loop; /* If the ITERATOR is equal to -1, then we don't have to loop;
we've already initialized all the elements. */ we've already initialized all the elements. */
expand_start_cond (build (NE_EXPR, boolean_type_node, tree if_stmt;
iterator, minus_one), tree do_stmt;
0); tree do_body;
tree elt_init;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build (NE_EXPR, boolean_type_node,
iterator, minus_one),
if_stmt);
/* Otherwise, loop through the elements. */ /* Otherwise, loop through the elements. */
expand_start_loop_continue_elsewhere (1); do_stmt = begin_do_stmt ();
do_body = begin_compound_stmt (/*has_no_scope=*/1);
/* The initialization of each array element is a full-expression. */
expand_start_target_temps (); /* When we're not building a statement-tree, things are a little
complicated. If, when we recursively call build_aggr_init,
an expression containing a TARGET_EXPR is expanded, then it
may get a cleanup. Then, the result of that expression is
passed to finish_expr_stmt, which will call
expand_start_target_temps/expand_end_target_temps. However,
the latter call will not cause the cleanup to run because
that block will still be on the block stack. So, we call
expand_start_target_temps here manually; the corresponding
call to expand_end_target_temps below will cause the cleanup
to be performed. */
if (!building_stmt_tree ())
expand_start_target_temps ();
if (from_array) if (from_array)
{ {
...@@ -2918,11 +2952,11 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -2918,11 +2952,11 @@ expand_vec_init (decl, base, maxindex, init, from_array)
from = NULL_TREE; from = NULL_TREE;
if (from_array == 2) if (from_array == 2)
expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from)); elt_init = build_modify_expr (to, NOP_EXPR, from);
else if (TYPE_NEEDS_CONSTRUCTING (type)) else if (TYPE_NEEDS_CONSTRUCTING (type))
expand_aggr_init (to, from, 0); elt_init = build_aggr_init (to, from, 0);
else if (from) else if (from)
expand_assignment (to, from, 0, 0); elt_init = build_modify_expr (to, NOP_EXPR, from);
else else
my_friendly_abort (57); my_friendly_abort (57);
} }
...@@ -2930,56 +2964,100 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -2930,56 +2964,100 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{ {
if (init != 0) if (init != 0)
sorry ("cannot initialize multi-dimensional array with initializer"); sorry ("cannot initialize multi-dimensional array with initializer");
expand_vec_init (decl, elt_init = (build_vec_init
build1 (NOP_EXPR, (decl,
build_pointer_type (TREE_TYPE build1 (NOP_EXPR,
(type)), build_pointer_type (TREE_TYPE (type)),
base), base),
array_type_nelts (type), 0, 0); array_type_nelts (type), 0, 0));
}
else
elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base),
init, 0);
/* The initialization of each array element is a
full-expression. */
if (!building_stmt_tree ())
{
finish_expr_stmt (elt_init);
expand_end_target_temps ();
} }
else else
expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0); {
stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
stmts_are_full_exprs_p = 0;
}
expand_assignment (base, finish_expr_stmt (build_modify_expr
(base,
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type), build (PLUS_EXPR, build_pointer_type (type),
base, size), 0, 0); base, size)));
if (base2) if (base2)
expand_assignment (base2, finish_expr_stmt (build_modify_expr
(base2,
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type), build (PLUS_EXPR, build_pointer_type (type),
base2, size), 0, 0); base2, size)));
/* Cleanup any temporaries needed for the initial value. */ if (obey_regdecls && !building_stmt_tree ())
expand_end_target_temps ();
expand_loop_continue_here ();
expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR,
ptrdiff_type_node,
iterator,
integer_one_node),
minus_one));
if (obey_regdecls)
{ {
use_variable (DECL_RTL (base)); use_variable (DECL_RTL (base));
if (base2) if (base2)
use_variable (DECL_RTL (base2)); use_variable (DECL_RTL (base2));
} }
expand_end_loop (); finish_compound_stmt (/*has_no_scope=*/1, do_body);
expand_end_cond (); finish_do_body (do_stmt);
finish_do_stmt (build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR,
ptrdiff_type_node,
iterator,
integer_one_node),
minus_one),
do_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
} }
/* Make sure to cleanup any partially constructed elements. */ /* Make sure to cleanup any partially constructed elements. */
expand_vec_init_catch_clause (rval, type, maxindex, iterator); if (flag_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
{
tree e;
if (obey_regdecls) /* Because CLEANUP will not be processed until later, it must go
on the temporary obstack. */
push_obstacks_nochange ();
resume_temporary_allocation ();
/* And MAXINDEX needs to be copied to the current obstack. It's
probably on the momentary obstack now. */
maxindex = mapcar (maxindex, permanent_p);
e = build_vec_delete_1 (rval,
build_binary_op (MINUS_EXPR, maxindex,
iterator),
type,
/*auto_delete_vec=*/integer_zero_node,
/*auto_delete=*/integer_zero_node,
/*use_global_delete=*/0);
pop_obstacks ();
finish_cleanup (e, try_block);
}
if (obey_regdecls && !building_stmt_tree ())
{ {
use_variable (DECL_RTL (iterator)); use_variable (DECL_RTL (iterator));
use_variable (DECL_RTL (rval)); use_variable (DECL_RTL (rval));
} }
return rval; /* The value of the array initialization is the address of the
first element in the array. */
finish_expr_stmt (rval);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
stmts_are_full_exprs_p = destroy_temps;
return stmt_expr;
} }
/* Free up storage of type TYPE, at address ADDR. /* Free up storage of type TYPE, at address ADDR.
......
...@@ -2177,11 +2177,9 @@ do_build_copy_constructor (fndecl) ...@@ -2177,11 +2177,9 @@ do_build_copy_constructor (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
tree t; tree t;
clear_last_expr ();
push_momentary ();
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
...@@ -2194,7 +2192,7 @@ do_build_copy_constructor (fndecl) ...@@ -2194,7 +2192,7 @@ do_build_copy_constructor (fndecl)
{ {
t = build (INIT_EXPR, void_type_node, current_class_ref, parm); t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t); finish_expr_stmt (t);
} }
else else
{ {
...@@ -2257,7 +2255,8 @@ do_build_copy_constructor (fndecl) ...@@ -2257,7 +2255,8 @@ do_build_copy_constructor (fndecl)
setup_vtbl_ptr (); 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 static void
...@@ -2265,10 +2264,9 @@ do_build_assign_ref (fndecl) ...@@ -2265,10 +2264,9 @@ do_build_assign_ref (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
clear_last_expr (); compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
push_momentary ();
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
...@@ -2279,7 +2277,7 @@ do_build_assign_ref (fndecl) ...@@ -2279,7 +2277,7 @@ do_build_assign_ref (fndecl)
{ {
tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
TREE_SIDE_EFFECTS (t) = 1; TREE_SIDE_EFFECTS (t) = 1;
cplus_expand_expr_stmt (t); finish_expr_stmt (t);
} }
else else
{ {
...@@ -2353,7 +2351,7 @@ do_build_assign_ref (fndecl) ...@@ -2353,7 +2351,7 @@ do_build_assign_ref (fndecl)
} }
} }
c_expand_return (current_class_ref); c_expand_return (current_class_ref);
pop_momentary (); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
} }
void void
...@@ -2374,6 +2372,7 @@ synthesize_method (fndecl) ...@@ -2374,6 +2372,7 @@ synthesize_method (fndecl)
interface_unknown = 1; interface_unknown = 1;
start_function (NULL_TREE, fndecl, NULL_TREE, 1); start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls (); store_parm_decls ();
clear_last_expr ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
do_build_assign_ref (fndecl); 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; typedef union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; } YYSTYPE;
#define IDENTIFIER 258 #define IDENTIFIER 257
#define TYPENAME 259 #define TYPENAME 258
#define SELFNAME 260 #define SELFNAME 259
#define PFUNCNAME 261 #define PFUNCNAME 260
#define SCSPEC 262 #define SCSPEC 261
#define TYPESPEC 263 #define TYPESPEC 262
#define CV_QUALIFIER 264 #define CV_QUALIFIER 263
#define CONSTANT 265 #define CONSTANT 264
#define STRING 266 #define STRING 265
#define ELLIPSIS 267 #define ELLIPSIS 266
#define SIZEOF 268 #define SIZEOF 267
#define ENUM 269 #define ENUM 268
#define IF 270 #define IF 269
#define ELSE 271 #define ELSE 270
#define WHILE 272 #define WHILE 271
#define DO 273 #define DO 272
#define FOR 274 #define FOR 273
#define SWITCH 275 #define SWITCH 274
#define CASE 276 #define CASE 275
#define DEFAULT 277 #define DEFAULT 276
#define BREAK 278 #define BREAK 277
#define CONTINUE 279 #define CONTINUE 278
#define RETURN_KEYWORD 280 #define RETURN_KEYWORD 279
#define GOTO 281 #define GOTO 280
#define ASM_KEYWORD 282 #define ASM_KEYWORD 281
#define TYPEOF 283 #define TYPEOF 282
#define ALIGNOF 284 #define ALIGNOF 283
#define SIGOF 285 #define SIGOF 284
#define ATTRIBUTE 286 #define ATTRIBUTE 285
#define EXTENSION 287 #define EXTENSION 286
#define LABEL 288 #define LABEL 287
#define REALPART 289 #define REALPART 288
#define IMAGPART 290 #define IMAGPART 289
#define VA_ARG 291 #define VA_ARG 290
#define AGGR 292 #define AGGR 291
#define VISSPEC 293 #define VISSPEC 292
#define DELETE 294 #define DELETE 293
#define NEW 295 #define NEW 294
#define THIS 296 #define THIS 295
#define OPERATOR 297 #define OPERATOR 296
#define CXX_TRUE 298 #define CXX_TRUE 297
#define CXX_FALSE 299 #define CXX_FALSE 298
#define NAMESPACE 300 #define NAMESPACE 299
#define TYPENAME_KEYWORD 301 #define TYPENAME_KEYWORD 300
#define USING 302 #define USING 301
#define LEFT_RIGHT 303 #define LEFT_RIGHT 302
#define TEMPLATE 304 #define TEMPLATE 303
#define TYPEID 305 #define TYPEID 304
#define DYNAMIC_CAST 306 #define DYNAMIC_CAST 305
#define STATIC_CAST 307 #define STATIC_CAST 306
#define REINTERPRET_CAST 308 #define REINTERPRET_CAST 307
#define CONST_CAST 309 #define CONST_CAST 308
#define SCOPE 310 #define SCOPE 309
#define EMPTY 311 #define EMPTY 310
#define PTYPENAME 312 #define PTYPENAME 311
#define NSNAME 313 #define NSNAME 312
#define THROW 314 #define THROW 313
#define ASSIGN 315 #define ASSIGN 314
#define OROR 316 #define OROR 315
#define ANDAND 317 #define ANDAND 316
#define MIN_MAX 318 #define MIN_MAX 317
#define EQCOMPARE 319 #define EQCOMPARE 318
#define ARITHCOMPARE 320 #define ARITHCOMPARE 319
#define LSHIFT 321 #define LSHIFT 320
#define RSHIFT 322 #define RSHIFT 321
#define POINTSAT_STAR 323 #define POINTSAT_STAR 322
#define DOT_STAR 324 #define DOT_STAR 323
#define UNARY 325 #define UNARY 324
#define PLUSPLUS 326 #define PLUSPLUS 325
#define MINUSMINUS 327 #define MINUSMINUS 326
#define HYPERUNARY 328 #define HYPERUNARY 327
#define POINTSAT 329 #define POINTSAT 328
#define TRY 330 #define TRY 329
#define CATCH 331 #define CATCH 330
#define PRE_PARSED_FUNCTION_DECL 332 #define PRE_PARSED_FUNCTION_DECL 331
#define EXTERN_LANG_STRING 333 #define EXTERN_LANG_STRING 332
#define ALL 334 #define ALL 333
#define PRE_PARSED_CLASS_DECL 335 #define PRE_PARSED_CLASS_DECL 334
#define DEFARG 336 #define DEFARG 335
#define DEFARG_MARKER 337 #define DEFARG_MARKER 336
#define TYPENAME_DEFN 338 #define TYPENAME_DEFN 337
#define IDENTIFIER_DEFN 339 #define IDENTIFIER_DEFN 338
#define PTYPENAME_DEFN 340 #define PTYPENAME_DEFN 339
#define END_OF_LINE 341 #define END_OF_LINE 340
#define END_OF_SAVED_INPUT 342 #define END_OF_SAVED_INPUT 341
extern YYSTYPE yylval; extern YYSTYPE yylval;
......
...@@ -780,10 +780,6 @@ base_init: ...@@ -780,10 +780,6 @@ base_init:
if ($3 == 0) if ($3 == 0)
error ("no base initializers given following ':'"); error ("no base initializers given following ':'");
setup_vtbl_ptr (); 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: ...@@ -1623,10 +1619,6 @@ nodecls:
if (! current_function_parms_stored) if (! current_function_parms_stored)
store_parm_decls (); store_parm_decls ();
setup_vtbl_ptr (); 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) ...@@ -7424,12 +7424,17 @@ tsubst_expr (t, args, complain, in_decl)
stmt = begin_try_block (); stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl); tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (stmt); finish_try_block (stmt);
{ if (CLEANUP_P (t))
tree handler = TRY_HANDLERS (t); finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
for (; handler; handler = TREE_CHAIN (handler)) complain, in_decl),
tsubst_expr (handler, args, complain, in_decl); stmt);
} else
finish_handler_sequence (stmt); {
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl);
finish_handler_sequence (stmt);
}
break; break;
case HANDLER: case HANDLER:
......
...@@ -42,12 +42,27 @@ ...@@ -42,12 +42,27 @@
much easier since it will be able to make use of these routines. */ much easier since it will be able to make use of these routines. */
static void expand_stmts PROTO((tree)); 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. /* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without When this is zero, we just accumulate tree structure, without
interacting with the back end. */ interacting with the back end. */
int expanding_p = 1; 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 /* The type of the last expression-statement we have seen. This is
required because the type of a statement-expression is the type of required because the type of a statement-expression is the type of
the last expression statement. */ the last expression statement. */
...@@ -91,10 +106,18 @@ finish_expr_stmt (expr) ...@@ -91,10 +106,18 @@ finish_expr_stmt (expr)
&& lvalue_p (expr)) && lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE) || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr); expr = default_conversion (expr);
if (stmts_are_full_exprs_p)
expand_start_target_temps ();
cplus_expand_expr_stmt (expr); cplus_expand_expr_stmt (expr);
}
clear_momentary (); if (stmts_are_full_exprs_p)
{
expand_end_target_temps ();
clear_momentary ();
}
}
} }
finish_stmt (); finish_stmt ();
...@@ -455,7 +478,7 @@ finish_for_stmt (expr, for_stmt) ...@@ -455,7 +478,7 @@ finish_for_stmt (expr, for_stmt)
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
expand_loop_continue_here (); expand_loop_continue_here ();
if (expr) if (expr)
cplus_expand_expr_stmt (expr); finish_expr_stmt (expr);
expand_end_loop (); expand_end_loop ();
} }
...@@ -647,11 +670,28 @@ finish_try_block (try_block) ...@@ -647,11 +670,28 @@ finish_try_block (try_block)
expand_start_all_catch (); 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. */ /* Likewise, for a function-try-block. */
void void
finish_function_try_block (try_block) finish_function_try_block (try_block)
tree try_block; tree try_block;
{ {
if (building_stmt_tree ()) if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block)); RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
...@@ -673,9 +713,7 @@ finish_handler_sequence (try_block) ...@@ -673,9 +713,7 @@ finish_handler_sequence (try_block)
if (building_stmt_tree ()) if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block)); RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else else
{ expand_end_all_catch ();
expand_end_all_catch ();
}
} }
/* Likewise, for a function-try-block. */ /* Likewise, for a function-try-block. */
...@@ -762,6 +800,12 @@ begin_compound_stmt (has_no_scope) ...@@ -762,6 +800,12 @@ begin_compound_stmt (has_no_scope)
if (!has_no_scope) if (!has_no_scope)
do_pushlevel (); 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; return r;
} }
...@@ -904,6 +948,23 @@ add_decl_stmt (decl) ...@@ -904,6 +948,23 @@ add_decl_stmt (decl)
add_tree (decl_stmt); 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 /* Bind a name and initialization to the return value of
the current function. */ the current function. */
...@@ -975,13 +1036,18 @@ setup_vtbl_ptr () ...@@ -975,13 +1036,18 @@ setup_vtbl_ptr ()
(CTOR_INITIALIZER, (CTOR_INITIALIZER,
current_member_init_list, current_base_init_list)); current_member_init_list, current_base_init_list));
else 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. */ /* Begin a new scope. */
void static void
do_pushlevel () do_pushlevel ()
{ {
if (!building_stmt_tree ()) if (!building_stmt_tree ())
...@@ -989,22 +1055,24 @@ do_pushlevel () ...@@ -989,22 +1055,24 @@ do_pushlevel ()
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
clear_last_expr (); clear_last_expr ();
} }
pushlevel (0);
push_momentary (); 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); expand_start_bindings (0);
} }
/* Finish a scope. */ /* Finish a scope. */
tree static tree
do_poplevel () do_poplevel ()
{ {
tree t; tree t;
if (!building_stmt_tree ()) if (!building_stmt_tree () && stmts_are_full_exprs_p)
expand_end_bindings (getdecls (), kept_level_p (), 0); 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 (); pop_momentary ();
return t; return t;
} }
...@@ -1028,7 +1096,7 @@ finish_parenthesized_expr (expr) ...@@ -1028,7 +1096,7 @@ finish_parenthesized_expr (expr)
tree tree
begin_stmt_expr () begin_stmt_expr ()
{ {
keep_next_level (); keep_next_level (1);
/* If we're building a statement tree, then the upcoming compound /* If we're building a statement tree, then the upcoming compound
statement will be chained onto the tree structure, starting at statement will be chained onto the tree structure, starting at
last_tree. We return last_tree so that we can later unhook the last_tree. We return last_tree so that we can later unhook the
...@@ -1055,39 +1123,35 @@ finish_stmt_expr (rtl_expr, expr) ...@@ -1055,39 +1123,35 @@ finish_stmt_expr (rtl_expr, expr)
TREE_SIDE_EFFECTS (rtl_expr) = 1; 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 (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 /* Remove the compound statement from the tree structure; it is
now saved in the STMT_EXPR. */ now saved in the STMT_EXPR. */
last_tree = rtl_expr; last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE; 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; return result;
} }
...@@ -2082,11 +2146,20 @@ expand_stmt (t) ...@@ -2082,11 +2146,20 @@ expand_stmt (t)
case TRY_BLOCK: case TRY_BLOCK:
lineno = STMT_LINENO (t); lineno = STMT_LINENO (t);
begin_try_block (); if (CLEANUP_P (t))
expand_stmt (TRY_STMTS (t)); {
finish_try_block (NULL_TREE); expand_eh_region_start ();
expand_stmts (TRY_HANDLERS (t)); expand_stmt (TRY_STMTS (t));
finish_handler_sequence (NULL_TREE); 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; break;
case HANDLER: case HANDLER:
...@@ -2105,6 +2178,11 @@ expand_stmt (t) ...@@ -2105,6 +2178,11 @@ expand_stmt (t)
finish_handler (NULL_TREE); finish_handler (NULL_TREE);
break; break;
case SUBOBJECT:
lineno = STMT_LINENO (t);
finish_subobject (SUBOBJECT_CLEANUP (t));
break;
default: default:
my_friendly_abort (19990810); my_friendly_abort (19990810);
break; break;
...@@ -2168,11 +2246,6 @@ expand_body (fn) ...@@ -2168,11 +2246,6 @@ expand_body (fn)
base-classes. */ base-classes. */
setup_vtbl_ptr (); 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 the body. */
expand_stmt (t); expand_stmt (t);
......
...@@ -1656,6 +1656,7 @@ search_tree (t, func) ...@@ -1656,6 +1656,7 @@ search_tree (t, func)
case CALL_EXPR: case CALL_EXPR:
case COMPOUND_EXPR: case COMPOUND_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
case INIT_EXPR:
TRY (TREE_OPERAND (t, 0)); TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1)); TRY (TREE_OPERAND (t, 1));
break; break;
...@@ -1920,6 +1921,7 @@ mapcar (t, func) ...@@ -1920,6 +1921,7 @@ mapcar (t, func)
case WITH_CLEANUP_EXPR: case WITH_CLEANUP_EXPR:
case COMPOUND_EXPR: case COMPOUND_EXPR:
case MODIFY_EXPR: case MODIFY_EXPR:
case INIT_EXPR:
t = copy_node (t); t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func); TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func); TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
......
...@@ -5989,32 +5989,11 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5989,32 +5989,11 @@ build_modify_expr (lhs, modifycode, rhs)
if (pedantic && ! DECL_ARTIFICIAL (current_function_decl)) if (pedantic && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment of arrays"); 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 from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0; ? 1 + (modifycode != INIT_EXPR): 0;
expand_vec_init (lhs, lhs, array_type_nelts (lhstype), newrhs, return (build_vec_init
from_array); (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;
} }
if (modifycode == INIT_EXPR) if (modifycode == INIT_EXPR)
......
...@@ -465,7 +465,7 @@ store_init_value (decl, init) ...@@ -465,7 +465,7 @@ store_init_value (decl, init)
; ;
/* Other code expects that initializers for objects of types that need /* Other code expects that initializers for objects of types that need
constructing never make it into DECL_INITIAL, and passes 'init' to 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)) else if (TYPE_NEEDS_CONSTRUCTING (type))
return value; return value;
else if (TREE_STATIC (decl) 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