diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-08-16 19:01:36 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-08-16 19:01:36 +0000 |
commit | 558475f07cfe622a964b7c0019be78bd81912a47 (patch) | |
tree | 941793477b95a8310030bd04dc3b51507e7b23d9 | |
parent | 63ebc2756028198247166b6f46554b62b028dce9 (diff) | |
download | gcc-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/ChangeLog | 98 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 14 | ||||
-rw-r--r-- | gcc/cp/decl.c | 165 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 21 | ||||
-rw-r--r-- | gcc/cp/error.c | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 8 | ||||
-rw-r--r-- | gcc/cp/expr.c | 15 | ||||
-rw-r--r-- | gcc/cp/parse.c | 8 | ||||
-rw-r--r-- | gcc/cp/parse.y | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 223 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 562 | ||||
-rw-r--r-- | gcc/cp/tree.c | 90 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 7 |
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) |