aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog127
-rw-r--r--gcc/Makefile.in38
-rw-r--r--gcc/c-common.c327
-rw-r--r--gcc/c-common.h90
-rw-r--r--gcc/c-decl.c331
-rw-r--r--gcc/c-lang.c12
-rw-r--r--gcc/c-lex.c1
-rw-r--r--gcc/c-parse.in235
-rw-r--r--gcc/c-semantics.c130
-rw-r--r--gcc/c-tree.h17
-rw-r--r--gcc/c-typeck.c142
-rw-r--r--gcc/cp/ChangeLog51
-rw-r--r--gcc/cp/Makefile.in2
-rw-r--r--gcc/cp/cp-tree.h40
-rw-r--r--gcc/cp/decl.c205
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/expr.c22
-rw-r--r--gcc/cp/friend.c1
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/lex.h2
-rw-r--r--gcc/cp/optimize.c2
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/cp/semantics.c97
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/cp/typeck.c34
-rw-r--r--gcc/dependence.c15
-rw-r--r--gcc/expr.c21
-rw-r--r--gcc/expr.h11
-rw-r--r--gcc/objc/Make-lang.in4
-rw-r--r--gcc/objc/objc-act.c18
-rw-r--r--gcc/objc/objc-act.h2
-rw-r--r--gcc/stmt.c5
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/920923-1.c2
-rw-r--r--gcc/toplev.c6
-rw-r--r--gcc/tree.c6
-rw-r--r--libiberty/ChangeLog4
-rw-r--r--libiberty/splay-tree.c2
38 files changed, 1245 insertions, 769 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 189eb2c..d3a8a6b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index dd08a84..2734aeb 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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)
+
#
# 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 \
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 2f35541..54335dd 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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));
}
/* 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,
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 389f32a..2477a0f 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index bc1857c..b8421a7 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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));
/* 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);
}
+
/* 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;
}
/* 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 ();
+ }
}
+
}
/* 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);
}
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index f8dd30b..21b8f0f 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -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 ();
}
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index f9c5cb4..f853fd0 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -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"
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 7f0fbd5..c590f31 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -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));
}
}
;
diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c
index f1b54c4..b349bd3 100644
--- a/gcc/c-semantics.c
+++ b/gcc/c-semantics.c
@@ -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);
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 92f0b45..5531731 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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. */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 002d4e7..f4b42b9 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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));
}
-/* 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);
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f54d9b3..66e3975 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in
index 839e574..b81c4f0 100644
--- a/gcc/cp/Makefile.in
+++ b/gcc/cp/Makefile.in
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index de76e52..b7bc919 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4430d55..3b2a057 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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);
}
/* 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;
}
-/* 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);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a2cdb1d..b579f59 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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"
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index e872859..ee2cf44 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -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"
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 39095ec..c49a2f9 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -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 */
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 950169a..1cc99052 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -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"
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 5a86965..89619ee 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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"
diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h
index 1439c18..272a917 100644
--- a/gcc/cp/lex.h
+++ b/gcc/cp/lex.h
@@ -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 */
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index fdc1a52..be53216 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -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 ();
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 99443b5..e3357a0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 88eaa72..2f4432f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 396b5c4..9b5e2be 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e15a724..3a16526 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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.
diff --git a/gcc/dependence.c b/gcc/dependence.c
index 141d9ac..3bfe34a 100644
--- a/gcc/dependence.c
+++ b/gcc/dependence.c
@@ -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;
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 034c132..bf2697a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
diff --git a/gcc/expr.h b/gcc/expr.h
index 9ed572c..596b68a 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -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));
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index 7ece705..9206838 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -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
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index ba5837a..5bb4fcd 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -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;
}
static void
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 05f7ad6..f13acc8 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -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
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 6adee81..25382cc 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/noncompile/920923-1.c b/gcc/testsuite/gcc.dg/noncompile/920923-1.c
index 57d4065..f0748e7 100644
--- a/gcc/testsuite/gcc.dg/noncompile/920923-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/920923-1.c
@@ -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)));
}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index fb41c78..333cde6 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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)
diff --git a/gcc/tree.c b/gcc/tree.c
index 15c482a..3f8d7c6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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)
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 1e5efa2..853b242 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -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>.
diff --git a/libiberty/splay-tree.c b/libiberty/splay-tree.c
index 319349b..eb88814 100644
--- a/libiberty/splay-tree.c
+++ b/libiberty/splay-tree.c
@@ -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)