diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-04-09 03:18:18 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-04-09 03:18:18 +0000 |
commit | e7911019b785da4b45f6ed37b7b03227afa38661 (patch) | |
tree | 54b12532b3129c3528d3e2a058b89210eef0f85b | |
parent | 88dbf20f7cbfc296419f03e500ea15fd2161ded7 (diff) | |
download | gcc-e7911019b785da4b45f6ed37b7b03227afa38661.tar.gz |
./
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97885 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 34 | ||||
-rw-r--r-- | gcc/c-common.c | 52 | ||||
-rw-r--r-- | gcc/c-common.def | 22 | ||||
-rw-r--r-- | gcc/c-common.h | 31 | ||||
-rw-r--r-- | gcc/c-dump.c | 31 | ||||
-rw-r--r-- | gcc/c-gimplify.c | 269 | ||||
-rw-r--r-- | gcc/c-pretty-print.c | 78 | ||||
-rw-r--r-- | gcc/c-semantics.c | 16 | ||||
-rw-r--r-- | gcc/c-typeck.c | 9 | ||||
-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 |
17 files changed, 517 insertions, 497 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b7192f1b21..b2324c6906e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2005-04-08 Ian Lance Taylor <ian@airs.com> + + * 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. + 2005-04-08 Diego Novillo <dnovillo@redhat.com> Merge from tree-cleanup-branch: VRP, store CCP, store diff --git a/gcc/c-common.c b/gcc/c-common.c index f68c8532ebe..050a1eb9791 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3708,11 +3708,16 @@ match_case_to_enum (splay_tree_node node, void *data) return 0; } -/* Common code for -Wswitch*. */ +/* Handle -Wswitch*. Called from the front end after parsing the + switch construct. */ +/* ??? Should probably be somewhere generic, since other languages + besides C and C++ would want this. At the moment, however, C/C++ + are the only tree-ssa languages that support enumerations at all, + so the point is moot. */ -static void -c_do_switch_warnings_1 (splay_tree cases, location_t switch_location, - tree type, tree cond) +void +c_do_switch_warnings (splay_tree cases, location_t switch_location, + tree type, tree cond) { splay_tree_node default_node; @@ -3773,45 +3778,6 @@ c_do_switch_warnings_1 (splay_tree cases, location_t switch_location, } } -/* Handle -Wswitch* for a SWITCH_STMT. Called from the front end - after parsing the switch construct. */ -/* ??? Should probably be somewhere generic, since other languages besides - C and C++ would want this. We'd want to agree on the data structure, - however, which is a problem. Alternately, we operate on gimplified - switch_exprs, which I don't especially like. At the moment, however, - C/C++ are the only tree-ssa languages that support enumerations at all, - so the point is moot. */ - -void -c_do_switch_warnings (splay_tree cases, tree switch_stmt) -{ - location_t switch_location; - - if (EXPR_HAS_LOCATION (switch_stmt)) - switch_location = EXPR_LOCATION (switch_stmt); - else - switch_location = input_location; - c_do_switch_warnings_1 (cases, switch_location, - SWITCH_STMT_TYPE (switch_stmt), - SWITCH_STMT_COND (switch_stmt)); -} - -/* Like c_do_switch_warnings, but takes a SWITCH_EXPR rather than a - SWITCH_STMT. */ - -void -c_do_switch_expr_warnings (splay_tree cases, tree switch_expr) -{ - location_t switch_location; - - if (EXPR_HAS_LOCATION (switch_expr)) - switch_location = EXPR_LOCATION (switch_expr); - else - switch_location = input_location; - c_do_switch_warnings_1 (cases, switch_location, TREE_TYPE (switch_expr), - SWITCH_COND (switch_expr)); -} - /* Finish an expression taking the address of LABEL (an IDENTIFIER_NODE). Returns an expression for the address. */ diff --git a/gcc/c-common.def b/gcc/c-common.def index 8851aa3eaee..381fe4ef75c 100644 --- a/gcc/c-common.def +++ b/gcc/c-common.def @@ -33,28 +33,6 @@ DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", tcc_unary, 1) obtain the expression. */ DEFTREECODE (EXPR_STMT, "expr_stmt", tcc_expression, 1) -/* 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) - /* A STMT_EXPR represents a statement-expression. The STMT_EXPR_STMT is the statement given by the expression. */ DEFTREECODE (STMT_EXPR, "stmt_expr", tcc_expression, 1) diff --git a/gcc/c-common.h b/gcc/c-common.h index 453739a3fca..d2b9a4a9cbd 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -709,32 +709,10 @@ extern void finish_file (void); #define STATEMENT_LIST_HAS_LABEL(NODE) \ TREE_LANG_FLAG_3 (STATEMENT_LIST_CHECK (NODE)) -/* 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) - /* EXPR_STMT accessor. This gives the expression associated with an expression statement. */ #define EXPR_STMT_EXPR(NODE) TREE_OPERAND (EXPR_STMT_CHECK (NODE), 0) -/* 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) - /* STMT_EXPR accessor. */ #define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0) @@ -759,9 +737,7 @@ enum c_tree_code { #undef DEFTREECODE #define c_common_stmt_codes \ - EXPR_STMT, FOR_STMT, \ - WHILE_STMT, DO_STMT, \ - BREAK_STMT, CONTINUE_STMT, SWITCH_STMT + EXPR_STMT /* TRUE if a code represents a statement. The front end init langhook should take care of initialization of this array. */ @@ -796,8 +772,6 @@ extern void emit_local_var (tree); extern tree do_case (tree, tree); extern tree build_stmt (enum tree_code, ...); extern tree build_case_label (tree, tree, tree); -extern tree build_continue_stmt (void); -extern tree build_break_stmt (void); /* These functions must be defined by each front-end which implements a variant of the C language. They are used in c-common.c. */ @@ -820,8 +794,7 @@ extern int case_compare (splay_tree_key, splay_tree_key); extern tree c_add_case_label (splay_tree, tree, tree, tree, tree); -extern void c_do_switch_warnings (splay_tree, tree); -extern void c_do_switch_expr_warnings (splay_tree, tree); +extern void c_do_switch_warnings (splay_tree, location_t, tree, tree); extern tree build_function_call (tree, tree); diff --git a/gcc/c-dump.c b/gcc/c-dump.c index 6e0d5024644..09850e6c810 100644 --- a/gcc/c-dump.c +++ b/gcc/c-dump.c @@ -54,42 +54,11 @@ c_dump_tree (void *dump_info, tree t) dump_string (di, "bitfield"); 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 EXPR_STMT: dump_stmt (di, t); dump_child ("expr", EXPR_STMT_EXPR (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; - case STMT_EXPR: dump_child ("stmt", STMT_EXPR_STMT (t)); break; diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index fd4ac4ed560..bea288ea0e8 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -70,34 +70,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA walk back up, we check that they fit our constraints, and copy them into temporaries if not. */ -/* Local declarations. */ - -enum bc_t { bc_break = 0, bc_continue = 1 }; - -static struct c_gimplify_ctx -{ - /* For handling break and continue. */ - tree current_bc_label; - tree bc_id[2]; -} *ctxp; - -static void -push_context (void) -{ - gcc_assert (!ctxp); - ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx)); - ctxp->bc_id[bc_continue] = get_identifier ("continue"); - ctxp->bc_id[bc_break] = get_identifier ("break"); -} - -static void -pop_context (void) -{ - gcc_assert (ctxp && !ctxp->current_bc_label); - free (ctxp); - ctxp = NULL; -} - /* Gimplification of statement trees. */ /* Convert the tree representation of FNDECL from C frontend trees to @@ -132,9 +104,7 @@ c_genericize (tree fndecl) } /* Go ahead and gimplify for now. */ - push_context (); gimplify_function_tree (fndecl); - pop_context (); /* Dump the genericized tree IR. */ dump_function (TDI_generic, fndecl); @@ -248,225 +218,6 @@ gimplify_expr_stmt (tree *stmt_p) return GS_OK; } -/* 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 (); - DECL_NAME (label) = ctxp->bc_id[bc]; - TREE_CHAIN (label) = ctxp->current_bc_label; - ctxp->current_bc_label = 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 (tree label, tree body) -{ - gcc_assert (label == ctxp->current_bc_label); - - if (TREE_USED (label)) - { - tree t, sl = NULL; - - /* Clear the name so flow can delete the label. */ - DECL_NAME (label) = NULL_TREE; - t = build1 (LABEL_EXPR, void_type_node, label); - - append_to_statement_list (body, &sl); - append_to_statement_list (t, &sl); - body = sl; - } - - ctxp->current_bc_label = 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; - tree target_name = ctxp->bc_id[bc]; - - /* Look for the appropriate type of label. */ - for (label = ctxp->current_bc_label; - label; - label = TREE_CHAIN (label)) - if (DECL_NAME (label) == target_name) - break; - - 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); -} - -/* 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_c_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 (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 (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_c_loop. */ - -static enum gimplify_status -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_c_loop (FOR_COND (stmt), FOR_BODY (stmt), - FOR_EXPR (stmt), 1); - - return GS_ALL_DONE; -} - -/* Gimplify a WHILE_STMT node. */ - -static enum gimplify_status -gimplify_while_stmt (tree *stmt_p) -{ - tree stmt = *stmt_p; - *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt), - NULL_TREE, 1); - return GS_ALL_DONE; -} - -/* Gimplify a DO_STMT node. */ - -static enum gimplify_status -gimplify_do_stmt (tree *stmt_p) -{ - tree stmt = *stmt_p; - *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt), - NULL_TREE, 0); - return GS_ALL_DONE; -} - -/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ - -static enum gimplify_status -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 (break_block, *stmt_p); - return GS_ALL_DONE; -} - /* Gimplification of expression trees. */ /* Gimplify a C99 compound literal expression. This just means adding the @@ -515,29 +266,9 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED) case COMPOUND_LITERAL_EXPR: return gimplify_compound_literal_expr (expr_p, pre_p); - case FOR_STMT: - return gimplify_for_stmt (expr_p, pre_p); - - case WHILE_STMT: - return gimplify_while_stmt (expr_p); - - case DO_STMT: - return gimplify_do_stmt (expr_p); - - case SWITCH_STMT: - return gimplify_switch_stmt (expr_p); - case EXPR_STMT: return gimplify_expr_stmt (expr_p); - case CONTINUE_STMT: - *expr_p = build_bc_goto (bc_continue); - return GS_ALL_DONE; - - case BREAK_STMT: - *expr_p = build_bc_goto (bc_break); - return GS_ALL_DONE; - default: return GS_UNHANDLED; } diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index 2176e34850b..21af965b138 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -1965,84 +1965,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) pp_needs_newline (pp) = true; break; - case SWITCH_STMT: - pp_c_identifier (pp, "switch"); - pp_space (pp); - pp_c_left_paren (pp); - pp_expression (pp, SWITCH_COND (stmt)); - pp_c_right_paren (pp); - pp_indentation (pp) += 3; - pp_needs_newline (pp) = true; - pp_statement (pp, SWITCH_BODY (stmt)); - 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_c_identifier (pp, "while"); - pp_space (pp); - pp_c_left_paren (pp); - pp_expression (pp, WHILE_COND (stmt)); - pp_c_right_paren (pp); - pp_newline_and_indent (pp, 3); - pp_statement (pp, WHILE_BODY (stmt)); - pp_indentation (pp) -= 3; - pp_needs_newline (pp) = true; - break; - - case DO_STMT: - pp_c_identifier (pp, "do"); - pp_newline_and_indent (pp, 3); - pp_statement (pp, DO_BODY (stmt)); - pp_newline_and_indent (pp, -3); - pp_c_identifier (pp, "while"); - pp_space (pp); - pp_c_left_paren (pp); - pp_expression (pp, DO_COND (stmt)); - pp_c_right_paren (pp); - pp_c_semicolon (pp); - pp_needs_newline (pp) = true; - break; - - case FOR_STMT: - pp_c_identifier (pp, "for"); - pp_space (pp); - pp_c_left_paren (pp); - if (FOR_INIT_STMT (stmt)) - pp_statement (pp, FOR_INIT_STMT (stmt)); - else - pp_c_semicolon (pp); - pp_needs_newline (pp) = false; - pp_c_whitespace (pp); - if (FOR_COND (stmt)) - pp_expression (pp, FOR_COND (stmt)); - pp_c_semicolon (pp); - pp_needs_newline (pp) = false; - pp_c_whitespace (pp); - if (FOR_EXPR (stmt)) - pp_expression (pp, FOR_EXPR (stmt)); - pp_c_right_paren (pp); - pp_newline_and_indent (pp, 3); - pp_statement (pp, FOR_BODY (stmt)); - 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, code == BREAK_STMT ? "break" : "continue"); - pp_c_semicolon (pp); - pp_needs_newline (pp) = true; - break; - default: dump_generic_node (pp_base (pp), stmt, pp_indentation (pp), 0, true); break; diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 1acf6e89956..567a440706b 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -193,22 +193,6 @@ emit_local_var (tree decl) } } -/* Build a break statement node and return it. */ - -tree -build_break_stmt (void) -{ - return (build_stmt (BREAK_STMT)); -} - -/* Build a continue statement node and return it. */ - -tree -build_continue_stmt (void) -{ - return (build_stmt (CONTINUE_STMT)); -} - /* Create a CASE_LABEL_EXPR tree node and return it. */ tree diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 663dd7f351e..8c3996613e3 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -6728,13 +6728,20 @@ void c_finish_case (tree body) { struct c_switch *cs = c_switch_stack; + location_t switch_location; SWITCH_BODY (cs->switch_expr) = body; gcc_assert (!cs->blocked_stmt_expr); /* Emit warnings as needed. */ - c_do_switch_expr_warnings (cs->cases, cs->switch_expr); + if (EXPR_HAS_LOCATION (cs->switch_expr)) + switch_location = EXPR_LOCATION (cs->switch_expr); + else + switch_location = input_location; + c_do_switch_warnings (cs->cases, switch_location, + TREE_TYPE (cs->switch_expr), + SWITCH_COND (cs->switch_expr)); /* Pop the stack. */ c_switch_stack = cs->next; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 50c1f0c620c..c63486e39df 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 413a9338010..4d8880acb3b 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 b7c580ab5b8..674de59f7b5 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 1f773c0702a..3ab569f7b7b 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 e799a8c9a54..e185defa88e 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 acf8a85ada1..c39ed7b8a51 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 357435f1dcd..f653d3ab3e7 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 07f614bedd3..e8240e8b29d 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 |