PATCH RFA: Move tree codes used only by C++ frontend into cp/*

Ian Lance Taylor ian@airs.com
Wed Apr 6 03:33:00 GMT 2005


There are several tree codes currently defined in the common C/C++
code which are only used by C++.  These are the basic language
constructs, such as FOR_STMT, WHILE_STMT, etc.  The C frontend now
simply generates GENERIC for these cases.  The C++ frontend continues
to use these language specific codes.

This patch moves these codes out of the C/C++ common code into the C++
specific code.  The code in the C++ frontend is basically the same,
although since I had to rewrote the gimplification context slightly, I
simplified the handling of break and continue statements to make them
compile a bit faster.

There are actually more tree codes which could move into the cp
directory if this patch is accepted.  I haven't checked thoroughly,
but I suspect that the only non-GENERIC code which the C frontend
currently generates is COMPOUND_LITERAL_EXPR.

Tested with bootstrap and gcc and libstdc++-v3 testsuite runs on
i686-pc-linux-gnu.

OK for mainline?

Ian


ChangeLog:
2005-04-05  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.

cp/ChangeLog:

2005-04-05  Ian Lance Taylor  <ian@airs.com>

	* cp/cp-tree.def: Define FOR_STMT, WHILE_STMT, DO_STMT,
	BREAK_STMT, CONTINUE_STMT, SWITCH_STMT.
	* cp/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.


Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.619
diff -p -u -r1.619 c-common.c
--- c-common.c	5 Apr 2005 01:15:06 -0000	1.619
+++ c-common.c	6 Apr 2005 02:54:30 -0000
@@ -3708,11 +3708,16 @@ match_case_to_enum (splay_tree_node node
   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
     }
 }
 
-/* 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.  */
 
Index: c-common.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.def,v
retrieving revision 1.26
diff -p -u -r1.26 c-common.def
--- c-common.def	27 Jan 2005 18:22:19 -0000	1.26
+++ c-common.def	6 Apr 2005 02:54:30 -0000
@@ -33,28 +33,6 @@ DEFTREECODE (ALIGNOF_EXPR, "alignof_expr
    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)
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.281
diff -p -u -r1.281 c-common.h
--- c-common.h	5 Apr 2005 01:15:07 -0000	1.281
+++ c-common.h	6 Apr 2005 02:54:31 -0000
@@ -713,32 +713,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)
 
@@ -763,9 +741,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.  */
@@ -800,8 +776,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.  */
@@ -824,8 +798,7 @@ extern int case_compare (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);
 
Index: c-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-dump.c,v
retrieving revision 1.29
diff -p -u -r1.29 c-dump.c
--- c-dump.c	27 Jan 2005 18:22:19 -0000	1.29
+++ c-dump.c	6 Apr 2005 02:54:31 -0000
@@ -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;
Index: c-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-gimplify.c,v
retrieving revision 2.26
diff -p -u -r2.26 c-gimplify.c
--- c-gimplify.c	27 Jan 2005 18:22:19 -0000	2.26
+++ c-gimplify.c	6 Apr 2005 02:54:31 -0000
@@ -70,34 +70,6 @@ Software Foundation, 59 Temple Place - S
     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
     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;
     }
Index: c-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-pretty-print.c,v
retrieving revision 1.59
diff -p -u -r1.59 c-pretty-print.c
--- c-pretty-print.c	21 Feb 2005 14:39:46 -0000	1.59
+++ c-pretty-print.c	6 Apr 2005 02:54:31 -0000
@@ -1965,84 +1965,6 @@ pp_c_statement (c_pretty_printer *pp, tr
       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;
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.95
diff -p -u -r1.95 c-semantics.c
--- c-semantics.c	8 Mar 2005 12:48:53 -0000	1.95
+++ c-semantics.c	6 Apr 2005 02:54:31 -0000
@@ -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
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.430
diff -p -u -r1.430 c-typeck.c
--- c-typeck.c	5 Apr 2005 01:15:08 -0000	1.430
+++ c-typeck.c	6 Apr 2005 02:54:32 -0000
@@ -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;
Index: cp/cp-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-gimplify.c,v
retrieving revision 1.17
diff -p -u -r1.17 cp-gimplify.c
--- cp/cp-gimplify.c	22 Dec 2004 18:00:38 -0000	1.17
+++ cp/cp-gimplify.c	6 Apr 2005 02:54:34 -0000
@@ -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 - S
 #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 *pr
       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 ();
 }
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.94
diff -p -u -r1.94 cp-tree.def
--- cp/cp-tree.def	11 Feb 2005 16:28:37 -0000	1.94
+++ cp/cp-tree.def	6 Apr 2005 02:54:34 -0000
@@ -285,6 +285,28 @@ DEFTREECODE (CLEANUP_STMT, "cleanup_stmt
    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.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1116
diff -p -u -r1.1116 cp-tree.h
--- cp/cp-tree.h	1 Apr 2005 08:29:50 -0000	1.1116
+++ cp/cp-tree.h	6 Apr 2005 02:54:35 -0000
@@ -844,8 +844,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.  */
@@ -2947,6 +2948,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.  */
Index: cp/cxx-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cxx-pretty-print.c,v
retrieving revision 1.29
diff -p -u -r1.29 cxx-pretty-print.c
--- cp/cxx-pretty-print.c	8 Feb 2005 14:46:52 -0000	1.29
+++ cp/cxx-pretty-print.c	6 Apr 2005 02:54:35 -0000
@@ -1551,6 +1551,84 @@ pp_cxx_statement (cxx_pretty_printer *pp
 	}
       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);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1382
diff -p -u -r1.1382 decl.c
--- cp/decl.c	30 Mar 2005 01:35:11 -0000	1.1382
+++ cp/decl.c	6 Apr 2005 02:54:37 -0000
@@ -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;
Index: cp/dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/dump.c,v
retrieving revision 1.81
diff -p -u -r1.81 dump.c
--- cp/dump.c	15 Oct 2004 14:49:30 -0000	1.81
+++ cp/dump.c	6 Apr 2005 02:54:37 -0000
@@ -423,6 +423,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;
     }
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.466
diff -p -u -r1.466 semantics.c
--- cp/semantics.c	30 Mar 2005 01:35:15 -0000	1.466
+++ cp/semantics.c	6 Apr 2005 02:54:38 -0000
@@ -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



More information about the Gcc-patches mailing list