splay-tree.c (splay_tree_predecessor): Fix typo in comment.

* splay-tree.c (splay_tree_predecessor): Fix typo in comment.

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

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

From-SVN: r36464
This commit is contained in:
Mark Mitchell 2000-09-17 07:38:23 +00:00 committed by Mark Mitchell
parent 4797e955c6
commit 8f17b5c5cb
38 changed files with 1268 additions and 792 deletions

View File

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

View File

@ -782,6 +782,9 @@ GCC_H = gcc.h version.h
GGC_H = ggc.h varray.h
TIMEVAR_H = timevar.h timevar.def
INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
C_COMMON_H = c-common.h $(SPLAY_TREE_H)
C_TREE_H = c-tree.h $(C_COMMON_H)
#
# 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 \

View File

@ -22,7 +22,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "c-common.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
@ -30,6 +29,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "ggc.h"
#include "expr.h"
#include "c-common.h"
#include "tm_p.h"
#include "intl.h"
@ -149,6 +149,10 @@ tree (*make_fname_decl) PARAMS ((tree, const char *, int));
returns 1 for language-specific statement codes. */
int (*lang_statement_code_p) PARAMS ((enum tree_code));
/* If non-NULL, the address of a language-specific function that takes
any action required right before expand_function_end is called. */
void (*lang_expand_function_end) PARAMS ((void));
/* Nonzero means the expression being parsed will never be evaluated.
This is a count, since unevaluated expressions can nest. */
int skip_evaluation;
@ -181,6 +185,7 @@ typedef struct
int line;
const char *file;
int needs_warning;
tree if_stmt;
} if_elt;
static void tfaff PARAMS ((void));
@ -192,15 +197,16 @@ static int if_stack_space = 0;
/* Stack pointer. */
static int if_stack_pointer = 0;
/* Generate RTL for the start of an if-then, and record the start of it
/* Record the start of an if-then, and record the start of it
for ambiguous else detection. */
void
c_expand_start_cond (cond, exitflag, compstmt_count)
c_expand_start_cond (cond, compstmt_count)
tree cond;
int exitflag;
int compstmt_count;
{
tree if_stmt;
/* Make sure there is enough space on the stack. */
if (if_stack_space == 0)
{
@ -213,17 +219,29 @@ c_expand_start_cond (cond, exitflag, compstmt_count)
if_stack = (if_elt *)xrealloc (if_stack, if_stack_space * sizeof (if_elt));
}
if_stmt = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
IF_COND (if_stmt) = cond;
add_stmt (if_stmt);
/* Record this if statement. */
if_stack[if_stack_pointer].compstmt_count = compstmt_count;
if_stack[if_stack_pointer].file = input_filename;
if_stack[if_stack_pointer].line = lineno;
if_stack[if_stack_pointer].needs_warning = 0;
if_stack[if_stack_pointer].if_stmt = if_stmt;
if_stack_pointer++;
expand_start_cond (cond, exitflag);
}
/* Generate RTL for the end of an if-then. Optionally warn if a nested
/* 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));
}
/* 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--;
}
expand_start_else ();
/* Called after the else-clause for an if-statement is processed. */
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,

View File

@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_C_COMMON_H
#define GCC_C_COMMON_H
#include "splay-tree.h"
/* Usage of TREE_LANG_FLAG_?:
0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
TREE_NEGATED_INT (in INTEGER_CST).
@ -194,6 +196,10 @@ enum c_tree_index
extern tree c_global_trees[CTI_MAX];
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
typedef enum c_language_kind
{
clk_c, /* A dialect of C: K&R C, ANSI/ISO C89, C2000,
@ -237,6 +243,11 @@ struct language_function {
/* While we are parsing the function, this contains information
about the statement-tree that we are building. */
struct stmt_tree_s x_stmt_tree;
/* The stack of SCOPE_STMTs for the current function. */
tree x_scope_stmt_stack;
/* Nonzero if __FUNCTION__ and its ilk have been declared in this
function. */
int x_function_name_declared_p;
};
/* When building a statement-tree, this is the last statement added to
@ -248,26 +259,6 @@ struct language_function {
#define last_expr_type (current_stmt_tree ()->x_last_expr_type)
/* The type of a function that walks over tree structure. */
typedef tree (*walk_tree_fn) PARAMS ((tree *,
int *,
void *));
extern stmt_tree current_stmt_tree PARAMS ((void));
extern void begin_stmt_tree PARAMS ((tree *));
extern tree add_stmt PARAMS ((tree));
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));
/* 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
@ -280,6 +271,54 @@ extern void expand_stmt PARAMS ((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 *,
int *,
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 tree walk_stmt_tree PARAMS ((tree *,
walk_tree_fn,
void *));
extern void prep_stmt PARAMS ((tree));
extern void expand_stmt PARAMS ((tree));
extern void mark_stmt_tree PARAMS ((void *));
/* 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. */
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

View File

@ -125,6 +125,19 @@ static tree current_function_parm_tags;
static const char *current_function_prototype_file;
static int current_function_prototype_line;
/* The current statement tree. */
static struct stmt_tree_s c_stmt_tree;
/* The current scope statement stack. */
static tree c_scope_stmt_stack;
/* Nonzero if __FUNCTION__ and its ilk have been declared in this
function. */
static int c_function_name_declared_p;
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
at the end of the function. */
@ -296,6 +309,7 @@ static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, const char *, int));
static void c_expand_body PARAMS ((tree, int));
/* 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. */
/* 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));
if (c_function_varargs)
mark_varargs ();
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
/* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
declare_function_name ();
/* 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. */
int
current_function_name_declared ()
{
abort ();
return 0;
}
/* Code to generate the RTL for a case label in C. */
void
do_case (low_value, high_value)
tree low_value;
tree high_value;
{
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);
if (pedantic && (high_value != NULL_TREE))
pedwarn ("ISO C forbids case ranges");
if (value1 != error_mark_node && value2 != error_mark_node)
{
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");
}
}
}
/* Accessor to set the 'current_function_name_declared' flag. */
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 ()
{
}
/* Return a new COMPOUND_STMT, after adding it to the current
statement tree. */
tree
c_begin_compound_stmt ()
{
tree stmt;
/* 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)
{
c_function_name_declared_p = 1;
declare_function_name ();
}
return stmt;
}
/* Expand T (a DECL_STMT) if it declares an entity not handled by the
common code. */
void
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);
}

View File

@ -25,13 +25,15 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "function.h"
#include "input.h"
#include "c-tree.h"
#include "c-lex.h"
#include "toplev.h"
#include "diagnostic.h"
#include "output.h"
#include "flags.h"
#include "ggc.h"
#include "rtl.h"
#include "expr.h"
#include "c-tree.h"
#include "c-lex.h"
static int c_tree_printer PARAMS ((output_buffer *));
@ -88,8 +90,10 @@ lang_init ()
save_lang_status = &push_c_function_context;
restore_lang_status = &pop_c_function_context;
mark_lang_status = &mark_c_function_context;
lang_printer = c_tree_printer;
lang_expand_expr = &c_expand_expr;
lang_safe_from_p = &c_safe_from_p;
lang_printer = &c_tree_printer;
lang_expand_decl_stmt = &c_expand_decl_stmt;
c_parse_init ();
}

View File

@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "expr.h"
#include "tree.h"
#include "input.h"
#include "output.h"

View File

@ -173,7 +173,8 @@ end ifc
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word extension
%type <ttype> compstmt compstmt_nostart compstmt_primary_start
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
%type <ttype> do_stmt_start poplevel
%type <ttype> declarator
%type <ttype> notype_declarator after_type_declarator
@ -661,33 +662,26 @@ primary:
| '(' error ')'
{ $$ = error_mark_node; }
| compstmt_primary_start compstmt_nostart ')'
{ tree rtl_exp;
if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions");
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;
{ tree saved_last_tree;
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;
if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions");
pop_label_level ();
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));
}
}
;

View File

@ -40,6 +40,13 @@ Boston, MA 02111-1307, USA. */
expanding statements. */
void (*lang_expand_stmt) PARAMS ((tree));
/* If non-NULL, the address of a language-specific function for
expanding a DECL_STMT. After the language-independent cases are
handled, this function will be called. If this function is not
defined, it is assumed that declarations other than those for
variables and labels do not require any RTL generation. */
void (*lang_expand_decl_stmt) PARAMS ((tree));
static tree prune_unused_decls PARAMS ((tree *, int *, void *));
/* Create an empty statement tree rooted at T. */
@ -71,6 +78,63 @@ add_stmt (t)
return t;
}
/* Create a declaration statement for the declaration given by the
DECL. */
void
add_decl_stmt (decl)
tree decl;
{
tree decl_stmt;
/* We need the type to last until instantiation time. */
decl_stmt = build_stmt (DECL_STMT, decl);
add_stmt (decl_stmt);
}
/* Add a scope-statement to the statement-tree. BEGIN_P indicates
whether this statements opens or closes a scope. PARTIAL_P is true
for a partial scope, i.e, the scope that begins after a label when
an object that needs a cleanup is created. If BEGIN_P is nonzero,
returns a new TREE_LIST representing the top of the SCOPE_STMT
stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is
zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
SCOPE_BEGIN_P set. */
tree
add_scope_stmt (begin_p, partial_p)
int begin_p;
int partial_p;
{
tree ss;
tree top;
/* Build the statement. */
ss = build_stmt (SCOPE_STMT, NULL_TREE);
SCOPE_BEGIN_P (ss) = begin_p;
SCOPE_PARTIAL_P (ss) = partial_p;
/* Keep the scope stack up to date. */
if (begin_p)
{
*current_scope_stmt_stack ()
= tree_cons (ss, NULL_TREE, *current_scope_stmt_stack ());
top = *current_scope_stmt_stack ();
}
else
{
top = *current_scope_stmt_stack ();
TREE_VALUE (top) = ss;
*current_scope_stmt_stack () = TREE_CHAIN (top);
}
/* Add the new statement to the statement-tree. */
add_stmt (ss);
return top;
}
/* Remove declarations of internal variables that are not used from a
stmt tree. To qualify, the variable must have a name and must have
a zero DECL_SOURCE_LINE. We tried to remove all variables for
@ -145,7 +209,7 @@ finish_stmt_tree (t)
/* Remove unused decls from the stmt tree. */
walk_stmt_tree (t, prune_unused_decls, NULL);
if (cfun)
if (cfun && stmt)
{
/* The line-number recorded in the outermost statement in a function
is the line number of the end of the function. */
@ -305,7 +369,8 @@ genrtl_expr_stmt (expr)
if (stmts_are_full_exprs_p ())
expand_start_target_temps ();
lang_expand_expr_stmt (expr);
if (expr != error_mark_node)
expand_expr_stmt (expr);
if (stmts_are_full_exprs_p ())
expand_end_target_temps ();
@ -348,6 +413,11 @@ genrtl_decl_stmt (t)
else
make_rtl_for_local_static (decl);
}
else if (TREE_CODE (decl) == LABEL_DECL
&& C_DECLARED_LABEL_FLAG (decl))
declare_nonlocal_label (decl);
else if (lang_expand_decl_stmt)
(*lang_expand_decl_stmt) (t);
}
/* Generate the RTL for T, which is an IF_STMT. */
@ -448,30 +518,43 @@ void
genrtl_for_stmt (t)
tree t;
{
tree tmp;
tree cond;
const char *saved_filename;
int saved_lineno;
if (NEW_FOR_SCOPE_P (t))
genrtl_do_pushlevel ();
expand_stmt (FOR_INIT_STMT (t));
/* Expand the initialization. */
emit_nop ();
emit_line_note (input_filename, lineno);
expand_start_loop_continue_elsewhere (1);
genrtl_do_pushlevel ();
cond = expand_cond (FOR_COND (t));
/* Save the filename and line number so that we expand the FOR_EXPR
we can reset them back to the saved values. */
saved_filename = input_filename;
saved_lineno = lineno;
/* Expand the condition. */
emit_line_note (input_filename, lineno);
if (cond)
expand_exit_loop_if_false (0, cond);
genrtl_do_pushlevel ();
tmp = FOR_EXPR (t);
/* Expand the body. */
genrtl_do_pushlevel ();
expand_stmt (FOR_BODY (t));
/* Expand the increment expression. */
input_filename = saved_filename;
lineno = saved_lineno;
emit_line_note (input_filename, lineno);
expand_loop_continue_here ();
if (tmp)
genrtl_expr_stmt (tmp);
if (FOR_EXPR (t))
genrtl_expr_stmt (FOR_EXPR (t));
expand_end_loop ();
}
@ -575,6 +658,22 @@ genrtl_case_label (case_label)
tree case_label;
{
tree duplicate;
tree cleanup;
cleanup = last_cleanup_this_contour ();
if (cleanup)
{
static int explained = 0;
warning_with_decl (TREE_PURPOSE (cleanup),
"destructor needed for `%#D'");
warning ("where case label appears here");
if (!explained)
{
warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
explained = 1;
}
}
add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label),
CASE_LABEL_DECL (case_label), &duplicate);
}
@ -585,16 +684,6 @@ void
genrtl_compound_stmt (t)
tree t;
{
/* If this is the outermost block of the function, declare the
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (cfun
&& !current_function_name_declared ()
&& !COMPOUND_STMT_NO_SCOPE (t))
{
set_current_function_name_declared (1);
declare_function_name ();
}
expand_stmt (COMPOUND_BODY (t));
}
@ -609,9 +698,6 @@ genrtl_asm_stmt (cv_qualifier, string, output_operands,
tree input_operands;
tree clobbers;
{
if (TREE_CHAIN (string))
string = combine_strings (string);
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
{
@ -733,6 +819,10 @@ expand_stmt (t)
ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
break;
case SCOPE_STMT:
genrtl_scope_stmt (t);
break;
default:
if (lang_expand_stmt)
(*lang_expand_stmt) (t);

View File

@ -42,6 +42,14 @@ struct lang_identifier
enum rid rid_code;
};
/* Wrapping c_lang_decl in another struct is an unfortunate
necessity. */
struct lang_decl
{
struct c_lang_decl base;
};
/* Macros for access to language-specific slots in an identifier. */
/* Each of these slots contains a DECL node or null. */
@ -103,10 +111,6 @@ struct lang_type
tree elts[1];
};
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
/* Record whether a type or decl was written with nonconstant size.
Note that TYPE_SIZE may have simplified to a constant. */
#define C_TYPE_VARIABLE_SIZE(type) TYPE_LANG_FLAG_1 (type)
@ -230,6 +234,8 @@ extern tree start_decl PARAMS ((tree, tree, int,
extern tree start_struct PARAMS ((enum tree_code, tree));
extern void store_parm_decls PARAMS ((void));
extern tree xref_tag PARAMS ((enum tree_code, tree));
extern tree c_begin_compound_stmt PARAMS ((void));
extern void c_expand_decl_stmt PARAMS ((tree));
/* in c-typeck.c */
extern tree require_complete_type PARAMS ((tree));
@ -268,7 +274,8 @@ extern void set_init_label PARAMS ((tree));
extern void process_init_element PARAMS ((tree));
extern void pedwarn_c99 PARAMS ((const char *, ...))
ATTRIBUTE_PRINTF_1;
extern tree c_expand_start_case PARAMS ((tree));
extern tree c_start_case PARAMS ((tree));
extern void c_finish_case PARAMS ((void));
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */

View File

@ -4999,7 +4999,8 @@ start_init (decl, asmspec_tree, top_level)
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
locus = IDENTIFIER_POINTER (DECL_NAME (decl));
constructor_incremental |= TREE_STATIC (decl);
constructor_incremental
|= (TREE_STATIC (decl) && !DECL_CONTEXT (decl));
}
else
{
@ -6541,7 +6542,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
if (TREE_CODE (string) == ADDR_EXPR)
string = TREE_OPERAND (string, 0);
if (TREE_CODE (string) != STRING_CST)
if (last_tree && TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
return;
@ -6567,7 +6568,8 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| TREE_CODE (output) == FIX_CEIL_EXPR)
output = TREE_OPERAND (output, 0);
lvalue_or_else (o[i], "invalid lvalue in asm statement");
if (last_tree)
lvalue_or_else (o[i], "invalid lvalue in asm statement");
}
/* Perform default conversions on array and function inputs. */
@ -6578,6 +6580,14 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
if (last_tree)
{
add_stmt (build_stmt (ASM_STMT,
vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
string, outputs, inputs, clobbers));
return;
}
/* Generate the ASM_OPERANDS insn;
store into the TREE_VALUEs of OUTPUTS some trees for
where the values were actually stored. */
@ -6703,53 +6713,115 @@ c_expand_return (retval)
current_function_returns_value = 1;
}
genrtl_return_stmt (build_return_stmt (retval));
add_stmt (build_return_stmt (retval));
}
/* 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;
code = TREE_CODE (TREE_TYPE (exp));
type = TREE_TYPE (exp);
if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
if (exp != error_mark_node)
{
error ("switch quantity not an integer");
exp = error_mark_node;
}
else
{
tree index;
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
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);
code = TREE_CODE (TREE_TYPE (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;
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 (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;
}
}
expand_start_case (1, exp, type, "switch statement");
/* 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 exp;
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
error ("`default' label not within a switch statement");
}
/* Finish the switch statement. */
void
c_finish_case ()
{
struct c_switch *cs = switch_stack;
RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt));
/* Pop the stack. */
switch_stack = switch_stack->next;
splay_tree_delete (cs->cases);
free (cs);
}

View File

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

View File

@ -265,7 +265,7 @@ class.o : class.c $(CXX_TREE_H) $(srcdir)/../flags.h \
call.o : call.c $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../toplev.h $(RTL_H) $(EXPR_H) $(GGC_H)
friend.o : friend.c $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(srcdir)/../toplev.h
$(srcdir)/../toplev.h $(EXPR_H)
init.o : init.c $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(EXPR_H) $(srcdir)/../toplev.h $(GGC_H) \
$(srcdir)/../except.h

View File

@ -878,7 +878,6 @@ struct cp_language_function
tree x_current_class_ptr;
tree x_current_class_ref;
tree x_eh_spec_try_block;
tree x_scope_stmt_stack;
tree x_in_charge_parm;
tree *x_vcalls_possible_p;
@ -889,7 +888,6 @@ struct cp_language_function
int returns_null;
int in_function_try_handler;
int x_expanding_p;
int name_declared;
int vtbls_set_up_p;
struct named_label_use_list *x_named_label_uses;
@ -928,10 +926,6 @@ struct cp_language_function
#define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block
/* The stack of SCOPE_STMTs for the current function. */
#define current_scope_stmt_stack cp_function_chain->x_scope_stmt_stack
/* The `__in_chrg' parameter for the current function. Only used for
destructors. */
@ -978,6 +972,12 @@ struct cp_language_function
#define in_function_try_handler cp_function_chain->in_function_try_handler
/* Nonzero if __FUNCTION__ and its ilk have been declared in this
function. */
#define function_name_declared_p \
(cp_function_chain->base.x_function_name_declared_p)
extern tree current_function_return_value;
extern tree global_namespace;
@ -1811,6 +1811,8 @@ struct lang_type
struct lang_decl_flags
{
struct c_lang_decl base;
ENUM_BITFIELD(languages) language : 8;
unsigned operator_attr : 1;
@ -1839,8 +1841,6 @@ struct lang_decl_flags
unsigned generate_with_vtable_p : 1;
unsigned dummy : 1;
tree context;
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
is DECL_TEMPLATE_INFO. */
@ -1872,8 +1872,9 @@ struct lang_decl
tree befriending_classes;
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
tree saved_tree;
/* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT. For a
non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT. */
tree context;
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
tree cloned_function;
@ -2168,12 +2169,12 @@ struct lang_decl
the DECL_FRIEND_CONTEXT for `f' will be `S'. */
#define DECL_FRIEND_CONTEXT(NODE) \
((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \
? DECL_LANG_SPECIFIC (NODE)->decl_flags.context \
? DECL_LANG_SPECIFIC (NODE)->context \
: NULL_TREE)
/* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT. */
#define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.context = (CONTEXT))
(DECL_LANG_SPECIFIC (NODE)->context = (CONTEXT))
/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
#define CP_DECL_CONTEXT(NODE) \
@ -2183,7 +2184,7 @@ struct lang_decl
/* For a virtual function, the base where we find its vtable entry.
For a non-virtual function, the base where it is defined. */
#define DECL_VIRTUAL_CONTEXT(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.context)
(DECL_LANG_SPECIFIC (NODE)->context)
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
@ -2409,12 +2410,6 @@ struct lang_decl
the class definition is complete. */
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
/* In a FUNCTION_DECL, the saved representation of the body of the
entire function. Usually a COMPOUND_STMT, but this may also be a
RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK. */
#define DECL_SAVED_TREE(NODE) \
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->saved_tree)
/* In a FUNCTION_DECL, the saved language-specific per-function data. */
#define DECL_SAVED_FUNCTION_DATA(NODE) \
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->u.saved_language_function)
@ -2532,10 +2527,6 @@ extern int flag_new_for_scope;
#define ARITHMETIC_TYPE_P(TYPE) \
(CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE)
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
/* Nonzero for _TYPE means that the _TYPE defines
at least one constructor. */
#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1(NODE))
@ -3904,7 +3895,6 @@ extern tree start_method PARAMS ((tree, tree, tree));
extern tree finish_method PARAMS ((tree));
extern void hack_incomplete_structures PARAMS ((tree));
extern tree maybe_build_cleanup PARAMS ((tree));
extern void cplus_expand_expr_stmt PARAMS ((tree));
extern void finish_stmt PARAMS ((void));
extern void replace_defarg PARAMS ((tree, tree));
extern void print_other_binding_stack PARAMS ((struct binding_level *));
@ -4356,12 +4346,10 @@ extern tree finish_base_specifier PARAMS ((tree, tree));
extern void finish_member_declaration PARAMS ((tree));
extern void check_multiple_declarators PARAMS ((void));
extern tree finish_typeof PARAMS ((tree));
extern void add_decl_stmt PARAMS ((tree));
extern void finish_decl_cleanup PARAMS ((tree, tree));
extern void finish_named_return_value PARAMS ((tree, tree));
extern void expand_body PARAMS ((tree));
extern void prep_stmt PARAMS ((tree));
extern tree add_scope_stmt PARAMS ((int, int));
extern void do_pushlevel PARAMS ((void));
extern tree do_poplevel PARAMS ((void));
extern void finish_mem_initializers PARAMS ((tree));

View File

@ -159,7 +159,6 @@ static void mark_named_label_lists PARAMS ((void *, void *));
static void mark_cp_function_context PARAMS ((struct function *));
static void mark_saved_scope PARAMS ((void *));
static void mark_lang_function PARAMS ((struct cp_language_function *));
static void mark_stmt_tree PARAMS ((stmt_tree));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
static void destroy_local_var PARAMS ((tree));
@ -176,7 +175,6 @@ static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree, tree));
static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
static void store_parm_decls PARAMS ((tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
@ -2411,16 +2409,6 @@ pop_nested_namespace (ns)
scope isn't enough, because more binding levels may be pushed. */
struct saved_scope *scope_chain;
/* Mark ST for GC. */
static void
mark_stmt_tree (st)
stmt_tree st;
{
ggc_mark_tree (st->x_last_stmt);
ggc_mark_tree (st->x_last_expr_type);
}
/* Mark ARG (which is really a struct saved_scope **) for GC. */
static void
@ -5156,21 +5144,6 @@ struct cp_switch
static struct cp_switch *switch_stack;
static int
case_compare (k1, k2)
splay_tree_key k1;
splay_tree_key k2;
{
/* Consider a NULL key (such as arises with a `default' label) to be
smaller than anything else. */
if (!k1)
return k2 ? -1 : 0;
else if (!k2)
return k1 ? 1 : 0;
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
/* Called right after a switch-statement condition is parsed.
SWITCH_STMT is the switch statement being parsed. */
@ -5206,12 +5179,7 @@ finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
tree label;
tree cleanup;
tree type;
tree cond;
tree case_label;
splay_tree_node node;
if (! switch_stack)
{
@ -5225,13 +5193,13 @@ finish_case_label (low_value, high_value)
return;
}
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (label) = current_function_decl;
if (processing_template_decl)
{
tree label;
/* For templates, just add the case label; we'll do semantic
analysis at instantiation-time. */
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
add_stmt (build_case_label (low_value, high_value, label));
return;
}
@ -5240,124 +5208,8 @@ finish_case_label (low_value, high_value)
cond = SWITCH_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
/* If there was an error processing the switch condition, bail now
before we get more confused. */
if (!cond || cond == error_mark_node)
return;
type = TREE_TYPE (cond);
if ((low_value && TREE_TYPE (low_value)
&& POINTER_TYPE_P (TREE_TYPE (low_value)))
|| (high_value && TREE_TYPE (high_value)
&& POINTER_TYPE_P (TREE_TYPE (high_value))))
error ("pointers are not permitted as case values");
/* Case ranges are a GNU extension. */
if (high_value && pedantic)
pedwarn ("ISO C++ forbids range expressions in switch statement");
if (low_value)
{
low_value = check_case_value (low_value);
low_value = convert_and_check (type, low_value);
}
if (high_value)
{
high_value = check_case_value (high_value);
high_value = convert_and_check (type, high_value);
}
/* If an error has occurred, bail out now. */
if (low_value == error_mark_node || high_value == error_mark_node)
return;
/* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
really a case range, even though it was written that way. Remove
the HIGH_VALUE to simplify later processing. */
if (tree_int_cst_equal (low_value, high_value))
high_value = NULL_TREE;
if (low_value && high_value
&& !tree_int_cst_lt (low_value, high_value))
warning ("empty range specified");
/* Look up the LOW_VALUE in the table of case labels we already
have. */
node = splay_tree_lookup (switch_stack->cases, (splay_tree_key) low_value);
/* If there was not an exact match, check for overlapping ranges.
There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
that's a `default' label and the only overlap is an exact match. */
if (!node && (low_value || high_value))
{
splay_tree_node low_bound;
splay_tree_node high_bound;
/* Even though there wasn't an exact match, there might be an
overlap between this case range and another case range.
Since we've (inductively) not allowed any overlapping case
ranges, we simply need to find the greatest low case label
that is smaller that LOW_VALUE, and the smallest low case
label that is greater than LOW_VALUE. If there is an overlap
it will occur in one of these two ranges. */
low_bound = splay_tree_predecessor (switch_stack->cases,
(splay_tree_key) low_value);
high_bound = splay_tree_successor (switch_stack->cases,
(splay_tree_key) low_value);
/* Check to see if the LOW_BOUND overlaps. It is smaller than
the LOW_VALUE, so there is no need to check unless the
LOW_BOUND is in fact itself a case range. */
if (low_bound
&& CASE_HIGH ((tree) low_bound->value)
&& tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
low_value) >= 0)
node = low_bound;
/* Check to see if the HIGH_BOUND overlaps. The low end of that
range is bigger than the low end of the current range, so we
are only interested if the current range is a real range, and
not an ordinary case label. */
else if (high_bound
&& high_value
&& (tree_int_cst_compare ((tree) high_bound->key,
high_value)
<= 0))
node = high_bound;
}
/* If there was an overlap, issue an error. */
if (node)
{
tree duplicate = CASE_LABEL_DECL ((tree) node->value);
if (high_value)
{
error ("duplicate (or overlapping) case value");
cp_error_at ("this is the first entry overlapping that value",
duplicate);
}
else if (low_value)
{
cp_error ("duplicate case value `%E'", low_value) ;
cp_error_at ("previously used here", duplicate);
}
else
{
error ("multiple default labels in one switch");
cp_error_at ("this is the first default label", duplicate);
}
return;
}
cleanup = last_cleanup_this_contour ();
if (cleanup)
{
static int explained = 0;
cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
warning ("where case label appears here");
if (!explained)
{
warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
explained = 1;
}
}
c_add_case_label (switch_stack->cases, cond, low_value, high_value);
check_switch_goto (switch_stack->level);
@ -5365,16 +5217,6 @@ finish_case_label (low_value, high_value)
own new (temporary) binding contour. */
current_binding_level->more_cleanups_ok = 0;
current_function_return_value = NULL_TREE;
/* Add a representation for the case label to the statement
tree. */
case_label = build_case_label (low_value, high_value, label);
add_stmt (case_label);
/* Register this case label in the splay tree. */
splay_tree_insert (switch_stack->cases,
(splay_tree_key) low_value,
(splay_tree_value) case_label);
}
/* 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);

View File

@ -32,13 +32,13 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
#include "lex.h"
#include "output.h"
#include "except.h"
#include "expr.h"
#include "defaults.h"
#include "toplev.h"
#include "dwarf2out.h"

View File

@ -27,10 +27,10 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "cp-tree.h"
#include "flags.h"
#include "obstack.h"
#include "expr.h"
#include "output.h"
#include "except.h"
#include "defaults.h"

View File

@ -133,28 +133,8 @@ cplus_expand_expr (exp, target, tmode, modifier)
/* We don't need to generate any code for an empty class. */
return const0_rtx;
case STMT_EXPR:
{
tree rtl_expr;
rtx result;
/* Since expand_expr_stmt calls free_temp_slots after every
expression statement, we must call push_temp_slots here.
Otherwise, any temporaries in use now would be considered
out-of-scope after the first EXPR_STMT from within the
STMT_EXPR. */
push_temp_slots ();
rtl_expr = expand_start_stmt_expr ();
expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier);
pop_temp_slots ();
return result;
}
break;
default:
break;
return c_expand_expr (exp, target, tmode, modifier);
}
my_friendly_abort (40);
/* NOTREACHED */

View File

@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"

View File

@ -26,11 +26,11 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
#include "except.h"
#include "expr.h"
#include "toplev.h"
#include "ggc.h"

View File

@ -88,6 +88,4 @@ extern int pending_lang_change;
extern int yylex PARAMS ((void));
extern struct lang_decl *free_lang_decl_chain;
#endif /* _CP_LEX_H */

View File

@ -1004,7 +1004,7 @@ maybe_clone_body (fn)
VARRAY_FREE (id.fns);
/* Now, expand this function into RTL, if appropriate. */
cp_function_chain->name_declared = 1;
function_name_declared_p = 1;
expand_body (finish_function (0));
pop_from_top_level ();
}

View File

@ -1985,7 +1985,8 @@ build_template_decl (decl, parms)
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
if (DECL_LANG_SPECIFIC (decl))
{
DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
if (CAN_HAVE_FULL_LANG_DECL_P (decl))
DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
@ -9689,7 +9690,7 @@ instantiate_decl (d, defer_ok)
/* We already set up __FUNCTION__, etc., so we don't want to do
it again now. */
cp_function_chain->name_declared = 1;
function_name_declared_p = 1;
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,

View File

@ -77,19 +77,6 @@ static void genrtl_finish_function PARAMS ((tree));
substmt = cond; \
} while (0)
/* Wrapper since C and C++ expand_expr_stmt are different. */
expand_expr_stmt_fn lang_expand_expr_stmt = cplus_expand_expr_stmt;
/* Wrapper function instead of #define for use with c-common code. */
void
set_current_function_name_declared (i)
int i;
{
cp_function_chain->name_declared = i;
}
/* Returns non-zero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
@ -112,16 +99,6 @@ current_stmt_tree ()
: &scope_chain->x_stmt_tree);
}
/* One if we have already declared __FUNCTION__ (and related
variables) in the current function. Two if we are in the process
of doing so. */
int
current_function_name_declared ()
{
return cp_function_chain->name_declared;
}
/* Nonzero if TYPE is an anonymous union or struct type. We have to use a
flag for this because "A union for which objects or pointers are
declared is not an anonymous union" [class.union]. */
@ -863,10 +840,10 @@ begin_compound_stmt (has_no_scope)
/* If this is the outermost block of the function, declare the
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (cfun
&& !(current_function_name_declared () )
&& !function_name_declared_p
&& !has_no_scope)
{
cp_function_chain->name_declared = 1;
function_name_declared_p = 1;
declare_function_name ();
}
@ -962,20 +939,6 @@ finish_label_decl (name)
add_decl_stmt (decl);
}
/* Create a declaration statement for the declaration given by the
DECL. */
void
add_decl_stmt (decl)
tree decl;
{
tree decl_stmt;
/* We need the type to last until instantiation time. */
decl_stmt = build_stmt (DECL_STMT, decl);
add_stmt (decl_stmt);
}
/* Generate the RTL for a SUBOBJECT. */
static void
@ -1216,10 +1179,10 @@ setup_vtbl_ptr (member_init_list, base_init_list)
/* Don't declare __PRETTY_FUNCTION__ and friends here when we
open the block for the if-body. */
saved_cfnd = current_function_name_declared ();
cp_function_chain->name_declared = 1;
saved_cfnd = function_name_declared_p;
function_name_declared_p = 1;
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
cp_function_chain->name_declared = saved_cfnd;
function_name_declared_p = saved_cfnd;
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
@ -1240,48 +1203,12 @@ setup_vtbl_ptr (member_init_list, base_init_list)
vtbls_set_up_p = 1;
}
/* Returns the stack of SCOPE_STMTs for the current function. */
/* Add a scope-statement to the statement-tree. BEGIN_P indicates
whether this statements opens or closes a scope. PARTIAL_P is true
for a partial scope, i.e, the scope that begins after a label when
an object that needs a cleanup is created. If BEGIN_P is nonzero,
returns a new TREE_LIST representing the top of the SCOPE_STMT
stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is
zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
SCOPE_BEGIN_P set. */
tree
add_scope_stmt (begin_p, partial_p)
int begin_p;
int partial_p;
tree *
current_scope_stmt_stack ()
{
tree ss;
tree top;
/* Build the statement. */
ss = build_stmt (SCOPE_STMT, NULL_TREE);
SCOPE_BEGIN_P (ss) = begin_p;
SCOPE_PARTIAL_P (ss) = partial_p;
/* Keep the scope stack up to date. */
if (begin_p)
{
current_scope_stmt_stack
= tree_cons (ss, NULL_TREE, current_scope_stmt_stack);
top = current_scope_stmt_stack;
}
else
{
top = current_scope_stmt_stack;
TREE_VALUE (top) = ss;
current_scope_stmt_stack = TREE_CHAIN (top);
}
/* Add the new statement to the statement-tree. */
add_stmt (ss);
return top;
return &cfun->language->x_scope_stmt_stack;
}
/* Finish a parenthesized expression EXPR. */
@ -2236,10 +2163,6 @@ cp_expand_stmt (t)
genrtl_subobject (SUBOBJECT_CLEANUP (t));
break;
case SCOPE_STMT:
genrtl_scope_stmt (t);
break;
case RETURN_INIT:
genrtl_named_return_value ();
break;
@ -2483,7 +2406,7 @@ expand_body (fn)
/* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
any of the other magic variables we set up when starting a
function body. */
cp_function_chain->name_declared = 1;
function_name_declared_p = 1;
/* Expand the body. */
expand_stmt (DECL_SAVED_TREE (fn));

View File

@ -1081,7 +1081,6 @@ cp_statement_code_p (code)
case CLEANUP_STMT:
case START_CATCH_STMT:
case CTOR_STMT:
case SCOPE_STMT:
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:

View File

@ -34,11 +34,11 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "cp-tree.h"
#include "tm_p.h"
#include "flags.h"
#include "output.h"
#include "expr.h"
#include "toplev.h"
#include "defaults.h"
@ -54,9 +54,6 @@ static int comp_except_types PARAMS ((tree, tree, int));
static int comp_array_types PARAMS ((int (*) (tree, tree, int), tree,
tree, int));
static tree common_base_type PARAMS ((tree, tree));
#if 0
static tree convert_sequence PARAMS ((tree, tree));
#endif
static tree lookup_anon_field PARAMS ((tree, tree));
static tree pointer_diff PARAMS ((tree, tree, tree));
static tree build_component_addr PARAMS ((tree, tree));
@ -4745,35 +4742,6 @@ build_unary_op (code, xarg, noconvert)
return error_mark_node;
}
#if 0
/* If CONVERSIONS is a conversion expression or a nested sequence of such,
convert ARG with the same conversions in the same order
and return the result. */
static tree
convert_sequence (conversions, arg)
tree conversions;
tree arg;
{
switch (TREE_CODE (conversions))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
return cp_convert (TREE_TYPE (conversions),
convert_sequence (TREE_OPERAND (conversions, 0),
arg));
default:
return arg;
}
}
#endif
/* Apply unary lvalue-demanding operator CODE to the expression ARG
for certain kinds of expressions which are not really lvalues
but which we can accept as lvalues.

View File

@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "expr.h"
#include "tree.h"
#include "c-common.h"
#include "flags.h"
@ -58,7 +59,7 @@ Boston, MA 02111-1307, USA. */
dependence to the dep_chain
*/
enum dependence_type {flow, anti, output, none};
enum dependence_type {dt_flow, dt_anti, dt_output, dt_none};
#if 0
static const char * dependence_string [] = {"flow", "anti", "output", "none"};
#endif
@ -756,23 +757,23 @@ check_node_dependence (du)
dep_ptr->next = 0;
if (def_ptr < use_ptr && use_ptr->type == use)
dep_ptr->dependence = flow;
dep_ptr->dependence = dt_flow;
else if (def_ptr > use_ptr && use_ptr->type == use)
dep_ptr->dependence = anti;
else dep_ptr->dependence = output;
dep_ptr->dependence = dt_anti;
else dep_ptr->dependence = dt_output;
for (j = 1 ; j <= i - 1 ; j++)
{
if (direction[j][0] == gt)
{
dep_ptr->dependence = anti;
dep_ptr->dependence = dt_anti;
direction[j][0] = lt;
distance[j][0] = -distance[j][0];
break;
}
else if (direction[j][0] == lt)
{
dep_ptr->dependence = flow;
dep_ptr->dependence = dt_flow;
break;
}
}
@ -796,7 +797,7 @@ check_node_dependence (du)
dep_root_ptr = VARRAY_TOP (dep_chain, generic);
dep_root_ptr->source = 0;
dep_root_ptr->destination = def_ptr->expression;
dep_root_ptr->dependence = none;
dep_root_ptr->dependence = dt_none;
dep_root_ptr->next = dep_ptr;
def_ptr->dep = dep_ptr;
}

View File

@ -85,6 +85,15 @@ Boston, MA 02111-1307, USA. */
#define CASE_VECTOR_PC_RELATIVE 0
#endif
/* Hook called by safe_from_p for language-specific tree codes. It is
up to the language front-end to install a hook if it has any such
codes that safe_from_p needs to know about. Since same_from_p will
recursively explore the TREE_OPERANDs of an expression, this hook
should not reexamine those pieces. This routine may recursively
call safe_from_p; it should always pass `0' as the TOP_P
parameter. */
int (*lang_safe_from_p) PARAMS ((rtx, tree));
/* If this is nonzero, we do not bother generating VOLATILE
around volatile memory references, and we are willing to
output indirect addresses. If cse is to follow, we reject
@ -168,7 +177,6 @@ static enum memory_use_mode
get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
static tree save_noncopied_parts PARAMS ((tree, tree));
static tree init_noncopied_parts PARAMS ((tree, tree));
static int safe_from_p PARAMS ((rtx, tree, int));
static int fixed_type_p PARAMS ((tree));
static rtx var_rtx PARAMS ((tree));
static int readonly_fields_p PARAMS ((tree));
@ -5396,7 +5404,7 @@ init_noncopied_parts (lhs, list)
It is always safe for this routine to return zero since it merely
searches for optimization opportunities. */
static int
int
safe_from_p (x, exp, top_p)
rtx x;
tree exp;
@ -5595,11 +5603,18 @@ safe_from_p (x, exp, top_p)
if (exp_rtl)
break;
nops = TREE_CODE_LENGTH (TREE_CODE (exp));
nops = first_rtl_op (TREE_CODE (exp));
for (i = 0; i < nops; i++)
if (TREE_OPERAND (exp, i) != 0
&& ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
return 0;
/* If this is a language-specific tree code, it may require
special handling. */
if (TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE
&& lang_safe_from_p
&& !(*lang_safe_from_p) (x, exp))
return 0;
}
/* If we have an rtl, find any enclosed object. Then see if we conflict

View File

@ -1257,6 +1257,17 @@ extern rtx (*lang_expand_expr) PARAMS ((union tree_node *, rtx,
such codes that output_constant needs to know about. Returns a
language-independent constant equivalent to its input. */
extern tree (*lang_expand_constant) PARAMS ((tree));
extern int safe_from_p PARAMS ((rtx, tree, int));
/* Hook called by safe_from_p for language-specific tree codes. It is
up to the language front-end to install a hook if it has any such
codes that safe_from_p needs to know about. Since same_from_p will
recursively explore the TREE_OPERANDs of an expression, this hook
should not reexamine those pieces. This routine may recursively
call safe_from_p; it should always pass `0' as the TOP_P
parameter. */
extern int (*lang_safe_from_p) PARAMS ((rtx, tree));
#endif
extern void init_all_optabs PARAMS ((void));

View File

@ -1,5 +1,5 @@
# Top level makefile fragment for GNU Objective-C
# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
# Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
#This file is part of GNU CC.
@ -85,7 +85,7 @@ $(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
$(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc/objc-parse.y
objc-act.o : $(srcdir)/objc/objc-act.c \
$(CONFIG_H) $(TREE_H) $(RTL_H) system.h \
$(CONFIG_H) $(TREE_H) $(RTL_H) system.h $(EXPR_H) \
$(srcdir)/c-tree.h $(srcdir)/c-common.h $(srcdir)/c-lex.h \
$(srcdir)/toplev.h $(srcdir)/flags.h $(srcdir)/objc/objc-act.h \
$(srcdir)/input.h $(srcdir)/function.h $(srcdir)/output.h

View File

@ -42,8 +42,11 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "c-tree.h"
#include "c-lex.h"
#include "c-common.h"
#include "flags.h"
#include "objc-act.h"
#include "input.h"
@ -198,6 +201,7 @@ static void encode_aggregate_within PARAMS ((tree, int, int,
int, int));
static const char *objc_demangle PARAMS ((const char *));
static const char *objc_printable_name PARAMS ((tree, int));
static void objc_expand_function_end PARAMS ((void));
/* Misc. bookkeeping */
@ -7410,12 +7414,18 @@ encode_method_def (func_decl)
return result;
}
static void
objc_expand_function_end ()
{
METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
}
void
finish_method_def ()
{
METHOD_ENCODING (method_context) = encode_method_def (current_function_decl);
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

View File

@ -110,7 +110,7 @@ enum objc_tree_code {
#ifdef OBJCPLUS
dummy_tree_code = LAST_CPLUS_TREE_CODE,
#else
dummy_tree_code = LAST_AND_UNUSED_TREE_CODE,
dummy_tree_code = LAST_C_TREE_CODE,
#endif
#include "objc-tree.def"
LAST_OBJC_TREE_CODE

View File

@ -1923,11 +1923,14 @@ expand_expr_stmt (exp)
if (expr_stmts_for_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
last_expr_type = TREE_TYPE (exp);
/* The call to `expand_expr' could cause last_expr_type and
last_expr_value to get reset. Therefore, we set last_expr_value
and last_expr_type *after* calling expand_expr. */
last_expr_value = expand_expr (exp,
(expr_stmts_for_value
? NULL_RTX : const0_rtx),
VOIDmode, 0);
last_expr_type = TREE_TYPE (exp);
/* If all we do is reference a volatile value in memory,
copy it to a register to be sure it is actually touched. */

View File

@ -75,7 +75,7 @@ caddr_t v_addr; /* { dg-error "parse error" } */
p_addr = fill_item_entry(va_op, v_addr);
goto page_type;
case((caddr_t)1): /* { dg-error "parse error" } */
default: /* { dg-error "default label" } */
default:
((void)(((0))?0:(__eprintf("Failed assertion`%s'at line%d of`%s'.\n",
"FALSE", 327, "b.c"), 0)));
}

View File

@ -2566,7 +2566,11 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
make_decl_rtl (decl, asmspec, top_level);
}
else
error ("invalid register name `%s' for register variable", asmspec);
{
error ("invalid register name `%s' for register variable", asmspec);
DECL_REGISTER (decl) = 0;
make_decl_rtl (decl, NULL, top_level);
}
}
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)

View File

@ -2794,11 +2794,15 @@ int
contains_placeholder_p (exp)
tree exp;
{
register enum tree_code code = TREE_CODE (exp);
register enum tree_code code;
int result;
if (!exp)
return 0;
/* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
in it since it is supplying a value for it. */
code = TREE_CODE (exp);
if (code == WITH_RECORD_EXPR)
return 0;
else if (code == PLACEHOLDER_EXPR)

View File

@ -1,3 +1,7 @@
2000-09-16 Mark Mitchell <mark@codesourcery.com>
* splay-tree.c (splay_tree_predecessor): Fix typo in comment.
2000-09-14 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* splay-tree.c: #include <stdio.h>.

View File

@ -392,7 +392,7 @@ splay_tree_predecessor (sp, key)
if (comparison < 0)
return sp->root;
/* Otherwise, find the rightmost element of the left subtree. */
/* Otherwise, find the leftmost element of the right subtree. */
node = sp->root->left;
if (node)
while (node->right)