splay-tree.c (splay_tree_predecessor): Fix typo in comment.
authorMark Mitchell <mark@codesourcery.com>
Sun, 17 Sep 2000 07:38:23 +0000 (07:38 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 17 Sep 2000 07:38:23 +0000 (07:38 +0000)
* splay-tree.c (splay_tree_predecessor): Fix typo in comment.

Convert the C front-end to use function-at-a-time mode.
* c-common.h: Include splay-tree.h.
(C_DECLARED_LABEL_FLAG): New macro.
(struct language_function): Add x_scope_stmt_stack and
x_function_name_declared_p.
(RECHAIN_STMTS): Move definition.
(lang_statment_code_p): Likewise.
(lang_expand_stmt): Likewise.
(lang_expand_decl_stmt): New variable.
(lang_expand_function_end): Likewise.
(current_scope_stmt_stack): New function.
(add_decl_stmt): Likewise.
(add_scope_stmt): Likewise.
(mark_stmt_tree): Likewise.
(struct c_lang_decl): New structure.
(DECL_SAVED_TREE): Define.
(c_mark_lang_decl): New function.
(c_expand_start_cond): Change prototype.
(c_finish_then): New function.
(c_finish_else): Likewise.
(current_function_name_declared): Remove.
(set_current_function_name_declared): Likewise.
(mark_c_language_function): Declare.
(case_compare): Likewise.
(c_add_case_label): Likewise.
(c_expand_expr): Likewise.
(c_safe_from_p): Likewise.
* c-common.c (lang_expand_function_end): New variable.
(struct if_elt): Add if_stmt.
(c_expand_start_cond): Add the if-statement to the statement-tree,
rather than generating RTL.
(c_finish_then): New function.
(c_expand_start_else): Don't generate RTL.
(c_finish_else): New function.
(c_expand_expr_stmt): Don't generate RTL.
(statement_code_p): Add SCOPE_STMT.
(case_compare): New function.
(c_add_case_label): Likewise.
(mark_stmt_tree): Likewise.
(c_mark_lang_decl): Likewise.
(mark_c_language_function): Likewise.
(c_expand_expr): Likewise.
(c_safe_from_p): Likewise.
* c-decl.c (c_stmt_tree): New variable
(c_scope_stmt_stack): Likewise.
(c_function_name_declared_p): Likewise.
(lang_expand_expr_stmt): Remove.
(poplevel): Don't call output_inline_function for nested
functions.
(pushdecl): Don't set DECL_CONTEXT for a local declaration of an
`extern' function.
(redeclaration_error_message): Change means of computing whether
or not a function is nested.
(lookup_label): Don't call label_rtx.
(init_decl_processing): Add more GC roots.
(start_decl): Add DECL_STMTs to the statement-tree, rather than
calling rest_of_decl_compilation.
(finish_decl): Don't call expand_decl.
(store_parm_decls): Begin the statement-tree, but don't generate
RTL.
(finish_function): Tie off the statement-tree.  Call c_expand_body
if appropriate.
(c_expand_body): New function.
(push_c_function_context): Save more information.
(pop_c_function_contxt): Likewise.
(copy_lang_decl): Now that we use DECL_LANG_SPECIFIC, copy it.
(lang_mark_tree): Mark it.
(current_stmt_tree): Adjust.
(current_scope_stmt_stack): New function.
(do_case): Remove.
(set_current_name_declared): Likewise.
(c_begin_compound_stmt): Define.
(c_expand_decl_stmt): Likewise.
* c-lang.c: Include rtl.h and expr.h.
(lang_init): Set more language-specific hooks.
* c-lex.c: Include expr.h.
* c-parse.in: Changes throughout to add statements to the
statement-tree, rather than generating RTL after every statement.
* c-semantics.c (lang_expand_decl_stmt): Define.
(add_decl_stmt): New function.
(add_scope_stmt): Likewise.
(finish_stmt_tree): Tweak.
(genrtl_expr_stmt): Likewise.
(genrtl_decl_stmt): Handle local labels, and call
lang_expand_decl_stmt if required.
(genrtl_for_stmt): Fix line-number handling.
(genrtl_case_label): Handle cleanups.
(genrtl_asm_stmt): Don't call combine_strings.
(genrtl_compound_stmt): Simplify.
(expand_stmt): Handle SCOPE_STMTs.
* c-tree.h (struct lang_decl): New structure.
(C_DECLARED_LABEL_FLAG): Remove.
(c_begin_compound_stmt): Declare.
(c_expand_decl_stmt): Likewise.
(c_expand_start_case): Rename to c_start_case.
(c_finish_case): New function.
* c-typeck.c (start_init): Tweak setting of
constructor_incremental.
(c_expand_asm_operands): Tweak error-handling.  Add to the
statement-tree.
(c_expand_return): Add to the statement-tree.
(c_expand_start_case): Rename to ...
(c_start_case): ... this.
(struct c_switch): New type.
(switch_stack): New variable.
(do_case): Simplify.
(c_finish_case): New function.
* dependence.c: Include expr.h.
(enum dependence_type): Change spelling of enumerals.
(check_node_dependence): Adjust.
* expr.h (lang_safe_from_p): Declare.
(safe_from_p): Likewise.
* expr.c (lang_safe_from_p): New variable.
(safe_from_p): Give it external linkage.  Use lang_safe_from_p.
* stmt.c (expand_expr_stmt): Avoid clobberring of last_expr_type.
* toplev.c (rest_of_decl_compilation): Robustify.
* tree.c (contains_placeholder_p): Likewise.
* Makefile.in: Update dependencies.
* objc/objc-act.h: Adjust calculation of value for dummy_tree_code.
* objc/objc-act.c: Include rtl.h, expr.h, and c-common.h.
(objc_expand_function_end): New function.
(finish_method_def): Use it.
(init_objc): Initialize more language-specific hooks.
* objc/Make-lang.in: Update dependencies.

* cp-tree.h (struct cp_language_function): Remove
x_scope_stmt_stack and name_declared.
(current_scope_stmt_stack): Remove.
(function_name_declared_p): New macro.
(struct lang_decl_flags): Use c_lang_decl as a base class.
(context): Remove.
(struct lang_decl): Replace saved_tree with context.
(DECL_FRIEND_CONTEXT): Adjust accordingly.
(SET_DECL_FRIEND_CONTEXT): Likewise.
(DECL_VIRTUAL_CONTEXT): Likewise.
(DECL_SAVED_TREE): Remove.
(C_DECLARED_LABEL_FLAG): Likewise.
(cplus_expand_expr_stmt): Don't declare.
(add_decl_stmt): Likewise.
(add_scope_stmt): Likewise.
* decl.c (mark_stmt_tree): Remove.
(case_compare): Likewise.
(finish_case_label): Use c_add_case_label.
(init_decl_processing): Set more language-specific hooks.
(build_enumerator): Fix typo in comment.
(cplus_expand_expr_stmt): Remove.
(mark_lang_function): Use mark_c_language_function.
(lang_mark_tree): Use c_mark_lang_decl.
* decl2.c: Change order of inclusion.
* except.c: Likewise.
* expr.c (cplus_expand_expr): Remove handling of STMT_EXPR.  Fall
back on c_expand_expr.
* friend.c: Include expr.h.
* init.c: Change order of inclusion.
* Makefile.in: Update dependencies.
* lex.h (free_lang_decl_chain): Remove.
* optimize.c (maybe_clone_body): Use function_name_declared_p.
* pt.c (build_template_decl): Don't copy DECL_VIRTUAL_CONTEXT if
it doesn't exist.
(instantiate_decl): Use function_name_declared_p.
* semantics.c (lang_expand_expr_stmt): Remove.
(set_current_function_name_declared): Likewise.
(current_function_name_declared): Likewise.
(begin_compound_stmt): Use function_name_declared_p.
(add_decl_stmt): Remove.
(setup_vtbl_ptr): Use function_name_declared_p.
(add_scope_stmt): Remove.
(current_scope_stmt_stack): New function.
(cp_expand_stmt): Don't handle SCOPE_STMTs.
(expand_body): Use function_name_declared_p.
* tree.c (cp_statement_code_p): Don't include SCOPE_STMT.
* typeck.c: Change order of includes.
(convert_sequence): Remove.

From-SVN: r36464

38 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/c-lang.c
gcc/c-lex.c
gcc/c-parse.in
gcc/c-semantics.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/friend.c
gcc/cp/init.c
gcc/cp/lex.h
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/dependence.c
gcc/expr.c
gcc/expr.h
gcc/objc/Make-lang.in
gcc/objc/objc-act.c
gcc/objc/objc-act.h
gcc/stmt.c
gcc/testsuite/gcc.dg/noncompile/920923-1.c
gcc/toplev.c
gcc/tree.c
libiberty/ChangeLog
libiberty/splay-tree.c

index 189eb2cf5eb6d6ed62a34da2a8fb9e76b7d89bed..d3a8a6bb80c940834c338536979931078dfacb60 100644 (file)
@@ -1,3 +1,130 @@
+2000-09-16  Mark Mitchell  <mark@codesourcery.com>
+
+       Convert the C front-end to use function-at-a-time mode.
+       * c-common.h: Include splay-tree.h.
+       (C_DECLARED_LABEL_FLAG): New macro.
+       (struct language_function): Add x_scope_stmt_stack and
+       x_function_name_declared_p.
+       (RECHAIN_STMTS): Move definition.
+       (lang_statment_code_p): Likewise.
+       (lang_expand_stmt): Likewise.
+       (lang_expand_decl_stmt): New variable.
+       (lang_expand_function_end): Likewise.
+       (current_scope_stmt_stack): New function.
+       (add_decl_stmt): Likewise.
+       (add_scope_stmt): Likewise.
+       (mark_stmt_tree): Likewise.
+       (struct c_lang_decl): New structure.
+       (DECL_SAVED_TREE): Define.
+       (c_mark_lang_decl): New function.
+       (c_expand_start_cond): Change prototype.
+       (c_finish_then): New function.
+       (c_finish_else): Likewise.
+       (current_function_name_declared): Remove.
+       (set_current_function_name_declared): Likewise.
+       (mark_c_language_function): Declare.
+       (case_compare): Likewise.
+       (c_add_case_label): Likewise.
+       (c_expand_expr): Likewise.
+       (c_safe_from_p): Likewise.
+       * c-common.c (lang_expand_function_end): New variable.
+       (struct if_elt): Add if_stmt.
+       (c_expand_start_cond): Add the if-statement to the statement-tree,
+       rather than generating RTL.
+       (c_finish_then): New function.
+       (c_expand_start_else): Don't generate RTL.
+       (c_finish_else): New function.
+       (c_expand_expr_stmt): Don't generate RTL.
+       (statement_code_p): Add SCOPE_STMT.
+       (case_compare): New function.
+       (c_add_case_label): Likewise.
+       (mark_stmt_tree): Likewise.
+       (c_mark_lang_decl): Likewise.
+       (mark_c_language_function): Likewise.
+       (c_expand_expr): Likewise.
+       (c_safe_from_p): Likewise.
+       * c-decl.c (c_stmt_tree): New variable
+       (c_scope_stmt_stack): Likewise.
+       (c_function_name_declared_p): Likewise.
+       (lang_expand_expr_stmt): Remove.
+       (poplevel): Don't call output_inline_function for nested
+       functions.
+       (pushdecl): Don't set DECL_CONTEXT for a local declaration of an
+       `extern' function.
+       (redeclaration_error_message): Change means of computing whether
+       or not a function is nested.
+       (lookup_label): Don't call label_rtx.
+       (init_decl_processing): Add more GC roots.
+       (start_decl): Add DECL_STMTs to the statement-tree, rather than
+       calling rest_of_decl_compilation.
+       (finish_decl): Don't call expand_decl.
+       (store_parm_decls): Begin the statement-tree, but don't generate
+       RTL.
+       (finish_function): Tie off the statement-tree.  Call c_expand_body
+       if appropriate.
+       (c_expand_body): New function.
+       (push_c_function_context): Save more information.
+       (pop_c_function_contxt): Likewise.
+       (copy_lang_decl): Now that we use DECL_LANG_SPECIFIC, copy it.
+       (lang_mark_tree): Mark it.
+       (current_stmt_tree): Adjust.
+       (current_scope_stmt_stack): New function.
+       (do_case): Remove.
+       (set_current_name_declared): Likewise.
+       (c_begin_compound_stmt): Define.
+       (c_expand_decl_stmt): Likewise.
+       * c-lang.c: Include rtl.h and expr.h.
+       (lang_init): Set more language-specific hooks.
+       * c-lex.c: Include expr.h.
+       * c-parse.in: Changes throughout to add statements to the
+       statement-tree, rather than generating RTL after every statement.
+       * c-semantics.c (lang_expand_decl_stmt): Define.
+       (add_decl_stmt): New function.
+       (add_scope_stmt): Likewise.
+       (finish_stmt_tree): Tweak.
+       (genrtl_expr_stmt): Likewise.
+       (genrtl_decl_stmt): Handle local labels, and call
+       lang_expand_decl_stmt if required.
+       (genrtl_for_stmt): Fix line-number handling.
+       (genrtl_case_label): Handle cleanups.
+       (genrtl_asm_stmt): Don't call combine_strings.
+       (genrtl_compound_stmt): Simplify.
+       (expand_stmt): Handle SCOPE_STMTs.
+       * c-tree.h (struct lang_decl): New structure.
+       (C_DECLARED_LABEL_FLAG): Remove.
+       (c_begin_compound_stmt): Declare.
+       (c_expand_decl_stmt): Likewise.
+       (c_expand_start_case): Rename to c_start_case.
+       (c_finish_case): New function.
+       * c-typeck.c (start_init): Tweak setting of
+       constructor_incremental.
+       (c_expand_asm_operands): Tweak error-handling.  Add to the
+       statement-tree.
+       (c_expand_return): Add to the statement-tree.
+       (c_expand_start_case): Rename to ...
+       (c_start_case): ... this.
+       (struct c_switch): New type.
+       (switch_stack): New variable.
+       (do_case): Simplify.
+       (c_finish_case): New function.
+       * dependence.c: Include expr.h.
+       (enum dependence_type): Change spelling of enumerals.
+       (check_node_dependence): Adjust.
+       * expr.h (lang_safe_from_p): Declare.
+       (safe_from_p): Likewise.
+       * expr.c (lang_safe_from_p): New variable.
+       (safe_from_p): Give it external linkage.  Use lang_safe_from_p.
+       * stmt.c (expand_expr_stmt): Avoid clobberring of last_expr_type.
+       * toplev.c (rest_of_decl_compilation): Robustify.
+       * tree.c (contains_placeholder_p): Likewise.
+       * Makefile.in: Update dependencies.
+       * objc/objc-act.h: Adjust calculation of value for dummy_tree_code.
+       * objc/objc-act.c: Include rtl.h, expr.h, and c-common.h.
+       (objc_expand_function_end): New function.
+       (finish_method_def): Use it.
+       (init_objc): Initialize more language-specific hooks.
+       * objc/Make-lang.in: Update dependencies.
+       
 2000-09-16  Geoffrey Keating  <geoffk@cygnus.com>
 
        * configure.in: Define macros that affect features before
index dd08a84997504e01cf4f41e63a97e90e302e2a9b..2734aebda04a7bec34cb7d759d3d5c5f18e388b0 100644 (file)
@@ -782,6 +782,9 @@ GCC_H = gcc.h version.h
 GGC_H = ggc.h varray.h
 TIMEVAR_H = timevar.h timevar.def
 INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
+C_COMMON_H = c-common.h $(SPLAY_TREE_H)
+C_TREE_H = c-tree.h $(C_COMMON_H)
+
 #\f
 # Language makefile fragments.
 
@@ -1077,10 +1080,10 @@ s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
 
 # C language specific files.
 
-c-errors.o: c-errors.c $(CONFIG_H) system.h $(TREE_H) c-tree.h flags.h \
+c-errors.o: c-errors.c $(CONFIG_H) system.h $(TREE_H) $(C_TREE_H) flags.h \
     diagnostic.h
 c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) c-lex.h $(GGC_H) intl.h \
-    c-tree.h c-common.h input.h flags.h system.h toplev.h output.h cpplib.h
+    $(C_TREE_H) input.h flags.h system.h toplev.h output.h cpplib.h
        $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c $(srcdir)/c-parse.c
 
 $(srcdir)/c-parse.c: $(srcdir)/c-parse.y
@@ -1092,18 +1095,19 @@ $(srcdir)/c-parse.y: c-parse.in
          $(srcdir)/c-parse.in >>tmp-c-parse.y
        $(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y
 
-c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \
-    c-common.h $(GGC_H) c-lex.h flags.h function.h output.h $(EXPR_H) \
+c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) $(C_TREE_H) \
+    $(GGC_H) c-lex.h flags.h function.h output.h $(EXPR_H) \
     toplev.h defaults.h intl.h
-c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
+c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) $(C_TREE_H) \
     flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h
-c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
-    $(GGC_H)  c-lex.h toplev.h diagnostic.h output.h function.h
-c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \
-    c-common.h c-pragma.h input.h intl.h flags.h toplev.h output.h \
-    mbchar.h $(GGC_H) cpplib.h $(SPLAY_TREE_H)
-c-aux-info.o : c-aux-info.c  $(CONFIG_H) system.h $(TREE_H) c-tree.h \
-    c-common.h flags.h toplev.h
+c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) $(C_TREE_H) \
+    $(GGC_H)  c-lex.h toplev.h diagnostic.h output.h function.h \
+    $(RTL_H) $(EXPR_H)
+c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h $(C_TREE_H) \
+    c-pragma.h input.h intl.h flags.h toplev.h output.h \
+    mbchar.h $(GGC_H) cpplib.h $(EXPR_H)
+c-aux-info.o : c-aux-info.c  $(CONFIG_H) system.h $(TREE_H) $(C_TREE_H) \
+    flags.h toplev.h
 c-convert.o : c-convert.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h
 c-pragma.o: c-pragma.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) function.h \
     defaults.h c-pragma.h toplev.h $(GGC_H)
@@ -1157,11 +1161,11 @@ s-under: $(GCC_PASSES)
 # A file used by all variants of C.
 
 c-common.o : c-common.c $(CONFIG_H) system.h $(TREE_H) \
-       c-common.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
+       $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
        $(EXPR_H)
 
-c-semantics.o : c-semantics.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h \
-       c-common.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
+c-semantics.o : c-semantics.c $(CONFIG_H) system.h $(TREE_H) $(C_TREE_H) \
+       c-lex.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
        $(EXPR_H)
 
 # Language-independent files.
@@ -1406,8 +1410,8 @@ regrename.o : regrename.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
 ifcvt.o : ifcvt.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \
    flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \
    output.h
-dependence.o : dependence.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) c-common.h \
-   flags.h varray.h
+dependence.o : dependence.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) \
+   $(C_COMMON_H) flags.h varray.h $(EXPR_H)
 
 $(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) $(GGC_H) \
    $(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
index 2f35541214af7e3dd5af269a3070a8231f92d99c..54335dd7c6bfb04c2c9b1a0a73d3346d1c89196c 100644 (file)
@@ -22,7 +22,6 @@ Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 #include "tree.h"
-#include "c-common.h"
 #include "flags.h"
 #include "toplev.h"
 #include "output.h"
@@ -30,6 +29,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "ggc.h"
 #include "expr.h"
+#include "c-common.h"
 #include "tm_p.h"
 #include "intl.h"
 
@@ -149,6 +149,10 @@ tree (*make_fname_decl)                PARAMS ((tree, const char *, int));
    returns 1 for language-specific statement codes.  */
 int (*lang_statement_code_p)           PARAMS ((enum tree_code));
 
+/* If non-NULL, the address of a language-specific function that takes
+   any action required right before expand_function_end is called.  */
+void (*lang_expand_function_end)       PARAMS ((void));
+
 /* Nonzero means the expression being parsed will never be evaluated.
    This is a count, since unevaluated expressions can nest.  */
 int skip_evaluation;
@@ -181,6 +185,7 @@ typedef struct
   int line;
   const char *file;
   int needs_warning;
+  tree if_stmt;
 } if_elt;
 static void tfaff                      PARAMS ((void));
 
@@ -192,15 +197,16 @@ static int if_stack_space = 0;
 /* Stack pointer.  */
 static int if_stack_pointer = 0;
 
-/* Generate RTL for the start of an if-then, and record the start of it
+/* Record the start of an if-then, and record the start of it
    for ambiguous else detection.  */
 
 void
-c_expand_start_cond (cond, exitflag, compstmt_count)
+c_expand_start_cond (cond, compstmt_count)
      tree cond;
-     int exitflag;
      int compstmt_count;
 {
+  tree if_stmt;
+
   /* Make sure there is enough space on the stack.  */
   if (if_stack_space == 0)
     {
@@ -213,17 +219,29 @@ c_expand_start_cond (cond, exitflag, compstmt_count)
       if_stack = (if_elt *)xrealloc (if_stack, if_stack_space * sizeof (if_elt));
     }
 
+  if_stmt = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+  IF_COND (if_stmt) = cond;
+  add_stmt (if_stmt);
+
   /* Record this if statement.  */
   if_stack[if_stack_pointer].compstmt_count = compstmt_count;
   if_stack[if_stack_pointer].file = input_filename;
   if_stack[if_stack_pointer].line = lineno;
   if_stack[if_stack_pointer].needs_warning = 0;
+  if_stack[if_stack_pointer].if_stmt = if_stmt;
   if_stack_pointer++;
+}
 
-  expand_start_cond (cond, exitflag);
+/* Called after the then-clause for an if-statement is processed.  */
+
+void
+c_finish_then ()
+{
+  tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
+  RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
 }
 
-/* Generate RTL for the end of an if-then.  Optionally warn if a nested
+/* Record the end of an if-then.  Optionally warn if a nested
    if statement had an ambiguous else clause.  */
 
 void
@@ -234,10 +252,10 @@ c_expand_end_cond ()
     warning_with_file_and_line (if_stack[if_stack_pointer].file,
                                if_stack[if_stack_pointer].line,
                                "suggest explicit braces to avoid ambiguous `else'");
-  expand_end_cond ();
+  last_expr_type = NULL_TREE;
 }
 
-/* Generate RTL between the then-clause and the else-clause
+/* Called between the then-clause and the else-clause
    of an if-then-else.  */
 
 void
@@ -256,8 +274,15 @@ c_expand_start_else ()
      case.  Also don't warn for any if statements nested in this else.  */
   if_stack[if_stack_pointer - 1].needs_warning = 0;
   if_stack[if_stack_pointer - 1].compstmt_count--;
+}
+
+/* Called after the else-clause for an if-statement is processed.  */
 
-  expand_start_else ();
+void
+c_finish_else ()
+{
+  tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
+  RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
 }
 
 /* Make bindings for __FUNCTION__, __PRETTY_FUNCTION__, and __func__.  */
@@ -2770,7 +2795,8 @@ c_expand_expr_stmt (expr)
       && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
     error ("expression statement has incomplete type");
 
-  expand_expr_stmt (expr);
+  last_expr_type = TREE_TYPE (expr); 
+  add_stmt (build_stmt (EXPR_STMT, expr));
 }
 \f
 /* Validate the expression after `case' and apply default promotions.  */
@@ -4540,6 +4566,7 @@ statement_code_p (code)
     case RETURN_STMT:
     case BREAK_STMT:
     case CONTINUE_STMT:
+    case SCOPE_STMT:
     case SWITCH_STMT:
     case GOTO_STMT:
     case LABEL_STMT:
@@ -4627,6 +4654,286 @@ walk_stmt_tree (tp, func, data)
 #undef WALK_SUBTREE
 }
 
+/* Used to compare case labels.  K1 and K2 are actually tree nodes
+   representing case labels, or NULL_TREE for a `default' label.
+   Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
+   K2, and 0 if K1 and K2 are equal.  */
+
+int
+case_compare (k1, k2)
+     splay_tree_key k1;
+     splay_tree_key k2;
+{
+  /* Consider a NULL key (such as arises with a `default' label) to be
+     smaller than anything else.  */
+  if (!k1)
+    return k2 ? -1 : 0;
+  else if (!k2)
+    return k1 ? 1 : 0;
+
+  return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
+/* Process a case label for the range LOW_VALUE ... HIGH_VALUE.  If
+   LOW_VALUE and HIGH_VALUE are both NULL_TREE then this case label is
+   actually a `default' label.  If only HIGH_VALUE is NULL_TREE, then
+   case label was declared using the usual C/C++ syntax, rather than
+   the GNU case range extension.  CASES is a tree containing all the
+   case ranges processed so far; COND is the condition for the
+   switch-statement itself.  Returns the CASE_LABEL created, or
+   ERROR_MARK_NODE if no CASE_LABEL is created.  */
+
+tree
+c_add_case_label (cases, cond, low_value, high_value)
+     splay_tree cases;
+     tree cond;
+     tree low_value;
+     tree high_value;
+{
+  tree type;
+  tree label;
+  tree case_label;
+  splay_tree_node node;
+
+  /* Create the LABEL_DECL itself.  */
+  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+  DECL_CONTEXT (label) = current_function_decl;
+
+  /* If there was an error processing the switch condition, bail now
+     before we get more confused.  */
+  if (!cond || cond == error_mark_node)
+    {
+      /* Add a label anyhow so that the back-end doesn't think that
+        the beginning of the switch is unreachable.  */
+      if (!cases->root)
+       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
+      return error_mark_node;
+    }
+
+  if ((low_value && TREE_TYPE (low_value) 
+       && POINTER_TYPE_P (TREE_TYPE (low_value))) 
+      || (high_value && TREE_TYPE (high_value)
+         && POINTER_TYPE_P (TREE_TYPE (high_value))))
+    error ("pointers are not permitted as case values");
+
+  /* Case ranges are a GNU extension.  */
+  if (high_value && pedantic)
+    {
+      if (c_language == clk_cplusplus)
+       pedwarn ("ISO C++ forbids range expressions in switch statements");
+      else
+       pedwarn ("ISO C forbids range expressions in switch statements");
+    }
+
+  type = TREE_TYPE (cond);
+  if (low_value)
+    {
+      low_value = check_case_value (low_value);
+      low_value = convert_and_check (type, low_value);
+    }
+  if (high_value)
+    {
+      high_value = check_case_value (high_value);
+      high_value = convert_and_check (type, high_value);
+    }
+
+  /* If an error has occurred, bail out now.  */
+  if (low_value == error_mark_node || high_value == error_mark_node)
+    {
+      if (!cases->root)
+       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
+      return error_mark_node;
+    }
+
+  /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+     really a case range, even though it was written that way.  Remove
+     the HIGH_VALUE to simplify later processing.  */
+  if (tree_int_cst_equal (low_value, high_value))
+    high_value = NULL_TREE;
+  if (low_value && high_value 
+      && !tree_int_cst_lt (low_value, high_value)) 
+    warning ("empty range specified");
+
+  /* Look up the LOW_VALUE in the table of case labels we already
+     have.  */
+  node = splay_tree_lookup (cases, (splay_tree_key) low_value);
+  /* If there was not an exact match, check for overlapping ranges.
+     There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
+     that's a `default' label and the only overlap is an exact match.  */
+  if (!node && (low_value || high_value))
+    {
+      splay_tree_node low_bound;
+      splay_tree_node high_bound;
+
+      /* Even though there wasn't an exact match, there might be an
+        overlap between this case range and another case range.
+        Since we've (inductively) not allowed any overlapping case
+        ranges, we simply need to find the greatest low case label
+        that is smaller that LOW_VALUE, and the smallest low case
+        label that is greater than LOW_VALUE.  If there is an overlap
+        it will occur in one of these two ranges.  */
+      low_bound = splay_tree_predecessor (cases,
+                                         (splay_tree_key) low_value);
+      high_bound = splay_tree_successor (cases,
+                                        (splay_tree_key) low_value);
+
+      /* Check to see if the LOW_BOUND overlaps.  It is smaller than
+        the LOW_VALUE, so there is no need to check unless the
+        LOW_BOUND is in fact itself a case range.  */
+      if (low_bound
+         && CASE_HIGH ((tree) low_bound->value)
+         && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
+                                   low_value) >= 0)
+       node = low_bound;
+      /* Check to see if the HIGH_BOUND overlaps.  The low end of that
+        range is bigger than the low end of the current range, so we
+        are only interested if the current range is a real range, and
+        not an ordinary case label.  */
+      else if (high_bound 
+              && high_value
+              && (tree_int_cst_compare ((tree) high_bound->key,
+                                        high_value)
+                  <= 0))
+       node = high_bound;
+    }
+  /* If there was an overlap, issue an error.  */
+  if (node)
+    {
+      tree duplicate = CASE_LABEL_DECL ((tree) node->value);
+
+      if (high_value)
+       {
+         error ("duplicate (or overlapping) case value");
+         error_with_decl (duplicate, 
+                          "this is the first entry overlapping that value");
+       }
+      else if (low_value)
+       {
+         error ("duplicate case value") ;
+         error_with_decl (duplicate, "previously used here");
+       }
+      else
+       {
+         error ("multiple default labels in one switch");
+         error_with_decl (duplicate, "this is the first default label");
+       }
+      if (!cases->root)
+       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
+    }
+
+  /* Add a CASE_LABEL to the statement-tree.  */
+  case_label = add_stmt (build_case_label (low_value, high_value, label));
+  /* Register this case label in the splay tree.  */
+  splay_tree_insert (cases, 
+                    (splay_tree_key) low_value,
+                    (splay_tree_value) case_label);
+
+  return case_label;
+}
+
+/* Mark P (a stmt_tree) for GC.  The use of a `void *' for the
+   parameter allows this function to be used as a GC-marking
+   function.  */
+
+void
+mark_stmt_tree (p)
+     void *p;
+{
+  stmt_tree st = (stmt_tree) p;
+
+  ggc_mark_tree (st->x_last_stmt);
+  ggc_mark_tree (st->x_last_expr_type);
+}
+
+/* Mark LD for GC.  */
+
+void
+c_mark_lang_decl (c)
+     struct c_lang_decl *c;
+{
+  ggc_mark_tree (c->saved_tree);
+}
+
+/* Mark F for GC.  */
+
+void
+mark_c_language_function (f)
+     struct language_function *f;
+{
+  if (!f)
+    return;
+
+  mark_stmt_tree (&f->x_stmt_tree);
+  ggc_mark_tree (f->x_scope_stmt_stack);
+}
+
+/* Hook used by expand_expr to expand language-specific tree codes.  */
+
+rtx
+c_expand_expr (exp, target, tmode, modifier)
+     tree exp;
+     rtx target;
+     enum machine_mode tmode;
+     enum expand_modifier modifier;
+{
+  switch (TREE_CODE (exp))
+    {
+    case STMT_EXPR:
+      {
+       tree rtl_expr;
+       rtx result;
+
+       /* Since expand_expr_stmt calls free_temp_slots after every
+          expression statement, we must call push_temp_slots here.
+          Otherwise, any temporaries in use now would be considered
+          out-of-scope after the first EXPR_STMT from within the
+          STMT_EXPR.  */
+       push_temp_slots ();
+       rtl_expr = expand_start_stmt_expr ();
+       expand_stmt (STMT_EXPR_STMT (exp));
+       expand_end_stmt_expr (rtl_expr);
+       result = expand_expr (rtl_expr, target, tmode, modifier);
+       pop_temp_slots ();
+       return result;
+      }
+      break;
+      
+    default:
+      abort ();
+    }
+
+  abort ();
+  return NULL;
+}
+
+/* Hook used by safe_from_p to handle language-specific tree codes.  */
+
+int
+c_safe_from_p (target, exp)
+     rtx target;
+     tree exp;
+{
+  /* We can see statements here when processing the body of a
+     statement-expression.  For a declaration statement declaring a
+     variable, look at the variable's initializer.  */
+  if (TREE_CODE (exp) == DECL_STMT) 
+    {
+      tree decl = DECL_STMT_DECL (exp);
+
+      if (TREE_CODE (decl) == VAR_DECL
+         && DECL_INITIAL (decl)
+         && !safe_from_p (target, DECL_INITIAL (decl), /*top_p=*/0))
+       return 0;
+    }
+
+  /* For any statement, we must follow the statement-chain.  */
+  if (statement_code_p (TREE_CODE (exp)) && TREE_CHAIN (exp))
+    return safe_from_p (target, TREE_CHAIN (exp), /*top_p=*/0);
+
+  /* Assume everything else is safe.  */
+  return 1;
+}
+
 /* Tree code classes. */
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
index 389f32a32333bcb3b78bc267fb7b3c08ecc17a10..2477a0f33aeef40bc0cf7be70efafb8788530e7b 100644 (file)
@@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA.  */
 #ifndef GCC_C_COMMON_H
 #define GCC_C_COMMON_H
 
+#include "splay-tree.h"
+
 /* Usage of TREE_LANG_FLAG_?:
    0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
       TREE_NEGATED_INT (in INTEGER_CST).
@@ -194,6 +196,10 @@ enum c_tree_index
 
 extern tree c_global_trees[CTI_MAX];
 
+/* Mark which labels are explicitly declared.
+   These may be shadowed, and may be referenced from nested functions.  */
+#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
+
 typedef enum c_language_kind
 {
   clk_c,           /* A dialect of C: K&R C, ANSI/ISO C89, C2000,
@@ -237,6 +243,11 @@ struct language_function {
   /* While we are parsing the function, this contains information
      about the statement-tree that we are building.  */
   struct stmt_tree_s x_stmt_tree;
+  /* The stack of SCOPE_STMTs for the current function.  */
+  tree x_scope_stmt_stack;
+  /* Nonzero if __FUNCTION__ and its ilk have been declared in this
+     function.  */
+  int x_function_name_declared_p;
 };
 
 /* When building a statement-tree, this is the last statement added to
@@ -248,6 +259,25 @@ struct language_function {
 
 #define last_expr_type (current_stmt_tree ()->x_last_expr_type)
 
+/* LAST_TREE contains the last statement parsed.  These are chained
+   together through the TREE_CHAIN field, but often need to be
+   re-organized since the parse is performed bottom-up.  This macro
+   makes LAST_TREE the indicated SUBSTMT of STMT.  */
+
+#define RECHAIN_STMTS(stmt, substmt)           \
+  do {                                         \
+    substmt = TREE_CHAIN (stmt);               \
+    TREE_CHAIN (stmt) = NULL_TREE;             \
+    last_tree = stmt;                          \
+  } while (0)
+
+/* Language-specific hooks.  */
+
+extern int (*lang_statement_code_p)             PARAMS ((enum tree_code));
+extern void (*lang_expand_stmt)                 PARAMS ((tree));
+extern void (*lang_expand_decl_stmt)            PARAMS ((tree));
+extern void (*lang_expand_function_end)         PARAMS ((void));
+
 /* The type of a function that walks over tree structure.  */
 
 typedef tree (*walk_tree_fn)                    PARAMS ((tree *, 
@@ -255,30 +285,39 @@ typedef tree (*walk_tree_fn)                    PARAMS ((tree *,
                                                         void *));
 
 extern stmt_tree current_stmt_tree              PARAMS ((void));
+extern tree *current_scope_stmt_stack           PARAMS ((void));
 extern void begin_stmt_tree                     PARAMS ((tree *));
 extern tree add_stmt                           PARAMS ((tree));
+extern void add_decl_stmt                       PARAMS ((tree));
+extern tree add_scope_stmt                      PARAMS ((int, int));
 extern void finish_stmt_tree                    PARAMS ((tree *));
 
 extern int statement_code_p                     PARAMS ((enum tree_code));
-extern int (*lang_statement_code_p)             PARAMS ((enum tree_code));
 extern tree walk_stmt_tree                     PARAMS ((tree *,
                                                         walk_tree_fn,
                                                         void *));
 extern void prep_stmt                           PARAMS ((tree));
-extern void (*lang_expand_stmt)                 PARAMS ((tree));
 extern void expand_stmt                         PARAMS ((tree));
+extern void mark_stmt_tree                      PARAMS ((void *));
 
-/* LAST_TREE contains the last statement parsed.  These are chained
-   together through the TREE_CHAIN field, but often need to be
-   re-organized since the parse is performed bottom-up.  This macro
-   makes LAST_TREE the indicated SUBSTMT of STMT.  */
+/* Extra information associated with a DECL.  Other C dialects extend
+   this structure in various ways.  The C front-end only uses this
+   structure for FUNCTION_DECLs; all other DECLs have a NULL
+   DECL_LANG_SPECIFIC field.  */
 
-#define RECHAIN_STMTS(stmt, substmt)           \
-  do {                                         \
-    substmt = TREE_CHAIN (stmt);               \
-    TREE_CHAIN (stmt) = NULL_TREE;             \
-    last_tree = stmt;                          \
-  } while (0)
+struct c_lang_decl {
+  /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
+  tree saved_tree;
+};
+
+/* In a FUNCTION_DECL, the saved representation of the body of the
+   entire function.  Usually a COMPOUND_STMT, but in C++ this may also
+   be a RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK.  */
+#define DECL_SAVED_TREE(NODE)                                              \
+  (((struct c_lang_decl *) DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))) \
+   ->saved_tree)
+
+extern void c_mark_lang_decl                    PARAMS ((struct c_lang_decl *));
 
 /* The variant of the C language being processed.  Each C language
    front-end defines this variable.  */
@@ -363,8 +402,10 @@ extern void c_apply_type_quals_to_decl             PARAMS ((int, tree));
    NOP_EXPR is used as a special case (see truthvalue_conversion).  */
 extern void binary_op_error                    PARAMS ((enum tree_code));
 extern void c_expand_expr_stmt                 PARAMS ((tree));
-extern void c_expand_start_cond                        PARAMS ((tree, int, int));
+extern void c_expand_start_cond                        PARAMS ((tree, int));
+extern void c_finish_then                       PARAMS ((void));
 extern void c_expand_start_else                        PARAMS ((void));
+extern void c_finish_else                   PARAMS ((void));
 extern void c_expand_end_cond                  PARAMS ((void));
 /* Validate the expression after `case' and apply default promotions.  */
 extern tree check_case_value                   PARAMS ((tree));
@@ -589,8 +630,6 @@ extern void genrtl_asm_stmt                     PARAMS ((tree, tree,
                                                         tree));
 extern void genrtl_decl_cleanup                 PARAMS ((tree, tree));
 extern int stmts_are_full_exprs_p               PARAMS ((void));
-typedef void (*expand_expr_stmt_fn)             PARAMS ((tree));
-extern expand_expr_stmt_fn lang_expand_expr_stmt;
 extern int anon_aggr_type_p                     PARAMS ((tree));
 
 /* For a VAR_DECL that is an anonymous union, these are the various
@@ -611,8 +650,6 @@ extern tree build_return_stmt                   PARAMS ((tree));
 #define COMPOUND_STMT_NO_SCOPE(NODE)   TREE_LANG_FLAG_0 (NODE)
 
 extern void c_expand_asm_operands              PARAMS ((tree, tree, tree, tree, int, const char *, int));
-extern int current_function_name_declared       PARAMS ((void));
-extern void set_current_function_name_declared  PARAMS ((int));
 
 /* These functions must be defined by each front-end which implements
    a variant of the C language.  They are used in c-common.c.  */
@@ -637,6 +674,25 @@ extern tree decl_constant_value            PARAMS ((tree));
    after entering or leaving a header file.  */
 extern void extract_interface_info             PARAMS ((void));
 
+extern void mark_c_language_function            PARAMS ((struct language_function *));
+
+extern int case_compare                         PARAMS ((splay_tree_key, 
+                                                        splay_tree_key));
+
+extern tree c_add_case_label                    PARAMS ((splay_tree,
+                                                        tree, tree,
+                                                        tree));
+
+#ifdef RTX_CODE
+
+extern struct rtx_def *c_expand_expr            PARAMS ((tree, rtx,
+                                                        enum machine_mode,
+                                                        enum expand_modifier));
+
+extern int c_safe_from_p                        PARAMS ((rtx, tree));
+
+#endif
+
 /* Information recorded about each file examined during compilation.  */
 
 struct c_fileinfo
index bc1857c1b345ce29d683535895489b5966a0b798..b8421a7c4bc1db30d2ab9a65db12375b020fe9c6 100644 (file)
@@ -125,6 +125,19 @@ static tree current_function_parm_tags;
 static const char *current_function_prototype_file;
 static int current_function_prototype_line;
 
+/* The current statement tree.  */
+
+static struct stmt_tree_s c_stmt_tree;
+
+/* The current scope statement stack.  */
+
+static tree c_scope_stmt_stack;
+
+/* Nonzero if __FUNCTION__ and its ilk have been declared in this
+   function.  */
+
+static int c_function_name_declared_p;
+
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
@@ -296,6 +309,7 @@ static tree grokdeclarator          PARAMS ((tree, tree, enum decl_context,
 static tree grokparms                  PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
 static tree c_make_fname_decl           PARAMS ((tree, const char *, int));
+static void c_expand_body               PARAMS ((tree, int));
 \f
 /* C-specific option variables.  */
 
@@ -471,10 +485,6 @@ int warn_float_equal = 0;
 
 int warn_multichar = 1;
 
-/* Wrapper since C and C++ expand_expr_stmt are different.  */
-
-expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
-
 /* The variant of the C language being processed.  */
 
 c_language_kind c_language = clk_c;
@@ -1088,12 +1098,6 @@ poplevel (keep, reverse, functionbody)
        if (DECL_ABSTRACT_ORIGIN (decl) != 0
            && DECL_ABSTRACT_ORIGIN (decl) != decl)
          TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else if (DECL_SAVED_INSNS (decl) != 0)
-         {
-           push_function_context ();
-           output_inline_function (decl);
-           pop_function_context ();
-         }
       }
 
   /* If there were any declarations or structure tags in that level,
@@ -1235,6 +1239,7 @@ poplevel (keep, reverse, functionbody)
 
   if (block)
     TREE_USED (block) = 1;
+
   return block;
 }
 
@@ -2063,8 +2068,8 @@ pushdecl (x)
   /* A local extern declaration for a function doesn't constitute nesting.
      A local auto declaration does, since it's a forward decl
      for a nested function coming later.  */
-  if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
-      && DECL_EXTERNAL (x))
+  if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+      && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
     DECL_CONTEXT (x) = 0;
 
   if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
@@ -2618,7 +2623,7 @@ redeclaration_error_message (newdecl, olddecl)
        return 1;
       return 0;
     }
-  else if (current_binding_level == global_binding_level)
+  else if (DECL_CONTEXT (newdecl) == NULL_TREE)
     {
       /* Objects declared at top level:  */
       /* If at least one is a reference, it's ok.  */
@@ -2678,9 +2683,6 @@ lookup_label (id)
 
   decl = build_decl (LABEL_DECL, id, void_type_node);
 
-  /* Make sure every label has an rtx.  */
-  label_rtx (decl);
-
   /* A label not explicitly declared must be local to where it's ref'd.  */
   DECL_CONTEXT (decl) = current_function_decl;
 
@@ -3217,6 +3219,8 @@ init_decl_processing ()
   /* Record our roots.  */
 
   ggc_add_tree_root (c_global_trees, CTI_MAX);
+  ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
+  ggc_add_tree_root (&c_scope_stmt_stack, 1);
   ggc_add_tree_root (&named_labels, 1);
   ggc_add_tree_root (&shadowed_labels, 1);
   ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
@@ -3553,7 +3557,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       /* But not if this is a duplicate decl
         and we preserved the rtl from the previous one
         (which may or may not happen).  */
-      && DECL_RTL (tem) == 0)
+      && DECL_RTL (tem) == 0
+      && !DECL_CONTEXT (tem))
     {
       if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
        expand_decl (tem);
@@ -3703,9 +3708,17 @@ finish_decl (decl, init, asmspec_tree)
     {
       /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
       maybe_objc_check_decl (decl);
-      rest_of_decl_compilation (decl, asmspec,
-                               (DECL_CONTEXT (decl) == 0
-                                || TREE_ASM_WRITTEN (decl)), 0);
+
+      if (!DECL_CONTEXT (decl))
+       rest_of_decl_compilation (decl, asmspec,
+                                 (DECL_CONTEXT (decl) == 0
+                                  || TREE_ASM_WRITTEN (decl)), 0);
+      else
+       {
+         if (asmspec)
+           DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+         add_decl_stmt (decl);
+       }
 
       if (DECL_CONTEXT (decl) != 0)
        {
@@ -3719,11 +3732,7 @@ finish_decl (decl, init, asmspec_tree)
              /* If it's still incomplete now, no init will save it.  */
              if (DECL_SIZE (decl) == 0)
                DECL_INITIAL (decl) = 0;
-             expand_decl (decl);
            }
-         /* Compute and store the initial value.  */
-         if (TREE_CODE (decl) != FUNCTION_DECL)
-           expand_decl_init (decl);
        }
     }
 
@@ -5784,6 +5793,7 @@ build_enumerator (name, value)
 
   return tree_cons (decl, value, NULL_TREE);
 }
+
 \f
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
@@ -6432,25 +6442,20 @@ store_parm_decls ()
 
   init_function_start (fndecl, input_filename, lineno);
 
-  /* If this is a varargs function, inform function.c.  */
-
-  if (c_function_varargs)
-    mark_varargs ();
+  /* Begin the statement tree for this function.  */
+  DECL_LANG_SPECIFIC (current_function_decl) 
+    =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
+  begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
 
-  /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function.  */
-
-  declare_function_name ();
+  /* This function is being processed in whole-function mode.  */
+  cfun->x_whole_function_mode_p = 1;
 
-  /* Set up parameters and prepare for return, for the function.  */
-
-  expand_function_start (fndecl, 0);
-
-  /* If this function is `main', emit a call to `__main'
-     to run global initializers, etc.  */
-  if (DECL_NAME (fndecl)
-      && MAIN_NAME_P (DECL_NAME (fndecl))
-      && DECL_CONTEXT (fndecl) == NULL_TREE)
-    expand_main_function ();
+  /* Even though we're inside a function body, we still don't want to
+     call expand_expr to calculate the size of a variable-sized array.
+     We haven't necessarily assigned RTL to all variables yet, so it's
+     not safe to try to expand expressions involving them.  */
+  immediate_size_expand = 0;
+  cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
 /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
@@ -6650,6 +6655,82 @@ finish_function (nested)
        }
     }
 
+  /* Tie off the statement tree for this function.  */
+  finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  /* Clear out memory we no longer need.  */
+  free_after_parsing (cfun);
+  /* Since we never call rest_of_compilation, we never clear
+     CFUN.  Do so explicitly.  */
+  free_after_compilation (cfun);
+  cfun = NULL;
+
+  if (! nested)
+    {
+      /* Generate RTL for the body of this function.  */
+      c_expand_body (fndecl, nested);
+      /* Let the error reporting routines know that we're outside a
+        function.  For a nested function, this value is used in
+        pop_c_function_context and then reset via pop_function_context.  */
+      current_function_decl = NULL;
+    }
+}
+
+/* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
+   then we are already in the process of generating RTL for another
+   function.  */
+
+static void
+c_expand_body (fndecl, nested_p)
+     tree fndecl;
+     int nested_p;
+{
+  /* Squirrel away our current state.  */
+  if (nested_p)
+    push_function_context ();
+
+  /* Initialize the RTL code for the function.  */
+  current_function_decl = fndecl;
+  init_function_start (fndecl, input_filename, lineno);
+
+  /* This function is being processed in whole-function mode.  */
+  cfun->x_whole_function_mode_p = 1;
+
+  /* Even though we're inside a function body, we still don't want to
+     call expand_expr to calculate the size of a variable-sized array.
+     We haven't necessarily assigned RTL to all variables yet, so it's
+     not safe to try to expand expressions involving them.  */
+  immediate_size_expand = 0;
+  cfun->x_dont_save_pending_sizes_p = 1;
+
+  /* Set up parameters and prepare for return, for the function.  */
+  expand_function_start (fndecl, 0);
+
+  /* If this function is `main', emit a call to `__main'
+     to run global initializers, etc.  */
+  if (DECL_NAME (fndecl)
+      && MAIN_NAME_P (DECL_NAME (fndecl))
+      && DECL_CONTEXT (fndecl) == NULL_TREE)
+    expand_main_function ();
+
+  /* If this is a varargs function, inform function.c.  */
+  if (c_function_varargs)
+    mark_varargs ();
+
+  /* Generate the RTL for this function.  */
+  expand_stmt (DECL_SAVED_TREE (fndecl));
+  /* Allow the body of the function to be garbage collected.  */
+  DECL_SAVED_TREE (fndecl) = NULL_TREE;
+
+  /* We hard-wired immediate_size_expand to zero in start_function.
+     expand_function_end will decrement this variable.  So, we set the
+     variable to one here, so that after the decrement it will remain
+     zero.  */
+  immediate_size_expand = 1;
+
+  /* Allow language dialects to perform special processing.  */
+  if (lang_expand_function_end)
+    (*lang_expand_function_end) ();
+
   /* Generate rtl for function exit.  */
   expand_function_end (input_filename, lineno, 0);
 
@@ -6658,14 +6739,14 @@ finish_function (nested)
 
   /* If this is a nested function, protect the local variables in the stack
      above us from being collected while we're compiling this function.  */
-  if (nested)
+  if (nested_p)
     ggc_push_context ();
 
   /* Run the optimizers and output the assembler code for this function.  */
   rest_of_compilation (fndecl);
 
   /* Undo the GC context switch.  */
-  if (nested)
+  if (nested_p)
     ggc_pop_context ();
 
   current_function_returns_null |= can_reach_end;
@@ -6715,7 +6796,7 @@ finish_function (nested)
        }
     }
 
-  if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
+  if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
     {
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
@@ -6748,13 +6829,20 @@ finish_function (nested)
        assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
     }
 
-  if (! nested)
+  if (nested_p)
     {
-      /* Let the error reporting routines know that we're outside a
-        function.  For a nested function, this value is used in
-        pop_c_function_context and then reset via pop_function_context.  */
-      current_function_decl = NULL;
+      /* Return to the enclosing function.  */
+      pop_function_context ();
+      /* If the nested function was inline, write it out if that is
+        necessary.  */
+      if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
+       {
+         push_function_context ();
+         output_inline_function (fndecl);
+         pop_function_context ();
+       }
     }
+      
 }
 \f
 /* Save and restore the variables in this file and elsewhere
@@ -6785,6 +6873,9 @@ push_c_function_context (f)
        xmalloc (sizeof (struct c_language_function)));
   f->language = (struct language_function *) p;
 
+  p->base.x_stmt_tree = c_stmt_tree;
+  p->base.x_scope_stmt_stack = c_scope_stmt_stack;
+  p->base.x_function_name_declared_p = c_function_name_declared_p;
   p->named_labels = named_labels;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
@@ -6810,7 +6901,8 @@ pop_c_function_context (f)
       IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
        = TREE_VALUE (link);
 
-  if (DECL_SAVED_INSNS (current_function_decl) == 0)
+  if (DECL_SAVED_INSNS (current_function_decl) == 0
+      && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
     {
       /* Stop pointing to the local nodes about to be freed.  */
       /* But DECL_INITIAL must remain nonzero so we know this
@@ -6819,6 +6911,9 @@ pop_c_function_context (f)
       DECL_ARGUMENTS (current_function_decl) = 0;
     }
 
+  c_stmt_tree = p->base.x_stmt_tree;
+  c_scope_stmt_stack = p->base.x_scope_stmt_stack;
+  c_function_name_declared_p = p->base.x_function_name_declared_p;
   named_labels = p->named_labels;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
@@ -6843,18 +6938,27 @@ mark_c_function_context (f)
   if (p == 0)
     return;
 
+  mark_c_language_function (&p->base);
   ggc_mark_tree (p->shadowed_labels);
   ggc_mark_tree (p->named_labels);
   mark_binding_level (&p->binding_level);
 }
 
-/* integrate_decl_tree calls this function, but since we don't use the
-   DECL_LANG_SPECIFIC field, this is a no-op.  */
+/* Copy the DECL_LANG_SEPECIFIC data associated with NODE.  */
 
 void
-copy_lang_decl (node)
-     tree node ATTRIBUTE_UNUSED;
+copy_lang_decl (decl)
+     tree decl;
 {
+  struct lang_decl *ld;
+
+  if (!DECL_LANG_SPECIFIC (decl))
+    return;
+
+  ld = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl));
+  bcopy ((char *)DECL_LANG_SPECIFIC (decl), (char *)ld, 
+        sizeof (struct lang_decl));
+  DECL_LANG_SPECIFIC (decl) = ld;
 }
 
 /* Mark ARG for GC.  */
@@ -6886,6 +6990,11 @@ lang_mark_tree (t)
     }
   else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
     ggc_mark (TYPE_LANG_SPECIFIC (t));
+  else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+    {
+      ggc_mark (DECL_LANG_SPECIFIC (t));
+      c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+    }
 }
 
 /* The functions below are required for functionality of doing
@@ -6910,7 +7019,15 @@ stmts_are_full_exprs_p ()
 stmt_tree
 current_stmt_tree ()
 {
-  return cfun ? &cfun->language->x_stmt_tree : NULL;
+  return &c_stmt_tree;
+}
+
+/* Returns the stack of SCOPE_STMTs for the current function.  */
+
+tree *
+current_scope_stmt_stack ()
+{
+  return &c_scope_stmt_stack;
 }
 
 /* Nonzero if TYPE is an anonymous union or struct type.  Always 0 in
@@ -6923,94 +7040,46 @@ anon_aggr_type_p (node)
   return 0;
 }
 
-/* One if we have already declared __FUNCTION__ (and related
-   variables) in the current function.  Two if we are in the process
-   of doing so.  */
+/* Dummy function in place of callback used by C++.  */
 
-int
-current_function_name_declared ()
+void
+extract_interface_info ()
 {
-  abort ();
-  return 0;
 }
 
-/* Code to generate the RTL for a case label in C.  */
+/* Return a new COMPOUND_STMT, after adding it to the current
+   statement tree.  */
 
-void
-do_case (low_value, high_value)
-     tree low_value;
-     tree high_value;
+tree
+c_begin_compound_stmt ()
 {
-  tree value1 = NULL_TREE, value2 = NULL_TREE, label;
-
-  if (low_value != NULL_TREE)
-    value1 = check_case_value (low_value);
-  if (high_value != NULL_TREE)
-    value2 = check_case_value (high_value);
-
-  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+  tree stmt;
 
-  if (pedantic && (high_value != NULL_TREE))
-    pedwarn ("ISO C forbids case ranges");
-
-  if (value1 != error_mark_node && value2 != error_mark_node)
+  /* Create the COMPOUND_STMT.  */
+  stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
+  /* If we haven't already declared __FUNCTION__ and its ilk then this
+     is the opening curly brace of the function.  Declare them now.  */
+  if (!c_function_name_declared_p) 
     {
-      tree duplicate;
-      int success;
-
-      if (high_value == NULL_TREE && value1 != NULL_TREE &&
-         pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value1)))
-       pedwarn ("label must have integral type in ISO C");
-
-      if (low_value == NULL_TREE)
-       success = pushcase (NULL_TREE, 0, label, &duplicate);
-      else if (high_value == NULL_TREE)
-       success = pushcase (value1, convert_and_check, label, &duplicate);
-      else
-       success = pushcase_range (value1, value2, convert_and_check,
-                                 label, &duplicate);
-
-      if (success == 1)
-       {
-         if (low_value == NULL_TREE)
-           error ("default label not within a switch statement");
-         else
-           error ("case label not within a switch statement");
-       }
-      else if (success == 2)
-       {
-         if (low_value == NULL_TREE)
-           {
-             error ("multiple default labels in one switch");
-             error_with_decl (duplicate, "this is the first default label");
-           }
-         else
-           error ("duplicate case value");
-         if (high_value != NULL_TREE)
-           error_with_decl (duplicate,
-                            "this is the first entry for that value");
-       }
-      else if (low_value != NULL_TREE)
-       {
-         if (success == 3)
-           warning ("case value out of range");
-         else if (success == 5)
-           error ("case label within scope of cleanup or variable array");
-       }
+      c_function_name_declared_p = 1;
+      declare_function_name ();
     }
+  
+  return stmt;
 }
 
-/* Accessor to set the 'current_function_name_declared' flag.  */
+/* Expand T (a DECL_STMT) if it declares an entity not handled by the
+   common code.  */
 
 void
-set_current_function_name_declared (i)
-     int i ATTRIBUTE_UNUSED;
-{
-  abort ();
-}
-
-/* Dummy function in place of callback used by C++.  */
-void
-extract_interface_info ()
+c_expand_decl_stmt (t)
+     tree t;
 {
+  tree decl = DECL_STMT_DECL (t);
+  
+  /* Expand nested functions.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_CONTEXT (decl) == current_function_decl
+      && DECL_SAVED_TREE (decl))
+    c_expand_body (decl, /*nested_p=*/1);
 }
index f8dd30b8f4398d04b40afce77b822bf7fcd111ad..21b8f0f273b6b501e45943fbe1c29874a7af02fb 100644 (file)
@@ -25,13 +25,15 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "function.h"
 #include "input.h"
-#include "c-tree.h"
-#include "c-lex.h"
 #include "toplev.h"
 #include "diagnostic.h"
 #include "output.h"
 #include "flags.h"
 #include "ggc.h"
+#include "rtl.h"
+#include "expr.h"
+#include "c-tree.h"
+#include "c-lex.h"
 
 static int c_tree_printer PARAMS ((output_buffer *));
 
@@ -88,8 +90,10 @@ lang_init ()
   save_lang_status = &push_c_function_context;
   restore_lang_status = &pop_c_function_context;
   mark_lang_status = &mark_c_function_context;
-
-  lang_printer = c_tree_printer;
+  lang_expand_expr = &c_expand_expr;
+  lang_safe_from_p = &c_safe_from_p;
+  lang_printer = &c_tree_printer;
+  lang_expand_decl_stmt = &c_expand_decl_stmt;
 
   c_parse_init ();
 }
index f9c5cb432f94af8739f8628b8a03adf0c0103ee6..f853fd067e9be84b7f3b24edf9679e394a2c40f0 100644 (file)
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 
 #include "rtl.h"
+#include "expr.h"
 #include "tree.h"
 #include "input.h"
 #include "output.h"
index 7f0fbd577df9d7afb1d344f8a96c92912a7e7d58..c590f31ae32f63eeab1bef43af4199e95a7c794a 100644 (file)
@@ -173,7 +173,8 @@ end ifc
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
 %type <ttype> any_word extension
 
-%type <ttype> compstmt compstmt_nostart compstmt_primary_start
+%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
+%type <ttype> do_stmt_start poplevel
 
 %type <ttype> declarator
 %type <ttype> notype_declarator after_type_declarator
@@ -661,33 +662,26 @@ primary:
        | '(' error ')'
                { $$ = error_mark_node; }
        | compstmt_primary_start compstmt_nostart ')'
-               { tree rtl_exp;
-                 if (pedantic)
-                   pedwarn ("ISO C forbids braced-groups within expressions");
+                 { tree saved_last_tree;
+
+                  if (pedantic)
+                    pedwarn ("ISO C forbids braced-groups within expressions");
                  pop_label_level ();
-                 rtl_exp = expand_end_stmt_expr ($1);
-                 /* The statements have side effects, so the group does.  */
-                 TREE_SIDE_EFFECTS (rtl_exp) = 1;
 
-                 if (TREE_CODE ($2) == BLOCK)
-                   {
-                     /* Make a BIND_EXPR for the BLOCK already made.  */
-                     $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
-                                 NULL_TREE, rtl_exp, $2);
-                     /* Remove the block from the tree at this point.
-                        It gets put back at the proper place
-                        when the BIND_EXPR is expanded.  */
-                     delete_block ($2);
-                   }
-                 else
-                   $$ = $2;
+                 saved_last_tree = COMPOUND_BODY ($1);
+                 RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+                 last_tree = saved_last_tree;
+                 TREE_CHAIN (last_tree) = NULL_TREE;
+                 if (!last_expr_type)
+                   last_expr_type = void_type_node;
+                 $$ = build1 (STMT_EXPR, last_expr_type, $1);
+                 TREE_SIDE_EFFECTS ($$) = 1;
                }
        | compstmt_primary_start error ')'
                {
-                 /* Make sure we call expand_end_stmt_expr.  Otherwise
-                    we are likely to lose sequences and crash later.  */
                  pop_label_level ();
-                 expand_end_stmt_expr ($1);
+                 last_tree = COMPOUND_BODY ($1);
+                 TREE_CHAIN (last_tree) = NULL_TREE;
                  $$ = error_mark_node;
                }
        | primary '(' exprlist ')'   %prec '.'
@@ -1196,8 +1190,10 @@ nested_function:
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
          compstmt
-               { finish_function (1);
-                 pop_function_context (); }
+               { tree decl = current_function_decl;
+                 finish_function (1);
+                 pop_function_context (); 
+                 add_decl_stmt (decl); }
        ;
 
 notype_nested_function:
@@ -1222,8 +1218,10 @@ notype_nested_function:
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
          compstmt
-               { finish_function (1);
-                 pop_function_context (); }
+               { tree decl = current_function_decl;
+                 finish_function (1);
+                 pop_function_context (); 
+                 add_decl_stmt (decl); }
        ;
 
 /* Any kind of declarator (thus, all declarators allowed
@@ -1604,10 +1602,9 @@ errstmt:  error ';'
        ;
 
 pushlevel:  /* empty */
-               { emit_line_note (input_filename, lineno);
-                 pushlevel (0);
+               { pushlevel (0);
                  clear_last_expr ();
-                 expand_start_bindings (0);
+                 add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
 ifobjc
                  if (objc_method_context)
                    add_objc_decls ();
@@ -1615,6 +1612,9 @@ end ifobjc
                }
        ;
 
+poplevel:  /* empty */
+                { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+
 /* Read zero or more forward-declarations for labels
    that nested functions can jump to.  */
 maybe_label_decls:
@@ -1636,7 +1636,7 @@ label_decl:
                    {
                      tree label = shadow_label (TREE_VALUE (link));
                      C_DECLARED_LABEL_FLAG (label) = 1;
-                     declare_nonlocal_label (label);
+                     add_decl_stmt (label);
                    }
                }
        ;
@@ -1649,22 +1649,26 @@ compstmt_or_error:
        | error compstmt
        ;
 
-compstmt_start: '{' { compstmt_count++; }
+compstmt_start: '{' { compstmt_count++;
+                      $$ = c_begin_compound_stmt (); } 
 
 compstmt_nostart: '}'
                { $$ = convert (void_type_node, integer_zero_node); }
-       | pushlevel maybe_label_decls decls xstmts '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), 1, 0);
-                 $$ = poplevel (1, 1, 0); }
-       | pushlevel maybe_label_decls error '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0); }
-       | pushlevel maybe_label_decls stmts '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0); }
+       | pushlevel maybe_label_decls decls xstmts '}' poplevel
+               { $$ = poplevel (1, 1, 0); 
+                 SCOPE_STMT_BLOCK (TREE_PURPOSE ($6)) 
+                   = SCOPE_STMT_BLOCK (TREE_VALUE ($6))
+                   = $$; }
+       | pushlevel maybe_label_decls error '}' poplevel
+               { $$ = poplevel (kept_level_p (), 0, 0); 
+                 SCOPE_STMT_BLOCK (TREE_PURPOSE ($5)) 
+                   = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
+                   = $$; }
+       | pushlevel maybe_label_decls stmts '}' poplevel
+               { $$ = poplevel (kept_level_p (), 0, 0); 
+                 SCOPE_STMT_BLOCK (TREE_PURPOSE ($5)) 
+                   = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
+                   = $$; }
        ;
 
 compstmt_primary_start:
@@ -1680,17 +1684,19 @@ compstmt_primary_start:
                     that are contained in it.  */
                  keep_next_level ();
                  push_label_level ();
-                 $$ = expand_start_stmt_expr ();
                  compstmt_count++;
+                 $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
                }
 
 compstmt: compstmt_start compstmt_nostart
-               { $$ = $2; }
+               { RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); 
+                  $$ = $2; }
        ;
 
 /* Value is number of statements counted as of the closeparen.  */
 simple_if:
          if_prefix lineno_labeled_stmt
+                { c_finish_then (); }
 /* Make sure c_expand_end_cond is run once
    for each call to c_expand_start_cond.
    Otherwise a crash is likely.  */
@@ -1699,8 +1705,7 @@ simple_if:
 
 if_prefix:
          IF '(' expr ')'
-               { emit_line_note ($<filename>-1, $<lineno>0);
-                 c_expand_start_cond (truthvalue_conversion ($3), 0, 
+               { c_expand_start_cond (truthvalue_conversion ($3), 
                                       compstmt_count);
                  $<itype>$ = stmt_count;
                  if_stmt_file = $<filename>-1;
@@ -1714,12 +1719,17 @@ do_stmt_start:
          DO
                { stmt_count++;
                  compstmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* See comment in `while' alternative, above.  */
-                 emit_nop ();
-                 expand_start_loop_continue_elsewhere (1); }
+                 $<ttype>$ 
+                   = add_stmt (build_stmt (DO_STMT, NULL_TREE,
+                                           NULL_TREE));
+                 /* In the event that a parse error prevents
+                    parsing the complete do-statement, set the
+                    condition now.  Otherwise, we can get crashes at
+                    RTL-generation time.  */
+                 DO_COND ($<ttype>$) = error_mark_node; }
          lineno_labeled_stmt WHILE
-               { expand_loop_continue_here (); }
+               { $$ = $<ttype>2;
+                 RECHAIN_STMTS ($$, DO_BODY ($$)); }
        ;
 
 /* The forced readahead in here is because we might be at the end of a
@@ -1765,25 +1775,13 @@ stmt:
                { stmt_count++; }
        | expr ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-/* It appears that this should not be done--that a non-lvalue array
-   shouldn't get an error if the value isn't used.
-   Section 3.2.2.1 says that an array lvalue gets converted to a pointer
-   if it appears as a top-level expression,
-   but says nothing about non-lvalue arrays.  */
-#if 0
-                 /* Call default_conversion to get an error
-                    on referring to a register array if pedantic.  */
-                 if (TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE
-                     || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
-                   $1 = default_conversion ($1);
-#endif
-                 expand_expr_stmt ($1); }
+                 c_expand_expr_stmt ($1); }
        | simple_if ELSE
                { c_expand_start_else ();
                  $<itype>1 = stmt_count; }
          lineno_labeled_stmt
-               { c_expand_end_cond ();
+                { c_finish_else ();
+                 c_expand_end_cond ();
                  if (extra_warnings && stmt_count == $<itype>1)
                    warning ("empty body in an else-statement"); }
        | simple_if %prec IF
@@ -1801,83 +1799,43 @@ stmt:
        | simple_if ELSE error
                { c_expand_end_cond (); }
        | WHILE
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* The emit_nop used to come before emit_line_note,
-                    but that made the nop seem like part of the preceding line.
-                    And that was confusing when the preceding line was
-                    inside of an if statement and was not really executed.
-                    I think it ought to work to put the nop after the line number.
-                    We will see.  --rms, July 15, 1991.  */
-                 emit_nop (); }
+                { stmt_count++; }
          '(' expr ')'
-               { /* Don't start the loop till we have succeeded
-                    in parsing the end test.  This is to make sure
-                    that we end every loop we start.  */
-                 expand_start_loop (1);
-                 emit_line_note (input_filename, lineno);
-                 expand_exit_loop_if_false (NULL_PTR,
-                                            truthvalue_conversion ($4)); }
+                { $4 = truthvalue_conversion ($4);
+                 $<ttype>$ 
+                   = add_stmt (build_stmt (WHILE_STMT, $4, NULL_TREE)); }
          lineno_labeled_stmt
-               { expand_end_loop (); }
+               { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
        | do_stmt_start
          '(' expr ')' ';'
-               { emit_line_note (input_filename, lineno);
-                 expand_exit_loop_if_false (NULL_PTR,
-                                            truthvalue_conversion ($3));
-                 expand_end_loop (); }
-/* This rule is needed to make sure we end every loop we start.  */
+                { DO_COND ($1) = truthvalue_conversion ($3); }
        | do_stmt_start error
-               { expand_end_loop (); }
+               { }
        | FOR
          '(' xexpr ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* See comment in `while' alternative, above.  */
-                 emit_nop ();
-                 if ($3) c_expand_expr_stmt ($3);
-                 /* Next step is to call expand_start_loop_continue_elsewhere,
-                    but wait till after we parse the entire for (...).
-                    Otherwise, invalid input might cause us to call that
-                    fn without calling expand_end_loop.  */
+                 $3 = build_stmt (EXPR_STMT, $3); 
+                 $<ttype>$ = build_stmt (FOR_STMT, $3, NULL_TREE,
+                                         NULL_TREE, NULL_TREE);
+                 add_stmt ($<ttype>$);
                }
          xexpr ';'
-               /* Can't emit now; wait till after expand_start_loop...  */
-               { $<lineno>7 = lineno;
-                 $<filename>$ = input_filename; }
+                { FOR_COND ($<ttype>5) = $6; }
          xexpr ')'
-               { 
-                 /* Start the loop.  Doing this after parsing
-                    all the expressions ensures we will end the loop.  */
-                 expand_start_loop_continue_elsewhere (1);
-                 /* Emit the end-test, with a line number.  */
-                 emit_line_note ($<filename>8, $<lineno>7);
-                 if ($6)
-                   expand_exit_loop_if_false (NULL_PTR,
-                                              truthvalue_conversion ($6));
-                 $<lineno>7 = lineno;
-                 $<filename>8 = input_filename; }
+               { FOR_EXPR ($<ttype>5) = $9; }
          lineno_labeled_stmt
-               { /* Emit the increment expression, with a line number.  */
-                 emit_line_note ($<filename>8, $<lineno>7);
-                 expand_loop_continue_here ();
-                 if ($9)
-                   c_expand_expr_stmt ($9);
-                 expand_end_loop (); }
+                { RECHAIN_STMTS ($<ttype>5, FOR_BODY ($<ttype>5)); }
        | SWITCH '(' expr ')'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 c_expand_start_case ($3); }
+                 $<ttype>$ = c_start_case ($3); }
          lineno_labeled_stmt
-               { expand_end_case ($3); }
+                { c_finish_case (); }
        | BREAK ';'
-               { build_break_stmt ();
-                 stmt_count++;
-                 genrtl_break_stmt (); }
+               { stmt_count++;
+                 add_stmt (build_break_stmt ()); }
        | CONTINUE ';'
-                { build_continue_stmt ();
-                  stmt_count++;
-                 genrtl_continue_stmt (); }
+                { stmt_count++;
+                 add_stmt (build_continue_stmt ()); }
        | RETURN ';'
                 { stmt_count++;
                  c_expand_return (NULL_TREE); }
@@ -1886,25 +1844,29 @@ stmt:
                  c_expand_return ($2); }
        | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  STRIP_NOPS ($4);
                  if ((TREE_CODE ($4) == ADDR_EXPR
                       && TREE_CODE (TREE_OPERAND ($4, 0)) == STRING_CST)
                      || TREE_CODE ($4) == STRING_CST)
-                   expand_asm ($4);
+                   {
+                     if (TREE_CODE ($4) == ADDR_EXPR)
+                       $4 = TREE_OPERAND ($4, 0);
+                     if (TREE_CHAIN ($4))
+                       $4 = combine_strings ($4);
+                     add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
+                                           NULL_TREE, NULL_TREE, NULL_TREE));
+                   }
                  else
                    error ("argument of `asm' is not a constant string"); }
        /* This is the case with just output operands.  */
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
        /* This is the case with input operands as well.  */
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, $8, NULL_TREE,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
@@ -1912,27 +1874,25 @@ stmt:
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
          asm_operands ':' asm_clobbers ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, $8, $10,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
        | GOTO identifier ';'
                { tree decl;
                  stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  decl = lookup_label ($2);
                  if (decl != 0)
                    {
                      TREE_USED (decl) = 1;
-                     expand_goto (decl);
+                     add_stmt (build_stmt (GOTO_STMT, decl));
                    }
                }
        | GOTO '*' expr ';'
                { if (pedantic)
                    pedwarn ("ISO C forbids `goto *expr;'");
                  stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 expand_computed_goto (convert (ptr_type_node, $3)); }
+                 $3 = convert (ptr_type_node, $3);
+                 add_stmt (build_stmt (GOTO_STMT, $3)); }
        | ';'
        ;
 
@@ -1952,11 +1912,10 @@ label:    CASE expr_no_commas ':'
        | identifier save_filename save_lineno ':' maybe_attribute
                { tree label = define_label ($2, $3, $1);
                  stmt_count++;
-                 emit_nop ();
                  if (label)
                    {
-                     expand_label (label);
                      decl_attributes (label, $5, NULL_TREE);
+                     add_stmt (build_stmt (LABEL_STMT, label));
                    }
                }
        ;
index f1b54c4cfd2eef29408fd01fd30ac8663c2e3911..b349bd383e91c146057ec054bbceb4d2f05ae88a 100644 (file)
@@ -40,6 +40,13 @@ Boston, MA 02111-1307, USA.  */
    expanding statements.  */
 void (*lang_expand_stmt) PARAMS ((tree));
 
+/* If non-NULL, the address of a language-specific function for
+   expanding a DECL_STMT.  After the language-independent cases are
+   handled, this function will be called.  If this function is not
+   defined, it is assumed that declarations other than those for
+   variables and labels do not require any RTL generation.  */
+void (*lang_expand_decl_stmt) PARAMS ((tree));
+
 static tree prune_unused_decls PARAMS ((tree *, int *, void *));
 
 /* Create an empty statement tree rooted at T.  */
@@ -71,6 +78,63 @@ add_stmt (t)
   return t;
 }
 
+/* Create a declaration statement for the declaration given by the
+   DECL.  */
+
+void
+add_decl_stmt (decl)
+     tree decl;
+{
+  tree decl_stmt;
+
+  /* We need the type to last until instantiation time.  */
+  decl_stmt = build_stmt (DECL_STMT, decl);
+  add_stmt (decl_stmt); 
+}
+
+/* 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
+   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
+   returns a new TREE_LIST representing the top of the SCOPE_STMT
+   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
+   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
+   and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
+   SCOPE_BEGIN_P set.  */
+
+tree
+add_scope_stmt (begin_p, partial_p)
+     int begin_p;
+     int partial_p;
+{
+  tree ss;
+  tree top;
+
+  /* Build the statement.  */
+  ss = build_stmt (SCOPE_STMT, NULL_TREE);
+  SCOPE_BEGIN_P (ss) = begin_p;
+  SCOPE_PARTIAL_P (ss) = partial_p;
+
+  /* Keep the scope stack up to date.  */
+  if (begin_p)
+    {
+      *current_scope_stmt_stack () 
+       = tree_cons (ss, NULL_TREE, *current_scope_stmt_stack ());
+      top = *current_scope_stmt_stack ();
+    }
+  else
+    {
+      top = *current_scope_stmt_stack ();
+      TREE_VALUE (top) = ss;
+      *current_scope_stmt_stack () = TREE_CHAIN (top);
+    }
+
+  /* Add the new statement to the statement-tree.  */
+  add_stmt (ss);
+
+  return top;
+}
+
 /* Remove declarations of internal variables that are not used from a
    stmt tree.  To qualify, the variable must have a name and must have
    a zero DECL_SOURCE_LINE.  We tried to remove all variables for
@@ -145,7 +209,7 @@ finish_stmt_tree (t)
   /* Remove unused decls from the stmt tree.  */
   walk_stmt_tree (t, prune_unused_decls, NULL);
 
-  if (cfun)
+  if (cfun && stmt)
     {
       /* The line-number recorded in the outermost statement in a function
         is the line number of the end of the function.  */
@@ -305,7 +369,8 @@ genrtl_expr_stmt (expr)
       if (stmts_are_full_exprs_p ())
        expand_start_target_temps ();
       
-      lang_expand_expr_stmt (expr);
+      if (expr != error_mark_node)
+       expand_expr_stmt (expr);
       
       if (stmts_are_full_exprs_p ())
        expand_end_target_temps ();
@@ -348,6 +413,11 @@ genrtl_decl_stmt (t)
       else
        make_rtl_for_local_static (decl);
     }
+  else if (TREE_CODE (decl) == LABEL_DECL 
+          && C_DECLARED_LABEL_FLAG (decl))
+    declare_nonlocal_label (decl);
+  else if (lang_expand_decl_stmt)
+    (*lang_expand_decl_stmt) (t);
 }
 
 /* Generate the RTL for T, which is an IF_STMT. */
@@ -448,30 +518,43 @@ void
 genrtl_for_stmt (t)
      tree t;
 {
-  tree tmp;
   tree cond;
+  const char *saved_filename;
+  int saved_lineno;
+
   if (NEW_FOR_SCOPE_P (t))
     genrtl_do_pushlevel ();
 
   expand_stmt (FOR_INIT_STMT (t));
 
+  /* Expand the initialization.  */
   emit_nop ();
   emit_line_note (input_filename, lineno);
   expand_start_loop_continue_elsewhere (1); 
   genrtl_do_pushlevel ();
   cond = expand_cond (FOR_COND (t));
+
+  /* Save the filename and line number so that we expand the FOR_EXPR
+     we can reset them back to the saved values.  */
+  saved_filename = input_filename;
+  saved_lineno = lineno;
+
+  /* Expand the condition.  */
   emit_line_note (input_filename, lineno);
   if (cond)
     expand_exit_loop_if_false (0, cond);
-  genrtl_do_pushlevel ();
-  tmp = FOR_EXPR (t);
 
+  /* Expand the body.  */
+  genrtl_do_pushlevel ();
   expand_stmt (FOR_BODY (t));
 
+  /* Expand the increment expression.  */
+  input_filename = saved_filename;
+  lineno = saved_lineno;
   emit_line_note (input_filename, lineno);
   expand_loop_continue_here ();
-  if (tmp) 
-    genrtl_expr_stmt (tmp);
+  if (FOR_EXPR (t))
+    genrtl_expr_stmt (FOR_EXPR (t));
   expand_end_loop ();
 }
 
@@ -575,6 +658,22 @@ genrtl_case_label (case_label)
      tree case_label;
 {
   tree duplicate;
+  tree cleanup;
+
+  cleanup = last_cleanup_this_contour ();
+  if (cleanup)
+    {
+      static int explained = 0;
+      warning_with_decl (TREE_PURPOSE (cleanup), 
+                        "destructor needed for `%#D'");
+      warning ("where case label appears here");
+      if (!explained)
+       {
+         warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
+         explained = 1;
+       }
+    }
+
   add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 
                 CASE_LABEL_DECL (case_label), &duplicate);
 }
@@ -585,16 +684,6 @@ void
 genrtl_compound_stmt (t)
     tree t;
 {
-  /* If this is the outermost block of the function, declare the
-     variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
-  if (cfun
-      && !current_function_name_declared () 
-      && !COMPOUND_STMT_NO_SCOPE (t))
-    {
-      set_current_function_name_declared (1);
-      declare_function_name ();
-    } 
-
   expand_stmt (COMPOUND_BODY (t));
 }
 
@@ -609,9 +698,6 @@ genrtl_asm_stmt (cv_qualifier, string, output_operands,
      tree input_operands;
      tree clobbers;
 {
-  if (TREE_CHAIN (string))
-    string = combine_strings (string);
-
   if (cv_qualifier != NULL_TREE
       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
     {
@@ -733,6 +819,10 @@ expand_stmt (t)
                           ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
          break;
 
+       case SCOPE_STMT:
+         genrtl_scope_stmt (t);
+         break;
+
        default:
          if (lang_expand_stmt)
            (*lang_expand_stmt) (t);
index 92f0b4533290e9d46fe1bac278ba05a547349eb3..5531731010e2ae318c8d0fcaf872c710fd4b1c7c 100644 (file)
@@ -42,6 +42,14 @@ struct lang_identifier
   enum rid rid_code;
 };
 
+/* Wrapping c_lang_decl in another struct is an unfortunate
+   necessity.  */
+
+struct lang_decl
+{
+  struct c_lang_decl base;
+};
+
 /* Macros for access to language-specific slots in an identifier.  */
 /* Each of these slots contains a DECL node or null.  */
 
@@ -103,10 +111,6 @@ struct lang_type
   tree elts[1];
 };
 
-/* Mark which labels are explicitly declared.
-   These may be shadowed, and may be referenced from nested functions.  */
-#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
-
 /* Record whether a type or decl was written with nonconstant size.
    Note that TYPE_SIZE may have simplified to a constant.  */
 #define C_TYPE_VARIABLE_SIZE(type) TYPE_LANG_FLAG_1 (type)
@@ -230,6 +234,8 @@ extern tree start_decl                          PARAMS ((tree, tree, int,
 extern tree start_struct                        PARAMS ((enum tree_code, tree));
 extern void store_parm_decls                    PARAMS ((void));
 extern tree xref_tag                            PARAMS ((enum tree_code, tree));
+extern tree c_begin_compound_stmt               PARAMS ((void));
+extern void c_expand_decl_stmt                  PARAMS ((tree));
 
 /* in c-typeck.c */
 extern tree require_complete_type              PARAMS ((tree));
@@ -268,7 +274,8 @@ extern void set_init_label                  PARAMS ((tree));
 extern void process_init_element               PARAMS ((tree));
 extern void pedwarn_c99                                PARAMS ((const char *, ...))
                                                        ATTRIBUTE_PRINTF_1;
-extern tree c_expand_start_case                 PARAMS ((tree));
+extern tree c_start_case                        PARAMS ((tree));
+extern void c_finish_case                       PARAMS ((void));
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
index 002d4e704fe9121f44fc28e69efbf785c27b2995..f4b42b991a50793ed1bd4cde343abe373708a835 100644 (file)
@@ -4999,7 +4999,8 @@ start_init (decl, asmspec_tree, top_level)
               || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
               || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
       locus = IDENTIFIER_POINTER (DECL_NAME (decl));
-      constructor_incremental |= TREE_STATIC (decl);
+      constructor_incremental 
+       |= (TREE_STATIC (decl) && !DECL_CONTEXT (decl));
     }
   else
     {
@@ -6541,7 +6542,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
 
   if (TREE_CODE (string) == ADDR_EXPR)
     string = TREE_OPERAND (string, 0);
-  if (TREE_CODE (string) != STRING_CST)
+  if (last_tree && TREE_CODE (string) != STRING_CST)
     {
       error ("asm template is not a string constant");
       return;
@@ -6567,7 +6568,8 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
             || TREE_CODE (output) == FIX_CEIL_EXPR)
        output = TREE_OPERAND (output, 0);
 
-      lvalue_or_else (o[i], "invalid lvalue in asm statement");
+      if (last_tree)
+       lvalue_or_else (o[i], "invalid lvalue in asm statement");
     }
 
   /* Perform default conversions on array and function inputs.  */
@@ -6578,6 +6580,14 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
        || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
       TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
 
+  if (last_tree)
+    {
+      add_stmt (build_stmt (ASM_STMT, 
+                           vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
+                           string, outputs, inputs, clobbers));
+      return;
+    }
+
   /* Generate the ASM_OPERANDS insn;
      store into the TREE_VALUEs of OUTPUTS some trees for
      where the values were actually stored.  */
@@ -6703,53 +6713,115 @@ c_expand_return (retval)
       current_function_returns_value = 1;
     }
 
 genrtl_return_stmt (build_return_stmt (retval));
add_stmt (build_return_stmt (retval));
 }
 \f
-/* Start a C switch statement, testing expression EXP.
-   Return EXP if it is valid, an error node otherwise.  */
+struct c_switch {
+  /* The SWITCH_STMT being built.  */
+  tree switch_stmt;
+  /* A splay-tree mapping the low element of a case range to the high
+     element, or NULL_TREE if there is no high element.  Used to
+     determine whether or not a new case label duplicates an old case
+     label.  We need a tree, rather than simply a hash table, because
+     of the GNU case range extension.  */
+  splay_tree cases;
+  /* The next node on the stack.  */
+  struct c_switch *next;
+};
+
+/* A stack of the currently active switch statements.  The innermost
+   switch statement is on the top of the stack.  There is no need to
+   mark the stack for garbage collection because it is only active
+   during the processing of the body of a function, and we never
+   collect at that point.  */
+
+static struct c_switch *switch_stack;
+
+/* Start a C switch statement, testing expression EXP.  Return the new
+   SWITCH_STMT.  */
 
 tree
-c_expand_start_case (exp)
+c_start_case (exp)
      tree exp;
 {
   register enum tree_code code;
   tree type;
+  struct c_switch *cs;
 
-  if (TREE_CODE (exp) == ERROR_MARK)
-    return exp;
+  if (exp != error_mark_node)
+    {
+      code = TREE_CODE (TREE_TYPE (exp));
+      type = TREE_TYPE (exp);
 
-  code = TREE_CODE (TREE_TYPE (exp));
-  type = TREE_TYPE (exp);
+      if (code != INTEGER_TYPE 
+         && code != ENUMERAL_TYPE 
+         && code != ERROR_MARK)
+       {
+         error ("switch quantity not an integer");
+         exp = integer_zero_node;
+       }
+      else
+       {
+         tree index;
+         type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
 
-  if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
-    {
-      error ("switch quantity not an integer");
-      exp = error_mark_node;
+         if (warn_traditional && !in_system_header
+             && (type == long_integer_type_node
+                 || type == long_unsigned_type_node))
+           warning ("`long' switch expression not converted to `int' in ISO C");
+
+         exp = default_conversion (exp);
+         type = TREE_TYPE (exp);
+         index = get_unwidened (exp, NULL_TREE);
+         /* 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 (exp))
+             == TREE_UNSIGNED (TREE_TYPE (index)))
+           exp = index;
+       }
     }
+
+  /* Add this new SWITCH_STMT to the stack.  */
+  cs = (struct c_switch *) xmalloc (sizeof (cs));
+  cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, NULL_TREE);
+  cs->cases = splay_tree_new (case_compare, NULL, NULL);
+  cs->next = switch_stack;
+  switch_stack = cs;
+
+  return add_stmt (switch_stack->switch_stmt);
+}
+
+/* Process a case label.  */
+
+void
+do_case (low_value, high_value)
+     tree low_value;
+     tree high_value;
+{
+  if (switch_stack)
+    c_add_case_label (switch_stack->cases, 
+                     SWITCH_COND (switch_stack->switch_stmt), 
+                     low_value, 
+                     high_value);
+  else if (low_value)
+    error ("case label not within a switch statement");
   else
-    {
-      tree index;
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+    error ("`default' label not within a switch statement");
+}
 
-      if (warn_traditional && !in_system_header
-         && (type == long_integer_type_node
-             || type == long_unsigned_type_node))
-       warning ("`long' switch expression not converted to `int' in ISO C");
+/* Finish the switch statement.  */
 
-      exp = default_conversion (exp);
-      type = TREE_TYPE (exp);
-      index = get_unwidened (exp, NULL_TREE);
-      /* 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 (exp))
-         == TREE_UNSIGNED (TREE_TYPE (index)))
-       exp = index;
-    }
+void
+c_finish_case ()
+{
+  struct c_switch *cs = switch_stack;
 
-  expand_start_case (1, exp, type, "switch statement");
+  RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt)); 
 
-  return exp;
+  /* Pop the stack.  */
+  switch_stack = switch_stack->next;
+  splay_tree_delete (cs->cases);
+  free (cs);
 }
index f54d9b305049717aaba631599cc10f0d6790b672..66e39759b8ee2cf0503b8b908a3a17786c5760e3 100644 (file)
@@ -1,3 +1,54 @@
+2000-09-16  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (struct cp_language_function): Remove
+       x_scope_stmt_stack and name_declared.
+       (current_scope_stmt_stack): Remove.
+       (function_name_declared_p): New macro.
+       (struct lang_decl_flags): Use c_lang_decl as a base class.
+       (context): Remove.
+       (struct lang_decl): Replace saved_tree with context.
+       (DECL_FRIEND_CONTEXT): Adjust accordingly.
+       (SET_DECL_FRIEND_CONTEXT): Likewise.
+       (DECL_VIRTUAL_CONTEXT): Likewise.
+       (DECL_SAVED_TREE): Remove.
+       (C_DECLARED_LABEL_FLAG): Likewise.
+       (cplus_expand_expr_stmt): Don't declare.
+       (add_decl_stmt): Likewise.
+       (add_scope_stmt): Likewise.
+       * decl.c (mark_stmt_tree): Remove.
+       (case_compare): Likewise.
+       (finish_case_label): Use c_add_case_label.
+       (init_decl_processing): Set more language-specific hooks.
+       (build_enumerator): Fix typo in comment.
+       (cplus_expand_expr_stmt): Remove.
+       (mark_lang_function): Use mark_c_language_function.
+       (lang_mark_tree): Use c_mark_lang_decl.
+       * decl2.c: Change order of inclusion.
+       * except.c: Likewise.
+       * expr.c (cplus_expand_expr): Remove handling of STMT_EXPR.  Fall
+       back on c_expand_expr.
+       * friend.c: Include expr.h.
+       * init.c: Change order of inclusion.
+       * Makefile.in: Update dependencies.
+       * lex.h (free_lang_decl_chain): Remove.
+       * optimize.c (maybe_clone_body): Use function_name_declared_p.
+       * pt.c (build_template_decl): Don't copy DECL_VIRTUAL_CONTEXT if
+       it doesn't exist.
+       (instantiate_decl): Use function_name_declared_p.
+       * semantics.c (lang_expand_expr_stmt): Remove.
+       (set_current_function_name_declared): Likewise.
+       (current_function_name_declared): Likewise.
+       (begin_compound_stmt): Use function_name_declared_p.
+       (add_decl_stmt): Remove.
+       (setup_vtbl_ptr): Use function_name_declared_p.
+       (add_scope_stmt): Remove.
+       (current_scope_stmt_stack): New function.
+       (cp_expand_stmt): Don't handle SCOPE_STMTs.
+       (expand_body): Use function_name_declared_p.
+       * tree.c (cp_statement_code_p): Don't include SCOPE_STMT.
+       * typeck.c: Change order of includes.
+       (convert_sequence): Remove.
+       
 2000-09-14  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * lex.c (reswords): Add _Complex.
index 839e5748e2d4b6a58716a68cbcc2879c5cb4e121..b81c4f025e301575aab990707b0185e2587dbb04 100644 (file)
@@ -265,7 +265,7 @@ class.o : class.c $(CXX_TREE_H) $(srcdir)/../flags.h \
 call.o : call.c $(CXX_TREE_H) $(srcdir)/../flags.h \
   $(srcdir)/../toplev.h $(RTL_H) $(EXPR_H) $(GGC_H)
 friend.o : friend.c $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
-  $(srcdir)/../toplev.h
+  $(srcdir)/../toplev.h $(EXPR_H)
 init.o : init.c $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
   $(EXPR_H) $(srcdir)/../toplev.h $(GGC_H) \
   $(srcdir)/../except.h
index de76e5293f5d26d45512a74b531294112f9c05e5..b7bc919791ba4e9a1995be3f8bc4171c41463224 100644 (file)
@@ -878,7 +878,6 @@ struct cp_language_function
   tree x_current_class_ptr;
   tree x_current_class_ref;
   tree x_eh_spec_try_block;
-  tree x_scope_stmt_stack;
   tree x_in_charge_parm;
 
   tree *x_vcalls_possible_p;
@@ -889,7 +888,6 @@ struct cp_language_function
   int returns_null;
   int in_function_try_handler;
   int x_expanding_p;
-  int name_declared;
   int vtbls_set_up_p;
 
   struct named_label_use_list *x_named_label_uses;
@@ -928,10 +926,6 @@ struct cp_language_function
 
 #define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block
 
-/* The stack of SCOPE_STMTs for the current function.  */
-
-#define current_scope_stmt_stack cp_function_chain->x_scope_stmt_stack
-
 /* The `__in_chrg' parameter for the current function.  Only used for
    destructors.  */
 
@@ -978,6 +972,12 @@ struct cp_language_function
 
 #define in_function_try_handler cp_function_chain->in_function_try_handler
 
+/* Nonzero if __FUNCTION__ and its ilk have been declared in this
+   function.  */
+
+#define function_name_declared_p \
+  (cp_function_chain->base.x_function_name_declared_p)
+
 extern tree current_function_return_value;
 extern tree global_namespace;
 
@@ -1811,6 +1811,8 @@ struct lang_type
 
 struct lang_decl_flags
 {
+  struct c_lang_decl base;
+
   ENUM_BITFIELD(languages) language : 8;
 
   unsigned operator_attr : 1;
@@ -1839,8 +1841,6 @@ struct lang_decl_flags
   unsigned generate_with_vtable_p : 1;
   unsigned dummy : 1;
 
-  tree context;
-
   union {
     /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
        is DECL_TEMPLATE_INFO.  */
@@ -1872,8 +1872,9 @@ struct lang_decl
 
   tree befriending_classes;
 
-  /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
-  tree saved_tree;
+  /* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT.  For a
+     non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT.  */
+  tree context;
 
   /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
   tree cloned_function;
@@ -2168,12 +2169,12 @@ struct lang_decl
    the DECL_FRIEND_CONTEXT for `f' will be `S'.  */
 #define DECL_FRIEND_CONTEXT(NODE)                              \
   ((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE))    \
-   ? DECL_LANG_SPECIFIC (NODE)->decl_flags.context              \
+   ? DECL_LANG_SPECIFIC (NODE)->context                         \
    : NULL_TREE)
 
 /* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT.  */
 #define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.context = (CONTEXT))
+  (DECL_LANG_SPECIFIC (NODE)->context = (CONTEXT))
 
 /* NULL_TREE in DECL_CONTEXT represents the global namespace. */
 #define CP_DECL_CONTEXT(NODE) \
@@ -2183,7 +2184,7 @@ struct lang_decl
 /* For a virtual function, the base where we find its vtable entry.
    For a non-virtual function, the base where it is defined.  */
 #define DECL_VIRTUAL_CONTEXT(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.context)
+  (DECL_LANG_SPECIFIC (NODE)->context)
 
 /* 1 iff NODE has namespace scope, including the global namespace.  */
 #define DECL_NAMESPACE_SCOPE_P(NODE)                           \
@@ -2409,12 +2410,6 @@ struct lang_decl
    the class definition is complete.  */
 #define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
 
-/* In a FUNCTION_DECL, the saved representation of the body of the
-   entire function.  Usually a COMPOUND_STMT, but this may also be a
-   RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK.  */
-#define DECL_SAVED_TREE(NODE) \
-  (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->saved_tree)
-
 /* In a FUNCTION_DECL, the saved language-specific per-function data.  */
 #define DECL_SAVED_FUNCTION_DATA(NODE) \
   (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->u.saved_language_function)
@@ -2532,10 +2527,6 @@ extern int flag_new_for_scope;
 #define ARITHMETIC_TYPE_P(TYPE) \
   (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE)
 
-/* Mark which labels are explicitly declared.
-   These may be shadowed, and may be referenced from nested functions.  */
-#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
-
 /* Nonzero for _TYPE means that the _TYPE defines
    at least one constructor.  */
 #define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE))
@@ -3904,7 +3895,6 @@ extern tree start_method                  PARAMS ((tree, tree, tree));
 extern tree finish_method                      PARAMS ((tree));
 extern void hack_incomplete_structures         PARAMS ((tree));
 extern tree maybe_build_cleanup                        PARAMS ((tree));
-extern void cplus_expand_expr_stmt             PARAMS ((tree));
 extern void finish_stmt                                PARAMS ((void));
 extern void replace_defarg                     PARAMS ((tree, tree));
 extern void print_other_binding_stack          PARAMS ((struct binding_level *));
@@ -4356,12 +4346,10 @@ extern tree finish_base_specifier               PARAMS ((tree, tree));
 extern void finish_member_declaration           PARAMS ((tree));
 extern void check_multiple_declarators          PARAMS ((void));
 extern tree finish_typeof                      PARAMS ((tree));
-extern void add_decl_stmt                       PARAMS ((tree));
 extern void finish_decl_cleanup                 PARAMS ((tree, tree));
 extern void finish_named_return_value           PARAMS ((tree, tree));
 extern void expand_body                         PARAMS ((tree));
 extern void prep_stmt                           PARAMS ((tree));
-extern tree add_scope_stmt                      PARAMS ((int, int));
 extern void do_pushlevel                        PARAMS ((void));
 extern tree do_poplevel                         PARAMS ((void));
 extern void finish_mem_initializers             PARAMS ((tree));
index 4430d55cc24fc2e616fcb165bf0f3efb2bc561ee..3b2a0573b53609218ac99d5b5d55da617c9662bb 100644 (file)
@@ -159,7 +159,6 @@ static void mark_named_label_lists PARAMS ((void *, void *));
 static void mark_cp_function_context PARAMS ((struct function *));
 static void mark_saved_scope PARAMS ((void *));
 static void mark_lang_function PARAMS ((struct cp_language_function *));
-static void mark_stmt_tree PARAMS ((stmt_tree));
 static void save_function_data PARAMS ((tree));
 static void check_function_type PARAMS ((tree, tree));
 static void destroy_local_var PARAMS ((tree));
@@ -176,7 +175,6 @@ static tree check_special_function_return_type
   PARAMS ((special_function_kind, tree, tree, tree));
 static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
 static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
-static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
 static void store_parm_decls PARAMS ((tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
@@ -2411,16 +2409,6 @@ pop_nested_namespace (ns)
    scope isn't enough, because more binding levels may be pushed.  */
 struct saved_scope *scope_chain;
 
-/* Mark ST for GC.  */
-
-static void
-mark_stmt_tree (st)
-     stmt_tree st;
-{
-  ggc_mark_tree (st->x_last_stmt);
-  ggc_mark_tree (st->x_last_expr_type);
-}
-
 /* Mark ARG (which is really a struct saved_scope **) for GC.  */
 
 static void
@@ -5156,21 +5144,6 @@ struct cp_switch
    
 static struct cp_switch *switch_stack;
 
-static int
-case_compare (k1, k2)
-     splay_tree_key k1;
-     splay_tree_key k2;
-{
-  /* Consider a NULL key (such as arises with a `default' label) to be
-     smaller than anything else.  */
-  if (!k1)
-    return k2 ? -1 : 0;
-  else if (!k2)
-    return k1 ? 1 : 0;
-
-  return tree_int_cst_compare ((tree) k1, (tree) k2);
-}
-
 /* Called right after a switch-statement condition is parsed.
    SWITCH_STMT is the switch statement being parsed.  */
 
@@ -5206,12 +5179,7 @@ finish_case_label (low_value, high_value)
      tree low_value;
      tree high_value;
 {
-  tree label;
-  tree cleanup;
-  tree type;
   tree cond;
-  tree case_label;
-  splay_tree_node node;
 
   if (! switch_stack)
     {
@@ -5225,13 +5193,13 @@ finish_case_label (low_value, high_value)
       return;
     }
 
-  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-  DECL_CONTEXT (label) = current_function_decl;
-
   if (processing_template_decl)
     {
+      tree label;
+
       /* For templates, just add the case label; we'll do semantic
         analysis at instantiation-time.  */
+      label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       add_stmt (build_case_label (low_value, high_value, label));
       return;
     }
@@ -5240,124 +5208,8 @@ finish_case_label (low_value, high_value)
   cond = SWITCH_COND (switch_stack->switch_stmt);
   if (cond && TREE_CODE (cond) == TREE_LIST)
     cond = TREE_VALUE (cond);
-  /* If there was an error processing the switch condition, bail now
-     before we get more confused.  */
-  if (!cond || cond == error_mark_node)
-    return;
-  type = TREE_TYPE (cond);
-
-  if ((low_value && TREE_TYPE (low_value) 
-       && POINTER_TYPE_P (TREE_TYPE (low_value))) 
-      || (high_value && TREE_TYPE (high_value)
-         && POINTER_TYPE_P (TREE_TYPE (high_value))))
-    error ("pointers are not permitted as case values");
 
-  /* Case ranges are a GNU extension.  */
-  if (high_value && pedantic)
-    pedwarn ("ISO C++ forbids range expressions in switch statement");
-
-  if (low_value)
-    {
-      low_value = check_case_value (low_value);
-      low_value = convert_and_check (type, low_value);
-    }
-  if (high_value)
-    {
-      high_value = check_case_value (high_value);
-      high_value = convert_and_check (type, high_value);
-    }
-
-  /* If an error has occurred, bail out now.  */
-  if (low_value == error_mark_node || high_value == error_mark_node)
-    return;
-
-  /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
-     really a case range, even though it was written that way.  Remove
-     the HIGH_VALUE to simplify later processing.  */
-  if (tree_int_cst_equal (low_value, high_value))
-    high_value = NULL_TREE;
-  if (low_value && high_value 
-      && !tree_int_cst_lt (low_value, high_value)) 
-    warning ("empty range specified");
-
-  /* Look up the LOW_VALUE in the table of case labels we already
-     have.  */
-  node = splay_tree_lookup (switch_stack->cases, (splay_tree_key) low_value);
-  /* If there was not an exact match, check for overlapping ranges.
-     There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
-     that's a `default' label and the only overlap is an exact match.  */
-  if (!node && (low_value || high_value))
-    {
-      splay_tree_node low_bound;
-      splay_tree_node high_bound;
-
-      /* Even though there wasn't an exact match, there might be an
-        overlap between this case range and another case range.
-        Since we've (inductively) not allowed any overlapping case
-        ranges, we simply need to find the greatest low case label
-        that is smaller that LOW_VALUE, and the smallest low case
-        label that is greater than LOW_VALUE.  If there is an overlap
-        it will occur in one of these two ranges.  */
-      low_bound = splay_tree_predecessor (switch_stack->cases,
-                                         (splay_tree_key) low_value);
-      high_bound = splay_tree_successor (switch_stack->cases,
-                                        (splay_tree_key) low_value);
-
-      /* Check to see if the LOW_BOUND overlaps.  It is smaller than
-        the LOW_VALUE, so there is no need to check unless the
-        LOW_BOUND is in fact itself a case range.  */
-      if (low_bound
-         && CASE_HIGH ((tree) low_bound->value)
-         && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
-                                   low_value) >= 0)
-       node = low_bound;
-      /* Check to see if the HIGH_BOUND overlaps.  The low end of that
-        range is bigger than the low end of the current range, so we
-        are only interested if the current range is a real range, and
-        not an ordinary case label.  */
-      else if (high_bound 
-              && high_value
-              && (tree_int_cst_compare ((tree) high_bound->key,
-                                        high_value)
-                  <= 0))
-       node = high_bound;
-    }
-  /* If there was an overlap, issue an error.  */
-  if (node)
-    {
-      tree duplicate = CASE_LABEL_DECL ((tree) node->value);
-
-      if (high_value)
-       {
-         error ("duplicate (or overlapping) case value");
-         cp_error_at ("this is the first entry overlapping that value",
-                      duplicate);
-       }
-      else if (low_value)
-       {
-         cp_error ("duplicate case value `%E'", low_value) ;
-         cp_error_at ("previously used here", duplicate);
-       }
-      else
-       {
-         error ("multiple default labels in one switch");
-         cp_error_at ("this is the first default label", duplicate);
-       }
-      return;
-    }
-
-  cleanup = last_cleanup_this_contour ();
-  if (cleanup)
-    {
-      static int explained = 0;
-      cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
-      warning ("where case label appears here");
-      if (!explained)
-       {
-         warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
-         explained = 1;
-       }
-    }
+  c_add_case_label (switch_stack->cases, cond, low_value, high_value);
 
   check_switch_goto (switch_stack->level);
 
@@ -5365,16 +5217,6 @@ finish_case_label (low_value, high_value)
      own new (temporary) binding contour.  */
   current_binding_level->more_cleanups_ok = 0;
   current_function_return_value = NULL_TREE;
-
-  /* Add a representation for the case label to the statement
-     tree.  */
-  case_label = build_case_label (low_value, high_value, label);
-  add_stmt (case_label);
-
-  /* Register this case label in the splay tree.  */
-  splay_tree_insert (switch_stack->cases, 
-                    (splay_tree_key) low_value,
-                    (splay_tree_value) case_label);
 }
 \f
 /* Return the list of declarations of the current level.
@@ -6462,11 +6304,11 @@ init_decl_processing ()
   /* Create all the identifiers we need.  */
   initialize_predefined_identifiers ();
 
-  /* Let the back-end now how to save and restore language-specific
-     per-function globals.  */
+  /* Fill in back-end hooks.  */
   init_lang_status = &push_cp_function_context;
   free_lang_status = &pop_cp_function_context;
   mark_lang_status = &mark_cp_function_context;
+  lang_safe_from_p = &c_safe_from_p;
 
   cp_parse_init ();
   init_decl2 ();
@@ -13557,7 +13399,7 @@ build_enumerator (name, value, enumtype)
 
   if (context && context == current_class_type)
     /* This enum declaration is local to the class.  We need the full
-      lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
+       lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
     decl = build_lang_decl (CONST_DECL, name, type);
   else
     /* It's a global enum, or it's local to a function.  (Note local to
@@ -14696,31 +14538,6 @@ maybe_build_cleanup (decl)
   return 0;
 }
 \f
-/* Expand a C++ expression at the statement level.
-   This is needed to ferret out nodes which have UNKNOWN_TYPE.
-   The C++ type checker should get all of these out when
-   expressions are combined with other, type-providing, expressions,
-   leaving only orphan expressions, such as:
-
-   &class::bar;                / / takes its address, but does nothing with it.  */
-
-void
-cplus_expand_expr_stmt (exp)
-     tree exp;
-{
-#if 0
-  /* We should do this eventually, but right now this causes regex.o from
-     libg++ to miscompile, and tString to core dump.  */
-  exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
-#endif
-
-  /* If we don't do this, we end up down inside expand_expr
-     trying to do TYPE_MODE on the ERROR_MARK, and really
-     go outside the bounds of the type.  */
-  if (exp != error_mark_node)
-    expand_expr_stmt (exp);
-}
-
 /* When a stmt has been parsed, this function is called.  */
 
 void
@@ -14801,17 +14618,17 @@ mark_lang_function (p)
   if (!p)
     return;
 
+  mark_c_language_function (&p->base);
+
   ggc_mark_tree (p->x_ctor_label);
   ggc_mark_tree (p->x_dtor_label);
   ggc_mark_tree (p->x_current_class_ptr);
   ggc_mark_tree (p->x_current_class_ref);
   ggc_mark_tree (p->x_eh_spec_try_block);
-  ggc_mark_tree (p->x_scope_stmt_stack);
 
   ggc_mark_rtx (p->x_result_rtx);
 
   mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
-  mark_stmt_tree (&p->base.x_stmt_tree);
   mark_binding_level (&p->bindings);
 }
 
@@ -14872,13 +14689,13 @@ lang_mark_tree (t)
       if (ld)
        {
          ggc_mark (ld);
+         c_mark_lang_decl (&ld->decl_flags.base);
          if (!DECL_GLOBAL_CTOR_P (t) 
              && !DECL_GLOBAL_DTOR_P (t)
              && !DECL_THUNK_P (t))
            ggc_mark_tree (ld->decl_flags.u2.access);
          else if (DECL_THUNK_P (t))
            ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
-         ggc_mark_tree (ld->decl_flags.context);
          if (TREE_CODE (t) != NAMESPACE_DECL)
            ggc_mark_tree (ld->decl_flags.u.template_info);
          else
@@ -14886,7 +14703,7 @@ lang_mark_tree (t)
          if (CAN_HAVE_FULL_LANG_DECL_P (t))
            {
              ggc_mark_tree (ld->befriending_classes);
-             ggc_mark_tree (ld->saved_tree);
+             ggc_mark_tree (ld->context);
              ggc_mark_tree (ld->cloned_function);
              if (!DECL_OVERLOADED_OPERATOR_P (t))
                ggc_mark_tree (ld->u2.vtt_parm);
index a2cdb1dd7c941efed974efbd60f1a2ce3479bb53..b579f5976f8fe880141f5a98c11a4beb6f69bf22 100644 (file)
@@ -32,13 +32,13 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
 #include "lex.h"
 #include "output.h"
 #include "except.h"
-#include "expr.h"
 #include "defaults.h"
 #include "toplev.h"
 #include "dwarf2out.h"
index e8728592d31fc2f708dd12a9dd0973c81b918890..ee2cf44675cf7f0b3c65284067dbf3e7a86c9042 100644 (file)
@@ -27,10 +27,10 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "obstack.h"
-#include "expr.h"
 #include "output.h"
 #include "except.h"
 #include "defaults.h"
index 39095ec17db9950f24d4163ee35f211cfc7fcb46..c49a2f93583cf835e02ab3e6a7154849c1c79d74 100644 (file)
@@ -133,28 +133,8 @@ cplus_expand_expr (exp, target, tmode, modifier)
       /* We don't need to generate any code for an empty class.  */
       return const0_rtx;
 
-    case STMT_EXPR:
-      {
-       tree rtl_expr;
-       rtx result;
-
-       /* Since expand_expr_stmt calls free_temp_slots after every
-          expression statement, we must call push_temp_slots here.
-          Otherwise, any temporaries in use now would be considered
-          out-of-scope after the first EXPR_STMT from within the
-          STMT_EXPR.  */
-       push_temp_slots ();
-       rtl_expr = expand_start_stmt_expr ();
-       expand_stmt (STMT_EXPR_STMT (exp));
-       expand_end_stmt_expr (rtl_expr);
-       result = expand_expr (rtl_expr, target, tmode, modifier);
-       pop_temp_slots ();
-       return result;
-      }
-      break;
-
     default:
-      break;
+      return c_expand_expr (exp, target, tmode, modifier);
     }
   my_friendly_abort (40);
   /* NOTREACHED */
index 950169a39f4df1944dcd109608036c72e401321d..1cc990522558023388d11606f4ae1404c4a63852 100644 (file)
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "output.h"
index 5a8696519f113dd88b993747f75e59f3e10d5490..89619ee4e503496c0ca46f611af1173d856207a9 100644 (file)
@@ -26,11 +26,11 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "output.h"
 #include "except.h"
-#include "expr.h"
 #include "toplev.h"
 #include "ggc.h"
 
index 1439c18917d381c4b2135f2bd278fa0329e51d84..272a917f97e5e2cf9c7cb7e369e97e29f0d87fc9 100644 (file)
@@ -88,6 +88,4 @@ extern int pending_lang_change;
 
 extern int yylex PARAMS ((void));
 
-extern struct lang_decl *free_lang_decl_chain;
-
 #endif /* _CP_LEX_H */
index fdc1a524947255d7a147b44d2fc5a4bd5b98999c..be53216ac7cac14222346758fba10ca545917319 100644 (file)
@@ -1004,7 +1004,7 @@ maybe_clone_body (fn)
       VARRAY_FREE (id.fns);
 
       /* Now, expand this function into RTL, if appropriate.  */
-      cp_function_chain->name_declared = 1;
+      function_name_declared_p = 1;
       expand_body (finish_function (0));
       pop_from_top_level ();
     }
index 99443b58841a99f5bcba2227ace4f95baf676dd7..e3357a0bce0cc1598509dfdf7ab35ed68ac341e6 100644 (file)
@@ -1985,7 +1985,8 @@ build_template_decl (decl, parms)
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   if (DECL_LANG_SPECIFIC (decl))
     {
-      DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
+      if (CAN_HAVE_FULL_LANG_DECL_P (decl))
+       DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
       DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
       DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
       DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
@@ -9689,7 +9690,7 @@ instantiate_decl (d, defer_ok)
 
       /* We already set up __FUNCTION__, etc., so we don't want to do
         it again now.  */
-      cp_function_chain->name_declared = 1;
+      function_name_declared_p = 1;
 
       /* Substitute into the body of the function.  */
       tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
index 88eaa72de4cc63882dd8e46d1402684fe79ea145..2f4432f5a18a6c14211747b1af1078dd9bd3c1d8 100644 (file)
@@ -77,19 +77,6 @@ static void genrtl_finish_function PARAMS ((tree));
       substmt = cond;                                  \
   } while (0)
 
-/* Wrapper since C and C++ expand_expr_stmt are different. */
-
-expand_expr_stmt_fn lang_expand_expr_stmt = cplus_expand_expr_stmt;
-
-/* Wrapper function instead of #define for use with c-common code. */
-
-void
-set_current_function_name_declared (i)
-     int i;
-{
-  cp_function_chain->name_declared = i;
-}
-
 /* Returns non-zero if the current statement is a full expression,
    i.e. temporaries created during that statement should be destroyed
    at the end of the statement.  */
@@ -112,16 +99,6 @@ current_stmt_tree ()
          : &scope_chain->x_stmt_tree);
 }
 
-/* One if we have already declared __FUNCTION__ (and related
-   variables) in the current function.  Two if we are in the process
-   of doing so.  */
-
-int
-current_function_name_declared ()
-{
-  return cp_function_chain->name_declared;
-}
-
 /* Nonzero if TYPE is an anonymous union or struct type.  We have to use a
    flag for this because "A union for which objects or pointers are
    declared is not an anonymous union" [class.union].  */
@@ -863,10 +840,10 @@ begin_compound_stmt (has_no_scope)
   /* If this is the outermost block of the function, declare the
      variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
   if (cfun
-      && !(current_function_name_declared () )
+      && !function_name_declared_p
       && !has_no_scope)
     {
-      cp_function_chain->name_declared = 1;
+      function_name_declared_p = 1;
       declare_function_name ();
     }
 
@@ -962,20 +939,6 @@ finish_label_decl (name)
   add_decl_stmt (decl);
 }
 
-/* Create a declaration statement for the declaration given by the
-   DECL.  */
-
-void
-add_decl_stmt (decl)
-     tree decl;
-{
-  tree decl_stmt;
-
-  /* We need the type to last until instantiation time.  */
-  decl_stmt = build_stmt (DECL_STMT, decl);
-  add_stmt (decl_stmt); 
-}
-
 /* Generate the RTL for a SUBOBJECT. */
 
 static void 
@@ -1216,10 +1179,10 @@ setup_vtbl_ptr (member_init_list, base_init_list)
 
       /* Don't declare __PRETTY_FUNCTION__ and friends here when we
         open the block for the if-body.  */
-      saved_cfnd = current_function_name_declared ();
-      cp_function_chain->name_declared = 1;
+      saved_cfnd = function_name_declared_p;
+      function_name_declared_p = 1;
       compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
-      cp_function_chain->name_declared = saved_cfnd;
+      function_name_declared_p = saved_cfnd;
 
       /* Make all virtual function table pointers in non-virtual base
         classes point to CURRENT_CLASS_TYPE's virtual function
@@ -1240,48 +1203,12 @@ setup_vtbl_ptr (member_init_list, base_init_list)
   vtbls_set_up_p = 1;
 }
 
+/* Returns the stack of SCOPE_STMTs for the current function.  */
 
-/* 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
-   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
-   returns a new TREE_LIST representing the top of the SCOPE_STMT
-   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
-   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
-   and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
-   SCOPE_BEGIN_P set.  */
-
-tree
-add_scope_stmt (begin_p, partial_p)
-     int begin_p;
-     int partial_p;
+tree *
+current_scope_stmt_stack ()
 {
-  tree ss;
-  tree top;
-
-  /* Build the statement.  */
-  ss = build_stmt (SCOPE_STMT, NULL_TREE);
-  SCOPE_BEGIN_P (ss) = begin_p;
-  SCOPE_PARTIAL_P (ss) = partial_p;
-
-  /* Keep the scope stack up to date.  */
-  if (begin_p)
-    {
-      current_scope_stmt_stack 
-       = tree_cons (ss, NULL_TREE, current_scope_stmt_stack);
-      top = current_scope_stmt_stack;
-    }
-  else
-    {
-      top = current_scope_stmt_stack;
-      TREE_VALUE (top) = ss;
-      current_scope_stmt_stack = TREE_CHAIN (top);
-    }
-
-  /* Add the new statement to the statement-tree.  */
-  add_stmt (ss);
-
-  return top;
+  return &cfun->language->x_scope_stmt_stack;
 }
 
 /* Finish a parenthesized expression EXPR.  */
@@ -2236,10 +2163,6 @@ cp_expand_stmt (t)
       genrtl_subobject (SUBOBJECT_CLEANUP (t));
       break;
 
-    case SCOPE_STMT:
-      genrtl_scope_stmt (t);
-      break;
-
     case RETURN_INIT:
       genrtl_named_return_value ();
       break;
@@ -2483,7 +2406,7 @@ expand_body (fn)
   /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
      any of the other magic variables we set up when starting a
      function body.  */
-  cp_function_chain->name_declared = 1;
+  function_name_declared_p = 1;
 
   /* Expand the body.  */
   expand_stmt (DECL_SAVED_TREE (fn));
index 396b5c4f807d4608d66048d9488b84b47d53de82..9b5e2be87f2f593f35fe44141a392931b8fef4cb 100644 (file)
@@ -1081,7 +1081,6 @@ cp_statement_code_p (code)
     case CLEANUP_STMT:
     case START_CATCH_STMT:
     case CTOR_STMT:
-    case SCOPE_STMT:
     case CTOR_INITIALIZER:
     case RETURN_INIT:
     case TRY_BLOCK:
index e15a7248930ff29cab49231ce97b3f6a00f6e172..3a16526b43436fabe84aff609291aa5876c7a31c 100644 (file)
@@ -34,11 +34,11 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "cp-tree.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "output.h"
-#include "expr.h"
 #include "toplev.h"
 #include "defaults.h"
 
@@ -54,9 +54,6 @@ static int comp_except_types PARAMS ((tree, tree, int));
 static int comp_array_types PARAMS ((int (*) (tree, tree, int), tree,
                                   tree, int));
 static tree common_base_type PARAMS ((tree, tree));
-#if 0
-static tree convert_sequence PARAMS ((tree, tree));
-#endif
 static tree lookup_anon_field PARAMS ((tree, tree));
 static tree pointer_diff PARAMS ((tree, tree, tree));
 static tree build_component_addr PARAMS ((tree, tree));
@@ -4745,35 +4742,6 @@ build_unary_op (code, xarg, noconvert)
   return error_mark_node;
 }
 
-#if 0
-/* If CONVERSIONS is a conversion expression or a nested sequence of such,
-   convert ARG with the same conversions in the same order
-   and return the result.  */
-
-static tree
-convert_sequence (conversions, arg)
-     tree conversions;
-     tree arg;
-{
-  switch (TREE_CODE (conversions))
-    {
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case FLOAT_EXPR:
-    case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
-      return cp_convert (TREE_TYPE (conversions),
-                        convert_sequence (TREE_OPERAND (conversions, 0),
-                                          arg));
-
-    default:
-      return arg;
-    }
-}
-#endif
-
 /* Apply unary lvalue-demanding operator CODE to the expression ARG
    for certain kinds of expressions which are not really lvalues
    but which we can accept as lvalues.
index 141d9ac9d409f782ceb7e9089175af1853c4b8c2..3bfe34a627b264ffb5bb162a741b03472a07d619 100644 (file)
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 
 #include "rtl.h"
+#include "expr.h"
 #include "tree.h"
 #include "c-common.h"
 #include "flags.h"
@@ -58,7 +59,7 @@ Boston, MA 02111-1307, USA.  */
    dependence to the dep_chain
 */
 
-enum dependence_type {flow, anti, output, none};
+enum dependence_type {dt_flow, dt_anti, dt_output, dt_none};
 #if 0
 static const char * dependence_string [] = {"flow", "anti", "output", "none"};
 #endif
@@ -756,23 +757,23 @@ check_node_dependence (du)
          dep_ptr->next = 0;
          
          if (def_ptr < use_ptr && use_ptr->type == use) 
-           dep_ptr->dependence = flow;
+           dep_ptr->dependence = dt_flow;
          else if (def_ptr > use_ptr && use_ptr->type == use)
-           dep_ptr->dependence = anti;
-         else dep_ptr->dependence = output;
+           dep_ptr->dependence = dt_anti;
+         else dep_ptr->dependence = dt_output;
 
          for (j = 1 ; j <= i - 1 ; j++)
            {
              if (direction[j][0] == gt)
                {
-                 dep_ptr->dependence = anti;
+                 dep_ptr->dependence = dt_anti;
                  direction[j][0] = lt;
                  distance[j][0] = -distance[j][0];
                  break;
                }
              else if (direction[j][0] == lt)
                {
-                 dep_ptr->dependence = flow;
+                 dep_ptr->dependence = dt_flow;
                  break;
                }
            }
@@ -796,7 +797,7 @@ check_node_dependence (du)
              dep_root_ptr = VARRAY_TOP (dep_chain, generic);
              dep_root_ptr->source = 0;
              dep_root_ptr->destination = def_ptr->expression;
-             dep_root_ptr->dependence = none;
+             dep_root_ptr->dependence = dt_none;
              dep_root_ptr->next = dep_ptr;
              def_ptr->dep = dep_ptr;
            }
index 034c132a6c6ce8b205e9fce39736133959bd6d32..bf2697a743c85c9839cee6c2d64500c43140d4bd 100644 (file)
@@ -85,6 +85,15 @@ Boston, MA 02111-1307, USA.  */
 #define CASE_VECTOR_PC_RELATIVE 0
 #endif
 
+/* Hook called by safe_from_p for language-specific tree codes.  It is
+   up to the language front-end to install a hook if it has any such
+   codes that safe_from_p needs to know about.  Since same_from_p will
+   recursively explore the TREE_OPERANDs of an expression, this hook
+   should not reexamine those pieces.  This routine may recursively
+   call safe_from_p; it should always pass `0' as the TOP_P
+   parameter.  */
+int (*lang_safe_from_p) PARAMS ((rtx, tree));
+
 /* If this is nonzero, we do not bother generating VOLATILE
    around volatile memory references, and we are willing to
    output indirect addresses.  If cse is to follow, we reject
@@ -168,7 +177,6 @@ static enum memory_use_mode
   get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
 static tree save_noncopied_parts PARAMS ((tree, tree));
 static tree init_noncopied_parts PARAMS ((tree, tree));
-static int safe_from_p         PARAMS ((rtx, tree, int));
 static int fixed_type_p                PARAMS ((tree));
 static rtx var_rtx             PARAMS ((tree));
 static int readonly_fields_p   PARAMS ((tree));
@@ -5396,7 +5404,7 @@ init_noncopied_parts (lhs, list)
    It is always safe for this routine to return zero since it merely
    searches for optimization opportunities.  */
 
-static int
+int
 safe_from_p (x, exp, top_p)
      rtx x;
      tree exp;
@@ -5595,11 +5603,18 @@ safe_from_p (x, exp, top_p)
       if (exp_rtl)
        break;
 
-      nops = TREE_CODE_LENGTH (TREE_CODE (exp));
+      nops = first_rtl_op (TREE_CODE (exp));
       for (i = 0; i < nops; i++)
        if (TREE_OPERAND (exp, i) != 0
            && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
          return 0;
+
+      /* If this is a language-specific tree code, it may require
+        special handling.  */
+      if (TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE
+         && lang_safe_from_p
+         && !(*lang_safe_from_p) (x, exp))
+       return 0;
     }
 
   /* If we have an rtl, find any enclosed object.  Then see if we conflict
index 9ed572cc1ec7ef9d24584e4f39288d4116e9eac6..596b68ab82f8c10bc6369e6763d3e5476ff48848 100644 (file)
@@ -1257,6 +1257,17 @@ extern rtx (*lang_expand_expr) PARAMS ((union tree_node *, rtx,
    such codes that output_constant needs to know about.  Returns a
    language-independent constant equivalent to its input.  */
 extern tree (*lang_expand_constant) PARAMS ((tree));
+
+extern int safe_from_p PARAMS ((rtx, tree, int));
+
+/* Hook called by safe_from_p for language-specific tree codes.  It is
+   up to the language front-end to install a hook if it has any such
+   codes that safe_from_p needs to know about.  Since same_from_p will
+   recursively explore the TREE_OPERANDs of an expression, this hook
+   should not reexamine those pieces.  This routine may recursively
+   call safe_from_p; it should always pass `0' as the TOP_P
+   parameter.  */
+extern int (*lang_safe_from_p) PARAMS ((rtx, tree));
 #endif
 
 extern void init_all_optabs                    PARAMS ((void));
index 7ece70589252b2060cbd7204db79f51d719454c6..920683815e4ed79d22c16249f125345f68c7761e 100644 (file)
@@ -1,5 +1,5 @@
 # Top level makefile fragment for GNU Objective-C
-#   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+#   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
 
 #This file is part of GNU CC.
 
@@ -85,7 +85,7 @@ $(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
        $(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc/objc-parse.y
 
 objc-act.o : $(srcdir)/objc/objc-act.c \
-   $(CONFIG_H) $(TREE_H) $(RTL_H) system.h \
+   $(CONFIG_H) $(TREE_H) $(RTL_H) system.h $(EXPR_H) \
    $(srcdir)/c-tree.h $(srcdir)/c-common.h $(srcdir)/c-lex.h \
    $(srcdir)/toplev.h $(srcdir)/flags.h $(srcdir)/objc/objc-act.h \
    $(srcdir)/input.h $(srcdir)/function.h $(srcdir)/output.h
index ba5837ad9f8c44c8c8ed47136c39b3386d1fa579..5bb4fcd369444c4ca22d976edda0943aaabe2748 100644 (file)
@@ -42,8 +42,11 @@ Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 #include "tree.h"
+#include "rtl.h"
+#include "expr.h"
 #include "c-tree.h"
 #include "c-lex.h"
+#include "c-common.h"
 #include "flags.h"
 #include "objc-act.h"
 #include "input.h"
@@ -198,6 +201,7 @@ static void encode_aggregate_within         PARAMS ((tree, int, int,
                                                       int, int));
 static const char *objc_demangle               PARAMS ((const char *));
 static const char *objc_printable_name         PARAMS ((tree, int));
+static void objc_expand_function_end            PARAMS ((void));
 
 /* Misc. bookkeeping */
 
@@ -7410,12 +7414,18 @@ encode_method_def (func_decl)
   return result;
 }
 
-void
-finish_method_def ()
+static void
+objc_expand_function_end ()
 {
   METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
+}
 
+void
+finish_method_def ()
+{
+  lang_expand_function_end = objc_expand_function_end;
   finish_function (0);
+  lang_expand_function_end = NULL;
 
   /* Required to implement _msgSuper. This must be done AFTER finish_function,
      since the optimizer may find "may be used before set" errors.  */
@@ -8172,7 +8182,7 @@ init_objc ()
 {
   /* Add the special tree codes of Objective C to the tables.  */
 
-#define LAST_CODE LAST_AND_UNUSED_TREE_CODE
+#define LAST_CODE LAST_C_TREE_CODE
 
   gcc_obstack_init (&util_obstack);
   util_firstobj = (char *) obstack_finish (&util_obstack);
@@ -8193,6 +8203,8 @@ init_objc ()
 
   /* Change the default error function */
   decl_printable_name = objc_printable_name;
+  lang_expand_expr = c_expand_expr;
+  lang_expand_decl_stmt = c_expand_decl_stmt;
 }
 \f
 static void
index 05f7ad656f3918652276495009a38a478b5c3a97..f13acc8f1927b60fe39b056d851f2a8f1c1e761c 100644 (file)
@@ -110,7 +110,7 @@ enum objc_tree_code {
 #ifdef OBJCPLUS
   dummy_tree_code = LAST_CPLUS_TREE_CODE,
 #else
-  dummy_tree_code = LAST_AND_UNUSED_TREE_CODE,
+  dummy_tree_code = LAST_C_TREE_CODE,
 #endif
 #include "objc-tree.def"
   LAST_OBJC_TREE_CODE
index 6adee8159d7321e3bc2d290bb82d04089616c10b..25382ccd40fd00293c352ec70477ee2d8ae5c8e0 100644 (file)
@@ -1923,11 +1923,14 @@ expand_expr_stmt (exp)
   if (expr_stmts_for_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
     exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
 
-  last_expr_type = TREE_TYPE (exp);
+  /* The call to `expand_expr' could cause last_expr_type and
+     last_expr_value to get reset.  Therefore, we set last_expr_value
+     and last_expr_type *after* calling expand_expr.  */
   last_expr_value = expand_expr (exp,
                                 (expr_stmts_for_value
                                  ? NULL_RTX : const0_rtx),
                                 VOIDmode, 0);
+  last_expr_type = TREE_TYPE (exp);
 
   /* If all we do is reference a volatile value in memory,
      copy it to a register to be sure it is actually touched.  */
index 57d40653b6585ad987eb650992a450a7b5c5f6da..f0748e714f696ae516284a539a6f3f83739233d4 100644 (file)
@@ -75,7 +75,7 @@ caddr_t v_addr;                       /* { dg-error "parse error" } */
          p_addr = fill_item_entry(va_op, v_addr);
          goto page_type;
      case((caddr_t)1):         /* { dg-error "parse error" } */
-     default:                  /* { dg-error "default label" } */
+     default:                  
          ((void)(((0))?0:(__eprintf("Failed assertion`%s'at line%d of`%s'.\n",
                                     "FALSE", 327, "b.c"), 0)));
      }
index fb41c789965e5de4572726fd8a30a48990ac5265..333cde6a00e2a0db8bb4b0acb9c123fa0ea7fa5f 100644 (file)
@@ -2566,7 +2566,11 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
          make_decl_rtl (decl, asmspec, top_level);
        }
       else
-       error ("invalid register name `%s' for register variable", asmspec);
+       {
+         error ("invalid register name `%s' for register variable", asmspec);
+         DECL_REGISTER (decl) = 0;
+         make_decl_rtl (decl, NULL, top_level);
+       }
     }
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
index 15c482ace884b3ff67c44e752cba488c0607b278..3f8d7c67c3f76156ab6286dc2a585bb84dc73590 100644 (file)
@@ -2794,11 +2794,15 @@ int
 contains_placeholder_p (exp)
      tree exp;
 {
-  register enum tree_code code = TREE_CODE (exp);
+  register enum tree_code code;
   int result;
 
+  if (!exp)
+    return 0;
+
   /* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
      in it since it is supplying a value for it.  */
+  code = TREE_CODE (exp);
   if (code == WITH_RECORD_EXPR)
     return 0;
   else if (code == PLACEHOLDER_EXPR)
index 1e5efa20917456cdd5a5cbb7160c4f2c010c9c20..853b2425bf59b944b299a93cf3168257b3cacb7e 100644 (file)
@@ -1,3 +1,7 @@
+2000-09-16  Mark Mitchell  <mark@codesourcery.com>
+
+       * splay-tree.c (splay_tree_predecessor): Fix typo in comment.
+
 2000-09-14  Michael Sokolov  <msokolov@ivan.Harhan.ORG>
 
        * splay-tree.c: #include <stdio.h>.
index 319349b8574afa1ccd32ccf1d936bb167ea27870..eb888148c80a78d30c948855758070dbfbd3666b 100644 (file)
@@ -392,7 +392,7 @@ splay_tree_predecessor (sp, key)
   if (comparison < 0)
     return sp->root;
 
-  /* Otherwise, find the rightmost element of the left subtree.  */
+  /* Otherwise, find the leftmost element of the right subtree.  */
   node = sp->root->left;
   if (node)
     while (node->right)