diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 49c585d..f90f804 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,22 @@ 1999-09-09 Mark Mitchell <mark@codesourcery.com> + * cp-tree.h (EXPR_STMT_ASSIGNS_THIS): New macro. + (STMT_IS_FULL_EXPR_P): Likewise. + (STMT_LINENO_FOR_FN_P): Likewise. + (prep_stmt): New function. + (building_stmt_tree): Tweak for safety. + * pt.c (tsubst_expr): Use prep_stmt throughout. + (add_tree): Move it to semantics.c + * semantics.c (add_tree): Move it here. + (finish_expr_stmt_real): New function. + (finish_expr_stmt): Use it. + (finish_if_stmt_cond): Use FINISH_COND. + (finish_while_stmt_cond): Likewise. + (finish_for_cond): Likewise. + (finish_stmt_tree): Tweak line-number handling. + (prep_stmt): New function. + (expand_stmt): Use it. + * cp-tree.h (begin_switch_stmt): Adjust prototype. (finish_switch_cond): Likewise. * parse.y (simple_stmt): Adjust accordingly. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c8fc430..bb47e9b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */ /* Usage of TREE_LANG_FLAG_?: 0: BINFO_MARKED (BINFO nodes). COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT). + EXPR_STMT_ASSIGNS_THIS (in EXPR_STMT). NEW_EXPR_USE_GLOBAL (in NEW_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR). @@ -49,12 +50,14 @@ Boston, MA 02111-1307, USA. */ INHERITED_VALUE_BINDING_P (in CPLUS_BINDING) BASELINK_P (in TREE_LIST) ICS_ELLIPSIS_FLAG (in _CONV) + STMT_IS_FULL_EXPR_P (in _STMT) 2: IDENTIFIER_OPNAME_P. BINFO_VBASE_MARKED. BINFO_FIELDS_MARKED. TYPE_VIRTUAL_P. ICS_THIS_FLAG (in _CONV) - BINDING_HAS_LEVEL_P (In CPLUS_BINDING) + STMT_LINENO_FOR_FN_P (in _STMT) + BINDING_HAS_LEVEL_P (in CPLUS_BINDING) 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). BINFO_VTABLE_PATH_MARKED. BINFO_PUSHDECLS_MARKED. @@ -1816,6 +1819,15 @@ struct lang_decl constructor call, rather than an ordinary function call. */ #define AGGR_INIT_VIA_CTOR_P(NODE) TREE_LANG_FLAG_0 (NODE) +/* Nonzero if this statement contained the first assigned to `this' in + the current function. (Of course, one cannot assign to `this' in + ANSI/ISO C++, but we still support assignments to this with + -fthis-is-variable.) */ +#define EXPR_STMT_ASSIGNS_THIS(NODE) TREE_LANG_FLAG_0 ((NODE)) + +/* Nonzero if this statement should be considered a full-expression. */ +#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE)) + /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a TEMPLATE_DECL. This macro determines whether or not a given class type is really a template type, as opposed to an instantiation or @@ -2430,10 +2442,17 @@ extern int flag_new_for_scope; #define ASM_VOLATILE_P(NODE) \ (ASM_CV_QUAL ((NODE)) != NULL_TREE) -/* The line-number at which a statement began. */ +/* The line-number at which a statement began. But if + STMT_LINENO_FOR_FN_P does holds, then this macro gives the + line number for the end of the current function instead. */ #define STMT_LINENO(NODE) \ (TREE_COMPLEXITY ((NODE))) +/* If non-zero, the STMT_LINENO for NODE is the line at which the + function ended. */ +#define STMT_LINENO_FOR_FN_P(NODE) \ + (TREE_LANG_FLAG_2 ((NODE))) + /* The parameters for a call-declarator. */ #define CALL_DECLARATOR_PARMS(NODE) \ (TREE_PURPOSE (TREE_OPERAND ((NODE), 1))) @@ -3635,10 +3654,11 @@ 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 void prep_stmt PROTO((tree)); /* 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) +#define building_stmt_tree() \ + (current_function && (processing_template_decl || !expanding_p)) /* in spew.c */ extern void init_spew PROTO((void)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0795a19..9fd1f2f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7235,6 +7235,7 @@ tsubst_expr (t, args, complain, in_decl) switch (TREE_CODE (t)) { case RETURN_INIT: + prep_stmt (t); finish_named_return_value (TREE_OPERAND (t, 0), tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl)); @@ -7242,6 +7243,7 @@ tsubst_expr (t, args, complain, in_decl) break; case CTOR_INITIALIZER: + prep_stmt (t); current_member_init_list = tsubst_expr_values (TREE_OPERAND (t, 0), args); current_base_init_list @@ -7251,13 +7253,18 @@ tsubst_expr (t, args, complain, in_decl) break; case RETURN_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); finish_return_stmt (tsubst_expr (RETURN_EXPR (t), args, complain, in_decl)); break; case EXPR_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); + /* If we're doing tsubst'ing, then we should not yet have done + semantic analysisy, so we should not know that this statement + assigns to the `this' pointer. */ + my_friendly_assert (EXPR_STMT_ASSIGNS_THIS (t) == 0, + 19990831); finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl)); break; @@ -7268,7 +7275,7 @@ tsubst_expr (t, args, complain, in_decl) tree decl; tree init; - lineno = STMT_LINENO (t); + prep_stmt (t); decl = DECL_STMT_DECL (t); if (TREE_CODE (decl) == LABEL_DECL) finish_label_decl (DECL_NAME (decl)); @@ -7296,7 +7303,7 @@ tsubst_expr (t, args, complain, in_decl) case FOR_STMT: { tree tmp; - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_for_stmt (); for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp)) @@ -7314,7 +7321,7 @@ tsubst_expr (t, args, complain, in_decl) case WHILE_STMT: { - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_while_stmt (); finish_while_stmt_cond (tsubst_expr (WHILE_COND (t), args, complain, in_decl), @@ -7326,7 +7333,7 @@ tsubst_expr (t, args, complain, in_decl) case DO_STMT: { - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_do_stmt (); tsubst_expr (DO_BODY (t), args, complain, in_decl); finish_do_body (stmt); @@ -7340,7 +7347,7 @@ tsubst_expr (t, args, complain, in_decl) { tree tmp; - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_if_stmt (); finish_if_stmt_cond (tsubst_expr (IF_COND (t), args, complain, in_decl), @@ -7367,7 +7374,7 @@ tsubst_expr (t, args, complain, in_decl) { tree substmt; - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); for (substmt = COMPOUND_BODY (t); substmt != NULL_TREE; @@ -7378,12 +7385,12 @@ tsubst_expr (t, args, complain, in_decl) break; case BREAK_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); finish_break_stmt (); break; case CONTINUE_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); finish_continue_stmt (); break; @@ -7391,7 +7398,7 @@ tsubst_expr (t, args, complain, in_decl) { tree val; - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_switch_stmt (); val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl); finish_switch_cond (val, stmt); @@ -7401,6 +7408,7 @@ tsubst_expr (t, args, complain, in_decl) break; case CASE_LABEL: + prep_stmt (t); finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl), tsubst_expr (CASE_HIGH (t), args, complain, in_decl)); break; @@ -7411,7 +7419,7 @@ tsubst_expr (t, args, complain, in_decl) break; case GOTO_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); t = GOTO_DESTINATION (t); if (TREE_CODE (t) != LABEL_DECL) /* Computed goto's must be tsubst'd into. On the other hand, @@ -7424,7 +7432,7 @@ tsubst_expr (t, args, complain, in_decl) break; case ASM_STMT: - lineno = STMT_LINENO (t); + prep_stmt (t); finish_asm_stmt (ASM_CV_QUAL (t), tsubst_expr (ASM_STRING (t), args, complain, in_decl), tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), @@ -7434,7 +7442,7 @@ tsubst_expr (t, args, complain, in_decl) break; case TRY_BLOCK: - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_try_block (); tsubst_expr (TRY_STMTS (t), args, complain, in_decl); finish_try_block (stmt); @@ -7452,7 +7460,7 @@ tsubst_expr (t, args, complain, in_decl) break; case HANDLER: - lineno = STMT_LINENO (t); + prep_stmt (t); stmt = begin_handler (); if (HANDLER_PARMS (t)) expand_start_catch_block @@ -7466,7 +7474,7 @@ tsubst_expr (t, args, complain, in_decl) break; case TAG_DEFN: - lineno = STMT_LINENO (t); + prep_stmt (t); t = TREE_TYPE (t); if (TREE_CODE (t) == ENUMERAL_TYPE) tsubst (t, args, complain, NULL_TREE); @@ -9854,14 +9862,6 @@ tsubst_expr_values (t, argvec) } void -add_tree (t) - tree t; -{ - last_tree = TREE_CHAIN (last_tree) = t; -} - - -void begin_tree () { if (current_function) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4d6a234..0b65dee 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -44,6 +44,7 @@ static void expand_stmts PROTO((tree)); static void do_pushlevel PROTO((void)); static tree do_poplevel PROTO((void)); +static void finish_expr_stmt_real PROTO((tree, int)); static tree expand_cond PROTO((tree)); /* When parsing a template, LAST_TREE contains the last statement @@ -75,11 +76,29 @@ static tree expand_cond PROTO((tree)); substmt = cond; \ } while (0) -/* Finish an expression-statement, whose EXPRESSION is as indicated. */ +/* T is a statement. Add it to the statement-tree. */ -void -finish_expr_stmt (expr) +void +add_tree (t) + tree t; +{ + /* Add T to the statement-tree. */ + last_tree = TREE_CHAIN (last_tree) = t; + + /* When we expand a statement-tree, we must know whether or not the + statements are full-expresions. We record that fact here. */ + if (building_stmt_tree ()) + STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p; +} + +/* Finish an expression-statement, whose EXPRESSION is as indicated. + If ASSIGNED_THIS is non-zero, then this statement just assigned to + the `this' pointer. */ + +static void +finish_expr_stmt_real (expr, assigned_this) tree expr; + int assigned_this; { if (expr != NULL_TREE) { @@ -109,6 +128,11 @@ finish_expr_stmt (expr) } } + /* If this statement assigned to the `this' pointer, record that + fact for finish_stmt. */ + if (assigned_this) + current_function_just_assigned_this = 1; + finish_stmt (); /* This was an expression-statement, so we save the type of the @@ -116,6 +140,15 @@ finish_expr_stmt (expr) last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE; } +/* Like finish_expr_stmt_real, but ASSIGNS_THIS is always zero. */ + +void +finish_expr_stmt (expr) + tree expr; +{ + finish_expr_stmt_real (expr, /*assigns_this=*/0); +} + /* Begin an if-statement. Returns a newly created IF_STMT if appropriate. */ @@ -146,12 +179,7 @@ finish_if_stmt_cond (cond, if_stmt) tree if_stmt; { if (building_stmt_tree ()) - { - if (last_tree != if_stmt) - RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt)); - else - IF_COND (if_stmt) = cond; - } + FINISH_COND (cond, if_stmt, IF_COND (if_stmt)); else { emit_line_note (input_filename, lineno); @@ -244,12 +272,7 @@ finish_while_stmt_cond (cond, while_stmt) tree while_stmt; { if (building_stmt_tree ()) - { - if (last_tree != while_stmt) - RECHAIN_STMTS_FROM_LAST (while_stmt, WHILE_COND (while_stmt)); - else - TREE_OPERAND (while_stmt, 0) = cond; - } + FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt)); else { emit_line_note (input_filename, lineno); @@ -409,12 +432,7 @@ finish_for_cond (cond, for_stmt) tree for_stmt; { if (building_stmt_tree ()) - { - if (last_tree != for_stmt) - RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt)); - else - FOR_COND (for_stmt) = cond; - } + FINISH_COND (cond, for_stmt, FOR_COND (for_stmt)); else { emit_line_note (input_filename, lineno); @@ -1973,7 +1991,28 @@ void finish_stmt_tree (fn) tree fn; { - DECL_SAVED_TREE (fn) = TREE_CHAIN (DECL_SAVED_TREE (fn)); + tree stmt; + + /* Remove the fake extra statement added in begin_stmt_tree. */ + stmt = TREE_CHAIN (DECL_SAVED_TREE (fn)); + DECL_SAVED_TREE (fn) = stmt; + + /* The line-number recorded in the outermost statement in a function + is the line number of the end of the function. */ + STMT_LINENO (stmt) = lineno; + STMT_LINENO_FOR_FN_P (stmt) = 1; +} + +/* We're about to expand T, a statement. Set up appropriate context + for the substitution. */ + +void +prep_stmt (t) + tree t; +{ + if (!STMT_LINENO_FOR_FN_P (t)) + lineno = STMT_LINENO (t); + stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t); } /* Some statements, like for-statements or if-statements, require a @@ -2013,19 +2052,28 @@ tree expand_stmt (t) tree t; { + int saved_stmts_are_full_exprs_p; + tree rval; + if (t == NULL_TREE || t == error_mark_node) return NULL_TREE; + /* Assume we'll have nothing to return. */ + rval = NULL_TREE; + + /* Set up context appropriately for handling this statement. */ + saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p; + prep_stmt (t); + 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)); + finish_expr_stmt_real (EXPR_STMT_EXPR (t), + EXPR_STMT_ASSIGNS_THIS (t)); break; case DECL_STMT: @@ -2064,7 +2112,6 @@ expand_stmt (t) { tree tmp; - lineno = STMT_LINENO (t); begin_for_stmt (); for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp)) expand_stmt (tmp); @@ -2079,7 +2126,6 @@ expand_stmt (t) case WHILE_STMT: { - lineno = STMT_LINENO (t); begin_while_stmt (); finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE); expand_stmt (WHILE_BODY (t)); @@ -2089,7 +2135,6 @@ expand_stmt (t) case DO_STMT: { - lineno = STMT_LINENO (t); begin_do_stmt (); expand_stmt (DO_BODY (t)); finish_do_body (NULL_TREE); @@ -2098,7 +2143,6 @@ expand_stmt (t) break; case IF_STMT: - lineno = STMT_LINENO (t); begin_if_stmt (); finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE); if (THEN_CLAUSE (t)) @@ -2116,19 +2160,17 @@ expand_stmt (t) 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), + rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), NULL_TREE); + break; case BREAK_STMT: - lineno = STMT_LINENO (t); finish_break_stmt (); break; case CONTINUE_STMT: - lineno = STMT_LINENO (t); finish_continue_stmt (); break; @@ -2136,7 +2178,6 @@ expand_stmt (t) { tree cond; - lineno = STMT_LINENO (t); begin_switch_stmt (); cond = expand_cond (SWITCH_COND (t)); finish_switch_cond (cond, NULL_TREE); @@ -2150,12 +2191,10 @@ expand_stmt (t) break; case LABEL_STMT: - lineno = STMT_LINENO (t); finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t))); break; case GOTO_STMT: - lineno = STMT_LINENO (t); if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL) finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t))); else @@ -2163,13 +2202,11 @@ expand_stmt (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); if (CLEANUP_P (t)) { expand_eh_region_start (); @@ -2187,7 +2224,6 @@ expand_stmt (t) break; case HANDLER: - lineno = STMT_LINENO (t); begin_handler (); if (HANDLER_PARMS (t)) expand_start_catch_block (DECL_STMT_DECL (HANDLER_PARMS (t))); @@ -2199,7 +2235,6 @@ expand_stmt (t) break; case SUBOBJECT: - lineno = STMT_LINENO (t); finish_subobject (SUBOBJECT_CLEANUP (t)); break; @@ -2208,7 +2243,10 @@ expand_stmt (t) break; } - return NULL_TREE; + /* Restore saved state. */ + stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; + + return rval; } /* Generate RTL for FN. */