This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[Patch] Separation of code to generate RTL in C++


This is the third patch that will move us towards using the C++ tree
representation in C as well as C++.  Eventually, the C front-end will work
like the C++ front-end, using function-at-a-time processing.  We want to
share as much code as possible between the two front-ends. These changes
were tested on i686-pc-linux-gnu. They split functions in cp/semantics.c
that previously were called to build the tree and generate the RTL. Now
the functions are only used to build the tree and new functions generate
the RTL. This patch also adds documentation to the nodes and their
accessors found in c-common.def and c-common.h.

This patch has been approved by Mark Mitchell.

Benjamin Chelf
chelf@codesourcery.com
CodeSourcery, LLC

2000-06-19  Benjamin Chelf  <chelf@codesourcery.com>

	* c-common.h (IF_COND): Added documentation.
	(THEN_CLAUSE): Likewise.
	(ELSE_CLAUSE): Likewise.
	(WHILE_COND): Likewise.
	(WHILE_BODY): Likewise.
	(DO_COND): Likewise.
	(DO_BODY): Likewise.
	(RETURN_EXPR): Likewise.
	(EXPR_STMT_EXPR): Likewise.
	(FOR_INIT_STMT): Likewise.
	(FOR_COND): Likewise.
	(FOR_EXPR): Likewise.
	(FOR_BODY): Likewise.
	(SWITCH_COND): Likewise.
	(SWITCH_BODY): Likewise.
	(CASE_LOW): Likewise.
	(CASE_HIGH): Likewise.
	(GOTO_DESTINATION): Likewise.
	(COMPOUND_BODY): Likewise.
	(ASM_CV_QUAL): Likewise.
	(ASM_STRING): Likewise.
	(ASM_OUTPUTS): Likewise.
	(ASM_INPUTS): Likewise.
	(ASM_CLOBBERS): Likewise.
	(DECL_STMT_DECL): Likewise.
	(STMT_EXPR_STMT): Likewise.
	(LABEL_STMT_LABEL): Likewise.

	* c-common.def: Added documenetion for SRCLOC, EXPR_STMT, 
	COMPOUND_STMT, DECL_STMT, IF_STMT, FOR_STMT, WHILE_STMT, DO_STMT, 
	RETURN_STMT, BREAK_STMT, CONTINUE_STMT, SWITCH_STMT, GOTO_STMT, 
	LABEL_STMT, ASM_STMT, SCOPE_STMT, CASE_LABEL, STMT_EXPR.

	* cp/cp-tree.h (genrtl_try_block): Declare function.
	(genrtl_handler): Likewise.
	(genrtl_catch_block): Likewise.
	(genrtl_ctor_stmt): Likewise.
	(genrtl_subobject): Likewise.
	(genrtl_decl_cleanup): Likewise.
	(genrtl_do_poplevel): Likewise.
	(genrtl_do_pushlevel): Likewise.
	(genrtl_clear_out_block): Likewise.
	(genrtl_goto_stmt): Likewise.
	(genrtl_expr_stmt): Likewise.
	(genrtl_decl_stmt): Likewise.
	(genrtl_if_stmt): Likewise.
	(genrtl_while_stmt): Likewise.
	(genrtl_do_stmt): Likewise.
	(genrtl_return_stmt): Likewise.
	(genrtl_for_stmt): Likewise.
	(genrtl_break_stmt): Likewise.
	(genrtl_continue_stmt): Likewise.
	(genrtl_scope_stmt): Likewise.
	(genrtl_switch_stmt): Likewise.
	(genrtl_case_label): Likewise.
	(genrtl_begin_compound_stmt): Likewise.
	(genrtl_finish_compound_stmt): Likewise.
	(genrtl_compound_stmt): Likewise.
	(genrtl_asm_stmt): Likewise.
	(genrtl_named_return_value): Likewise.
	(genrtl_begin_stmt_expr): Likewise.
	(genrtl_finish_stmt_expr): Likewise.
	(finish_for_stmt): Removed first argument.
	(finish_switch_stmt): Likewise.

	* cp/semantics.c (genrtl_try_block): Define function.
	(genrtl_handler): Likewise.
	(genrtl_catch_block): Likewise.
	(genrtl_ctor_stmt): Likewise.
	(genrtl_subobject): Likewise.
	(genrtl_decl_cleanup): Likewise.
	(genrtl_do_poplevel): Likewise.
	(genrtl_do_pushlevel): Likewise.
	(genrtl_clear_out_block): Likewise.
	(genrtl_goto_stmt): Likewise.
	(genrtl_expr_stmt): Likewise.
	(genrtl_decl_stmt): Likewise.
	(genrtl_if_stmt): Likewise.
	(genrtl_while_stmt): Likewise.
	(genrtl_do_stmt): Likewise.
	(genrtl_return_stmt): Likewise.
	(genrtl_for_stmt): Likewise.
	(genrtl_break_stmt): Likewise.
	(genrtl_continue_stmt): Likewise.
	(genrtl_scope_stmt): Likewise.
	(genrtl_switch_stmt): Likewise.
	(genrtl_case_label): Likewise.
	(genrtl_begin_compound_stmt): Likewise.
	(genrtl_finish_compound_stmt): Likewise.
	(genrtl_compound_stmt): Likewise.
	(genrtl_asm_stmt): Likewise.
	(genrtl_named_return_value): Likewise.
	(genrtl_begin_stmt_expr): Likewise.
	(genrtl_finish_stmt_expr): Likewise.
	(finish_for_stmt): Removed first argument and generate rtl 
	specific code.
	(finish_switch_stmt): Likewise.
	(do_poplevel): Removed generate rtl specific code.
	(do_pushlevel): Likewise.
	(add_tree): Likewise.
	(finish_goto_stmt): Likewise.
	(finish_expr_stmt): Likewise.
	(begin_if_stmt): Likewise.
	(finish_if_stmt_cond): Likewise.
	(finish_then_clause): Likewise.
	(begin_else_clause): Likewise.
	(finish_else_clause): Likewise.
	(finish_if_stmt): Likewise.
	(clear_out_block): Likewise.
	(begin_while_stmt): Likewise.
	(finish_while_stmt_cond): Likewise.
	(finish_while_stmt): Likewise.
	(begin_do_stmt): Likewise.
	(finish_do_body): Likewise.
	(finish_do_stmt): Likewise.
	(finish_return_stmt): Likewise.
	(begin_for_stmt): Likewise.
	(finish_for_init_stmt): Likewise.
	(finish_for_cond): Likewise.
	(finish_for_expr): Likewise.
	(finish_break_stmt): Likewise.
	(finish_continue_stmt): Likewise.
	(begin_switch_stmt): Likewise.
	(finish_switch_cond): Likewise.
	(finish_case_label): Likewise.
	(begin_try_block): Likewise.
	(begin_function_try_block): Likewise.
	(finish_try_block): Likewise.
	(finish_cleanup_try_block): Likewise.
	(finish_cleanup): Likewise.
	(finish_function_try_block): Likewise.
	(finish_handler_sequence): Likewise.
	(finish_function_handler_sequence): Likewise.
	(begin_handler): Likewise.
	(finish_handler_parms): Likewise.
	(begin_catch_block): Likewise.
	(finish_handler): Likewise.
	(begin_compound_stmt): Likewise.
	(finish_compound_stmt): Likewise.
	(finish_asm_stmt): Likewise.
	(finish_label_stmt): Likewise.
	(finish_label_decl): Likewise.
	(finish_subobject): Likewise.
	(finish_decl_cleanup): Likewise.
	(finish_named_return_value): Likewise.
	(begin_stmt_expr): Likewise.
	(finish_stmt_expr): Likewise.
	
	* cp/decl.c (initialize_local_var): Changed call to finish_expr_stmt
	to call genrtl_expr_stmt when appropriate.

	* cp/init.c (begin_init_stmts): Changed calls to begin_stmt_expr and
	begin_compound_expr to call genrtl_begin_stmt_expr and
	genrtl_begin_compound_expr when appropriate.
	(finish_init_stmts): Changed calls to finish_compound_expr and
	finish_stmt_expr to call genrtl_finish_compound_expr and
	genrtl_finish_stmt_expr when appropriate.
	(expand_default_init): Changed call to finish_expr_stmt to call
	genrtl_expr_stmt when appropriate.
	(build_vec_init): Likewise.

	* cp/parse.y (simple_stmt): Removed first argument from call to 
	finish_for_stmt. Removed first argument from call to 
	finish_switch_stmt.

	* cp/parse.c: Regenerated.

	* cp/pt.c (tsubst_expr): Removed first argument from call to 
	finish_for_stmt. Removed first argument from call to 
	finish_switch_stmt.

Index: c-common.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.def,v
retrieving revision 1.1
diff -c -p -r1.1 c-common.def
*** c-common.def	2000/06/14 17:26:15	1.1
--- c-common.def	2000/06/19 18:24:22
*************** cp-tree.def in the cp subdir. */
*** 28,52 ****
  /* A node to remember a source position.  */
  DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
  
- /* A whole bunch of tree codes for the initial, superficial parsing of
-    templates.  */
  DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1)
  DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
  DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
  
  DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
  DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
  DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
  DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
  DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
  DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
  DEFTREECODE (DO_STMT, "do_stmt", 'e', 2)
  DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1)
  DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
  DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
  DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
  DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
  DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
  DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
  
  /* A SCOPE_STMT marks the beginning or end of a scope.  If
--- 28,87 ----
  /* A node to remember a source position.  */
  DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
  
  DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1)
  DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
  DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
  
+ /* Used to represent an expression statement.  Use `EXPR_STMT_EXPR' to
+    obtain the expression. */
  DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
+ 
+ /* Used to represent a brace-enclosed block.  The operand is
+    COMPOUND_BODY. */ 
  DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
+ 
+ /* Used to represent a local declaration. The operand is
+    DECL_STMT_DECL. */
  DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
+ 
+ /* Represents an 'if' statement. The operands are IF_COND,
+    THEN_CLAUSE, and ELSE_CLAUSE, respectively. */
  DEFTREECODE (IF_STMT, "if_stmt", 'e', 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", 'e', 4)
+ 
+ /* Used to represent a 'while' statement. The operands are WHILE_COND
+    and WHILE_BODY, respectively. */
  DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
+ 
+ /* Used to represent a 'do' statement. The operands are DO_BODY and
+    DO_COND, respectively. */
  DEFTREECODE (DO_STMT, "do_stmt", 'e', 2)
+ 
+ /* Used to represent a 'return' statement. The operand is
+    RETURN_EXPR. */
  DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1)
+ 
+ /* Used to represent a 'break' statement. */
  DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
+ 
+ /* Used to represent a 'continue' statement. */
  DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
+ 
+ /* Used to represent a 'switch' statement. The operands are
+    SWITCH_COND and SWITCH_BODY, respectively. */
  DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
+ 
+ /* Used to represent a 'goto' statement. The operand is GOTO_DESTINATION. */
  DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
+ 
+ /* Used to represent a 'label' statement. The operand is a LABEL_DECL
+    and can be obtained through the macro LABEL_STMT_LABEL. */
  DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
+ 
+ /* Used to represent an inline assembly statement. */
  DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
  
  /* A SCOPE_STMT marks the beginning or end of a scope.  If
*************** DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 
*** 56,61 ****
--- 91,101 ----
     this scope.  The SCOPE_STMT_BLOCK is the BLOCK containing the
     variables declared in this scope.  */
  DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 1)
+ 
+ /* Used to represent a CASE_LABEL. The operands are CASE_LOW and
+    CASE_HIGH, respectively. If CASE_LOW is NULL_TREE, the label is a
+    'default' label. If CASE_HIGH is NULL_TREE, the label is a normal case
+    label. */
  DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
  
  /* A STMT_EXPR represents a statement-expression.  The
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.17
diff -c -p -r1.17 c-common.h
*** c-common.h	2000/06/17 02:37:21	1.17
--- c-common.h	2000/06/19 18:24:22
*************** extern tree simple_type_promotes_to		PAR
*** 167,198 ****
--- 167,245 ----
  
  /* These macros provide convenient access to the various _STMT nodes
     created when parsing template declarations.  */
+ 
+ /* IF_STMT accessors. These give access to the condtion of the if
+    statement, the then block of the if statement, and the else block
+    of the if stsatement if it exists. */
  #define IF_COND(NODE)           TREE_OPERAND (IF_STMT_CHECK (NODE), 0)
  #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 condtion 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)
+ 
+ /* RETURN_STMT accessor. This gives the expression associated with a
+    return statement. */
  #define RETURN_EXPR(NODE)       TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
+ 
+ /* 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)
+ 
+ /* SWITCH_STMT accessors. These give access to the condition and body
+    of the switch statement, respectively. */
  #define SWITCH_COND(NODE)       TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
  #define SWITCH_BODY(NODE)       TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
+ 
+ /* CASE_LABEL accessors. These give access to the high and low values
+    of a case label, respectively. */
  #define CASE_LOW(NODE)          TREE_OPERAND (CASE_LABEL_CHECK (NODE), 0)
  #define CASE_HIGH(NODE)         TREE_OPERAND (CASE_LABEL_CHECK (NODE), 1)
+ 
+ /* GOTO_STMT accessor. This gives access to the label associated with
+    a goto statement. */
  #define GOTO_DESTINATION(NODE)  TREE_OPERAND (GOTO_STMT_CHECK (NODE), 0)
+ 
+ /* COMPOUND_STMT accessor. This gives access to the TREE_LIST of
+    statements assocated with a compound statement. The result is the
+    first statement in the list. Succeeding nodes can be acccessed by
+    calling TREE_CHAIN on a node in the list. */
  #define COMPOUND_BODY(NODE)     TREE_OPERAND (COMPOUND_STMT_CHECK (NODE), 0)
+ 
+ /* ASM_STMT accessors. ASM_STRING returns a STRING_CST for the
+    instruction (e.g., "mov x, y"). ASM_OUTPUTS, ASM_INPUTS, and
+    ASM_CLOBBERS represent the outputs, inputs, and clobbers for the
+    statement. */
  #define ASM_CV_QUAL(NODE)       TREE_OPERAND (ASM_STMT_CHECK (NODE), 0)
  #define ASM_STRING(NODE)        TREE_OPERAND (ASM_STMT_CHECK (NODE), 1)
  #define ASM_OUTPUTS(NODE)       TREE_OPERAND (ASM_STMT_CHECK (NODE), 2)
  #define ASM_INPUTS(NODE)        TREE_OPERAND (ASM_STMT_CHECK (NODE), 3)
  #define ASM_CLOBBERS(NODE)      TREE_OPERAND (ASM_STMT_CHECK (NODE), 4)
+ 
+ /* DECL_STMT accessor. This gives access to the DECL associated with
+    the given declaration statement. */ 
  #define DECL_STMT_DECL(NODE)    TREE_OPERAND (DECL_STMT_CHECK (NODE), 0)
+ 
+ /* STMT_EXPR accessor. */
  #define STMT_EXPR_STMT(NODE)    TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0)
+ 
+ /* LABEL_STMT accessor. This gives access to the label associated with
+    the given label statement. */
  #define LABEL_STMT_LABEL(NODE)  TREE_OPERAND (LABEL_STMT_CHECK (NODE), 0)
  
  /* Nonzero if this SCOPE_STMT is for the beginning of a scope.  */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.485
diff -c -p -r1.485 cp-tree.h
*** cp-tree.h	2000/06/17 02:37:23	1.485
--- cp-tree.h	2000/06/19 18:24:51
*************** extern tree begin_for_stmt              
*** 4406,4417 ****
  extern void finish_for_init_stmt                PARAMS ((tree));
  extern void finish_for_cond                     PARAMS ((tree, tree));
  extern void finish_for_expr                     PARAMS ((tree, tree));
! extern void finish_for_stmt                     PARAMS ((tree, tree));
  extern void finish_break_stmt                   PARAMS ((void));
  extern void finish_continue_stmt                PARAMS ((void));
  extern tree begin_switch_stmt                   PARAMS ((void));
  extern void finish_switch_cond                  PARAMS ((tree, tree));
! extern void finish_switch_stmt                  PARAMS ((tree, tree));
  extern void finish_case_label                   PARAMS ((tree, tree));
  extern void finish_goto_stmt                    PARAMS ((tree));
  extern tree begin_try_block                     PARAMS ((void));
--- 4406,4417 ----
  extern void finish_for_init_stmt                PARAMS ((tree));
  extern void finish_for_cond                     PARAMS ((tree, tree));
  extern void finish_for_expr                     PARAMS ((tree, tree));
! extern void finish_for_stmt                     PARAMS ((tree));
  extern void finish_break_stmt                   PARAMS ((void));
  extern void finish_continue_stmt                PARAMS ((void));
  extern tree begin_switch_stmt                   PARAMS ((void));
  extern void finish_switch_cond                  PARAMS ((tree, tree));
! extern void finish_switch_stmt                  PARAMS ((tree));
  extern void finish_case_label                   PARAMS ((tree, tree));
  extern void finish_goto_stmt                    PARAMS ((tree));
  extern tree begin_try_block                     PARAMS ((void));
*************** extern tree add_scope_stmt              
*** 4479,4484 ****
--- 4479,4518 ----
  extern void do_pushlevel                        PARAMS ((void));
  extern tree do_poplevel                         PARAMS ((void));
  extern void finish_mem_initializers             PARAMS ((tree));
+ 
+ extern void genrtl_try_block                    PARAMS ((tree));
+ extern void genrtl_handler                      PARAMS ((tree));
+ extern void genrtl_catch_block                  PARAMS ((tree));
+ extern void genrtl_ctor_stmt                    PARAMS ((tree));
+ extern void genrtl_subobject                    PARAMS ((tree));
+ extern void genrtl_decl_cleanup                 PARAMS ((tree, tree));
+ extern tree genrtl_do_poplevel                  PARAMS ((void));
+ extern void genrtl_do_pushlevel                 PARAMS ((void));
+ extern void genrtl_clear_out_block              PARAMS ((void));
+ extern void genrtl_goto_stmt                    PARAMS ((tree));
+ extern void genrtl_expr_stmt                    PARAMS ((tree));
+ extern void genrtl_decl_stmt                    PARAMS ((tree));
+ extern void genrtl_if_stmt                      PARAMS ((tree));
+ extern void genrtl_while_stmt                   PARAMS ((tree));
+ extern void genrtl_do_stmt                      PARAMS ((tree));
+ extern void genrtl_return_stmt                  PARAMS ((tree));
+ extern void genrtl_for_stmt                     PARAMS ((tree));
+ extern void genrtl_break_stmt                   PARAMS ((void));
+ extern void genrtl_continue_stmt                PARAMS ((void));
+ extern void genrtl_scope_stmt                   PARAMS ((tree));
+ extern void genrtl_switch_stmt                  PARAMS ((tree));
+ extern void genrtl_case_label                   PARAMS ((tree, tree));
+ extern tree genrtl_begin_compound_stmt          PARAMS ((int));
+ extern tree genrtl_finish_compound_stmt         PARAMS ((int));
+ extern tree genrtl_compound_stmt                PARAMS ((tree));
+ extern void genrtl_asm_stmt                     PARAMS ((tree, tree,
+ 							 tree, tree,
+ 							 tree));
+ extern void genrtl_named_return_value           PARAMS ((tree,
+ 							 tree));
+ extern tree genrtl_begin_stmt_expr              PARAMS ((void));
+ extern tree genrtl_finish_stmt_expr             PARAMS ((tree));
+ 
  
  /* in spew.c */
  extern void init_spew				PARAMS ((void));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.637
diff -c -p -r1.637 decl.c
*** decl.c	2000/06/16 07:34:41	1.637
--- decl.c	2000/06/19 18:25:26
*************** initialize_local_var (decl, init, flags)
*** 7980,7986 ****
  			  DECL_SOURCE_LINE (decl));
  	  saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
  	  stmts_are_full_exprs_p = 1;
! 	  finish_expr_stmt (build_aggr_init (decl, init, flags));
  	  stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
  	}
  
--- 7980,7989 ----
  			  DECL_SOURCE_LINE (decl));
  	  saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
  	  stmts_are_full_exprs_p = 1;
! 	  if (building_stmt_tree ())
! 	    finish_expr_stmt (build_aggr_init (decl, init, flags));
! 	  else
! 	    genrtl_expr_stmt (build_aggr_init (decl, init, flags));
  	  stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
  	}
  
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.201
diff -c -p -r1.201 init.c
*** init.c	2000/06/16 07:34:42	1.201
--- init.c	2000/06/19 18:25:29
*************** begin_init_stmts (stmt_expr_p, compound_
*** 97,104 ****
       tree *stmt_expr_p;
       tree *compound_stmt_p;
  {
!   *stmt_expr_p = begin_stmt_expr ();
!   *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
  }
  
  /* Finish out the statement-expression begun by the previous call to
--- 97,111 ----
       tree *stmt_expr_p;
       tree *compound_stmt_p;
  {
!   if (building_stmt_tree ())
!     *stmt_expr_p = begin_stmt_expr ();
!   else
!     *stmt_expr_p = genrtl_begin_stmt_expr ();
!   
!   if (building_stmt_tree ())
!     *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
!   else
!     *compound_stmt_p = genrtl_begin_compound_stmt (/*has_no_scope=*/1);
  }
  
  /* Finish out the statement-expression begun by the previous call to
*************** tree
*** 108,117 ****
  finish_init_stmts (stmt_expr, compound_stmt)
       tree stmt_expr;
       tree compound_stmt;
- {
-   finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
-   stmt_expr = finish_stmt_expr (stmt_expr);
  
    /* To avoid spurious warnings about unused values, we set 
       TREE_USED.  */
    if (stmt_expr)
--- 115,132 ----
  finish_init_stmts (stmt_expr, compound_stmt)
       tree stmt_expr;
       tree compound_stmt;
  
+ {  
+   if (building_stmt_tree ())
+     finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+   else
+     genrtl_finish_compound_stmt (/*has_no_scope=*/1);
+   
+   if (building_stmt_tree ())
+     stmt_expr = finish_stmt_expr (stmt_expr);
+   else
+     stmt_expr = genrtl_finish_stmt_expr (stmt_expr);
+   
    /* To avoid spurious warnings about unused values, we set 
       TREE_USED.  */
    if (stmt_expr)
*************** expand_default_init (binfo, true_exp, ex
*** 1297,1303 ****
  
    rval = build_method_call (exp, ctor_name, parms, binfo, flags);
    if (TREE_SIDE_EFFECTS (rval))
!     finish_expr_stmt (rval);
  }
  
  /* This function is responsible for initializing EXP with INIT
--- 1312,1323 ----
  
    rval = build_method_call (exp, ctor_name, parms, binfo, flags);
    if (TREE_SIDE_EFFECTS (rval))
!     {
!       if (building_stmt_tree ())
! 	finish_expr_stmt (rval);
!       else
! 	genrtl_expr_stmt (rval);
!     }
  }
  
  /* This function is responsible for initializing EXP with INIT
*************** build_vec_init (decl, base, maxindex, in
*** 2988,2994 ****
  	 full-expression.  */
        if (!building_stmt_tree ())
  	{
! 	  finish_expr_stmt (elt_init);
  	  expand_end_target_temps ();
  	}
        else
--- 3008,3014 ----
  	 full-expression.  */
        if (!building_stmt_tree ())
  	{
! 	  genrtl_expr_stmt (elt_init);
  	  expand_end_target_temps ();
  	}
        else
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.176
diff -c -p -r1.176 parse.y
*** parse.y	2000/06/16 15:35:10	1.176
--- parse.y	2000/06/19 18:25:36
*************** simple_stmt:
*** 3294,3306 ****
  	  xexpr ')'
                  { finish_for_expr ($9, $<ttype>2); }
  	  already_scoped_stmt
!                 { finish_for_stmt ($9, $<ttype>2); }
  	| SWITCH 
                  { $<ttype>$ = begin_switch_stmt (); }
  	    '(' condition ')'
                  { finish_switch_cond ($4, $<ttype>2); }
  	  implicitly_scoped_stmt
!                 { finish_switch_stmt ($4, $<ttype>2); }
  	| CASE expr_no_commas ':'
                  { finish_case_label ($2, NULL_TREE); }
  	  stmt
--- 3294,3306 ----
  	  xexpr ')'
                  { finish_for_expr ($9, $<ttype>2); }
  	  already_scoped_stmt
!                 { finish_for_stmt ($<ttype>2); }
  	| SWITCH 
                  { $<ttype>$ = begin_switch_stmt (); }
  	    '(' condition ')'
                  { finish_switch_cond ($4, $<ttype>2); }
  	  implicitly_scoped_stmt
!                 { finish_switch_stmt ($<ttype>2); }
  	| CASE expr_no_commas ':'
                  { finish_case_label ($2, NULL_TREE); }
  	  stmt
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.441
diff -c -p -r1.441 pt.c
*** pt.c	2000/06/16 07:34:51	1.441
--- pt.c	2000/06/19 18:25:42
*************** tsubst_expr (t, args, complain, in_decl)
*** 7215,7221 ****
  	tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
  	finish_for_expr (tmp, stmt);
  	tsubst_expr (FOR_BODY (t), args, complain, in_decl);
! 	finish_for_stmt (tmp, stmt);
        }
        break;
  
--- 7215,7221 ----
  	tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
  	finish_for_expr (tmp, stmt);
  	tsubst_expr (FOR_BODY (t), args, complain, in_decl);
! 	finish_for_stmt (stmt);
        }
        break;
  
*************** tsubst_expr (t, args, complain, in_decl)
*** 7303,7309 ****
  	val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
  	finish_switch_cond (val, stmt);
  	tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
! 	finish_switch_stmt (val, stmt);
        }
        break;
  
--- 7303,7309 ----
  	val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
  	finish_switch_cond (val, stmt);
  	tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
! 	finish_switch_stmt (stmt);
        }
        break;
  
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.150
diff -c -p -r1.150 semantics.c
*** semantics.c	2000/06/16 15:35:10	1.150
--- semantics.c	2000/06/19 18:25:44
*************** static void deferred_type_access_control
*** 86,92 ****
      else						\
        substmt = cond;					\
    } while (0)
!   
  /* T is a statement.  Add it to the statement-tree.  */
  
  void
--- 86,184 ----
      else						\
        substmt = cond;					\
    } while (0)
! 
! /* Finish a scope.  */
! 
! tree
! do_poplevel ()
! {
!   tree block = NULL_TREE;
! 
!   if (stmts_are_full_exprs_p)
!     {
!       tree scope_stmts;
! 
!       if (!processing_template_decl)
! 	scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
! 
!       block = poplevel (kept_level_p (), 1, 0);
!       if (block && !processing_template_decl)
! 	{
! 	  SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
! 	  SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
! 	}
!     }
! 
!   return block;
! }
! 
! /* Begin a new scope.  */ 
! 
! void
! do_pushlevel ()
! {
!   if (stmts_are_full_exprs_p)
!     {
!       pushlevel (0);
!       if (!processing_template_decl)
! 	add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
!     }
! }
! 
! /* Helper for generating the RTL at the end of a scope. */
! 
! tree
! genrtl_do_poplevel ()
! {
!   tree block = NULL_TREE;
! 
!   if (stmts_are_full_exprs_p)
!     {
!       tree scope_stmts;
!       scope_stmts = NULL_TREE;
! 
!       block = poplevel (kept_level_p (), 1, 0);
!       if (block && !processing_template_decl)
! 	{
! 	  SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
! 	  SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
! 	}
!     }
! 
!   return block;
! }
! 
! /* Helper for generating the RTL at the beginning of a scope. */
! 
! void
! genrtl_do_pushlevel ()
! {
!   emit_line_note (input_filename, lineno);
!   clear_last_expr ();
! 
!   if (stmts_are_full_exprs_p)
!     {
!       pushlevel (0); // Try to get rid of me.
!       if (!cfun->x_whole_function_mode_p)
! 	my_friendly_abort (19991129);
!     }
! }
! 
! /* Helper for generating the RTL. */
! 
! void
! genrtl_clear_out_block ()
! {
!   /* If COND wasn't a declaration, clear out the
!      block we made for it and start a new one here so the
!      optimization in expand_end_loop will work.  */
!   if (getdecls () == NULL_TREE)
!     {
!       genrtl_do_poplevel ();
!       genrtl_do_pushlevel ();
!     }
! }
! 
  /* T is a statement.  Add it to the statement-tree.  */
  
  void
*************** add_tree (t)
*** 96,106 ****
    /* Add T to the statement-tree.  */
    TREE_CHAIN (last_tree) = t;
    SET_LAST_STMT (t);
- 
    /* When we expand a statement-tree, we must know whether or not the
       statements are full-expresions.  We record that fact here.  */
!   if (building_stmt_tree ())
!     STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p;
  }
  
  /* COND is the condition-expression for an if, while, etc.,
--- 188,247 ----
    /* Add T to the statement-tree.  */
    TREE_CHAIN (last_tree) = t;
    SET_LAST_STMT (t);
    /* When we expand a statement-tree, we must know whether or not the
       statements are full-expresions.  We record that fact here.  */
!   STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p;
! }
! 
! /* Finish a goto-statement.  */
! 
! void
! finish_goto_stmt (destination)
!      tree destination;
! {
!   if (TREE_CODE (destination) == IDENTIFIER_NODE)
!     destination = lookup_label (destination);
! 
!   /* We warn about unused labels with -Wunused.  That means we have to
!      mark the used labels as used.  */
!   if (TREE_CODE (destination) == LABEL_DECL)
!     TREE_USED (destination) = 1;
!     
!   if (TREE_CODE (destination) != LABEL_DECL)
!     /* We don't inline calls to functions with computed gotos.
!        Those functions are typically up to some funny business,
!        and may be depending on the labels being at particular
!        addresses, or some such.  */
!     DECL_UNINLINABLE (current_function_decl) = 1;
!   
!   check_goto (destination);
! 
!   add_tree (build_min_nt (GOTO_STMT, destination));
! }
! 
! /* Generate the RTL for DESTINATION, which is a GOTO_STMT. */
! 
! void
! genrtl_goto_stmt (destination)
!      tree destination;
! {
!   if (TREE_CODE (destination) == IDENTIFIER_NODE)
!     destination = lookup_label (destination);
! 
!   /* We warn about unused labels with -Wunused.  That means we have to
!      mark the used labels as used.  */
!   if (TREE_CODE (destination) == LABEL_DECL)
!     TREE_USED (destination) = 1;
!     
!   emit_line_note (input_filename, lineno);
!   
!   if (TREE_CODE (destination) == LABEL_DECL)
!     {
!       label_rtx (destination);
!       expand_goto (destination); 
!     }
!   else
!     expand_computed_goto (destination);
  }
  
  /* COND is the condition-expression for an if, while, etc.,
*************** finish_expr_stmt (expr)
*** 131,167 ****
  {
    if (expr != NULL_TREE)
      {
!       if (building_stmt_tree ())
! 	{
! 	  /* Do default conversion if safe and possibly important,
! 	     in case within ({...}).  */
! 	  if (!processing_template_decl
! 	      && !stmts_are_full_exprs_p
! 	      && ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
! 		   && lvalue_p (expr))
! 		  || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
! 	    expr = default_conversion (expr);
! 
! 	  if (stmts_are_full_exprs_p)
! 	    expr = convert_to_void (expr, "statement");
  
! 	  if (!processing_template_decl)
! 	    expr = break_out_cleanups (expr);
  
! 	  add_tree (build_min_nt (EXPR_STMT, expr));
! 	}
!       else
! 	{
! 	  emit_line_note (input_filename, lineno);
  
! 	  if (stmts_are_full_exprs_p)
! 	    expand_start_target_temps ();
! 	    
! 	  cplus_expand_expr_stmt (expr);
  
! 	  if (stmts_are_full_exprs_p)
! 	    expand_end_target_temps ();
! 	}
      }
  
    finish_stmt ();
--- 272,317 ----
  {
    if (expr != NULL_TREE)
      {
!       if (!processing_template_decl
! 	  && !stmts_are_full_exprs_p
! 	  && ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
! 	       && lvalue_p (expr))
! 	      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
! 	expr = default_conversion (expr);
!       
!       if (stmts_are_full_exprs_p)
! 	expr = convert_to_void (expr, "statement");
!       
!       if (!processing_template_decl)
! 	expr = break_out_cleanups (expr);
!       
!       add_tree (build_min_nt (EXPR_STMT, expr));
!     }
  
!   finish_stmt ();
  
!   /* This was an expression-statement, so we save the type of the
!      expression.  */
!   last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
! }
  
! /* Generate the RTL for EXPR, which is an EXPR_STMT. */
  
! void 
! genrtl_expr_stmt (expr)
!      tree expr;
! {
!   if (expr != NULL_TREE)
!     {
!       emit_line_note (input_filename, lineno);
!       
!       if (stmts_are_full_exprs_p)
! 	expand_start_target_temps ();
!       
!       cplus_expand_expr_stmt (expr);
!       
!       if (stmts_are_full_exprs_p)
! 	expand_end_target_temps ();
      }
  
    finish_stmt ();
*************** finish_expr_stmt (expr)
*** 171,176 ****
--- 321,387 ----
    last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
  }
  
+ /* Generate the RTL for T, which is a DECL_STMT. */
+ 
+ void
+ genrtl_decl_stmt (t)
+      tree t;
+ {
+   tree decl;
+   emit_line_note (input_filename, lineno);
+   decl = DECL_STMT_DECL (t);
+   /* If this is a declaration for an automatic local
+      variable, initialize it.  Note that we might also see a
+      declaration for a namespace-scope object (declared with
+      `extern').  We don't have to handle the initialization
+      of those objects here; they can only be declarations,
+      rather than definitions.  */
+   if (TREE_CODE (decl) == VAR_DECL 
+       && !TREE_STATIC (decl)
+       && !DECL_EXTERNAL (decl))
+     {
+       /* Let the back-end know about this variable.  */
+       if (!ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+ 	emit_local_var (decl);
+       else
+ 	expand_anon_union_decl (decl, NULL_TREE, 
+ 				DECL_ANON_UNION_ELEMS (decl));
+     }
+   else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+     {
+       if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
+ 	/* Do not emit unused decls. This is not just an
+ 	   optimization. We really do not want to emit
+ 	   __PRETTY_FUNCTION__ etc, if they're never used.  */
+ 	DECL_IGNORED_P (decl) = 1;
+       else
+ 	make_rtl_for_local_static (decl);
+     }
+ }
+ 
+ /* Generate the RTL for T, which is an IF_STMT. */
+ 
+ void
+ genrtl_if_stmt (t)
+      tree t;
+ {
+   tree cond;
+   genrtl_do_pushlevel ();
+   cond = maybe_convert_cond (expand_cond (IF_COND (t)));
+   emit_line_note (input_filename, lineno);
+   expand_start_cond (cond, 0);
+   if (THEN_CLAUSE (t))
+     expand_stmt (THEN_CLAUSE (t));
+   if (ELSE_CLAUSE (t))
+     {
+       expand_start_else ();
+       expand_stmt (ELSE_CLAUSE (t));
+     }
+   expand_end_cond ();
+   genrtl_do_poplevel ();
+   finish_stmt ();
+ }
+ 
  /* Begin an if-statement.  Returns a newly created IF_STMT if
     appropriate.  */
  
*************** tree
*** 178,194 ****
  begin_if_stmt ()
  {
    tree r;
- 
    do_pushlevel ();
! 
!   if (building_stmt_tree ())
!     {
!       r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
!       add_tree (r);
!     }
!   else
!     r = NULL_TREE;
! 
    return r;
  }
  
--- 389,397 ----
  begin_if_stmt ()
  {
    tree r;
    do_pushlevel ();
!   r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
!   add_tree (r);
    return r;
  }
  
*************** finish_if_stmt_cond (cond, if_stmt)
*** 201,214 ****
       tree if_stmt;
  {
    cond = maybe_convert_cond (cond);
! 
!   if (building_stmt_tree ())
!     FINISH_COND (cond, if_stmt, IF_COND (if_stmt));
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       expand_start_cond (cond, 0);
!     }
  }
  
  /* Finish the then-clause of an if-statement, which may be given by
--- 404,410 ----
       tree if_stmt;
  {
    cond = maybe_convert_cond (cond);
!   FINISH_COND (cond, if_stmt, IF_COND (if_stmt));
  }
  
  /* Finish the then-clause of an if-statement, which may be given by
*************** tree
*** 218,231 ****
  finish_then_clause (if_stmt)
       tree if_stmt;
  {
!   if (building_stmt_tree ())
!     {
!       RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
!       SET_LAST_STMT (if_stmt);
!       return if_stmt;
!     }
!   else
!     return NULL_TREE;
  }
  
  /* Begin the else-clause of an if-statement.  */
--- 414,422 ----
  finish_then_clause (if_stmt)
       tree if_stmt;
  {
!   RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
!   SET_LAST_STMT (if_stmt);
!   return if_stmt;
  }
  
  /* Begin the else-clause of an if-statement.  */
*************** finish_then_clause (if_stmt)
*** 233,240 ****
  void 
  begin_else_clause ()
  {
-   if (!building_stmt_tree ())
-     expand_start_else ();
  }
  
  /* Finish the else-clause of an if-statement, which may be given by
--- 424,429 ----
*************** void
*** 244,251 ****
  finish_else_clause (if_stmt)
       tree if_stmt;
  {
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
  }
  
  /* Finsh an if-statement.  */
--- 433,439 ----
  finish_else_clause (if_stmt)
       tree if_stmt;
  {
!   RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
  }
  
  /* Finsh an if-statement.  */
*************** finish_else_clause (if_stmt)
*** 253,265 ****
  void 
  finish_if_stmt ()
  {
-   if (!building_stmt_tree ())
-     expand_end_cond ();
- 
    do_poplevel ();
    finish_stmt ();
  }
  
  /* Begin a while-statement.  Returns a newly created WHILE_STMT if
     appropriate.  */
  
--- 441,487 ----
  void 
  finish_if_stmt ()
  {
    do_poplevel ();
    finish_stmt ();
  }
  
+ void
+ clear_out_block ()
+ {
+   /* If COND wasn't a declaration, clear out the
+      block we made for it and start a new one here so the
+      optimization in expand_end_loop will work.  */
+   if (getdecls () == NULL_TREE)
+     {
+       do_poplevel ();
+       do_pushlevel ();
+     }
+ }
+ 
+ /* Generate the RTL for T, which is a WHILE_STMT. */
+ 
+ void
+ genrtl_while_stmt (t)
+      tree t;
+ {
+   tree cond;
+   emit_nop ();
+   emit_line_note (input_filename, lineno);
+   expand_start_loop (1); 
+   genrtl_do_pushlevel ();
+ 
+   cond = maybe_convert_cond (expand_cond (WHILE_COND (t)));
+   emit_line_note (input_filename, lineno);
+   expand_exit_loop_if_false (0, cond);
+   genrtl_clear_out_block ();
+   
+   expand_stmt (WHILE_BODY (t));
+ 
+   genrtl_do_poplevel ();
+   expand_end_loop ();
+   finish_stmt ();
+ }
+ 
  /* Begin a while-statement.  Returns a newly created WHILE_STMT if
     appropriate.  */
  
*************** tree
*** 267,288 ****
  begin_while_stmt ()
  {
    tree r;
! 
!   if (building_stmt_tree ())
!     {
!       r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
!       add_tree (r);
!     }
!   else
!     {
!       emit_nop ();
!       emit_line_note (input_filename, lineno);
!       expand_start_loop (1); 
!       r = NULL_TREE;
!     }
! 
    do_pushlevel ();
- 
    return r;
  }
  
--- 489,497 ----
  begin_while_stmt ()
  {
    tree r;
!   r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
!   add_tree (r);
    do_pushlevel ();
    return r;
  }
  
*************** finish_while_stmt_cond (cond, while_stmt
*** 295,317 ****
       tree while_stmt;
  {
    cond = maybe_convert_cond (cond);
! 
!   if (building_stmt_tree ())
!     FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       expand_exit_loop_if_false (0, cond);
!     }
! 
!   /* If COND wasn't a declaration, clear out the
!      block we made for it and start a new one here so the
!      optimization in expand_end_loop will work.  */
!   if (getdecls () == NULL_TREE)
!     {
!       do_poplevel ();
!       do_pushlevel ();
!     }
  }
  
  /* Finish a while-statement, which may be given by WHILE_STMT.  */
--- 504,511 ----
       tree while_stmt;
  {
    cond = maybe_convert_cond (cond);
!   FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
!   clear_out_block ();
  }
  
  /* Finish a while-statement, which may be given by WHILE_STMT.  */
*************** finish_while_stmt (while_stmt)
*** 321,353 ****
       tree while_stmt;
  {
    do_poplevel ();
! 
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt));
!   else
!     expand_end_loop ();
    finish_stmt ();
  }
  
  /* Begin a do-statement.  Returns a newly created DO_STMT if
     appropriate.  */
  
  tree
  begin_do_stmt ()
  {
!   if (building_stmt_tree ())
!     {
!       tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
!       add_tree (r);
!       return r;
!     }
!   else
!     {
!       emit_nop ();
!       emit_line_note (input_filename, lineno);
!       expand_start_loop_continue_elsewhere (1);
!       return NULL_TREE;
!     }
  }
  
  /* Finish the body of a do-statement, which may be given by DO_STMT.  */
--- 515,555 ----
       tree while_stmt;
  {
    do_poplevel ();
!   RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt));
    finish_stmt ();
  }
  
+ /* Generate the RTL for T, which is a DO_STMT. */
+ 
+ void
+ genrtl_do_stmt (t)
+     tree t;
+ {
+   tree cond;
+   emit_nop ();
+   emit_line_note (input_filename, lineno);
+   expand_start_loop_continue_elsewhere (1);
+ 
+   expand_stmt (DO_BODY (t));
+ 
+   expand_loop_continue_here ();
+ 
+   cond = maybe_convert_cond (DO_COND (t));
+   emit_line_note (input_filename, lineno);
+   expand_exit_loop_if_false (0, cond);
+   expand_end_loop ();
+   finish_stmt ();  
+ }
+ 
  /* Begin a do-statement.  Returns a newly created DO_STMT if
     appropriate.  */
  
  tree
  begin_do_stmt ()
  {
!   tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
!   add_tree (r);
!   return r;
  }
  
  /* Finish the body of a do-statement, which may be given by DO_STMT.  */
*************** void
*** 356,365 ****
  finish_do_body (do_stmt)
       tree do_stmt;
  {
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt));
!   else
!     expand_loop_continue_here ();
  }
  
  /* Finish a do-statement, which may be given by DO_STMT, and whose
--- 558,564 ----
  finish_do_body (do_stmt)
       tree do_stmt;
  {
!   RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt));
  }
  
  /* Finish a do-statement, which may be given by DO_STMT, and whose
*************** finish_do_stmt (cond, do_stmt)
*** 371,386 ****
       tree do_stmt;
  {
    cond = maybe_convert_cond (cond);
  
!   if (building_stmt_tree ())
!     DO_COND (do_stmt) = cond;
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       expand_exit_loop_if_false (0, cond);
!       expand_end_loop ();
!     }
  
    finish_stmt ();
  }
  
--- 570,587 ----
       tree do_stmt;
  {
    cond = maybe_convert_cond (cond);
+   DO_COND (do_stmt) = cond;
+   finish_stmt ();
+ }
  
! /* Generate the RTL for EXPR, which is a RETURN_STMT. */
  
+ void
+ genrtl_return_stmt (expr)
+      tree expr;
+ {
+   emit_line_note (input_filename, lineno);
+   c_expand_return (expr);
    finish_stmt ();
  }
  
*************** void
*** 391,400 ****
  finish_return_stmt (expr)
       tree expr;
  {
!   if (doing_semantic_analysis_p () && !processing_template_decl)
      expr = check_return_expr (expr);
! 
!   if (doing_semantic_analysis_p () && !processing_template_decl)
      {
        if (DECL_CONSTRUCTOR_P (current_function_decl) && ctor_label)
  	{
--- 592,600 ----
  finish_return_stmt (expr)
       tree expr;
  {
!   if (!processing_template_decl)
      expr = check_return_expr (expr);
!   if (!processing_template_decl)
      {
        if (DECL_CONSTRUCTOR_P (current_function_decl) && ctor_label)
  	{
*************** finish_return_stmt (expr)
*** 417,450 ****
  	  return;
  	}
      }
  
!   if (building_stmt_tree ())
!     add_tree (build_min_nt (RETURN_STMT, expr));
!   else
      {
!       emit_line_note (input_filename, lineno);
!       c_expand_return (expr);
!     }
  
!   finish_stmt ();
  }
  
  /* Begin a for-statement.  Returns a new FOR_STMT if appropriate.  */
  
! tree
! begin_for_stmt ()
! {
!   tree r;
! 
!   if (building_stmt_tree ())
!     {
!       r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, 
! 			NULL_TREE, NULL_TREE);
!       add_tree (r);
!     }
!   else
!     r = NULL_TREE;
  
    if (flag_new_for_scope > 0)
      {
        do_pushlevel ();
--- 617,678 ----
  	  return;
  	}
      }
+   add_tree (build_min_nt (RETURN_STMT, expr));
+   finish_stmt ();
+ }
  
! /* Generate the RTL for T, which is a FOR_STMT. */
! 
! void
! genrtl_for_stmt (t)
!      tree t;
! {
!   tree tmp;
!   tree cond;
!   if (flag_new_for_scope > 0)
      {
!       genrtl_do_pushlevel ();
!       note_level_for_for ();
!     }  
  
!   expand_stmt (FOR_INIT_STMT (t));
! 
!   emit_nop ();
!   emit_line_note (input_filename, lineno);
!   expand_start_loop_continue_elsewhere (1); 
!   genrtl_do_pushlevel ();
!   cond = maybe_convert_cond (expand_cond (FOR_COND (t)));
!   emit_line_note (input_filename, lineno);
!   if (cond)
!     expand_exit_loop_if_false (0, cond);
!   genrtl_clear_out_block ();
!   tmp = FOR_EXPR (t);
! 
!   expand_stmt (FOR_BODY (t));
! 
!   /* Pop the scope for the body of the loop.  */
!   genrtl_do_poplevel ();
!   emit_line_note (input_filename, lineno);
!   expand_loop_continue_here ();
!   if (tmp) 
!     genrtl_expr_stmt (tmp);
!   expand_end_loop ();
!   if (flag_new_for_scope > 0)
!     genrtl_do_poplevel ();
!   finish_stmt (); 
  }
  
  /* Begin a for-statement.  Returns a new FOR_STMT if appropriate.  */
  
! tree
! begin_for_stmt ()
! {
!   tree r;
  
+   r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, 
+ 		    NULL_TREE, NULL_TREE);
+   add_tree (r);
+   
    if (flag_new_for_scope > 0)
      {
        do_pushlevel ();
*************** void
*** 461,478 ****
  finish_for_init_stmt (for_stmt)
       tree for_stmt;
  {
!   if (building_stmt_tree ())
!     {
!       if (last_tree != for_stmt)
! 	RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt));
!     }
!   else
!     {
!       emit_nop ();
!       emit_line_note (input_filename, lineno);
!       expand_start_loop_continue_elsewhere (1); 
!     }
! 
    do_pushlevel ();
  }
  
--- 689,696 ----
  finish_for_init_stmt (for_stmt)
       tree for_stmt;
  {
!   if (last_tree != for_stmt)
!     RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt));
    do_pushlevel ();
  }
  
*************** finish_for_cond (cond, for_stmt)
*** 485,508 ****
       tree for_stmt;
  {
    cond = maybe_convert_cond (cond);
! 
!   if (building_stmt_tree ())
!     FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       if (cond)
! 	expand_exit_loop_if_false (0, cond);
!     }
!   
!   /* If the cond wasn't a declaration, clear out the
!      block we made for it and start a new one here so the
!      optimization in expand_end_loop will work.  */
!   if (getdecls () == NULL_TREE)
!     {
!       do_poplevel ();
!       do_pushlevel ();
!     }  
  }
  
  /* Finish the increment-EXPRESSION in a for-statement, which may be
--- 703,710 ----
       tree for_stmt;
  {
    cond = maybe_convert_cond (cond);
!   FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
!   clear_out_block ();
  }
  
  /* Finish the increment-EXPRESSION in a for-statement, which may be
*************** finish_for_expr (expr, for_stmt)
*** 513,520 ****
       tree expr;
       tree for_stmt;
  {
!   if (building_stmt_tree ())
!     FOR_EXPR (for_stmt) = expr;
  }
  
  /* Finish the body of a for-statement, which may be given by
--- 715,721 ----
       tree expr;
       tree for_stmt;
  {
!   FOR_EXPR (for_stmt) = expr;
  }
  
  /* Finish the body of a for-statement, which may be given by
*************** finish_for_expr (expr, for_stmt)
*** 522,561 ****
     provided.  */
  
  void
! finish_for_stmt (expr, for_stmt)
!      tree expr;
       tree for_stmt;
  {
    /* Pop the scope for the body of the loop.  */
    do_poplevel ();
! 
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       expand_loop_continue_here ();
!       if (expr) 
! 	finish_expr_stmt (expr);
!       expand_end_loop ();
!     }
! 
    if (flag_new_for_scope > 0)
      do_poplevel ();
- 
    finish_stmt (); 
  }
  
  /* Finish a break-statement.  */
  
  void
  finish_break_stmt ()
  {
    emit_line_note (input_filename, lineno);
!   if (building_stmt_tree ())
!     add_tree (build_min_nt (BREAK_STMT));
!   else if ( ! expand_exit_something ())
!     cp_error ("break statement not within loop or switch");
  }
  
  /* Finish a continue-statement.  */
--- 723,766 ----
     provided.  */
  
  void
! finish_for_stmt (for_stmt)
       tree for_stmt;
  {
    /* Pop the scope for the body of the loop.  */
    do_poplevel ();
!   RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
    if (flag_new_for_scope > 0)
      do_poplevel ();
    finish_stmt (); 
  }
  
+ /* Generate the RTL for a BREAK_STMT. */
+ 
+ void
+ genrtl_break_stmt ()
+ {
+   emit_line_note (input_filename, lineno);
+   if ( ! expand_exit_something ())
+     cp_error ("break statement not within loop or switch");
+ }
+ 
  /* Finish a break-statement.  */
  
  void
  finish_break_stmt ()
  {
    emit_line_note (input_filename, lineno);
!   add_tree (build_min_nt (BREAK_STMT));
! }
! 
! /* Generate the RTL for a CONTINUE_STMT. */
! 
! void
! genrtl_continue_stmt ()
! {
!   emit_line_note (input_filename, lineno);
!   if (! expand_continue_loop (0))
!     cp_error ("continue statement not within a loop");   
  }
  
  /* Finish a continue-statement.  */
*************** void
*** 564,593 ****
  finish_continue_stmt ()
  {
    emit_line_note (input_filename, lineno);
!   if (building_stmt_tree ())
!     add_tree (build_min_nt (CONTINUE_STMT));
!   else if (! expand_continue_loop (0))
!     cp_error ("continue statement not within a loop");   
  }
  
! /* Begin a switch-statement.  Returns a new SWITCH_STMT if
!    appropriate.  */
  
! tree
! begin_switch_stmt ()
  {
!   tree r;
  
!   if (building_stmt_tree ())
      {
!       r = build_min_nt (SWITCH_STMT, NULL_TREE, NULL_TREE);
!       add_tree (r);
      }
    else
!     r = NULL_TREE;
  
!   do_pushlevel ();
  
    return r;
  }
  
--- 769,841 ----
  finish_continue_stmt ()
  {
    emit_line_note (input_filename, lineno);
!   add_tree (build_min_nt (CONTINUE_STMT));
  }
  
! /* Generate the RTL for T, which is a SCOPE_STMT. */
  
! void
! genrtl_scope_stmt (t)
!      tree t;
  {
!   if (!SCOPE_NO_CLEANUPS_P (t))
!     {
!       if (SCOPE_BEGIN_P (t))
! 	expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
! 					 SCOPE_STMT_BLOCK (t));
!       else if (SCOPE_END_P (t))
! 	expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
!     }
!   else if (!SCOPE_NULLIFIED_P (t))
!     {
!       rtx note = emit_note (NULL,
! 			    (SCOPE_BEGIN_P (t) 
! 			     ? NOTE_INSN_BLOCK_BEG
! 			     : NOTE_INSN_BLOCK_END));
!       NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
!     }
! }
! 
! /* Generate the RTL for T, which is a SWITCH_STMT. */
  
! void
! genrtl_switch_stmt (t)
!      tree t;
! {
!   tree cond;
!   genrtl_do_pushlevel ();
!  
!   cond = expand_cond (SWITCH_COND (t));
!   if (cond != error_mark_node)
      {
!       emit_line_note (input_filename, lineno);
!       c_expand_start_case (cond);
      }
    else
!     /* The code is in error, but we don't want expand_end_case to
!        crash. */
!     c_expand_start_case (boolean_false_node);
  
!   push_switch ();
! 
!   expand_stmt (SWITCH_BODY (t));
! 
!   expand_end_case (cond);
!   pop_switch (); 
!   genrtl_do_poplevel ();
!   finish_stmt ();  
! }
! 
! /* Begin a switch-statement.  Returns a new SWITCH_STMT if
!    appropriate.  */
  
+ tree
+ begin_switch_stmt ()
+ {
+   tree r;
+   r = build_min_nt (SWITCH_STMT, NULL_TREE, NULL_TREE);
+   add_tree (r);
+   do_pushlevel ();
    return r;
  }
  
*************** finish_switch_cond (cond, switch_stmt)
*** 598,645 ****
       tree cond;
       tree switch_stmt;
  {
!   if (building_stmt_tree ())
      {
!       if (!processing_template_decl)
  	{
! 	  /* Convert the condition to an integer or enumeration type.  */
! 	  cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, 1);
! 	  if (cond == NULL_TREE)
! 	    {
! 	      error ("switch quantity not an integer");
! 	      cond = error_mark_node;
! 	    }
! 	  if (cond != error_mark_node)
! 	    {
! 	      tree idx;
! 	      tree type;
! 	      
! 	      cond = default_conversion (cond);
! 	      type = TREE_TYPE (cond);
! 	      idx = get_unwidened (cond, 0);
! 	      /* We can't strip a conversion from a signed type to an unsigned,
! 		 because if we did, int_fits_type_p would do the wrong thing
! 		 when checking case values for being in range,
! 		 and it's too hard to do the right thing.  */
! 	      if (TREE_UNSIGNED (TREE_TYPE (cond)) 
! 		  == TREE_UNSIGNED (TREE_TYPE (idx)))
! 		cond = idx;
! 
! 	      cond = fold (build1 (CLEANUP_POINT_EXPR, type, cond));
! 	    }
  	}
!       FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
!     }
!   else if (cond != error_mark_node)
!     {
!       emit_line_note (input_filename, lineno);
!       c_expand_start_case (cond);
      }
!   else
!     /* The code is in error, but we don't want expand_end_case to
!        crash. */
!     c_expand_start_case (boolean_false_node);
! 
    push_switch ();
  }
  
--- 846,880 ----
       tree cond;
       tree switch_stmt;
  {
!   if (!processing_template_decl)
      {
!       /* Convert the condition to an integer or enumeration type.  */
!       cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, 1);
!       if (cond == NULL_TREE)
  	{
! 	  error ("switch quantity not an integer");
! 	  cond = error_mark_node;
  	}
!       if (cond != error_mark_node)
! 	{
! 	  tree idx;
! 	  tree type;
! 	  
! 	  cond = default_conversion (cond);
! 	  type = TREE_TYPE (cond);
! 	  idx = get_unwidened (cond, 0);
! 	  /* We can't strip a conversion from a signed type to an unsigned,
! 	     because if we did, int_fits_type_p would do the wrong thing
! 	     when checking case values for being in range,
! 	     and it's too hard to do the right thing.  */
! 	  if (TREE_UNSIGNED (TREE_TYPE (cond)) 
! 	      == TREE_UNSIGNED (TREE_TYPE (idx)))
! 	    cond = idx;
! 	  
! 	  cond = fold (build1 (CLEANUP_POINT_EXPR, type, cond));
! 	}
      }
!   FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
    push_switch ();
  }
  
*************** finish_switch_cond (cond, switch_stmt)
*** 647,724 ****
     SWITCH_STMT.  The COND to switch on is indicated.  */
  
  void
! finish_switch_stmt (cond, switch_stmt)
!      tree cond;
       tree switch_stmt;
  {
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
!   else
!     expand_end_case (cond);
    pop_switch (); 
    do_poplevel ();
    finish_stmt ();
  }
  
! /* Finish a case-label.  */
  
  void 
! finish_case_label (low_value, high_value)
       tree low_value;
       tree high_value;
  {
-   if (building_stmt_tree ())
-     {
-       /* Add a representation for the case label to the statement
- 	 tree.  */
-       add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
-       /* And warn about crossing initializations, etc.  */
-       if (!processing_template_decl)
- 	define_case_label ();
-       return;
-     }
- 
    do_case (low_value, high_value);
  }
  
! /* Finish a goto-statement.  */
  
! void
! finish_goto_stmt (destination)
!      tree destination;
  {
!   if (TREE_CODE (destination) == IDENTIFIER_NODE)
!     destination = lookup_label (destination);
! 
!   /* We warn about unused labels with -Wunused.  That means we have to
!      mark the used labels as used.  */
!   if (TREE_CODE (destination) == LABEL_DECL)
!     TREE_USED (destination) = 1;
!     
!   if (building_stmt_tree ())
!     {
!       if (TREE_CODE (destination) != LABEL_DECL)
! 	/* We don't inline calls to functions with computed gotos.
! 	   Those functions are typically up to some funny business,
! 	   and may be depending on the labels being at particular
! 	   addresses, or some such.  */
! 	DECL_UNINLINABLE (current_function_decl) = 1;
  
!       check_goto (destination);
  
!       add_tree (build_min_nt (GOTO_STMT, destination));
      }
    else
      {
!       emit_line_note (input_filename, lineno);
  
!       if (TREE_CODE (destination) == LABEL_DECL)
  	{
! 	  label_rtx (destination);
! 	  expand_goto (destination); 
  	}
-       else
- 	expand_computed_goto (destination);
      }
  }
  
--- 882,961 ----
     SWITCH_STMT.  The COND to switch on is indicated.  */
  
  void
! finish_switch_stmt (switch_stmt)
       tree switch_stmt;
  {
!   RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
    pop_switch (); 
    do_poplevel ();
    finish_stmt ();
  }
  
! /* Generate the RTL for a CASE_LABEL. */
  
  void 
! genrtl_case_label (low_value, high_value)
       tree low_value;
       tree high_value;
  {
    do_case (low_value, high_value);
  }
  
! /* Finish a case-label.  */
  
! void 
! finish_case_label (low_value, high_value)
!      tree low_value;
!      tree high_value;
  {
!   /* Add a representation for the case label to the statement
!      tree.  */
!   add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
!   /* And warn about crossing initializations, etc.  */
!   if (!processing_template_decl)
!     define_case_label ();
! }
  
! /* Generate the RTL for T, which is a TRY_BLOCK. */
  
! void genrtl_try_block (t)
!      tree t;
! {
!   if (CLEANUP_P (t))
!     {
!       expand_eh_region_start ();
!       expand_stmt (TRY_STMTS (t));
!       expand_eh_region_end (protect_with_terminate (TRY_HANDLERS (t)));
      }
    else
      {
!       if (FN_TRY_BLOCK_P (t)) {
! 	if (! current_function_parms_stored)
! 	  store_parm_decls ();
! 	expand_start_early_try_stmts ();
!       }
!       else {
! 	emit_line_note (input_filename, lineno);
! 	expand_start_try_stmts ();
!       }
  
!       expand_stmt (TRY_STMTS (t));
! 
!       if (FN_TRY_BLOCK_P (t))
  	{
! 	  end_protect_partials ();
! 	  expand_start_all_catch ();
! 	  in_function_try_handler = 1;
! 	  expand_stmt (TRY_HANDLERS (t));
! 	  in_function_try_handler = 0;
! 	  expand_end_all_catch ();
! 	}
!       else 
! 	{
! 	  expand_start_all_catch ();  
! 	  expand_stmt (TRY_HANDLERS (t));
! 	  expand_end_all_catch ();
  	}
      }
  }
  
*************** finish_goto_stmt (destination)
*** 728,746 ****
  tree
  begin_try_block ()
  {
!   if (building_stmt_tree ())
!     {
!       tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
! 			     NULL_TREE);
!       add_tree (r);
!       return r;
!     }
!   else
!     {
!       emit_line_note (input_filename, lineno);
!       expand_start_try_stmts ();
!       return NULL_TREE;
!     }
  }
  
  /* Likewise, for a function-try-block.  */
--- 965,973 ----
  tree
  begin_try_block ()
  {
!   tree r = build_min_nt (TRY_BLOCK, NULL_TREE, NULL_TREE);
!   add_tree (r);
!   return r;
  }
  
  /* Likewise, for a function-try-block.  */
*************** begin_try_block ()
*** 748,768 ****
  tree
  begin_function_try_block ()
  {
!   if (building_stmt_tree ())
!     {
!       tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
! 			     NULL_TREE);
!       FN_TRY_BLOCK_P (r) = 1;
!       add_tree (r);
!       return r;
!     }
!   else
!     {
!       if (! current_function_parms_stored)
! 	store_parm_decls ();
!       expand_start_early_try_stmts ();
!       return NULL_TREE;
!     }
  }
  
  /* Finish a try-block, which may be given by TRY_BLOCK.  */
--- 975,984 ----
  tree
  begin_function_try_block ()
  {
!   tree r = build_min_nt (TRY_BLOCK, NULL_TREE, NULL_TREE);
!   FN_TRY_BLOCK_P (r) = 1;
!   add_tree (r);
!   return r;
  }
  
  /* Finish a try-block, which may be given by TRY_BLOCK.  */
*************** void
*** 771,780 ****
  finish_try_block (try_block)
       tree try_block;
  {
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
!   else
!     expand_start_all_catch ();  
  }
  
  /* Finish the body of a cleanup try-block, which may be given by
--- 987,993 ----
  finish_try_block (try_block)
       tree try_block;
  {
!   RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
  }
  
  /* Finish the body of a cleanup try-block, which may be given by
*************** void
*** 784,791 ****
  finish_cleanup_try_block (try_block)
       tree try_block;
  {
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
  }
  
  /* Finish an implicitly generated try-block, with a cleanup is given
--- 997,1003 ----
  finish_cleanup_try_block (try_block)
       tree try_block;
  {
!   RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
  }
  
  /* Finish an implicitly generated try-block, with a cleanup is given
*************** finish_cleanup (cleanup, try_block)
*** 796,808 ****
       tree cleanup;
       tree try_block;
  {
!   if (building_stmt_tree ()) 
!     {
!       TRY_HANDLERS (try_block) = cleanup;
!       CLEANUP_P (try_block) = 1;
!     }
!   else
!     expand_eh_region_end (protect_with_terminate (cleanup));
  }
  
  /* Likewise, for a function-try-block.  */
--- 1008,1015 ----
       tree cleanup;
       tree try_block;
  {
!   TRY_HANDLERS (try_block) = cleanup;
!   CLEANUP_P (try_block) = 1;
  }
  
  /* Likewise, for a function-try-block.  */
*************** void
*** 811,835 ****
  finish_function_try_block (try_block)
       tree try_block; 
  {
!   if (building_stmt_tree ())
      {
!       if (TREE_CHAIN (try_block) 
! 	  && TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER)
! 	{
! 	  /* Chain the compound statement after the CTOR_INITIALIZER.  */
! 	  TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree;
! 	  /* And make the CTOR_INITIALIZER the body of the try-block.  */
! 	  RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
! 	}
!       else
! 	RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
      }
    else
!     {
!       end_protect_partials ();
!       expand_start_all_catch ();
!     }
! 
    in_function_try_handler = 1;
  }
  
--- 1018,1033 ----
  finish_function_try_block (try_block)
       tree try_block; 
  {
!   if (TREE_CHAIN (try_block) 
!       && TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER)
      {
!       /* Chain the compound statement after the CTOR_INITIALIZER.  */
!       TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree;
!       /* And make the CTOR_INITIALIZER the body of the try-block.  */
!       RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
      }
    else
!     RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
    in_function_try_handler = 1;
  }
  
*************** void
*** 840,852 ****
  finish_handler_sequence (try_block)
       tree try_block;
  {
!   if (building_stmt_tree ())
!     {
!       RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
!       check_handlers (TRY_HANDLERS (try_block));
!     }
!   else
!     expand_end_all_catch ();
  }
  
  /* Likewise, for a function-try-block.  */
--- 1038,1045 ----
  finish_handler_sequence (try_block)
       tree try_block;
  {
!   RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
!   check_handlers (TRY_HANDLERS (try_block));
  }
  
  /* Likewise, for a function-try-block.  */
*************** finish_function_handler_sequence (try_bl
*** 856,869 ****
       tree try_block;
  {
    in_function_try_handler = 0;
  
!   if (building_stmt_tree ())
      {
!       RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
!       check_handlers (TRY_HANDLERS (try_block));
      }
!   else
!     expand_end_all_catch ();
  }
  
  /* Begin a handler.  Returns a HANDLER if appropriate.  */
--- 1049,1076 ----
       tree try_block;
  {
    in_function_try_handler = 0;
+   RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
+   check_handlers (TRY_HANDLERS (try_block));
+ }
  
! /* Generate the RTL for T, which is a HANDLER. */
! 
! void
! genrtl_handler (t)
!      tree t;
! {
!   genrtl_do_pushlevel ();
!   expand_stmt (HANDLER_BODY (t));
!   if (!processing_template_decl)
      {
!       /* Fall to outside the try statement when done executing
! 	 handler and we fall off end of handler.  This is jump
! 	 Lresume in the documentation.  */
!       expand_goto (top_label_entry (&caught_return_label_stack));
!       end_catch_handler ();
      }
! 
!   genrtl_do_poplevel ();  
  }
  
  /* Begin a handler.  Returns a HANDLER if appropriate.  */
*************** tree
*** 872,888 ****
  begin_handler ()
  {
    tree r;
! 
!   if (building_stmt_tree ())
!     {
!       r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
!       add_tree (r);
!     }
!   else
!     r = NULL_TREE;
! 
    do_pushlevel ();
- 
    return r;
  }
  
--- 1079,1087 ----
  begin_handler ()
  {
    tree r;
!   r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
!   add_tree (r);
    do_pushlevel ();
    return r;
  }
  
*************** finish_handler_parms (decl, handler)
*** 906,962 ****
  	  add_decl_stmt (decl);
  	  RECHAIN_STMTS (handler, HANDLER_PARMS (handler));
  	}
      }
-   else if (building_stmt_tree ())
-     blocks = expand_start_catch_block (decl);
- 
-   if (decl)
-     TREE_TYPE (handler) = TREE_TYPE (decl);
  
!   return blocks;
  }
  
! /* Note the beginning of a handler for TYPE.  This function is called
!    at the point to which control should be transferred when an
!    appropriately-typed exception is thrown.  */
  
! void
! begin_catch_block (type)
!      tree type;
  {
!   if (building_stmt_tree ())
!     add_tree (build (START_CATCH_STMT, type));
!   else
!     start_catch_handler (type);
! }
  
! /* Finish a handler, which may be given by HANDLER.  The BLOCKs are
!    the return value from the matching call to finish_handler_parms.  */
  
! void
! finish_handler (blocks, handler)
!      tree blocks;
!      tree handler;
! {
!   if (!processing_template_decl)
!     {
!       if (building_stmt_tree ())
! 	expand_end_catch_block (blocks);
  
!       if (!building_stmt_tree ())
! 	{
! 	  /* Fall to outside the try statement when done executing
! 	     handler and we fall off end of handler.  This is jump
! 	     Lresume in the documentation.  */
! 	  expand_goto (top_label_entry (&caught_return_label_stack));
! 	  end_catch_handler ();
! 	}
!     }
  
!   do_poplevel ();
  
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (handler, HANDLER_BODY (handler));
  }
  
  /* Begin a compound-statement.  If HAS_NO_SCOPE is non-zero, the
--- 1105,1240 ----
  	  add_decl_stmt (decl);
  	  RECHAIN_STMTS (handler, HANDLER_PARMS (handler));
  	}
+     }
+   else
+     blocks = expand_start_catch_block (decl);
+ 
+   if (decl)
+     TREE_TYPE (handler) = TREE_TYPE (decl);
+ 
+   return blocks;
+ }
+ 
+ /* Generate the RTL for a CATCH_BLOCK. */
+ 
+ void
+ genrtl_catch_block (type)
+      tree type;
+ {
+   start_catch_handler (type);
+ }
+ 
+ /* Note the beginning of a handler for TYPE.  This function is called
+    at the point to which control should be transferred when an
+    appropriately-typed exception is thrown.  */
+ 
+ void
+ begin_catch_block (type)
+      tree type;
+ {
+   add_tree (build (START_CATCH_STMT, type));
+ }
+ 
+ /* Finish a handler, which may be given by HANDLER.  The BLOCKs are
+    the return value from the matching call to finish_handler_parms.  */
+ 
+ void
+ finish_handler (blocks, handler)
+      tree blocks;
+      tree handler;
+ {
+   if (!processing_template_decl)
+       expand_end_catch_block (blocks);
+   do_poplevel ();
+   RECHAIN_STMTS (handler, HANDLER_BODY (handler));
+ }
+ 
+ /* Generate the RTL for T, which is a CTOR_STMT. */
+ 
+ void
+ genrtl_ctor_stmt (t)
+      tree t;
+ {
+   if (CTOR_BEGIN_P (t))
+     begin_protect_partials ();
+   else
+     /* After this point, any exceptions will cause the
+        destructor to be executed, so we no longer need to worry
+        about destroying the various subobjects ourselves.  */
+     end_protect_partials ();
+ }
+ 
+ /* Generate the RTL for the start of a COMPOUND_STMT. */
+ 
+ tree genrtl_begin_compound_stmt (has_no_scope)
+      int has_no_scope;
+ {
+   tree r; 
+   int is_try = 0;
+ 
+   r = NULL_TREE;
+ 
+   last_expr_type = NULL_TREE;
+ 
+   if (!has_no_scope)
+     {
+       genrtl_do_pushlevel ();
+       if (is_try)
+ 	note_level_for_eh ();
+     }
+   else
+     /* Normally, we try hard to keep the BLOCK for a
+        statement-expression.  But, if it's a statement-expression with
+        a scopeless block, there's nothing to keep, and we don't want
+        to accidentally keep a block *inside* the scopeless block.  */ 
+     keep_next_level (0);
+ 
+   /* If this is the outermost block of the function, declare the
+      variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
+   if (cfun
+       && !current_function_name_declared 
+       && !has_no_scope)
+     {
+       current_function_name_declared = 1;
+       declare_function_name ();
      }
  
!   return r;
  }
  
! /* Generate the RTL for the end of a COMPOUND_STMT. */
  
! tree genrtl_finish_compound_stmt (has_no_scope)
!      int has_no_scope;
  {
!   tree r;
!   tree t;
  
!   if (!has_no_scope)
!     r = genrtl_do_poplevel ();
!   else
!     r = NULL_TREE;
  
!   /* When we call finish_stmt we will lose LAST_EXPR_TYPE.  But, since
!      the precise purpose of that variable is store the type of the
!      last expression statement within the last compound statement, we
!      preserve the value.  */
!   t = last_expr_type;
!   finish_stmt ();
!   last_expr_type = t;
  
!   return r;
! }
  
! /* Generate the RTL for T, which is a COMPOUND_STMT. */
  
! tree 
! genrtl_compound_stmt (t)
!     tree t;
! {
!   genrtl_begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
!   expand_stmt (COMPOUND_BODY (t));
!   return (genrtl_finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)));
  }
  
  /* Begin a compound-statement.  If HAS_NO_SCOPE is non-zero, the
*************** begin_compound_stmt (has_no_scope)
*** 970,989 ****
    tree r; 
    int is_try = 0;
  
!   if (building_stmt_tree ())
!     {
!       r = build_min_nt (COMPOUND_STMT, NULL_TREE);
!       /* Mark that this block is for a try so that we can yell at
!          people trying to jump in.  */
!       if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
! 	is_try = 1;
!       add_tree (r);
!       if (has_no_scope)
! 	COMPOUND_STMT_NO_SCOPE (r) = 1;
!     }
!   else
!     r = NULL_TREE;
  
    last_expr_type = NULL_TREE;
  
    if (!has_no_scope)
--- 1248,1262 ----
    tree r; 
    int is_try = 0;
  
!   r = build_min_nt (COMPOUND_STMT, NULL_TREE);
  
+   if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
+     is_try = 1;
+ 
+   add_tree (r);
+   if (has_no_scope)
+     COMPOUND_STMT_NO_SCOPE (r) = 1;
+ 
    last_expr_type = NULL_TREE;
  
    if (!has_no_scope)
*************** begin_compound_stmt (has_no_scope)
*** 1012,1018 ****
    return r;
  }
  
- 
  /* Finish a compound-statement, which may be given by COMPOUND_STMT.
     If HAS_NO_SCOPE is non-zero, the compound statement does not define
     a scope.  */
--- 1285,1290 ----
*************** finish_compound_stmt (has_no_scope, comp
*** 1030,1037 ****
    else
      r = NULL_TREE;
  
!   if (building_stmt_tree ())
!     RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt));
  
    /* When we call finish_stmt we will lose LAST_EXPR_TYPE.  But, since
       the precise purpose of that variable is store the type of the
--- 1302,1308 ----
    else
      r = NULL_TREE;
  
!   RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt));
  
    /* When we call finish_stmt we will lose LAST_EXPR_TYPE.  But, since
       the precise purpose of that variable is store the type of the
*************** finish_compound_stmt (has_no_scope, comp
*** 1044,1055 ****
    return r;
  }
  
! /* Finish an asm-statement, whose components are a CV_QUALIFIER, a
!    STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
!    CLOBBERS.  */
  
  void
! finish_asm_stmt (cv_qualifier, string, output_operands,
  		 input_operands, clobbers)
       tree cv_qualifier;
       tree string;
--- 1315,1324 ----
    return r;
  }
  
! /* Generate the RTL for an ASM_STMT. */
  
  void
! genrtl_asm_stmt (cv_qualifier, string, output_operands,
  		 input_operands, clobbers)
       tree cv_qualifier;
       tree string;
*************** finish_asm_stmt (cv_qualifier, string, o
*** 1068,1102 ****
        cv_qualifier = NULL_TREE;
      }
  
!   if (building_stmt_tree ())
      {
!       tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
! 			     output_operands, input_operands,
! 			     clobbers);
!       add_tree (r);
      }
    else
!     {
!       emit_line_note (input_filename, lineno);
!       if (output_operands != NULL_TREE || input_operands != NULL_TREE
! 	    || clobbers != NULL_TREE)
! 	{
! 	  tree t;
  
! 	  for (t = input_operands; t; t = TREE_CHAIN (t))
! 	    TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
  
! 	  c_expand_asm_operands (string, output_operands,
! 				 input_operands, 
! 				 clobbers,
! 				 cv_qualifier != NULL_TREE,
! 				 input_filename, lineno);
! 	}
!       else
! 	expand_asm (string);
!       
!       finish_stmt ();
      }
  }
  
  /* Finish a label with the indicated NAME.  */
--- 1337,1392 ----
        cv_qualifier = NULL_TREE;
      }
  
!   emit_line_note (input_filename, lineno);
!   if (output_operands != NULL_TREE || input_operands != NULL_TREE
!       || clobbers != NULL_TREE)
      {
!       tree t;
!       
!       for (t = input_operands; t; t = TREE_CHAIN (t))
! 	TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
!       
!       c_expand_asm_operands (string, output_operands,
! 			     input_operands, 
! 			     clobbers,
! 			     cv_qualifier != NULL_TREE,
! 			     input_filename, lineno);
      }
    else
!     expand_asm (string);
!   
!   finish_stmt ();
! }
  
! /* Finish an asm-statement, whose components are a CV_QUALIFIER, a
!    STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
!    CLOBBERS.  */
  
! void
! finish_asm_stmt (cv_qualifier, string, output_operands,
! 		 input_operands, clobbers)
!      tree cv_qualifier;
!      tree string;
!      tree output_operands;
!      tree input_operands;
!      tree clobbers;
! {
!   tree r;
!   if (TREE_CHAIN (string))
!     string = combine_strings (string);
! 
!   if (cv_qualifier != NULL_TREE
!       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
!     {
!       cp_warning ("%s qualifier ignored on asm",
! 		  IDENTIFIER_POINTER (cv_qualifier));
!       cv_qualifier = NULL_TREE;
      }
+ 
+   r = build_min_nt (ASM_STMT, cv_qualifier, string,
+ 		    output_operands, input_operands,
+ 		    clobbers);
+   add_tree (r);
  }
  
  /* Finish a label with the indicated NAME.  */
*************** finish_label_stmt (name)
*** 1106,1116 ****
       tree name;
  {
    tree decl = define_label (input_filename, lineno, name);
! 
!   if (building_stmt_tree ())
!     add_tree (build_min_nt (LABEL_STMT, decl));
!   else if (decl)
!     expand_label (decl);
  }
  
  /* Finish a series of declarations for local labels.  G++ allows users
--- 1396,1402 ----
       tree name;
  {
    tree decl = define_label (input_filename, lineno, name);
!   add_tree (build_min_nt (LABEL_STMT, decl));
  }
  
  /* Finish a series of declarations for local labels.  G++ allows users
*************** finish_label_decl (name)
*** 1122,1129 ****
       tree name;
  {
    tree decl = declare_local_label (name);
!   if (building_stmt_tree ())
!     add_decl_stmt (decl);
  }
  
  /* Create a declaration statement for the declaration given by the
--- 1408,1414 ----
       tree name;
  {
    tree decl = declare_local_label (name);
!   add_decl_stmt (decl);
  }
  
  /* Create a declaration statement for the declaration given by the
*************** add_decl_stmt (decl)
*** 1137,1145 ****
  
    /* We need the type to last until instantiation time.  */
    decl_stmt = build_min_nt (DECL_STMT, decl);
!   add_tree (decl_stmt);
  }
  
  /* We're in a constructor, and have just constructed a a subobject of
     *THIS.  CLEANUP is code to run if an exception is thrown before the
     end of the current function is reached.   */
--- 1422,1439 ----
  
    /* We need the type to last until instantiation time.  */
    decl_stmt = build_min_nt (DECL_STMT, decl);
!   add_tree (decl_stmt); 
  }
  
+ /* Generate the RTL for a SUBOBJECT. */
+ 
+ void 
+ genrtl_subobject (cleanup)
+      tree cleanup;
+ {
+   add_partial_entry (cleanup);
+ }
+ 
  /* We're in a constructor, and have just constructed a a subobject of
     *THIS.  CLEANUP is code to run if an exception is thrown before the
     end of the current function is reached.   */
*************** void 
*** 1148,1160 ****
  finish_subobject (cleanup)
       tree cleanup;
  {
!   if (building_stmt_tree ())
!     {
!       tree r = build_min_nt (SUBOBJECT, cleanup);
!       add_tree (r);
!     }
!   else
!     add_partial_entry (cleanup);
  }
  
  /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
--- 1442,1460 ----
  finish_subobject (cleanup)
       tree cleanup;
  {
!   tree r = build_min_nt (SUBOBJECT, cleanup);
!   add_tree (r);
! }
! 
! /* Generate the RTL for a DECL_CLEANUP. */
! 
! void 
! genrtl_decl_cleanup (decl, cleanup)
!      tree decl;
!      tree cleanup;
! {
!   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
!     expand_decl_cleanup (decl, cleanup);
  }
  
  /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
*************** finish_decl_cleanup (decl, cleanup)
*** 1164,1174 ****
       tree decl;
       tree cleanup;
  {
!   if (building_stmt_tree ())
!     add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
!   else if (!decl 
! 	   || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
!     expand_decl_cleanup (decl, cleanup);
  }
  
  /* Bind a name and initialization to the return value of
--- 1464,1524 ----
       tree decl;
       tree cleanup;
  {
!   add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
! }
! 
! /* Generate the RTL for a RETURN_INIT. */
! 
! void
! genrtl_named_return_value (return_id, init)
!      tree return_id, init;
! {
!   tree decl;
!   /* Clear this out so that finish_named_return_value can set it
!      again.  */
!   DECL_NAME (DECL_RESULT (current_function_decl)) = NULL_TREE;
! 
!   decl = DECL_RESULT (current_function_decl);
!   if (pedantic)
!     /* Give this error as many times as there are occurrences,
!        so that users can use Emacs compilation buffers to find
!        and fix all such places.  */
!     pedwarn ("ISO C++ does not permit named return values");
! 
!   if (return_id != NULL_TREE)
!     {
!       if (DECL_NAME (decl) == NULL_TREE)
! 	{
! 	  DECL_NAME (decl) = return_id;
! 	  DECL_ASSEMBLER_NAME (decl) = return_id;
! 	}
!       else
! 	{
! 	  cp_error ("return identifier `%D' already in place", return_id);
! 	  return;
! 	}
!     }
! 
!   /* Can't let this happen for constructors.  */
!   if (DECL_CONSTRUCTOR_P (current_function_decl))
!     {
!       error ("can't redefine default return value for constructors");
!       return;
!     }
! 
!   /* If we have a named return value, put that in our scope as well.  */
!   if (DECL_NAME (decl) != NULL_TREE)
!     {
!       /* Let `cp_finish_decl' know that this initializer is ok.  */
!       DECL_INITIAL (decl) = init;
!       cp_finish_decl (decl, init, NULL_TREE, 0);
!       store_return_init (decl);
!     }
! 
!   /* Don't use tree-inlining for functions with named return values.
!      That doesn't work properly because we don't do any translation of
!      the RETURN_INITs when they are copied.  */
!   DECL_UNINLINABLE (current_function_decl) = 1;
  }
  
  /* Bind a name and initialization to the return value of
*************** finish_named_return_value (return_id, in
*** 1214,1227 ****
        DECL_INITIAL (decl) = init;
        if (doing_semantic_analysis_p ())
  	pushdecl (decl);
! 
!       if (building_stmt_tree ())
! 	add_tree (build_min_nt (RETURN_INIT, return_id, init));
!       else
! 	{
! 	  cp_finish_decl (decl, init, NULL_TREE, 0);
! 	  store_return_init (decl);
! 	}
      }
  
    /* Don't use tree-inlining for functions with named return values.
--- 1564,1570 ----
        DECL_INITIAL (decl) = init;
        if (doing_semantic_analysis_p ())
  	pushdecl (decl);
!       add_tree (build_min_nt (RETURN_INIT, return_id, init));
      }
  
    /* Don't use tree-inlining for functions with named return values.
*************** setup_vtbl_ptr (member_init_list, base_i
*** 1375,1380 ****
--- 1718,1724 ----
    vtbls_set_up_p = 1;
  }
  
+ 
  /* Add a scope-statement to the statement-tree.  BEGIN_P indicates
     whether this statements opens or closes a scope.  PARTIAL_P is true
     for a partial scope, i.e, the scope that begins after a label when
*************** add_scope_stmt (begin_p, partial_p)
*** 1418,1472 ****
    return top;
  }
  
- /* Begin a new scope.  */
- 
- void
- do_pushlevel ()
- {
-   if (!building_stmt_tree ())
-     {
-       emit_line_note (input_filename, lineno);
-       clear_last_expr ();
-     }
-   if (stmts_are_full_exprs_p)
-     {
-       pushlevel (0);
-       if (!building_stmt_tree ()
- 	  && !cfun->x_whole_function_mode_p)
- 	my_friendly_abort (19991129);
- 
-       if (building_stmt_tree () && !processing_template_decl)
- 	add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-     }
- }
- 
- /* Finish a scope.  */
- 
- tree
- do_poplevel ()
- {
-   tree block = NULL_TREE;
- 
-   if (stmts_are_full_exprs_p)
-     {
-       tree scope_stmts;
- 
-       if (building_stmt_tree () && !processing_template_decl)
- 	scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
-       else
- 	scope_stmts = NULL_TREE;
- 
-       block = poplevel (kept_level_p (), 1, 0);
-       if (block && !processing_template_decl)
- 	{
- 	  SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
- 	  SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
- 	}
-     }
- 
-   return block;
- }
- 
  /* Finish a parenthesized expression EXPR.  */
  
  tree
--- 1762,1767 ----
*************** finish_parenthesized_expr (expr)
*** 1480,1485 ****
--- 1775,1795 ----
    return expr;
  }
  
+ /* The last_tree will be NULL_TREE when entering this function. Unlike
+    the other genrtl functions, in this function, that state can change
+    hence the check at the end as in the original version of
+    begin_stmt_expr. Generate the RTL for the start of a STMT_EXPR. */
+ tree
+ genrtl_begin_stmt_expr ()
+ {
+   if (! cfun && !last_tree)
+     begin_stmt_tree (&scope_chain->x_saved_tree);
+ 
+   keep_next_level (1);
+   
+   return (last_tree != NULL_TREE) ? last_tree : expand_start_stmt_expr(); 
+ }
+ 
  /* Begin a statement-expression.  The value returned must be passed to
     finish_stmt_expr.  */
  
*************** begin_stmt_expr ()
*** 1497,1503 ****
       statement will be chained onto the tree structure, starting at
       last_tree.  We return last_tree so that we can later unhook the
       compound statement.  */
!   return building_stmt_tree () ? last_tree : expand_start_stmt_expr(); 
  }
  
  /* Finish a statement-expression.  RTL_EXPR should be the value
--- 1807,1831 ----
       statement will be chained onto the tree structure, starting at
       last_tree.  We return last_tree so that we can later unhook the
       compound statement.  */
!   return last_tree; 
! }
! 
! /* Generate the RTL for the end of the STMT_EXPR. */
! 
! tree 
! genrtl_finish_stmt_expr (rtl_expr)
!      tree rtl_expr;
! {
!   tree result;
! 
!   rtl_expr = expand_end_stmt_expr (rtl_expr);
!   result = rtl_expr;
!   
!   if (! cfun
!       && TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE)
!     finish_stmt_tree (&scope_chain->x_saved_tree);
! 
!   return result;
  }
  
  /* Finish a statement-expression.  RTL_EXPR should be the value
*************** finish_stmt_expr (rtl_expr)
*** 1510,1535 ****
       tree rtl_expr;
  {
    tree result;
- 
-   if (!building_stmt_tree ())
-     rtl_expr = expand_end_stmt_expr (rtl_expr);
  
!   if (building_stmt_tree ())
!     {
!       /* If the last thing in the statement-expression was not an
! 	 expression-statement, then it has type `void'.  */
!       if (!last_expr_type)
! 	last_expr_type = void_type_node;
!       result = build_min (STMT_EXPR, last_expr_type, last_tree);
!       TREE_SIDE_EFFECTS (result) = 1;
!       
!       /* Remove the compound statement from the tree structure; it is
! 	 now saved in the STMT_EXPR.  */
!       SET_LAST_STMT (rtl_expr);
!       TREE_CHAIN (last_tree) = NULL_TREE;
!     }
!   else 
!     result = rtl_expr;
  
    /* If we created a statement-tree for this statement-expression,
       remove it now.  */ 
--- 1838,1855 ----
       tree rtl_expr;
  {
    tree result;
  
!   /* If the last thing in the statement-expression was not an
!      expression-statement, then it has type `void'.  */
!   if (!last_expr_type)
!     last_expr_type = void_type_node;
!   result = build_min (STMT_EXPR, last_expr_type, last_tree);
!   TREE_SIDE_EFFECTS (result) = 1;
!   
!   /* Remove the compound statement from the tree structure; it is
!      now saved in the STMT_EXPR.  */
!   SET_LAST_STMT (rtl_expr);
!   TREE_CHAIN (last_tree) = NULL_TREE;
  
    /* If we created a statement-tree for this statement-expression,
       remove it now.  */ 
*************** expand_stmt (t)
*** 2449,2594 ****
        switch (TREE_CODE (t))
  	{
  	case RETURN_STMT:
! 	  finish_return_stmt (RETURN_EXPR (t));
  	  break;
  
  	case EXPR_STMT:
! 	  finish_expr_stmt (EXPR_STMT_EXPR (t));
  	  break;
  
  	case DECL_STMT:
! 	  {
! 	    tree decl;
! 
! 	    emit_line_note (input_filename, lineno);
! 	    decl = DECL_STMT_DECL (t);
! 	    /* If this is a declaration for an automatic local
! 	       variable, initialize it.  Note that we might also see a
! 	       declaration for a namespace-scope object (declared with
! 	       `extern').  We don't have to handle the initialization
! 	       of those objects here; they can only be declarations,
! 	       rather than definitions.  */
! 	    if (TREE_CODE (decl) == VAR_DECL 
! 		&& !TREE_STATIC (decl)
! 		&& !DECL_EXTERNAL (decl))
! 	      {
! 		/* Let the back-end know about this variable.  */
! 		if (!ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
! 		  emit_local_var (decl);
! 		else
! 		  expand_anon_union_decl (decl, NULL_TREE, 
! 					  DECL_ANON_UNION_ELEMS (decl));
! 	      }
! 	    else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
! 	      {
! 		if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
! 		  /* Do not emit unused decls. This is not just an
! 		     optimization. We really do not want to emit
! 		     __PRETTY_FUNCTION__ etc, if they're never used.  */
! 		  DECL_IGNORED_P (decl) = 1;
! 		else
! 		  make_rtl_for_local_static (decl);
! 	      }
! 	  }
  	  break;
  
  	case CLEANUP_STMT:
! 	  finish_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
  	  break;
  
  	case START_CATCH_STMT:
! 	  begin_catch_block (TREE_TYPE (t));
  	  break;
  
  	case CTOR_STMT:
! 	  if (CTOR_BEGIN_P (t))
! 	    begin_protect_partials ();
! 	  else
! 	    /* After this point, any exceptions will cause the
! 	       destructor to be executed, so we no longer need to worry
! 	       about destroying the various subobjects ourselves.  */
! 	    end_protect_partials ();
  	  break;
  
  	case FOR_STMT:
! 	  {
! 	    tree tmp;
! 
! 	    begin_for_stmt ();
! 	    expand_stmt (FOR_INIT_STMT (t));
! 	    finish_for_init_stmt (NULL_TREE);
! 	    finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE);
! 	    tmp = FOR_EXPR (t);
! 	    finish_for_expr (tmp, NULL_TREE);
! 	    expand_stmt (FOR_BODY (t));
! 	    finish_for_stmt (tmp, NULL_TREE);
! 	  }
  	  break;
  
  	case WHILE_STMT:
! 	  {
! 	    begin_while_stmt ();
! 	    finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE);
! 	    expand_stmt (WHILE_BODY (t));
! 	    finish_while_stmt (NULL_TREE);
! 	  }
  	  break;
  
  	case DO_STMT:
! 	  {
! 	    begin_do_stmt ();
! 	    expand_stmt (DO_BODY (t));
! 	    finish_do_body (NULL_TREE);
! 	    finish_do_stmt (DO_COND (t), NULL_TREE);
! 	  }
  	  break;
  
  	case IF_STMT:
! 	  begin_if_stmt ();
! 	  finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE);
! 	  if (THEN_CLAUSE (t))
! 	    {
! 	      expand_stmt (THEN_CLAUSE (t));
! 	      finish_then_clause (NULL_TREE);
! 	    }
! 	  if (ELSE_CLAUSE (t))
! 	    {
! 	      begin_else_clause ();
! 	      expand_stmt (ELSE_CLAUSE (t));
! 	      finish_else_clause (NULL_TREE);
! 	    }
! 	  finish_if_stmt ();
  	  break;
  
  	case COMPOUND_STMT:
! 	  begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
! 	  expand_stmt (COMPOUND_BODY (t));
! 	  rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), 
! 				       NULL_TREE);
  	  break;
  
  	case BREAK_STMT:
! 	  finish_break_stmt ();
  	  break;
  
  	case CONTINUE_STMT:
! 	  finish_continue_stmt ();
  	  break;
  
  	case SWITCH_STMT:
! 	  {
! 	    tree cond;
! 
! 	    begin_switch_stmt ();
! 	    cond = expand_cond (SWITCH_COND (t));
! 	    finish_switch_cond (cond, NULL_TREE);
! 	    expand_stmt (SWITCH_BODY (t));
! 	    finish_switch_stmt (cond, NULL_TREE);
! 	  }
  	  break;
  
  	case CASE_LABEL:
! 	  finish_case_label (CASE_LOW (t), CASE_HIGH (t));
  	  break;
  
  	case LABEL_STMT:
--- 2769,2831 ----
        switch (TREE_CODE (t))
  	{
  	case RETURN_STMT:
! 	  genrtl_return_stmt (RETURN_EXPR (t));
  	  break;
  
  	case EXPR_STMT:
! 	  genrtl_expr_stmt (EXPR_STMT_EXPR (t));
  	  break;
  
  	case DECL_STMT:
! 	  genrtl_decl_stmt (t);
  	  break;
  
  	case CLEANUP_STMT:
! 	  genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
  	  break;
  
  	case START_CATCH_STMT:
! 	  genrtl_catch_block (TREE_TYPE (t));
  	  break;
  
  	case CTOR_STMT:
! 	  genrtl_ctor_stmt (t);
  	  break;
  
  	case FOR_STMT:
! 	  genrtl_for_stmt (t);
  	  break;
  
  	case WHILE_STMT:
! 	  genrtl_while_stmt (t);
  	  break;
  
  	case DO_STMT:
! 	  genrtl_do_stmt (t);
  	  break;
  
  	case IF_STMT:
! 	  genrtl_if_stmt (t);
  	  break;
  
  	case COMPOUND_STMT:
! 	  rval = genrtl_compound_stmt (t);
  	  break;
  
  	case BREAK_STMT:
! 	  genrtl_break_stmt ();
  	  break;
  
  	case CONTINUE_STMT:
! 	  genrtl_continue_stmt ();
  	  break;
  
  	case SWITCH_STMT:
! 	  genrtl_switch_stmt (t);
  	  break;
  
  	case CASE_LABEL:
! 	  genrtl_case_label (CASE_LOW (t), CASE_HIGH (t));
  	  break;
  
  	case LABEL_STMT:
*************** expand_stmt (t)
*** 2596,2676 ****
  	  break;
  
  	case GOTO_STMT:
! 	  finish_goto_stmt (GOTO_DESTINATION (t));
  	  break;
  
  	case ASM_STMT:
! 	  finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS
! 			   (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
  	  break;
  
  	case TRY_BLOCK:
! 	  if (CLEANUP_P (t))
! 	    {
! 	      expand_eh_region_start ();
! 	      expand_stmt (TRY_STMTS (t));
! 	      finish_cleanup_try_block (NULL_TREE);
! 	      finish_cleanup (TRY_HANDLERS (t), NULL_TREE);
! 	    }
! 	  else
! 	    {
! 	      if (FN_TRY_BLOCK_P (t))
! 		begin_function_try_block ();
! 	      else
! 		begin_try_block ();
! 
! 	      expand_stmt (TRY_STMTS (t));
! 
! 	      if (FN_TRY_BLOCK_P (t))
! 		{
! 		  finish_function_try_block (NULL_TREE);
! 		  expand_stmt (TRY_HANDLERS (t));
! 		  finish_function_handler_sequence (NULL_TREE);
! 		}
! 	      else
! 		{
! 		  finish_try_block (NULL_TREE);
! 		  expand_stmt (TRY_HANDLERS (t));
! 		  finish_handler_sequence (NULL_TREE);
! 		}
! 	    }
  	  break;
  
  	case HANDLER:
! 	  begin_handler ();
! 	  expand_stmt (HANDLER_BODY (t));
! 	  finish_handler (NULL_TREE, NULL_TREE);
  	  break;
  
  	case SUBOBJECT:
! 	  finish_subobject (SUBOBJECT_CLEANUP (t));
  	  break;
  
  	case SCOPE_STMT:
! 	  if (!SCOPE_NO_CLEANUPS_P (t))
! 	    {
! 	      if (SCOPE_BEGIN_P (t))
! 		expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
! 						 SCOPE_STMT_BLOCK (t));
! 	      else if (SCOPE_END_P (t))
! 		expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
! 	    }
! 	  else if (!SCOPE_NULLIFIED_P (t))
! 	    {
! 	      rtx note = emit_note (NULL,
! 				    (SCOPE_BEGIN_P (t) 
! 				     ? NOTE_INSN_BLOCK_BEG
! 				     : NOTE_INSN_BLOCK_END));
! 	      NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
! 	    }
! 	      
  	  break;
  
  	case RETURN_INIT:
! 	  /* Clear this out so that finish_named_return_value can set it
! 	     again.  */
! 	  DECL_NAME (DECL_RESULT (current_function_decl)) = NULL_TREE;
! 	  finish_named_return_value (TREE_OPERAND (t, 0), 
  				     TREE_OPERAND (t, 1));
  	  break;
  
--- 2833,2864 ----
  	  break;
  
  	case GOTO_STMT:
! 	  genrtl_goto_stmt (GOTO_DESTINATION (t));
  	  break;
  
  	case ASM_STMT:
! 	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
! 			   ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
  	  break;
  
  	case TRY_BLOCK:
! 	  genrtl_try_block (t);
  	  break;
  
  	case HANDLER:
! 	  genrtl_handler (t);
  	  break;
  
  	case SUBOBJECT:
! 	  genrtl_subobject (SUBOBJECT_CLEANUP (t));
  	  break;
  
  	case SCOPE_STMT:
! 	  genrtl_scope_stmt (t);
  	  break;
  
  	case RETURN_INIT:
! 	  genrtl_named_return_value (TREE_OPERAND (t, 0), 
  				     TREE_OPERAND (t, 1));
  	  break;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]