diff options
author | Ian Lance Taylor <ian@airs.com> | 2005-04-09 03:18:18 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2005-04-09 03:18:18 +0000 |
commit | fbc315db4a79aee216b2e56e1653e22d86436fea (patch) | |
tree | 54b12532b3129c3528d3e2a058b89210eef0f85b /gcc/cp | |
parent | 0bca51f080dfff5e943b1f1775d874a73bbc441a (diff) | |
download | gcc-fbc315db4a79aee216b2e56e1653e22d86436fea.zip gcc-fbc315db4a79aee216b2e56e1653e22d86436fea.tar.gz gcc-fbc315db4a79aee216b2e56e1653e22d86436fea.tar.bz2 |
c-common.def: Move FOR_STMT...
./ * c-common.def: Move FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT,
CONTINUE_STMT, and SWITCH_STMT to cp/cp-tree.def.
* c-common.h (WHILE_COND, WHILE_BODY): Move to cp/cp-tree.h.
(DO_COND, DO_BODY): Likewise.
(FOR_INIT_STMT, FOR_COND, FOR_EXPR, FOR_BODY): Likewise.
(SWITCH_STMT_COND, SWITCH_STMT_BODY, SWITCH_STMT_TYPE): Likewise.
(c_common_stmt_codes): Remove FOR_STMT, WHILE_STMT, DO_STMT,
BREAK_STMT, CONTINUE_STMT, and SWITCH_STMT.
(build_continue_stmt, build_break_stmt): Don't declare.
(c_do_switch_warnings): Update declaration.
* c-gimplify.c (enum bc_t): Remove.
(struct c_gimplify_ctx, ctxp): Remove.
(push_context, pop_context): Remove static functions.
(c_genericize): Don't call push_context or pop_context.
(begin_bc_block, finish_bc_block): Remove static functions.
(build_bc_goto): Likewise.
(gimplify_c_loop): Likewise.
(gimplify_for_stmt, gimplify_while_stmt): Likewise.
(gimplify_do_stmt, gimplify_switch_stmt): Likewise.
(c_gimplify_expr): Remove handling of FOR_STMT, WHILE_STMT,
DO_STMT, SWITCH_STMT, CONTINUE_STMT, BREAK_STMT.
* c-common.c (c_do_switch_warnings): Rename from
c_do_switch_warnings_1.
(c_do_switch_warnings) [old version]: Remove.
(c_do_switch_expr_warnings): Remove.
* c-typeck.c (c_finish_case): Call new c_do_switch_warnings
function instead of c_do_switch_expr_warnings.
* c-dump.c (c_dump_tree): Remove handling of BREAK_STMT,
CONTINUE_STMT, DO_STMT, FOR_STMT, SWITCH_STMT, and WHILE_STMT.
* c-pretty-print.c (pp_c_statement): Likewise.
* c-semantics.c (build_break_stmt, build_continue_stmt): Remove.
cp/
* cp-tree.def: Define FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT,
CONTINUE_STMT, SWITCH_STMT.
* cp-tree.h (cp_stmt_codes): Add FOR_STMT, WHILE_STMT, DO_STMT,
BREAK_STMT, CONTINUE_STMT, SWITCH_STMT.
(WHILE_COND, WHILE_BODY): Define.
(DO_COND, DO_BODY): Define.
(FOR_INIT_STMT, FOR_COND, FOR_EXPR, FOR_BODY): Define.
(SWITCH_STMT_COND, SWITCH_STMT_BODY, SWITCH_STMT_TYPE): Define.
* cp-gimplify.c (enum bc_t): Define.
(struct cp_gimplify_ctx, ctxp): Define.
(push_context, pop_context): New static functions.
(begin_bc_block, finish_bc_block): New static functions.
(build_bc_goto): New static function.
(gimplify_cp_loop, gimplify_for_stmt): New static functions.
(gimplify_while_stmt, gimplify_do_stmt): Likewise.
(gimplify_switch_stmt): Likewise.
(cp_gimplify_expr): Handle FOR_STMT, WHILE_STMT, DO_STMT,
SWITCH_STMT, CONTINUE_STMT, BREAK_STMT.
(cp_genericize): Call push_context and pop_context.
* semantics.c (finish_break_stmt): Just call build_stmt
(BREAK_STMT) rather than build_break_stmt.
(finish_continue_stmt): Corresponding change.
* decl.c (pop_switch): Update call to c_do_switch_warnings for new
parameters.
* cxx-pretty-print.c (pp_cxx_statement): Handle SWITCH_STMT,
WHILE_STMT, DO_STMT, FOR_STMT, BREAK_STMT, CONTINUE_STMT.
* dump.c (cp_dump_tree): Likewise.
From-SVN: r97885
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 266 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 24 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 27 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 78 | ||||
-rw-r--r-- | gcc/cp/decl.c | 9 | ||||
-rw-r--r-- | gcc/cp/dump.c | 34 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 4 |
8 files changed, 464 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 50c1f0c..c63486e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,33 @@ +2005-04-08 Ian Lance Taylor <ian@airs.com> + + * cp-tree.def: Define FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT, + CONTINUE_STMT, SWITCH_STMT. + * cp-tree.h (cp_stmt_codes): Add FOR_STMT, WHILE_STMT, DO_STMT, + BREAK_STMT, CONTINUE_STMT, SWITCH_STMT. + (WHILE_COND, WHILE_BODY): Define. + (DO_COND, DO_BODY): Define. + (FOR_INIT_STMT, FOR_COND, FOR_EXPR, FOR_BODY): Define. + (SWITCH_STMT_COND, SWITCH_STMT_BODY, SWITCH_STMT_TYPE): Define. + * cp-gimplify.c (enum bc_t): Define. + (struct cp_gimplify_ctx, ctxp): Define. + (push_context, pop_context): New static functions. + (begin_bc_block, finish_bc_block): New static functions. + (build_bc_goto): New static function. + (gimplify_cp_loop, gimplify_for_stmt): New static functions. + (gimplify_while_stmt, gimplify_do_stmt): Likewise. + (gimplify_switch_stmt): Likewise. + (cp_gimplify_expr): Handle FOR_STMT, WHILE_STMT, DO_STMT, + SWITCH_STMT, CONTINUE_STMT, BREAK_STMT. + (cp_genericize): Call push_context and pop_context. + * semantics.c (finish_break_stmt): Just call build_stmt + (BREAK_STMT) rather than build_break_stmt. + (finish_continue_stmt): Corresponding change. + * decl.c (pop_switch): Update call to c_do_switch_warnings for new + parameters. + * cxx-pretty-print.c (pp_cxx_statement): Handle SWITCH_STMT, + WHILE_STMT, DO_STMT, FOR_STMT, BREAK_STMT, CONTINUE_STMT. + * dump.c (cp_dump_tree): Likewise. + 2005-04-08 Mark Mitchell <mark@codesourcery.com> PR c++/20905 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 413a933..4d8880a 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1,6 +1,6 @@ /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. - Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Jason Merrill <jason@redhat.com> This file is part of GCC. @@ -32,6 +32,100 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "hashtab.h" #include "pointer-set.h" +/* Local declarations. */ + +enum bc_t { bc_break = 0, bc_continue = 1 }; + +static struct cp_gimplify_ctx +{ + /* Stack of labels which are targets for "break" or "continue", + linked through TREE_CHAIN. */ + tree current_label[2]; +} *ctxp; + +static void +push_context (void) +{ + gcc_assert (!ctxp); + ctxp = ((struct cp_gimplify_ctx *) + xcalloc (1, sizeof (struct cp_gimplify_ctx))); +} + +static void +pop_context (void) +{ + gcc_assert (ctxp + && !ctxp->current_label[0] + && !ctxp->current_label[1]); + free (ctxp); + ctxp = NULL; +} + +/* Begin a scope which can be exited by a break or continue statement. BC + indicates which. + + Just creates a label and pushes it into the current context. */ + +static tree +begin_bc_block (enum bc_t bc) +{ + tree label = create_artificial_label (); + TREE_CHAIN (label) = ctxp->current_label[bc]; + ctxp->current_label[bc] = label; + return label; +} + +/* Finish a scope which can be exited by a break or continue statement. + LABEL was returned from the most recent call to begin_bc_block. BODY is + an expression for the contents of the scope. + + If we saw a break (or continue) in the scope, append a LABEL_EXPR to + body. Otherwise, just forget the label. */ + +static tree +finish_bc_block (enum bc_t bc, tree label, tree body) +{ + gcc_assert (label == ctxp->current_label[bc]); + + if (TREE_USED (label)) + { + tree t, sl = NULL; + + t = build1 (LABEL_EXPR, void_type_node, label); + + append_to_statement_list (body, &sl); + append_to_statement_list (t, &sl); + body = sl; + } + + ctxp->current_label[bc] = TREE_CHAIN (label); + TREE_CHAIN (label) = NULL_TREE; + return body; +} + +/* Build a GOTO_EXPR to represent a break or continue statement. BC + indicates which. */ + +static tree +build_bc_goto (enum bc_t bc) +{ + tree label = ctxp->current_label[bc]; + + if (label == NULL_TREE) + { + if (bc == bc_break) + error ("break statement not within loop or switch"); + else + error ("continue statement not within loop or switch"); + + return NULL_TREE; + } + + /* Mark the label used for finish_bc_block. */ + TREE_USED (label) = 1; + return build1 (GOTO_EXPR, void_type_node, label); +} + /* Genericize a TRY_BLOCK. */ static void @@ -106,6 +200,144 @@ gimplify_if_stmt (tree *stmt_p) *stmt_p = stmt; } +/* Build a generic representation of one of the C loop forms. COND is the + loop condition or NULL_TREE. BODY is the (possibly compound) statement + controlled by the loop. INCR is the increment expression of a for-loop, + or NULL_TREE. COND_IS_FIRST indicates whether the condition is + evaluated before the loop body as in while and for loops, or after the + loop body as in do-while loops. */ + +static tree +gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) +{ + tree top, entry, exit, cont_block, break_block, stmt_list, t; + location_t stmt_locus; + + stmt_locus = input_location; + stmt_list = NULL_TREE; + entry = NULL_TREE; + + break_block = begin_bc_block (bc_break); + cont_block = begin_bc_block (bc_continue); + + /* If condition is zero don't generate a loop construct. */ + if (cond && integer_zerop (cond)) + { + top = NULL_TREE; + exit = NULL_TREE; + if (cond_is_first) + { + t = build_bc_goto (bc_break); + append_to_statement_list (t, &stmt_list); + } + } + else + { + /* If we use a LOOP_EXPR here, we have to feed the whole thing + back through the main gimplifier to lower it. Given that we + have to gimplify the loop body NOW so that we can resolve + break/continue stmts, seems easier to just expand to gotos. */ + top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); + + /* If we have an exit condition, then we build an IF with gotos either + out of the loop, or to the top of it. If there's no exit condition, + then we just build a jump back to the top. */ + exit = build_and_jump (&LABEL_EXPR_LABEL (top)); + if (cond && !integer_nonzerop (cond)) + { + t = build_bc_goto (bc_break); + exit = build3 (COND_EXPR, void_type_node, cond, exit, t); + exit = fold (exit); + gimplify_stmt (&exit); + + if (cond_is_first) + { + if (incr) + { + entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); + t = build_and_jump (&LABEL_EXPR_LABEL (entry)); + } + else + t = build_bc_goto (bc_continue); + append_to_statement_list (t, &stmt_list); + } + } + } + + gimplify_stmt (&body); + gimplify_stmt (&incr); + + body = finish_bc_block (bc_continue, cont_block, body); + + append_to_statement_list (top, &stmt_list); + append_to_statement_list (body, &stmt_list); + append_to_statement_list (incr, &stmt_list); + append_to_statement_list (entry, &stmt_list); + append_to_statement_list (exit, &stmt_list); + + annotate_all_with_locus (&stmt_list, stmt_locus); + + return finish_bc_block (bc_break, break_block, stmt_list); +} + +/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the + prequeue and hand off to gimplify_cp_loop. */ + +static void +gimplify_for_stmt (tree *stmt_p, tree *pre_p) +{ + tree stmt = *stmt_p; + + if (FOR_INIT_STMT (stmt)) + gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); + + *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), + FOR_EXPR (stmt), 1); +} + +/* Gimplify a WHILE_STMT node. */ + +static void +gimplify_while_stmt (tree *stmt_p) +{ + tree stmt = *stmt_p; + *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), + NULL_TREE, 1); +} + +/* Gimplify a DO_STMT node. */ + +static void +gimplify_do_stmt (tree *stmt_p) +{ + tree stmt = *stmt_p; + *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), + NULL_TREE, 0); +} + +/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ + +static void +gimplify_switch_stmt (tree *stmt_p) +{ + tree stmt = *stmt_p; + tree break_block, body; + location_t stmt_locus = input_location; + + break_block = begin_bc_block (bc_break); + + body = SWITCH_STMT_BODY (stmt); + if (!body) + body = build_empty_stmt (); + + *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), + SWITCH_STMT_COND (stmt), body, NULL_TREE); + SET_EXPR_LOCATION (*stmt_p, stmt_locus); + gimplify_stmt (stmt_p); + + *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); +} + /* Gimplify initialization from an AGGR_INIT_EXPR. */ static void @@ -254,6 +486,36 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) ret = GS_OK; break; + case FOR_STMT: + gimplify_for_stmt (expr_p, pre_p); + ret = GS_ALL_DONE; + break; + + case WHILE_STMT: + gimplify_while_stmt (expr_p); + ret = GS_ALL_DONE; + break; + + case DO_STMT: + gimplify_do_stmt (expr_p); + ret = GS_ALL_DONE; + break; + + case SWITCH_STMT: + gimplify_switch_stmt (expr_p); + ret = GS_ALL_DONE; + break; + + case CONTINUE_STMT: + *expr_p = build_bc_goto (bc_continue); + ret = GS_ALL_DONE; + break; + + case BREAK_STMT: + *expr_p = build_bc_goto (bc_break); + ret = GS_ALL_DONE; + break; + default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; @@ -369,5 +631,7 @@ cp_genericize (tree fndecl) pointer_set_destroy (p_set); /* Do everything else. */ + push_context (); c_genericize (fndecl); + pop_context (); } diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index b7c580a..674de59 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -2,7 +2,7 @@ additional tree codes used in the GNU C++ compiler (see tree.def for the standard codes). Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003, 2004, 2005, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -283,6 +283,28 @@ DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", tcc_expression, 3) and COND_EXPR for the benefit of templates. */ DEFTREECODE (IF_STMT, "if_stmt", tcc_expression, 3) +/* Used to represent a `for' statement. The operands are + FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */ +DEFTREECODE (FOR_STMT, "for_stmt", tcc_expression, 4) + +/* Used to represent a 'while' statement. The operands are WHILE_COND + and WHILE_BODY, respectively. */ +DEFTREECODE (WHILE_STMT, "while_stmt", tcc_expression, 2) + +/* Used to represent a 'do' statement. The operands are DO_BODY and + DO_COND, respectively. */ +DEFTREECODE (DO_STMT, "do_stmt", tcc_expression, 2) + +/* Used to represent a 'break' statement. */ +DEFTREECODE (BREAK_STMT, "break_stmt", tcc_expression, 0) + +/* Used to represent a 'continue' statement. */ +DEFTREECODE (CONTINUE_STMT, "continue_stmt", tcc_expression, 0) + +/* Used to represent a 'switch' statement. The operands are + SWITCH_STMT_COND, SWITCH_STMT_BODY and SWITCH_STMT_TYPE, respectively. */ +DEFTREECODE (SWITCH_STMT, "switch_stmt", tcc_expression, 3) + DEFTREECODE (TAG_DEFN, "tag_defn", tcc_expression, 0) /* Template instantiation level node. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1f773c0..3ab569f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -845,8 +845,9 @@ enum cplus_tree_code { #define cp_stmt_codes \ CTOR_INITIALIZER, TRY_BLOCK, HANDLER, \ EH_SPEC_BLOCK, USING_STMT, TAG_DEFN, \ - IF_STMT, CLEANUP_STMT - + IF_STMT, CLEANUP_STMT, FOR_STMT, \ + WHILE_STMT, DO_STMT, BREAK_STMT, \ + CONTINUE_STMT, SWITCH_STMT enum languages { lang_c, lang_cplusplus, lang_java }; /* Macros to make error reporting functions' lives easier. */ @@ -2948,6 +2949,28 @@ struct lang_decl GTY(()) #define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) #define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) +/* WHILE_STMT accessors. These give access to the condition of the + while statement and the body of the while statement, respectively. */ +#define WHILE_COND(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0) +#define WHILE_BODY(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 1) + +/* DO_STMT accessors. These give access to the condition of the do + statement and the body of the do statement, respectively. */ +#define DO_COND(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 0) +#define DO_BODY(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 1) + +/* FOR_STMT accessors. These give access to the init statement, + condition, update expression, and body of the for statement, + respectively. */ +#define FOR_INIT_STMT(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 0) +#define FOR_COND(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 1) +#define FOR_EXPR(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 2) +#define FOR_BODY(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 3) + +#define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0) +#define SWITCH_STMT_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1) +#define SWITCH_STMT_TYPE(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 2) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { none_type = 0, /* Not a tag type. */ diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index e799a8c..e185def 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1551,6 +1551,84 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t) } break; + case SWITCH_STMT: + pp_cxx_identifier (pp, "switch"); + pp_space (pp); + pp_cxx_left_paren (pp); + pp_expression (pp, SWITCH_STMT_COND (t)); + pp_cxx_right_paren (pp); + pp_indentation (pp) += 3; + pp_needs_newline (pp) = true; + pp_statement (pp, SWITCH_STMT_BODY (t)); + pp_newline_and_indent (pp, -3); + break; + + /* iteration-statement: + while ( expression ) statement + do statement while ( expression ) ; + for ( expression(opt) ; expression(opt) ; expression(opt) ) statement + for ( declaration expression(opt) ; expression(opt) ) statement */ + case WHILE_STMT: + pp_cxx_identifier (pp, "while"); + pp_space (pp); + pp_cxx_left_paren (pp); + pp_expression (pp, WHILE_COND (t)); + pp_cxx_right_paren (pp); + pp_newline_and_indent (pp, 3); + pp_statement (pp, WHILE_BODY (t)); + pp_indentation (pp) -= 3; + pp_needs_newline (pp) = true; + break; + + case DO_STMT: + pp_cxx_identifier (pp, "do"); + pp_newline_and_indent (pp, 3); + pp_statement (pp, DO_BODY (t)); + pp_newline_and_indent (pp, -3); + pp_cxx_identifier (pp, "while"); + pp_space (pp); + pp_cxx_left_paren (pp); + pp_expression (pp, DO_COND (t)); + pp_cxx_right_paren (pp); + pp_cxx_semicolon (pp); + pp_needs_newline (pp) = true; + break; + + case FOR_STMT: + pp_cxx_identifier (pp, "for"); + pp_space (pp); + pp_cxx_left_paren (pp); + if (FOR_INIT_STMT (t)) + pp_statement (pp, FOR_INIT_STMT (t)); + else + pp_cxx_semicolon (pp); + pp_needs_newline (pp) = false; + pp_cxx_whitespace (pp); + if (FOR_COND (t)) + pp_expression (pp, FOR_COND (t)); + pp_cxx_semicolon (pp); + pp_needs_newline (pp) = false; + pp_cxx_whitespace (pp); + if (FOR_EXPR (t)) + pp_expression (pp, FOR_EXPR (t)); + pp_cxx_right_paren (pp); + pp_newline_and_indent (pp, 3); + pp_statement (pp, FOR_BODY (t)); + pp_indentation (pp) -= 3; + pp_needs_newline (pp) = true; + break; + + /* jump-statement: + goto identifier; + continue ; + return expression(opt) ; */ + case BREAK_STMT: + case CONTINUE_STMT: + pp_identifier (pp, TREE_CODE (t) == BREAK_STMT ? "break" : "continue"); + pp_cxx_semicolon (pp); + pp_needs_newline (pp) = true; + break; + case CLEANUP_STMT: pp_cxx_identifier (pp, "try"); pp_newline_and_indent (pp, 2); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index acf8a85..c39ed7b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2369,9 +2369,16 @@ void pop_switch (void) { struct cp_switch *cs = switch_stack; + location_t switch_location; /* Emit warnings as needed. */ - c_do_switch_warnings (cs->cases, cs->switch_stmt); + if (EXPR_HAS_LOCATION (cs->switch_stmt)) + switch_location = EXPR_LOCATION (cs->switch_stmt); + else + switch_location = input_location; + c_do_switch_warnings (cs->cases, switch_location, + SWITCH_STMT_TYPE (cs->switch_stmt), + SWITCH_STMT_COND (cs->switch_stmt)); splay_tree_delete (cs->cases); switch_stack = switch_stack->next; diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 357435f..f653d3a 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -1,5 +1,6 @@ /* Tree-dumping functionality for intermediate representation. - Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by Mark Mitchell <mark@codesourcery.com> This file is part of GCC. @@ -423,6 +424,37 @@ cp_dump_tree (void* dump_info, tree t) dump_child ("else", ELSE_CLAUSE (t)); break; + case BREAK_STMT: + case CONTINUE_STMT: + dump_stmt (di, t); + break; + + case DO_STMT: + dump_stmt (di, t); + dump_child ("body", DO_BODY (t)); + dump_child ("cond", DO_COND (t)); + break; + + case FOR_STMT: + dump_stmt (di, t); + dump_child ("init", FOR_INIT_STMT (t)); + dump_child ("cond", FOR_COND (t)); + dump_child ("expr", FOR_EXPR (t)); + dump_child ("body", FOR_BODY (t)); + break; + + case SWITCH_STMT: + dump_stmt (di, t); + dump_child ("cond", SWITCH_STMT_COND (t)); + dump_child ("body", SWITCH_STMT_BODY (t)); + break; + + case WHILE_STMT: + dump_stmt (di, t); + dump_child ("cond", WHILE_COND (t)); + dump_child ("body", WHILE_BODY (t)); + break; + default: break; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 07f614b..e8240e8 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -834,7 +834,7 @@ finish_for_stmt (tree for_stmt) tree finish_break_stmt (void) { - return add_stmt (build_break_stmt ()); + return add_stmt (build_stmt (BREAK_STMT)); } /* Finish a continue-statement. */ @@ -842,7 +842,7 @@ finish_break_stmt (void) tree finish_continue_stmt (void) { - return add_stmt (build_continue_stmt ()); + return add_stmt (build_stmt (CONTINUE_STMT)); } /* Begin a switch-statement. Returns a new SWITCH_STMT if |