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),
......
...@@ -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