aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-08-16 19:01:36 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-08-16 19:01:36 +0000
commit558475f07cfe622a964b7c0019be78bd81912a47 (patch)
tree941793477b95a8310030bd04dc3b51507e7b23d9
parent63ebc2756028198247166b6f46554b62b028dce9 (diff)
downloadgcc-558475f07cfe622a964b7c0019be78bd81912a47.zip
gcc-558475f07cfe622a964b7c0019be78bd81912a47.tar.gz
gcc-558475f07cfe622a964b7c0019be78bd81912a47.tar.bz2
cp-tree.def (STMT_EXPR): New tree node.
* cp-tree.def (STMT_EXPR): New tree node. * cp-tree.h (STMT_EXPR_STMT): New macro. (store_return_init): Change prototype. (finish_named_return_value): New function. (expand_stmt): Likewise. (expand_body): Likewise. (begin_stmt_tree): Likewise. (finish_stmt_tree): Likewise. (expanding_p): New variable. (last_expr_type): Likewise. (building_stmt_tree): New macro. * decl.c (start_function): Use building_stmt_tree, not processing_template_decl, where appropriate. (store_parm_decls): Likewise. (store_return_init): Move most of the body to semantics.c. (finish_function): Use building_stmt_tree. (finish_stmt): Clear last_expr_type here. (cp_function): Add expanding_p, last_tree, last_expr_type. (push_cp_function_context): Save them. (pop_cp_function_context): Restore them. * decl2.c (setup_vtbl_ptr): Move to semantics.c. * error.c (dump_expr): Handle STMT_EXPR. * except.c (expand_start_catch_block): Use building_stmt_tree. Use add_decl_stmt. * expr.c (cplus_expand_expr): Handle STMT_EXPR. (do_case): Move add_tree call to semantics.c. * parse.y (return_init): Use finish_named_return_value. (for.init.statement): Use finish_expr_stmt. * parse.c: Regenerated. * pt.c (do_pushlevel): Move to semantics.c. (do_poplevel): Likewise. (tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR. (tsubst_expr): Don't expand all the way to RTL here. Handle RETURN_INIT and CTOR_INITIALIZER. (instantiate_decl): Call expand_body after tsubst'ing into DECL_SAVED_TREE. * semantics.c (expand_stmts): New function. (expanding_p): New variable. (last_expr_type): Likewise. (finish_expr_stmt): Use building_stmt_tree. (begin_if_stmt): Likewise. (finish_if_stmt_cond): Likewise. (finish_then_clause): Likewise. (begin_else_clause): Likewise. (finish_else_clause): Likewise. (begin_while_stmt): Likewise. (finish_while_stmt_cond): Likewise. (finish_while_stmt): Likewise. (finish_do_body): Likewise. (finish_do_stmt): Likewise. (finish_return_stmt): Likewise. (begin_for_stmt): Likewise. (fnish_for_init_stmt): Likewise. (finish_for_cond): Likewise. (finish_for_expr): Likewise. (finish_for_stmt): Likewise. (finish_break_stmt): Likewise. (finish_continue_stmt): Likewise. (finish_switch_cond): Likewise. (finish_switch_stmt): Likewise. (finish_case_label): Call add_tree here if necessary. (finish_goto_statement): Use building_stmt_tree. (begin_try_block): Likewise. (begin_function_try_block): Likewise. (finish_try_block): Likewise. (finish_function_try_block): Likewise. (finish_handler_sequence): Likewise. (finish_function_handler_sequence): Likewise. (begin_handler): Likewise. (finish_handler_parms): Likewise. (finish_handler): Likewise. (begin_compound_stmt): Likewise. (finish_compound_stmt): Likewise. (finish_asm_stmt): Likewise. (finish_label_stmt): Likewise. (finish_named_return_value): New function. (setup_vtbl_ptr): Moved here from decl2.c. (do_pushlevel): Moved here from pt.c. (do_poplevel): Likewise. (begin_stmt_expr): Use building_stmt_tree. (finish_stmt_expr): Likewise. Build a STMT_EXPR, not a BIND_EXPR, when building_stmt_tree. (begin_stmt_tree): New function. (finish_stmt_tree): Likewise. (expand_stmt): Likewise. (expand_body): Likewise. * tree.c (build_cplus_method_type): Make sure the argument types end up on the same obstack as the METHOD_TYPE. (search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR, THROW_EXPR, STMT_EXPR. (mapcar): Break out common cases. Handle COMPOUND_EXPR, MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR. Abort, rather than sorry, if an unsupported node is encountered. * typeck.c (require_complete_type_in_void): Handle BIND_EXPR. (c_expand_return): Don't call add_tree here. From-SVN: r28729
-rw-r--r--gcc/cp/ChangeLog98
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/cp-tree.h14
-rw-r--r--gcc/cp/decl.c165
-rw-r--r--gcc/cp/decl2.c21
-rw-r--r--gcc/cp/error.c6
-rw-r--r--gcc/cp/except.c8
-rw-r--r--gcc/cp/expr.c15
-rw-r--r--gcc/cp/parse.c8
-rw-r--r--gcc/cp/parse.y8
-rw-r--r--gcc/cp/pt.c223
-rw-r--r--gcc/cp/semantics.c562
-rw-r--r--gcc/cp/tree.c90
-rw-r--r--gcc/cp/typeck.c7
14 files changed, 846 insertions, 383 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f80f374..bf6c0ac 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,101 @@
+1999-08-16 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (STMT_EXPR): New tree node.
+ * cp-tree.h (STMT_EXPR_STMT): New macro.
+ (store_return_init): Change prototype.
+ (finish_named_return_value): New function.
+ (expand_stmt): Likewise.
+ (expand_body): Likewise.
+ (begin_stmt_tree): Likewise.
+ (finish_stmt_tree): Likewise.
+ (expanding_p): New variable.
+ (last_expr_type): Likewise.
+ (building_stmt_tree): New macro.
+ * decl.c (start_function): Use building_stmt_tree, not
+ processing_template_decl, where appropriate.
+ (store_parm_decls): Likewise.
+ (store_return_init): Move most of the body to semantics.c.
+ (finish_function): Use building_stmt_tree.
+ (finish_stmt): Clear last_expr_type here.
+ (cp_function): Add expanding_p, last_tree, last_expr_type.
+ (push_cp_function_context): Save them.
+ (pop_cp_function_context): Restore them.
+ * decl2.c (setup_vtbl_ptr): Move to semantics.c.
+ * error.c (dump_expr): Handle STMT_EXPR.
+ * except.c (expand_start_catch_block): Use building_stmt_tree.
+ Use add_decl_stmt.
+ * expr.c (cplus_expand_expr): Handle STMT_EXPR.
+ (do_case): Move add_tree call to semantics.c.
+ * parse.y (return_init): Use finish_named_return_value.
+ (for.init.statement): Use finish_expr_stmt.
+ * parse.c: Regenerated.
+ * pt.c (do_pushlevel): Move to semantics.c.
+ (do_poplevel): Likewise.
+ (tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR.
+ (tsubst_expr): Don't expand all the way to RTL here. Handle
+ RETURN_INIT and CTOR_INITIALIZER.
+ (instantiate_decl): Call expand_body after tsubst'ing into
+ DECL_SAVED_TREE.
+ * semantics.c (expand_stmts): New function.
+ (expanding_p): New variable.
+ (last_expr_type): Likewise.
+ (finish_expr_stmt): Use building_stmt_tree.
+ (begin_if_stmt): Likewise.
+ (finish_if_stmt_cond): Likewise.
+ (finish_then_clause): Likewise.
+ (begin_else_clause): Likewise.
+ (finish_else_clause): Likewise.
+ (begin_while_stmt): Likewise.
+ (finish_while_stmt_cond): Likewise.
+ (finish_while_stmt): Likewise.
+ (finish_do_body): Likewise.
+ (finish_do_stmt): Likewise.
+ (finish_return_stmt): Likewise.
+ (begin_for_stmt): Likewise.
+ (fnish_for_init_stmt): Likewise.
+ (finish_for_cond): Likewise.
+ (finish_for_expr): Likewise.
+ (finish_for_stmt): Likewise.
+ (finish_break_stmt): Likewise.
+ (finish_continue_stmt): Likewise.
+ (finish_switch_cond): Likewise.
+ (finish_switch_stmt): Likewise.
+ (finish_case_label): Call add_tree here if necessary.
+ (finish_goto_statement): Use building_stmt_tree.
+ (begin_try_block): Likewise.
+ (begin_function_try_block): Likewise.
+ (finish_try_block): Likewise.
+ (finish_function_try_block): Likewise.
+ (finish_handler_sequence): Likewise.
+ (finish_function_handler_sequence): Likewise.
+ (begin_handler): Likewise.
+ (finish_handler_parms): Likewise.
+ (finish_handler): Likewise.
+ (begin_compound_stmt): Likewise.
+ (finish_compound_stmt): Likewise.
+ (finish_asm_stmt): Likewise.
+ (finish_label_stmt): Likewise.
+ (finish_named_return_value): New function.
+ (setup_vtbl_ptr): Moved here from decl2.c.
+ (do_pushlevel): Moved here from pt.c.
+ (do_poplevel): Likewise.
+ (begin_stmt_expr): Use building_stmt_tree.
+ (finish_stmt_expr): Likewise. Build a STMT_EXPR, not a BIND_EXPR,
+ when building_stmt_tree.
+ (begin_stmt_tree): New function.
+ (finish_stmt_tree): Likewise.
+ (expand_stmt): Likewise.
+ (expand_body): Likewise.
+ * tree.c (build_cplus_method_type): Make sure the argument types
+ end up on the same obstack as the METHOD_TYPE.
+ (search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR,
+ THROW_EXPR, STMT_EXPR.
+ (mapcar): Break out common cases. Handle COMPOUND_EXPR,
+ MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR. Abort, rather than
+ sorry, if an unsupported node is encountered.
+ * typeck.c (require_complete_type_in_void): Handle BIND_EXPR.
+ (c_expand_return): Don't call add_tree here.
+
1999-08-15 Mark Mitchell <mark@codesourcery.com>
* pt.c (check_default_tmpl_args): Don't check in local scopes.
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index fecbbe5..1970922 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -235,6 +235,10 @@ DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2)
DEFTREECODE (HANDLER, "catch_stmt", 'e', 2)
+/* A STMT_EXPR represents a statement-expression. The
+ STMT_EXPR_STMT is the statement given by the expression. */
+DEFTREECODE (STMT_EXPR, "cp_stmt_expr", 'e', 1)
+
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/* And some codes for expressing conversions for overload resolution. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 82022fa..4867013 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2138,6 +2138,7 @@ extern int flag_new_for_scope;
#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
+#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \
@@ -2919,7 +2920,7 @@ extern tree build_enumerator PROTO((tree, tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_parm_decls PROTO((void));
-extern void store_return_init PROTO((tree, tree));
+extern void store_return_init PROTO((tree));
extern void finish_function PROTO((int, int, int));
extern tree start_method PROTO((tree, tree, tree));
extern tree finish_method PROTO((tree));
@@ -3365,6 +3366,17 @@ extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree));
+extern void finish_named_return_value PROTO((tree, tree));
+extern tree expand_stmt PROTO((tree));
+extern void expand_body PROTO((tree));
+extern void begin_stmt_tree PROTO((tree));
+extern void finish_stmt_tree PROTO((tree));
+extern int expanding_p;
+extern tree last_expr_type;
+/* Non-zero if we are presently building a statement tree, rather
+ than expanding each statement as we encounter it. */
+#define building_stmt_tree() \
+ (processing_template_decl || !expanding_p)
/* in spew.c */
extern void init_spew PROTO((void));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6fb61f7..374717c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4341,7 +4341,7 @@ maybe_push_decl (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == UNKNOWN_TYPE
- /* The declaration of template specializations does not affect
+ /* The declaration of a template specialization does not affect
the functions available for overload resolution, so we do not
call pushdecl. */
|| (TREE_CODE (decl) == FUNCTION_DECL
@@ -12882,7 +12882,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
- announce_function (decl1);
+ if (!building_stmt_tree ())
+ announce_function (decl1);
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
@@ -13110,12 +13111,14 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
pushlevel (0);
current_binding_level->parm_flag = 1;
- GNU_xref_function (decl1, current_function_parms);
-
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
- make_function_rtl (decl1);
+ if (!building_stmt_tree ())
+ {
+ GNU_xref_function (decl1, current_function_parms);
+ make_function_rtl (decl1);
+ }
/* Promote the value to int before returning it. */
if (C_PROMOTING_INTEGER_TYPE_P (restype))
@@ -13141,9 +13144,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (! hack_decl_function_context (decl1))
temporary_allocation ();
- if (processing_template_decl)
- last_tree = DECL_SAVED_TREE (decl1)
- = build_nt (EXPR_STMT, void_zero_node);
+ if (building_stmt_tree ())
+ begin_stmt_tree (decl1);
++function_depth;
@@ -13254,7 +13256,7 @@ store_parm_decls ()
pushdecl (parm);
}
- if (! processing_template_decl
+ if (! building_stmt_tree ()
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
@@ -13295,21 +13297,20 @@ store_parm_decls ()
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = 0;
- if (! processing_template_decl)
+ if (! building_stmt_tree ())
expand_function_start (fndecl, parms_have_cleanups);
current_function_parms_stored = 1;
/* If this function is `main', emit a call to `__main'
to run global initializers, etc. */
- if (DECL_MAIN_P (fndecl))
+ if (DECL_MAIN_P (fndecl) && !building_stmt_tree ())
expand_main_function ();
/* Now that we have initialized the parms, we can start their
cleanups. We cannot do this before, since expand_decl_cleanup
should not be called before the parm can be used. */
- if (cleanups
- && ! processing_template_decl)
+ if (cleanups && !building_stmt_tree ())
{
for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
{
@@ -13325,10 +13326,11 @@ store_parm_decls ()
if (parms_have_cleanups)
{
pushlevel (0);
- expand_start_bindings (0);
+ if (!building_stmt_tree ())
+ expand_start_bindings (0);
}
- if (! processing_template_decl && flag_exceptions)
+ if (! building_stmt_tree () && flag_exceptions)
{
/* Do the starting of the exception specifications, if we have any. */
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
@@ -13343,55 +13345,15 @@ store_parm_decls ()
the current function. */
void
-store_return_init (return_id, init)
- tree return_id, init;
+store_return_init (decl)
+ tree decl;
{
- tree decl = DECL_RESULT (current_function_decl);
-
- if (pedantic)
- /* Give this error as many times as there are occurrences,
- so that users can use Emacs compilation buffers to find
- and fix all such places. */
- pedwarn ("ANSI C++ does not permit named return values");
-
- if (return_id != NULL_TREE)
- {
- if (DECL_NAME (decl) == NULL_TREE)
- {
- DECL_NAME (decl) = return_id;
- DECL_ASSEMBLER_NAME (decl) = return_id;
- }
- else
- cp_error ("return identifier `%D' already in place", decl);
- }
-
- /* Can't let this happen for constructors. */
- if (DECL_CONSTRUCTOR_P (current_function_decl))
+ /* If this named return value comes in a register, put it in a
+ pseudo-register. */
+ if (DECL_REGISTER (decl))
{
- error ("can't redefine default return value for constructors");
- return;
- }
-
- /* If we have a named return value, put that in our scope as well. */
- if (DECL_NAME (decl) != NULL_TREE)
- {
- /* If this named return value comes in a register,
- put it in a pseudo-register. */
- if (DECL_REGISTER (decl))
- {
- original_result_rtx = DECL_RTL (decl);
- DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
- }
-
- /* Let `cp_finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = init;
- pushdecl (decl);
-
- if (processing_template_decl && current_function_decl)
- add_tree (build_min_nt (RETURN_INIT, return_id,
- copy_to_permanent (init)));
- else
- cp_finish_decl (decl, init, NULL_TREE, 0, 0);
+ original_result_rtx = DECL_RTL (decl);
+ DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
}
}
@@ -13430,7 +13392,7 @@ finish_function (lineno, flags, nested)
tree decls = NULL_TREE;
int call_poplevel = (flags & 1) != 0;
int inclass_inline = (flags & 2) != 0;
- int in_template;
+ int expand_p;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
@@ -13453,7 +13415,7 @@ finish_function (lineno, flags, nested)
store_parm_decls ();
}
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
{
@@ -13834,19 +13796,15 @@ finish_function (lineno, flags, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
+
+ /* We have to save this value here in case
+ maybe_end_member_template_processing decides to pop all the
+ template parameters. */
+ expand_p = !building_stmt_tree ();
- /* If we're processing a template, squirrel away the definition
- until we do an instantiation. */
- if (processing_template_decl)
- {
- DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
- /* We have to save this value here in case
- maybe_end_member_template_processing decides to pop all the
- template parameters. */
- in_template = 1;
- }
- else
- in_template = 0;
+ /* If we're saving up tree structure, tie off the function now. */
+ if (!expand_p)
+ finish_stmt_tree (fndecl);
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@@ -13880,7 +13838,7 @@ finish_function (lineno, flags, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- if (!in_template)
+ if (expand_p)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@@ -14285,12 +14243,6 @@ void
cplus_expand_expr_stmt (exp)
tree exp;
{
- if (processing_template_decl)
- {
- add_tree (build_min_nt (EXPR_STMT, exp));
- return;
- }
-
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
@@ -14324,28 +14276,30 @@ cplus_expand_expr_stmt (exp)
expand_end_target_temps ();
}
-/* When a stmt has been parsed, this function is called.
-
- Currently, this function only does something within a
- constructor's scope: if a stmt has just assigned to this,
- and we are in a derived class, we call `emit_base_init'. */
+/* When a stmt has been parsed, this function is called. */
void
finish_stmt ()
{
- if (current_function_assigns_this
- || ! current_function_just_assigned_this)
- return;
- if (DECL_CONSTRUCTOR_P (current_function_decl))
+ if (!current_function_assigns_this
+ && current_function_just_assigned_this)
{
- /* Constructors must wait until we are out of control
- zones before calling base constructors. */
- if (in_control_zone_p ())
- return;
- expand_expr_stmt (base_init_expr);
- check_base_init (current_class_type);
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ {
+ /* Constructors must wait until we are out of control
+ zones before calling base constructors. */
+ if (in_control_zone_p ())
+ return;
+ expand_expr_stmt (base_init_expr);
+ check_base_init (current_class_type);
+ }
+ current_function_assigns_this = 1;
}
- current_function_assigns_this = 1;
+
+ /* Always assume this statement was not an expression statement. If
+ it actually was an expression statement, its our callers
+ responsibility to fix this up. */
+ last_expr_type = NULL_TREE;
}
/* Change a static member function definition into a FUNCTION_TYPE, instead
@@ -14408,6 +14362,9 @@ struct cp_function
struct binding_level *binding_level;
int static_labelno;
int in_function_try_handler;
+ int expanding_p;
+ tree last_tree;
+ tree last_expr_type;
};
static struct cp_function *cp_function_chain;
@@ -14451,6 +14408,13 @@ push_cp_function_context (context)
p->current_class_ref = current_class_ref;
p->static_labelno = static_labelno;
p->in_function_try_handler = in_function_try_handler;
+ p->last_tree = last_tree;
+ p->last_expr_type = last_expr_type;
+ p->expanding_p = expanding_p;
+
+ /* For now, we always assume we're expanding all the way to RTL
+ unless we're explicitly doing otherwise. */
+ expanding_p = 1;
}
/* Restore the variables used during compilation of a C++ function. */
@@ -14494,6 +14458,9 @@ pop_cp_function_context (context)
current_class_ref = p->current_class_ref;
static_labelno = p->static_labelno;
in_function_try_handler = p->in_function_try_handler;
+ last_tree = p->last_tree;
+ last_expr_type = p->last_expr_type;
+ expanding_p = p->expanding_p;
free (p);
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index ab82a8e..e4d2d0e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2001,27 +2001,6 @@ constructor_name (thing)
return t;
}
-/* Cache the value of this class's main virtual function table pointer
- in a register variable. This will save one indirection if a
- more than one virtual function call is made this function. */
-
-void
-setup_vtbl_ptr ()
-{
- extern tree base_init_expr;
-
- if (base_init_expr == 0
- && DECL_CONSTRUCTOR_P (current_function_decl))
- {
- if (processing_template_decl)
- add_tree (build_min_nt
- (CTOR_INITIALIZER,
- current_member_init_list, current_base_init_list));
- else
- emit_base_init (current_class_type, 0);
- }
-}
-
/* Record the existence of an addressable inline function. */
void
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 9c911ad..ce0ffbf 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1780,6 +1780,12 @@ dump_expr (t, nop)
dump_decl (t, 0);
break;
+ case STMT_EXPR:
+ /* We don't yet have a way of dumping statements in a
+ human-readable format. */
+ OB_PUTS ("{ ... }");
+ break;
+
case BIND_EXPR:
OB_PUTS ("{ ");
dump_expr (TREE_OPERAND (t, 1), nop);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 0ef6e82..2dbdbd3 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -558,17 +558,14 @@ expand_start_catch_block (declspecs, declarator)
{
tree decl;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
1, NULL_TREE);
pushdecl (decl);
- decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
- copy_to_permanent (declspecs),
- NULL_TREE);
- add_tree (decl);
+ add_decl_stmt (decl);
}
return;
}
@@ -579,7 +576,6 @@ expand_start_catch_block (declspecs, declarator)
process_start_catch_block (declspecs, declarator);
}
-
/* This function performs the expand_start_catch_block functionality for
exceptions implemented in the new style. __throw determines whether
a handler needs to be called or not, so the handler itself has to do
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index d5250ae..42fb757 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -246,6 +246,15 @@ cplus_expand_expr (exp, target, tmode, modifier)
case NEW_EXPR:
return expand_expr (build_new_1 (exp), target, tmode, modifier);
+ case STMT_EXPR:
+ {
+ tree rtl_expr = begin_stmt_expr ();
+ tree block = expand_stmt (STMT_EXPR_STMT (exp));
+ finish_stmt_expr (rtl_expr, block);
+ return expand_expr (rtl_expr, target, tmode, modifier);
+ }
+ break;
+
default:
break;
}
@@ -388,12 +397,6 @@ do_case (start, end)
if (end && pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement");
- if (processing_template_decl)
- {
- add_tree (build_min_nt (CASE_LABEL, start, end));
- return;
- }
-
if (start)
value1 = check_cp_case_value (start);
if (end)
diff --git a/gcc/cp/parse.c b/gcc/cp/parse.c
index b2b85c9..c5d435c 100644
--- a/gcc/cp/parse.c
+++ b/gcc/cp/parse.c
@@ -4912,15 +4912,15 @@ case 122:
break;}
case 123:
#line 770 "parse.y"
-{ store_return_init (yyval.ttype, yyvsp[0].ttype); ;
+{ finish_named_return_value (yyval.ttype, yyvsp[0].ttype); ;
break;}
case 124:
#line 772 "parse.y"
-{ store_return_init (yyval.ttype, yyvsp[-1].ttype); ;
+{ finish_named_return_value (yyval.ttype, yyvsp[-1].ttype); ;
break;}
case 125:
#line 774 "parse.y"
-{ store_return_init (yyval.ttype, NULL_TREE); ;
+{ finish_named_return_value (yyval.ttype, NULL_TREE); ;
break;}
case 126:
#line 779 "parse.y"
@@ -7732,7 +7732,7 @@ case 783:
break;}
case 784:
#line 3411 "parse.y"
-{ if (yyvsp[-1].ttype) cplus_expand_expr_stmt (yyvsp[-1].ttype); ;
+{ finish_expr_stmt (yyvsp[-1].ttype); ;
break;}
case 786:
#line 3414 "parse.y"
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 5698789..d735aa7 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -767,11 +767,11 @@ return_id:
return_init:
return_id maybe_init
- { store_return_init ($<ttype>$, $2); }
+ { finish_named_return_value ($<ttype>$, $2); }
| return_id '(' nonnull_exprlist ')'
- { store_return_init ($<ttype>$, $3); }
+ { finish_named_return_value ($<ttype>$, $3); }
| return_id LEFT_RIGHT
- { store_return_init ($<ttype>$, NULL_TREE); }
+ { finish_named_return_value ($<ttype>$, NULL_TREE); }
;
base_init:
@@ -3408,7 +3408,7 @@ label_colon:
for.init.statement:
xexpr ';'
- { if ($1) cplus_expand_expr_stmt ($1); }
+ { finish_expr_stmt ($1); }
| decl
| '{' compstmtend
{ if (pedantic)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4087ef3..674834b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6839,35 +6839,6 @@ tsubst (t, args, complain, in_decl)
}
}
-void
-do_pushlevel ()
-{
- emit_line_note (input_filename, lineno);
- pushlevel (0);
- clear_last_expr ();
- push_momentary ();
- expand_start_bindings (0);
-}
-
-tree
-do_poplevel ()
-{
- tree t;
- int saved_warn_unused = 0;
-
- if (processing_template_decl)
- {
- saved_warn_unused = warn_unused;
- warn_unused = 0;
- }
- expand_end_bindings (getdecls (), kept_level_p (), 0);
- if (processing_template_decl)
- warn_unused = saved_warn_unused;
- t = poplevel (kept_level_p (), 1, 0);
- pop_momentary ();
- return t;
-}
-
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_expr. */
@@ -7083,7 +7054,21 @@ tsubst_copy (t, args, complain, in_decl)
NULL_TREE);
}
- case BIND_EXPR:
+ case STMT_EXPR:
+ /* This processing should really occur in tsubst_expr, However,
+ tsubst_expr does not recurse into expressions, since it
+ assumes that there aren't any statements inside them.
+ Instead, it simply calls build_expr_from_tree. So, we need
+ to expand the STMT_EXPR here. */
+ if (!processing_template_decl)
+ {
+ tree rtl_expr = begin_stmt_expr ();
+ tree block = tsubst_expr (STMT_EXPR_STMT (t), args,
+ complain, in_decl);
+ r = finish_stmt_expr (rtl_expr, block);
+ }
+ return r;
+
case COND_EXPR:
case MODOP_EXPR:
{
@@ -7091,21 +7076,6 @@ tsubst_copy (t, args, complain, in_decl)
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
-
- if (code == BIND_EXPR && !processing_template_decl)
- {
- /* This processing should really occur in tsubst_expr,
- However, tsubst_expr does not recurse into expressions,
- since it assumes that there aren't any statements
- inside them. Instead, it simply calls
- build_expr_from_tree. So, we need to expand the
- BIND_EXPR here. */
- tree rtl_expr = begin_stmt_expr ();
- tree block = tsubst_expr (TREE_OPERAND (r, 1), args,
- complain, in_decl);
- r = finish_stmt_expr (rtl_expr, block);
- }
-
return r;
}
@@ -7218,7 +7188,7 @@ tsubst_copy (t, args, complain, in_decl)
}
}
-/* Like tsubst_copy, but also does semantic processing and RTL expansion. */
+/* Like tsubst_copy, but also does semantic processing. */
tree
tsubst_expr (t, args, complain, in_decl)
@@ -7226,6 +7196,8 @@ tsubst_expr (t, args, complain, in_decl)
int complain;
tree in_decl;
{
+ tree stmt;
+
if (t == NULL_TREE || t == error_mark_node)
return t;
@@ -7234,6 +7206,22 @@ tsubst_expr (t, args, complain, in_decl)
switch (TREE_CODE (t))
{
+ case RETURN_INIT:
+ finish_named_return_value
+ (TREE_OPERAND (t, 0),
+ tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl));
+ tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+ break;
+
+ case CTOR_INITIALIZER:
+ current_member_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 0), args);
+ current_base_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 1), args);
+ setup_vtbl_ptr ();
+ tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+ break;
+
case RETURN_STMT:
lineno = STMT_LINENO (t);
finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
@@ -7253,18 +7241,19 @@ tsubst_expr (t, args, complain, in_decl)
tree init;
lineno = STMT_LINENO (t);
- emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
DECL_INITIAL (decl) = init;
- maybe_push_decl (decl);
+ /* By marking the declaration as instantiated, we avoid trying
+ to instantiate it. Since instantiate_decl can't handle
+ local variables, and since we've already done all that
+ needs to be done, that's the right thing to do. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
- start_decl_1 (decl);
- cp_finish_decl
- (decl, init, NULL_TREE, 0, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
+ maybe_push_decl (decl);
+ add_decl_stmt (decl);
resume_momentary (i);
return decl;
}
@@ -7274,41 +7263,41 @@ tsubst_expr (t, args, complain, in_decl)
tree tmp;
lineno = STMT_LINENO (t);
- begin_for_stmt ();
+ stmt = begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
tsubst_expr (tmp, args, complain, in_decl);
- finish_for_init_stmt (NULL_TREE);
+ finish_for_init_stmt (stmt);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
complain, in_decl),
- NULL_TREE);
+ stmt);
tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
- finish_for_expr (tmp, NULL_TREE);
+ finish_for_expr (tmp, stmt);
tsubst_expr (FOR_BODY (t), args, complain, in_decl);
- finish_for_stmt (tmp, NULL_TREE);
+ finish_for_stmt (tmp, stmt);
}
break;
case WHILE_STMT:
{
lineno = STMT_LINENO (t);
- begin_while_stmt ();
+ stmt = begin_while_stmt ();
finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
args, complain, in_decl),
- NULL_TREE);
+ stmt);
tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
- finish_while_stmt (NULL_TREE);
+ finish_while_stmt (stmt);
}
break;
case DO_STMT:
{
lineno = STMT_LINENO (t);
- begin_do_stmt ();
+ stmt = begin_do_stmt ();
tsubst_expr (DO_BODY (t), args, complain, in_decl);
- finish_do_body (NULL_TREE);
+ finish_do_body (stmt);
finish_do_stmt (tsubst_expr (DO_COND (t), args,
complain, in_decl),
- NULL_TREE);
+ stmt);
}
break;
@@ -7317,22 +7306,22 @@ tsubst_expr (t, args, complain, in_decl)
tree tmp;
lineno = STMT_LINENO (t);
- begin_if_stmt ();
+ stmt = begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
args, complain, in_decl),
- NULL_TREE);
+ stmt);
if (tmp = THEN_CLAUSE (t), tmp)
{
tsubst_expr (tmp, args, complain, in_decl);
- finish_then_clause (NULL_TREE);
+ finish_then_clause (stmt);
}
if (tmp = ELSE_CLAUSE (t), tmp)
{
begin_else_clause ();
tsubst_expr (tmp, args, complain, in_decl);
- finish_else_clause (NULL_TREE);
+ finish_else_clause (stmt);
}
finish_if_stmt ();
@@ -7344,13 +7333,12 @@ tsubst_expr (t, args, complain, in_decl)
tree substmt;
lineno = STMT_LINENO (t);
- begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
for (substmt = COMPOUND_BODY (t);
substmt != NULL_TREE;
substmt = TREE_CHAIN (substmt))
tsubst_expr (substmt, args, complain, in_decl);
- return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
- NULL_TREE);
+ return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
}
break;
@@ -7366,17 +7354,14 @@ tsubst_expr (t, args, complain, in_decl)
case SWITCH_STMT:
{
- tree val, tmp;
+ tree val;
lineno = STMT_LINENO (t);
begin_switch_stmt ();
val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
- finish_switch_cond (val);
-
- if (tmp = TREE_OPERAND (t, 1), tmp)
- tsubst_expr (tmp, args, complain, in_decl);
-
- finish_switch_stmt (val, NULL_TREE);
+ stmt = finish_switch_cond (val);
+ tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
+ finish_switch_stmt (val, stmt);
}
break;
@@ -7414,20 +7399,20 @@ tsubst_expr (t, args, complain, in_decl)
case TRY_BLOCK:
lineno = STMT_LINENO (t);
- begin_try_block ();
+ stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
- finish_try_block (NULL_TREE);
+ finish_try_block (stmt);
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl);
}
- finish_handler_sequence (NULL_TREE);
+ finish_handler_sequence (stmt);
break;
case HANDLER:
lineno = STMT_LINENO (t);
- begin_handler ();
+ stmt = begin_handler ();
if (HANDLER_PARMS (t))
{
tree d = HANDLER_PARMS (t);
@@ -7437,9 +7422,9 @@ tsubst_expr (t, args, complain, in_decl)
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
- finish_handler_parms (NULL_TREE);
+ finish_handler_parms (stmt);
tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
- finish_handler (NULL_TREE);
+ finish_handler (stmt);
break;
case TAG_DEFN:
@@ -9654,57 +9639,39 @@ instantiate_decl (d)
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
- tree t = DECL_SAVED_TREE (code_pattern);
- tree try_block = NULL_TREE;
+ extern struct obstack *saveable_obstack;
+ extern struct obstack *rtl_obstack;
+ int saved_expanding_p = expanding_p;
+
+ /* We're not expanding all the way to RTL here. */
+ expanding_p = 0;
+ /* Set up context. */
start_function (NULL_TREE, d, NULL_TREE, 1);
store_parm_decls ();
- if (t && TREE_CODE (t) == TRY_BLOCK)
- {
- try_block = t;
- begin_function_try_block ();
- t = TRY_STMTS (try_block);
- }
-
- if (t && TREE_CODE (t) == RETURN_INIT)
- {
- store_return_init
- (TREE_OPERAND (t, 0),
- tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, tmpl));
- t = TREE_CHAIN (t);
- }
-
- if (t && TREE_CODE (t) == CTOR_INITIALIZER)
- {
- current_member_init_list
- = tsubst_expr_values (TREE_OPERAND (t, 0), args);
- current_base_init_list
- = tsubst_expr_values (TREE_OPERAND (t, 1), args);
- t = TREE_CHAIN (t);
- }
-
- 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 ();
-
- my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
- tsubst_expr (t, args, /*complain=*/1, tmpl);
-
- if (try_block)
- {
- finish_function_try_block (NULL_TREE);
- {
- tree handler = TRY_HANDLERS (try_block);
- for (; handler; handler = TREE_CHAIN (handler))
- tsubst_expr (handler, args, /*complain=*/1, tmpl);
- }
- finish_function_handler_sequence (NULL_TREE);
- }
-
+ /* Anything we might
+ want to save is going to have to be saved forever. Note that
+ we don't want to save all kinds of temporary clutter that
+ might end up on the temporary obstack so we don't want to
+ call push_permanent_obstack. */
+ push_obstacks_nochange ();
+ saveable_obstack = &permanent_obstack;
+ /* We only need this because of the cases where we generate
+ RTL_EXPRs. We should really be generating RTL_EXPRs until
+ final expansion time; when that is fixed, this can go. */
+ rtl_obstack = &permanent_obstack;
+ /* Substitute into the body of the function. */
+ tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
+ /*complain=*/1, tmpl);
+
+ /* Clean up. */
+ pop_obstacks ();
finish_function (lineno, 0, nested);
+ expanding_p = saved_expanding_p;
+
+ /* Now, generate RTL for the function. */
+ expand_body (d);
}
out:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0711da3..dc6b541 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -41,6 +41,18 @@
parsing into this file; that will make implementing the new parser
much easier since it will be able to make use of these routines. */
+static void expand_stmts PROTO((tree));
+
+/* Non-zero if we should generate RTL for functions that we process.
+ When this is zero, we just accumulate tree structure, without
+ interacting with the back end. */
+int expanding_p = 1;
+
+/* The type of the last expression-statement we have seen. This is
+ required because the type of a statement-expression is the type of
+ the last expression statement. */
+tree last_expr_type;
+
/* When parsing a template, LAST_TREE contains the last statement
parsed. These are chained together through the TREE_CHAIN field,
but often need to be re-organized since the parse is performed
@@ -68,7 +80,9 @@ finish_expr_stmt (expr)
{
if (expr != NULL_TREE)
{
- if (!processing_template_decl)
+ if (building_stmt_tree ())
+ add_tree (build_min_nt (EXPR_STMT, expr));
+ else
{
emit_line_note (input_filename, lineno);
/* Do default conversion if safe and possibly important,
@@ -77,13 +91,17 @@ finish_expr_stmt (expr)
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr);
+ cplus_expand_expr_stmt (expr);
}
-
- cplus_expand_expr_stmt (expr);
+
clear_momentary ();
}
finish_stmt ();
+
+ /* This was an expression-statement, so we save the type of the
+ expression. */
+ last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
}
/* Begin an if-statement. Returns a newly created IF_STMT if
@@ -94,7 +112,7 @@ begin_if_stmt ()
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_tree (r);
@@ -115,7 +133,7 @@ finish_if_stmt_cond (cond, if_stmt)
tree cond;
tree if_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (last_tree != if_stmt)
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
@@ -136,7 +154,7 @@ tree
finish_then_clause (if_stmt)
tree if_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
RECHAIN_STMTS_FROM_CHAIN (if_stmt,
THEN_CLAUSE (if_stmt));
@@ -152,7 +170,7 @@ finish_then_clause (if_stmt)
void
begin_else_clause ()
{
- if (!processing_template_decl)
+ if (!building_stmt_tree ())
expand_start_else ();
}
@@ -163,7 +181,7 @@ void
finish_else_clause (if_stmt)
tree if_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
}
@@ -172,7 +190,7 @@ finish_else_clause (if_stmt)
void
finish_if_stmt ()
{
- if (!processing_template_decl)
+ if (!building_stmt_tree ())
expand_end_cond ();
do_poplevel ();
@@ -187,7 +205,7 @@ begin_while_stmt ()
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
@@ -213,11 +231,10 @@ finish_while_stmt_cond (cond, while_stmt)
tree cond;
tree while_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (last_tree != while_stmt)
- RECHAIN_STMTS_FROM_LAST (while_stmt,
- WHILE_COND (while_stmt));
+ RECHAIN_STMTS_FROM_LAST (while_stmt, WHILE_COND (while_stmt));
else
TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
}
@@ -245,7 +262,7 @@ finish_while_stmt (while_stmt)
{
do_poplevel ();
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
else
expand_end_loop ();
@@ -258,7 +275,7 @@ finish_while_stmt (while_stmt)
tree
begin_do_stmt ()
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
@@ -279,7 +296,7 @@ void
finish_do_body (do_stmt)
tree do_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
else
expand_loop_continue_here ();
@@ -293,7 +310,7 @@ finish_do_stmt (cond, do_stmt)
tree cond;
tree do_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
DO_COND (do_stmt) = copy_to_permanent (cond);
else
{
@@ -313,8 +330,14 @@ void
finish_return_stmt (expr)
tree expr;
{
- emit_line_note (input_filename, lineno);
- c_expand_return (expr);
+ if (building_stmt_tree ())
+ add_tree (build_min_nt (RETURN_STMT, expr));
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ c_expand_return (expr);
+ }
+
finish_stmt ();
}
@@ -325,7 +348,7 @@ begin_for_stmt ()
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
@@ -350,7 +373,7 @@ void
finish_for_init_stmt (for_stmt)
tree for_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
@@ -373,7 +396,7 @@ finish_for_cond (cond, for_stmt)
tree cond;
tree for_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
@@ -405,8 +428,8 @@ finish_for_expr (expr, for_stmt)
tree expr;
tree for_stmt;
{
- if (processing_template_decl)
- FOR_EXPR (for_stmt) = expr;
+ if (building_stmt_tree ())
+ FOR_EXPR (for_stmt) = copy_to_permanent (expr);
/* Don't let the tree nodes for EXPR be discarded
by clear_momentary during the parsing of the next stmt. */
@@ -425,7 +448,7 @@ finish_for_stmt (expr, for_stmt)
/* Pop the scope for the body of the loop. */
do_poplevel ();
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
else
{
@@ -450,7 +473,7 @@ void
finish_break_stmt ()
{
emit_line_note (input_filename, lineno);
- if (processing_template_decl)
+ if (building_stmt_tree ())
add_tree (build_min_nt (BREAK_STMT));
else if ( ! expand_exit_something ())
cp_error ("break statement not within loop or switch");
@@ -462,7 +485,7 @@ void
finish_continue_stmt ()
{
emit_line_note (input_filename, lineno);
- if (processing_template_decl)
+ if (building_stmt_tree ())
add_tree (build_min_nt (CONTINUE_STMT));
else if (! expand_continue_loop (0))
cp_error ("continue statement not within a loop");
@@ -485,7 +508,7 @@ finish_switch_cond (cond)
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
add_tree (r);
@@ -521,7 +544,7 @@ finish_switch_stmt (cond, switch_stmt)
tree cond;
tree switch_stmt;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
else
expand_end_case (cond);
@@ -538,17 +561,22 @@ finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
+ if (building_stmt_tree ())
+ {
+ add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
+ return;
+ }
+
do_case (low_value, high_value);
}
-
/* Finish a goto-statement. */
void
finish_goto_stmt (destination)
tree destination;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
add_tree (build_min_nt (GOTO_STMT, destination));
else
{
@@ -571,7 +599,7 @@ finish_goto_stmt (destination)
tree
begin_try_block ()
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
@@ -591,7 +619,7 @@ begin_try_block ()
tree
begin_function_try_block ()
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
@@ -613,12 +641,10 @@ void
finish_try_block (try_block)
tree try_block;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
- {
- expand_start_all_catch ();
- }
+ expand_start_all_catch ();
}
/* Likewise, for a function-try-block. */
@@ -627,7 +653,7 @@ void
finish_function_try_block (try_block)
tree try_block;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
{
@@ -644,7 +670,7 @@ void
finish_handler_sequence (try_block)
tree try_block;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
@@ -658,7 +684,7 @@ void
finish_function_handler_sequence (try_block)
tree try_block;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
@@ -674,7 +700,7 @@ begin_handler ()
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
add_tree (r);
@@ -694,7 +720,7 @@ void
finish_handler_parms (handler)
tree handler;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
}
@@ -704,7 +730,7 @@ void
finish_handler (handler)
tree handler;
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
else
expand_end_catch_block ();
@@ -722,7 +748,7 @@ begin_compound_stmt (has_no_scope)
{
tree r;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
r = build_min_nt (COMPOUND_STMT, NULL_TREE);
add_tree (r);
@@ -732,6 +758,8 @@ begin_compound_stmt (has_no_scope)
else
r = NULL_TREE;
+ last_expr_type = NULL_TREE;
+
if (!has_no_scope)
do_pushlevel ();
@@ -749,17 +777,24 @@ finish_compound_stmt (has_no_scope, compound_stmt)
tree compound_stmt;
{
tree r;
+ tree t;
if (!has_no_scope)
r = do_poplevel ();
else
r = NULL_TREE;
- if (processing_template_decl)
+ if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (compound_stmt,
COMPOUND_BODY (compound_stmt));
+ /* When we call finish_stmt we will lost LAST_EXPR_TYPE. But, since
+ the precise purpose of that variable is store the type of the
+ last expression statement within the last compound statement, we
+ preserve the value. */
+ t = last_expr_type;
finish_stmt ();
+ last_expr_type = t;
return r;
}
@@ -779,14 +814,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
{
if (TREE_CHAIN (string))
{
- if (processing_template_decl)
+ if (building_stmt_tree ())
/* We need to build the combined string on the permanent
obstack so that we can use it during instantiations. */
push_permanent_obstack ();
string = combine_strings (string);
- if (processing_template_decl)
+ if (building_stmt_tree ())
pop_obstacks ();
}
@@ -798,7 +833,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
cv_qualifier = NULL_TREE;
}
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
@@ -837,7 +872,7 @@ finish_label_stmt (name)
{
tree decl;
- if (processing_template_decl)
+ if (building_stmt_tree ())
{
push_permanent_obstack ();
decl = build_decl (LABEL_DECL, name, void_type_node);
@@ -869,6 +904,111 @@ add_decl_stmt (decl)
add_tree (decl_stmt);
}
+/* Bind a name and initialization to the return value of
+ the current function. */
+
+void
+finish_named_return_value (return_id, init)
+ tree return_id, init;
+{
+ tree decl = DECL_RESULT (current_function_decl);
+
+ if (pedantic)
+ /* Give this error as many times as there are occurrences,
+ so that users can use Emacs compilation buffers to find
+ and fix all such places. */
+ pedwarn ("ANSI C++ does not permit named return values");
+
+ if (return_id != NULL_TREE)
+ {
+ if (DECL_NAME (decl) == NULL_TREE)
+ {
+ DECL_NAME (decl) = return_id;
+ DECL_ASSEMBLER_NAME (decl) = return_id;
+ }
+ else
+ {
+ cp_error ("return identifier `%D' already in place", return_id);
+ return;
+ }
+ }
+
+ /* Can't let this happen for constructors. */
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ {
+ error ("can't redefine default return value for constructors");
+ return;
+ }
+
+ /* If we have a named return value, put that in our scope as well. */
+ if (DECL_NAME (decl) != NULL_TREE)
+ {
+ /* Let `cp_finish_decl' know that this initializer is ok. */
+ DECL_INITIAL (decl) = init;
+ pushdecl (decl);
+
+ if (building_stmt_tree ())
+ add_tree (build_min_nt (RETURN_INIT, return_id,
+ copy_to_permanent (init)));
+ else
+ {
+ cp_finish_decl (decl, init, NULL_TREE, 0, 0);
+ store_return_init (decl);
+ }
+ }
+}
+
+/* Cache the value of this class's main virtual function table pointer
+ in a register variable. This will save one indirection if a
+ more than one virtual function call is made this function. */
+
+void
+setup_vtbl_ptr ()
+{
+ extern tree base_init_expr;
+
+ if (base_init_expr == 0
+ && DECL_CONSTRUCTOR_P (current_function_decl))
+ {
+ if (building_stmt_tree ())
+ add_tree (build_min_nt
+ (CTOR_INITIALIZER,
+ current_member_init_list, current_base_init_list));
+ else
+ emit_base_init (current_class_type, 0);
+ }
+}
+
+/* Begin a new scope. */
+
+void
+do_pushlevel ()
+{
+ if (!building_stmt_tree ())
+ {
+ emit_line_note (input_filename, lineno);
+ clear_last_expr ();
+ }
+ pushlevel (0);
+ push_momentary ();
+ if (!building_stmt_tree ())
+ expand_start_bindings (0);
+}
+
+/* Finish a scope. */
+
+tree
+do_poplevel ()
+{
+ tree t;
+
+ if (!building_stmt_tree ())
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ t = poplevel (kept_level_p (), 1, 0);
+ pop_momentary ();
+ return t;
+}
+
/* Finish a parenthesized expression EXPR. */
tree
@@ -889,11 +1029,11 @@ tree
begin_stmt_expr ()
{
keep_next_level ();
- /* If we're processing_template_decl, 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
last_tree. We return last_tree so that we can later unhook the
compound statement. */
- return processing_template_decl ? last_tree : expand_start_stmt_expr();
+ return building_stmt_tree () ? last_tree : expand_start_stmt_expr();
}
/* Finish a statement-expression. RTL_EXPR should be the value
@@ -908,7 +1048,7 @@ finish_stmt_expr (rtl_expr, expr)
{
tree result;
- if (!processing_template_decl)
+ if (!building_stmt_tree ())
{
rtl_expr = expand_end_stmt_expr (rtl_expr);
/* The statements have side effects, so the group does. */
@@ -917,26 +1057,29 @@ finish_stmt_expr (rtl_expr, expr)
if (TREE_CODE (expr) == BLOCK)
{
- /* Make a BIND_EXPR for the BLOCK already made. */
- if (processing_template_decl)
- result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
- NULL_TREE);
+ /* Make a CP_BIND_EXPR for the BLOCK already made. */
+ if (building_stmt_tree ())
+ {
+ 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 BIND_EXPR is expanded. */
+ /* 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 (processing_template_decl)
+ if (building_stmt_tree ())
{
/* Remove the compound statement from the tree structure; it is
- now saved in the BIND_EXPR. */
+ now saved in the STMT_EXPR. */
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
}
@@ -1746,3 +1889,300 @@ finish_typeof (expr)
return TREE_TYPE (expr);
}
+
+/* Create an empty statement tree for FN. */
+
+void
+begin_stmt_tree (fn)
+ tree fn;
+{
+ /* We create a trivial EXPR_STMT so that last_tree is never NULL in
+ what follows. We remove the extraneous statement in
+ finish_stmt_tree. */
+ DECL_SAVED_TREE (fn) = build_nt (EXPR_STMT, void_zero_node);
+ last_tree = DECL_SAVED_TREE (fn);
+ last_expr_type = NULL_TREE;
+}
+
+/* Finish the statement tree for FN. */
+
+void
+finish_stmt_tree (fn)
+ tree fn;
+{
+ DECL_SAVED_TREE (fn) = TREE_CHAIN (DECL_SAVED_TREE (fn));
+}
+
+/* Generate RTL for the chain of statements T. */
+
+static void
+expand_stmts (t)
+ tree t;
+{
+ while (t)
+ {
+ expand_stmt (t);
+ t = TREE_CHAIN (t);
+ }
+}
+
+/* Generate RTL for the statement T, and its substatements. */
+
+tree
+expand_stmt (t)
+ tree t;
+{
+ if (t == NULL_TREE || t == error_mark_node)
+ return NULL_TREE;
+
+ switch (TREE_CODE (t))
+ {
+ case RETURN_STMT:
+ lineno = STMT_LINENO (t);
+ finish_return_stmt (RETURN_EXPR (t));
+ break;
+
+ case EXPR_STMT:
+ lineno = STMT_LINENO (t);
+ finish_expr_stmt (EXPR_STMT_EXPR (t));
+ break;
+
+ case DECL_STMT:
+ {
+ tree decl;
+ int i = suspend_momentary ();
+
+ lineno = STMT_LINENO (t);
+ emit_line_note (input_filename, lineno);
+ decl = DECL_STMT_DECL (t);
+ /* We need to clear DECL_CONTEXT so that maybe_push_decl
+ will push it into the current scope. */
+ if (DECL_CONTEXT (decl) == current_function_decl)
+ DECL_CONTEXT (decl) = NULL_TREE;
+ /* If we marked this variable as dead when we processed it
+ before, we must undo that now. The variable has been
+ resuscitated. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_DEAD_FOR_LOCAL (decl) = 0;
+ maybe_push_decl (decl);
+ cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
+ resume_momentary (i);
+ }
+ break;
+
+ case FOR_STMT:
+ {
+ tree tmp;
+
+ lineno = STMT_LINENO (t);
+ begin_for_stmt ();
+ for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
+ expand_stmt (tmp);
+ finish_for_init_stmt (NULL_TREE);
+ finish_for_cond (FOR_COND (t), NULL_TREE);
+ tmp = FOR_EXPR (t);
+ finish_for_expr (tmp, NULL_TREE);
+ expand_stmt (FOR_BODY (t));
+ finish_for_stmt (tmp, NULL_TREE);
+ }
+ break;
+
+ case WHILE_STMT:
+ {
+ lineno = STMT_LINENO (t);
+ begin_while_stmt ();
+ finish_while_stmt_cond (WHILE_COND (t), NULL_TREE);
+ expand_stmt (WHILE_BODY (t));
+ finish_while_stmt (NULL_TREE);
+ }
+ break;
+
+ case DO_STMT:
+ {
+ lineno = STMT_LINENO (t);
+ begin_do_stmt ();
+ expand_stmt (DO_BODY (t));
+ finish_do_body (NULL_TREE);
+ finish_do_stmt (DO_COND (t), NULL_TREE);
+ }
+ break;
+
+ case IF_STMT:
+ lineno = STMT_LINENO (t);
+ begin_if_stmt ();
+ finish_if_stmt_cond (IF_COND (t), NULL_TREE);
+ if (THEN_CLAUSE (t))
+ {
+ expand_stmt (THEN_CLAUSE (t));
+ finish_then_clause (NULL_TREE);
+ }
+ if (ELSE_CLAUSE (t))
+ {
+ begin_else_clause ();
+ expand_stmt (ELSE_CLAUSE (t));
+ finish_else_clause (NULL_TREE);
+ }
+ finish_if_stmt ();
+ break;
+
+ case COMPOUND_STMT:
+ lineno = STMT_LINENO (t);
+ begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ expand_stmts (COMPOUND_BODY (t));
+ return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
+ NULL_TREE);
+
+ case BREAK_STMT:
+ lineno = STMT_LINENO (t);
+ finish_break_stmt ();
+ break;
+
+ case CONTINUE_STMT:
+ lineno = STMT_LINENO (t);
+ finish_continue_stmt ();
+ break;
+
+ case SWITCH_STMT:
+ lineno = STMT_LINENO (t);
+ begin_switch_stmt ();
+ finish_switch_cond (SWITCH_COND (t));
+ if (TREE_OPERAND (t, 1))
+ expand_stmt (SWITCH_BODY (t));
+ finish_switch_stmt (SWITCH_COND (t), NULL_TREE);
+ break;
+
+ case CASE_LABEL:
+ finish_case_label (CASE_LOW (t), CASE_HIGH (t));
+ break;
+
+ case LABEL_DECL:
+ t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
+ DECL_NAME (t));
+ if (t)
+ expand_label (t);
+ break;
+
+ case GOTO_STMT:
+ lineno = STMT_LINENO (t);
+ finish_goto_stmt (GOTO_DESTINATION (t));
+ break;
+
+ case ASM_STMT:
+ lineno = STMT_LINENO (t);
+ finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS
+ (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
+ break;
+
+ case TRY_BLOCK:
+ lineno = STMT_LINENO (t);
+ begin_try_block ();
+ expand_stmt (TRY_STMTS (t));
+ finish_try_block (NULL_TREE);
+ expand_stmts (TRY_HANDLERS (t));
+ finish_handler_sequence (NULL_TREE);
+ break;
+
+ case HANDLER:
+ lineno = STMT_LINENO (t);
+ begin_handler ();
+ if (HANDLER_PARMS (t))
+ {
+ tree d = HANDLER_PARMS (t);
+ expand_start_catch_block (TREE_OPERAND (d, 1),
+ TREE_OPERAND (d, 0));
+ }
+ else
+ expand_start_catch_block (NULL_TREE, NULL_TREE);
+ finish_handler_parms (NULL_TREE);
+ expand_stmt (HANDLER_BODY (t));
+ finish_handler (NULL_TREE);
+ break;
+
+ default:
+ my_friendly_abort (19990810);
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+/* Generate RTL for FN. */
+
+void
+expand_body (fn)
+ tree fn;
+{
+ int saved_expanding_p;
+ int nested;
+ tree t;
+ tree try_block;
+
+ /* Remember whether we're already processing a function definition
+ so that we can tell finish_function. */
+ nested = in_function_p ();
+
+ /* Let the compiler know that now is the time to really generate
+ actualy RTL. */
+ saved_expanding_p = expanding_p;
+ expanding_p = 1;
+
+ start_function (NULL_TREE, fn, NULL_TREE, 1);
+ store_parm_decls ();
+
+ /* There are a few things that we do not handle recursively. For
+ example, a function try-block is handled differently from an
+ ordinary try-block, so we must handle it here. */
+ t = DECL_SAVED_TREE (fn);
+ try_block = NULL_TREE;
+ if (t && TREE_CODE (t) == TRY_BLOCK)
+ {
+ try_block = t;
+ begin_function_try_block ();
+ t = TRY_STMTS (try_block);
+ }
+
+ if (t && TREE_CODE (t) == RETURN_INIT)
+ {
+ /* Clear this out so that finish_named_return_value can set it
+ again. */
+ DECL_NAME (DECL_RESULT (fn)) = NULL_TREE;
+ finish_named_return_value (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+ t = TREE_CHAIN (t);
+ }
+
+ if (t && TREE_CODE (t) == CTOR_INITIALIZER)
+ {
+ current_member_init_list = TREE_OPERAND (t, 0);
+ current_base_init_list = TREE_OPERAND (t, 1);
+ t = TREE_CHAIN (t);
+ }
+
+ /* If this is a constructor, we need to initialize our members and
+ base-classes. */
+ setup_vtbl_ptr ();
+
+ /* Always keep the BLOCK node associated with the outermost pair of
+ curly braces of a function. These are needed for correct
+ operation of dwarfout.c. */
+ keep_next_level ();
+
+ /* Expand the body. */
+ expand_stmt (t);
+
+ /* If there was a function try-block, expand the handlers. */
+ if (try_block)
+ {
+ finish_function_try_block (NULL_TREE);
+ {
+ tree handler = TRY_HANDLERS (try_block);
+ for (; handler; handler = TREE_CHAIN (handler))
+ expand_stmt (handler);
+ }
+ finish_function_handler_sequence (NULL_TREE);
+ }
+
+ finish_function (lineno, 0, nested);
+
+ /* Restore EXPANDING_P. */
+ expanding_p = saved_expanding_p;
+}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f2e8257..b9732b3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -412,15 +412,20 @@ build_cplus_method_type (basetype, rettype, argtypes)
ptype = build_pointer_type (basetype);
/* The actual arglist for this function includes a "hidden" argument
- which is "this". Put it into the list of argument types. */
-
+ which is "this". Put it into the list of argument types. Make
+ sure that the new argument list is allocated on the same obstack
+ as the type. */
+ push_obstacks (TYPE_OBSTACK (t), TYPE_OBSTACK (t));
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
TREE_SIDE_EFFECTS (argtypes) = 1; /* Mark first argtype as "artificial". */
+ pop_obstacks ();
/* If we already have such a type, use the old one and free this one.
Note that it also frees up the above cons cell if found. */
- hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
+ hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
+ type_hash_list (argtypes);
+
t = type_hash_canon (hashcode, t);
if (TYPE_SIZE (t) == 0)
@@ -1646,6 +1651,8 @@ search_tree (t, func)
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case CALL_EXPR:
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1));
break;
@@ -1657,6 +1664,7 @@ search_tree (t, func)
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
case LOOKUP_EXPR:
+ case THROW_EXPR:
TRY (TREE_OPERAND (t, 0));
break;
@@ -1681,6 +1689,7 @@ search_tree (t, func)
break;
case BIND_EXPR:
+ case STMT_EXPR:
break;
case REAL_TYPE:
@@ -1774,6 +1783,7 @@ mapcar (t, func)
tree (*func) PROTO((tree));
{
tree tmp;
+ enum tree_code code;
if (t == NULL_TREE)
return t;
@@ -1785,6 +1795,24 @@ mapcar (t, func)
return tmp;
}
+ /* Handle some common cases up front. */
+ code = TREE_CODE (t);
+ if (TREE_CODE_CLASS (code) == '1')
+ {
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ return t;
+ }
+ else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
+ {
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+ return t;
+ }
+
switch (TREE_CODE (t))
{
case ERROR_MARK:
@@ -1871,40 +1899,8 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
return t;
- case SAVE_EXPR:
- t = copy_node (t);
- TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
- return t;
-
- case MODIFY_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case COMPOUND_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
@@ -1913,6 +1909,8 @@ mapcar (t, func)
case SCOPE_REF:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@@ -1933,16 +1931,14 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = NULL_TREE;
return t;
- case CONVERT_EXPR:
+ case SAVE_EXPR:
case ADDR_EXPR:
case INDIRECT_REF:
- case NEGATE_EXPR:
- case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
- case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
- case NON_LVALUE_EXPR:
+ case THROW_EXPR:
+ case STMT_EXPR:
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
@@ -2009,19 +2005,19 @@ mapcar (t, func)
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
+ case RTL_EXPR:
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ return t;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
(mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func));
/* else fall through */
-
- /* This list is incomplete, but should suffice for now.
- It is very important that `sorry' not call
- `report_error_function'. That could cause an infinite loop. */
- default:
- sorry ("initializer contains unrecognized tree code");
- return error_mark_node;
+ default:
+ my_friendly_abort (19990815);
}
my_friendly_abort (107);
/* NOTREACHED */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 044f48f..5d12bee 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -197,6 +197,7 @@ require_complete_type_in_void (expr)
case EXIT_EXPR: /* have no return */
case LOOP_EXPR: /* have no return */
case BIND_EXPR: /* have no return */
+ case STMT_EXPR: /* have no return */
case THROW_EXPR: /* have no return */
case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
case CONVERT_EXPR: /* sometimes has a void type */
@@ -6801,12 +6802,6 @@ c_expand_return (retval)
return;
}
- if (processing_template_decl)
- {
- add_tree (build_min_nt (RETURN_STMT, retval));
- return;
- }
-
if (dtor_label)
{
if (retval)