mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-24 03:14:08 +08:00
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:
parent
4797e955c6
commit
8f17b5c5cb
127
gcc/ChangeLog
127
gcc/ChangeLog
@ -1,3 +1,130 @@
|
||||
2000-09-16 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
Convert the C front-end to use function-at-a-time mode.
|
||||
* c-common.h: Include splay-tree.h.
|
||||
(C_DECLARED_LABEL_FLAG): New macro.
|
||||
(struct language_function): Add x_scope_stmt_stack and
|
||||
x_function_name_declared_p.
|
||||
(RECHAIN_STMTS): Move definition.
|
||||
(lang_statment_code_p): Likewise.
|
||||
(lang_expand_stmt): Likewise.
|
||||
(lang_expand_decl_stmt): New variable.
|
||||
(lang_expand_function_end): Likewise.
|
||||
(current_scope_stmt_stack): New function.
|
||||
(add_decl_stmt): Likewise.
|
||||
(add_scope_stmt): Likewise.
|
||||
(mark_stmt_tree): Likewise.
|
||||
(struct c_lang_decl): New structure.
|
||||
(DECL_SAVED_TREE): Define.
|
||||
(c_mark_lang_decl): New function.
|
||||
(c_expand_start_cond): Change prototype.
|
||||
(c_finish_then): New function.
|
||||
(c_finish_else): Likewise.
|
||||
(current_function_name_declared): Remove.
|
||||
(set_current_function_name_declared): Likewise.
|
||||
(mark_c_language_function): Declare.
|
||||
(case_compare): Likewise.
|
||||
(c_add_case_label): Likewise.
|
||||
(c_expand_expr): Likewise.
|
||||
(c_safe_from_p): Likewise.
|
||||
* c-common.c (lang_expand_function_end): New variable.
|
||||
(struct if_elt): Add if_stmt.
|
||||
(c_expand_start_cond): Add the if-statement to the statement-tree,
|
||||
rather than generating RTL.
|
||||
(c_finish_then): New function.
|
||||
(c_expand_start_else): Don't generate RTL.
|
||||
(c_finish_else): New function.
|
||||
(c_expand_expr_stmt): Don't generate RTL.
|
||||
(statement_code_p): Add SCOPE_STMT.
|
||||
(case_compare): New function.
|
||||
(c_add_case_label): Likewise.
|
||||
(mark_stmt_tree): Likewise.
|
||||
(c_mark_lang_decl): Likewise.
|
||||
(mark_c_language_function): Likewise.
|
||||
(c_expand_expr): Likewise.
|
||||
(c_safe_from_p): Likewise.
|
||||
* c-decl.c (c_stmt_tree): New variable
|
||||
(c_scope_stmt_stack): Likewise.
|
||||
(c_function_name_declared_p): Likewise.
|
||||
(lang_expand_expr_stmt): Remove.
|
||||
(poplevel): Don't call output_inline_function for nested
|
||||
functions.
|
||||
(pushdecl): Don't set DECL_CONTEXT for a local declaration of an
|
||||
`extern' function.
|
||||
(redeclaration_error_message): Change means of computing whether
|
||||
or not a function is nested.
|
||||
(lookup_label): Don't call label_rtx.
|
||||
(init_decl_processing): Add more GC roots.
|
||||
(start_decl): Add DECL_STMTs to the statement-tree, rather than
|
||||
calling rest_of_decl_compilation.
|
||||
(finish_decl): Don't call expand_decl.
|
||||
(store_parm_decls): Begin the statement-tree, but don't generate
|
||||
RTL.
|
||||
(finish_function): Tie off the statement-tree. Call c_expand_body
|
||||
if appropriate.
|
||||
(c_expand_body): New function.
|
||||
(push_c_function_context): Save more information.
|
||||
(pop_c_function_contxt): Likewise.
|
||||
(copy_lang_decl): Now that we use DECL_LANG_SPECIFIC, copy it.
|
||||
(lang_mark_tree): Mark it.
|
||||
(current_stmt_tree): Adjust.
|
||||
(current_scope_stmt_stack): New function.
|
||||
(do_case): Remove.
|
||||
(set_current_name_declared): Likewise.
|
||||
(c_begin_compound_stmt): Define.
|
||||
(c_expand_decl_stmt): Likewise.
|
||||
* c-lang.c: Include rtl.h and expr.h.
|
||||
(lang_init): Set more language-specific hooks.
|
||||
* c-lex.c: Include expr.h.
|
||||
* c-parse.in: Changes throughout to add statements to the
|
||||
statement-tree, rather than generating RTL after every statement.
|
||||
* c-semantics.c (lang_expand_decl_stmt): Define.
|
||||
(add_decl_stmt): New function.
|
||||
(add_scope_stmt): Likewise.
|
||||
(finish_stmt_tree): Tweak.
|
||||
(genrtl_expr_stmt): Likewise.
|
||||
(genrtl_decl_stmt): Handle local labels, and call
|
||||
lang_expand_decl_stmt if required.
|
||||
(genrtl_for_stmt): Fix line-number handling.
|
||||
(genrtl_case_label): Handle cleanups.
|
||||
(genrtl_asm_stmt): Don't call combine_strings.
|
||||
(genrtl_compound_stmt): Simplify.
|
||||
(expand_stmt): Handle SCOPE_STMTs.
|
||||
* c-tree.h (struct lang_decl): New structure.
|
||||
(C_DECLARED_LABEL_FLAG): Remove.
|
||||
(c_begin_compound_stmt): Declare.
|
||||
(c_expand_decl_stmt): Likewise.
|
||||
(c_expand_start_case): Rename to c_start_case.
|
||||
(c_finish_case): New function.
|
||||
* c-typeck.c (start_init): Tweak setting of
|
||||
constructor_incremental.
|
||||
(c_expand_asm_operands): Tweak error-handling. Add to the
|
||||
statement-tree.
|
||||
(c_expand_return): Add to the statement-tree.
|
||||
(c_expand_start_case): Rename to ...
|
||||
(c_start_case): ... this.
|
||||
(struct c_switch): New type.
|
||||
(switch_stack): New variable.
|
||||
(do_case): Simplify.
|
||||
(c_finish_case): New function.
|
||||
* dependence.c: Include expr.h.
|
||||
(enum dependence_type): Change spelling of enumerals.
|
||||
(check_node_dependence): Adjust.
|
||||
* expr.h (lang_safe_from_p): Declare.
|
||||
(safe_from_p): Likewise.
|
||||
* expr.c (lang_safe_from_p): New variable.
|
||||
(safe_from_p): Give it external linkage. Use lang_safe_from_p.
|
||||
* stmt.c (expand_expr_stmt): Avoid clobberring of last_expr_type.
|
||||
* toplev.c (rest_of_decl_compilation): Robustify.
|
||||
* tree.c (contains_placeholder_p): Likewise.
|
||||
* Makefile.in: Update dependencies.
|
||||
* objc/objc-act.h: Adjust calculation of value for dummy_tree_code.
|
||||
* objc/objc-act.c: Include rtl.h, expr.h, and c-common.h.
|
||||
(objc_expand_function_end): New function.
|
||||
(finish_method_def): Use it.
|
||||
(init_objc): Initialize more language-specific hooks.
|
||||
* objc/Make-lang.in: Update dependencies.
|
||||
|
||||
2000-09-16 Geoffrey Keating <geoffk@cygnus.com>
|
||||
|
||||
* configure.in: Define macros that affect features before
|
||||
|
@ -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 \
|
||||
|
329
gcc/c-common.c
329
gcc/c-common.c
@ -22,7 +22,6 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "tree.h"
|
||||
#include "c-common.h"
|
||||
#include "flags.h"
|
||||
#include "toplev.h"
|
||||
#include "output.h"
|
||||
@ -30,6 +29,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "rtl.h"
|
||||
#include "ggc.h"
|
||||
#include "expr.h"
|
||||
#include "c-common.h"
|
||||
#include "tm_p.h"
|
||||
#include "intl.h"
|
||||
|
||||
@ -149,6 +149,10 @@ tree (*make_fname_decl) PARAMS ((tree, const char *, int));
|
||||
returns 1 for language-specific statement codes. */
|
||||
int (*lang_statement_code_p) PARAMS ((enum tree_code));
|
||||
|
||||
/* If non-NULL, the address of a language-specific function that takes
|
||||
any action required right before expand_function_end is called. */
|
||||
void (*lang_expand_function_end) PARAMS ((void));
|
||||
|
||||
/* Nonzero means the expression being parsed will never be evaluated.
|
||||
This is a count, since unevaluated expressions can nest. */
|
||||
int skip_evaluation;
|
||||
@ -181,6 +185,7 @@ typedef struct
|
||||
int line;
|
||||
const char *file;
|
||||
int needs_warning;
|
||||
tree if_stmt;
|
||||
} if_elt;
|
||||
static void tfaff PARAMS ((void));
|
||||
|
||||
@ -192,15 +197,16 @@ static int if_stack_space = 0;
|
||||
/* Stack pointer. */
|
||||
static int if_stack_pointer = 0;
|
||||
|
||||
/* Generate RTL for the start of an if-then, and record the start of it
|
||||
/* Record the start of an if-then, and record the start of it
|
||||
for ambiguous else detection. */
|
||||
|
||||
void
|
||||
c_expand_start_cond (cond, exitflag, compstmt_count)
|
||||
c_expand_start_cond (cond, compstmt_count)
|
||||
tree cond;
|
||||
int exitflag;
|
||||
int compstmt_count;
|
||||
{
|
||||
tree if_stmt;
|
||||
|
||||
/* Make sure there is enough space on the stack. */
|
||||
if (if_stack_space == 0)
|
||||
{
|
||||
@ -213,17 +219,29 @@ c_expand_start_cond (cond, exitflag, compstmt_count)
|
||||
if_stack = (if_elt *)xrealloc (if_stack, if_stack_space * sizeof (if_elt));
|
||||
}
|
||||
|
||||
if_stmt = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
|
||||
IF_COND (if_stmt) = cond;
|
||||
add_stmt (if_stmt);
|
||||
|
||||
/* Record this if statement. */
|
||||
if_stack[if_stack_pointer].compstmt_count = compstmt_count;
|
||||
if_stack[if_stack_pointer].file = input_filename;
|
||||
if_stack[if_stack_pointer].line = lineno;
|
||||
if_stack[if_stack_pointer].needs_warning = 0;
|
||||
if_stack[if_stack_pointer].if_stmt = if_stmt;
|
||||
if_stack_pointer++;
|
||||
|
||||
expand_start_cond (cond, exitflag);
|
||||
}
|
||||
|
||||
/* 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,
|
||||
|
106
gcc/c-common.h
106
gcc/c-common.h
@ -22,6 +22,8 @@ Boston, MA 02111-1307, USA. */
|
||||
#ifndef GCC_C_COMMON_H
|
||||
#define GCC_C_COMMON_H
|
||||
|
||||
#include "splay-tree.h"
|
||||
|
||||
/* Usage of TREE_LANG_FLAG_?:
|
||||
0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
|
||||
TREE_NEGATED_INT (in INTEGER_CST).
|
||||
@ -194,6 +196,10 @@ enum c_tree_index
|
||||
|
||||
extern tree c_global_trees[CTI_MAX];
|
||||
|
||||
/* Mark which labels are explicitly declared.
|
||||
These may be shadowed, and may be referenced from nested functions. */
|
||||
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
|
||||
|
||||
typedef enum c_language_kind
|
||||
{
|
||||
clk_c, /* A dialect of C: K&R C, ANSI/ISO C89, C2000,
|
||||
@ -237,6 +243,11 @@ struct language_function {
|
||||
/* While we are parsing the function, this contains information
|
||||
about the statement-tree that we are building. */
|
||||
struct stmt_tree_s x_stmt_tree;
|
||||
/* The stack of SCOPE_STMTs for the current function. */
|
||||
tree x_scope_stmt_stack;
|
||||
/* Nonzero if __FUNCTION__ and its ilk have been declared in this
|
||||
function. */
|
||||
int x_function_name_declared_p;
|
||||
};
|
||||
|
||||
/* When building a statement-tree, this is the last statement added to
|
||||
@ -248,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
|
||||
|
351
gcc/c-decl.c
351
gcc/c-decl.c
@ -125,6 +125,19 @@ static tree current_function_parm_tags;
|
||||
static const char *current_function_prototype_file;
|
||||
static int current_function_prototype_line;
|
||||
|
||||
/* The current statement tree. */
|
||||
|
||||
static struct stmt_tree_s c_stmt_tree;
|
||||
|
||||
/* The current scope statement stack. */
|
||||
|
||||
static tree c_scope_stmt_stack;
|
||||
|
||||
/* Nonzero if __FUNCTION__ and its ilk have been declared in this
|
||||
function. */
|
||||
|
||||
static int c_function_name_declared_p;
|
||||
|
||||
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
|
||||
that have names. Here so we can clear out their names' definitions
|
||||
at the end of the function. */
|
||||
@ -296,6 +309,7 @@ static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
|
||||
static tree grokparms PARAMS ((tree, int));
|
||||
static void layout_array_type PARAMS ((tree));
|
||||
static tree c_make_fname_decl PARAMS ((tree, const char *, int));
|
||||
static void c_expand_body PARAMS ((tree, int));
|
||||
|
||||
/* C-specific option variables. */
|
||||
|
||||
@ -471,10 +485,6 @@ int warn_float_equal = 0;
|
||||
|
||||
int warn_multichar = 1;
|
||||
|
||||
/* Wrapper since C and C++ expand_expr_stmt are different. */
|
||||
|
||||
expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
|
||||
|
||||
/* The variant of the C language being processed. */
|
||||
|
||||
c_language_kind c_language = clk_c;
|
||||
@ -1088,12 +1098,6 @@ poplevel (keep, reverse, functionbody)
|
||||
if (DECL_ABSTRACT_ORIGIN (decl) != 0
|
||||
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
|
||||
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
|
||||
else if (DECL_SAVED_INSNS (decl) != 0)
|
||||
{
|
||||
push_function_context ();
|
||||
output_inline_function (decl);
|
||||
pop_function_context ();
|
||||
}
|
||||
}
|
||||
|
||||
/* If there were any declarations or structure tags in that level,
|
||||
@ -1235,6 +1239,7 @@ poplevel (keep, reverse, functionbody)
|
||||
|
||||
if (block)
|
||||
TREE_USED (block) = 1;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
@ -2063,8 +2068,8 @@ pushdecl (x)
|
||||
/* A local extern declaration for a function doesn't constitute nesting.
|
||||
A local auto declaration does, since it's a forward decl
|
||||
for a nested function coming later. */
|
||||
if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
|
||||
&& DECL_EXTERNAL (x))
|
||||
if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
|
||||
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
|
||||
DECL_CONTEXT (x) = 0;
|
||||
|
||||
if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
|
||||
@ -2618,7 +2623,7 @@ redeclaration_error_message (newdecl, olddecl)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
else if (current_binding_level == global_binding_level)
|
||||
else if (DECL_CONTEXT (newdecl) == NULL_TREE)
|
||||
{
|
||||
/* Objects declared at top level: */
|
||||
/* If at least one is a reference, it's ok. */
|
||||
@ -2678,9 +2683,6 @@ lookup_label (id)
|
||||
|
||||
decl = build_decl (LABEL_DECL, id, void_type_node);
|
||||
|
||||
/* Make sure every label has an rtx. */
|
||||
label_rtx (decl);
|
||||
|
||||
/* A label not explicitly declared must be local to where it's ref'd. */
|
||||
DECL_CONTEXT (decl) = current_function_decl;
|
||||
|
||||
@ -3217,6 +3219,8 @@ init_decl_processing ()
|
||||
/* Record our roots. */
|
||||
|
||||
ggc_add_tree_root (c_global_trees, CTI_MAX);
|
||||
ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
|
||||
ggc_add_tree_root (&c_scope_stmt_stack, 1);
|
||||
ggc_add_tree_root (&named_labels, 1);
|
||||
ggc_add_tree_root (&shadowed_labels, 1);
|
||||
ggc_add_root (¤t_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);
|
||||
}
|
||||
|
12
gcc/c-lang.c
12
gcc/c-lang.c
@ -25,13 +25,15 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "tree.h"
|
||||
#include "function.h"
|
||||
#include "input.h"
|
||||
#include "c-tree.h"
|
||||
#include "c-lex.h"
|
||||
#include "toplev.h"
|
||||
#include "diagnostic.h"
|
||||
#include "output.h"
|
||||
#include "flags.h"
|
||||
#include "ggc.h"
|
||||
#include "rtl.h"
|
||||
#include "expr.h"
|
||||
#include "c-tree.h"
|
||||
#include "c-lex.h"
|
||||
|
||||
static int c_tree_printer PARAMS ((output_buffer *));
|
||||
|
||||
@ -88,8 +90,10 @@ lang_init ()
|
||||
save_lang_status = &push_c_function_context;
|
||||
restore_lang_status = &pop_c_function_context;
|
||||
mark_lang_status = &mark_c_function_context;
|
||||
|
||||
lang_printer = c_tree_printer;
|
||||
lang_expand_expr = &c_expand_expr;
|
||||
lang_safe_from_p = &c_safe_from_p;
|
||||
lang_printer = &c_tree_printer;
|
||||
lang_expand_decl_stmt = &c_expand_decl_stmt;
|
||||
|
||||
c_parse_init ();
|
||||
}
|
||||
|
@ -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"
|
||||
|
237
gcc/c-parse.in
237
gcc/c-parse.in
@ -173,7 +173,8 @@ end ifc
|
||||
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
|
||||
%type <ttype> any_word extension
|
||||
|
||||
%type <ttype> compstmt compstmt_nostart compstmt_primary_start
|
||||
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
|
||||
%type <ttype> do_stmt_start poplevel
|
||||
|
||||
%type <ttype> declarator
|
||||
%type <ttype> notype_declarator after_type_declarator
|
||||
@ -661,33 +662,26 @@ primary:
|
||||
| '(' error ')'
|
||||
{ $$ = error_mark_node; }
|
||||
| compstmt_primary_start compstmt_nostart ')'
|
||||
{ tree rtl_exp;
|
||||
if (pedantic)
|
||||
pedwarn ("ISO C forbids braced-groups within expressions");
|
||||
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));
|
||||
}
|
||||
}
|
||||
;
|
||||
|
@ -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);
|
||||
|
17
gcc/c-tree.h
17
gcc/c-tree.h
@ -42,6 +42,14 @@ struct lang_identifier
|
||||
enum rid rid_code;
|
||||
};
|
||||
|
||||
/* Wrapping c_lang_decl in another struct is an unfortunate
|
||||
necessity. */
|
||||
|
||||
struct lang_decl
|
||||
{
|
||||
struct c_lang_decl base;
|
||||
};
|
||||
|
||||
/* Macros for access to language-specific slots in an identifier. */
|
||||
/* Each of these slots contains a DECL node or null. */
|
||||
|
||||
@ -103,10 +111,6 @@ struct lang_type
|
||||
tree elts[1];
|
||||
};
|
||||
|
||||
/* Mark which labels are explicitly declared.
|
||||
These may be shadowed, and may be referenced from nested functions. */
|
||||
#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
|
||||
|
||||
/* Record whether a type or decl was written with nonconstant size.
|
||||
Note that TYPE_SIZE may have simplified to a constant. */
|
||||
#define C_TYPE_VARIABLE_SIZE(type) TYPE_LANG_FLAG_1 (type)
|
||||
@ -230,6 +234,8 @@ extern tree start_decl PARAMS ((tree, tree, int,
|
||||
extern tree start_struct PARAMS ((enum tree_code, tree));
|
||||
extern void store_parm_decls PARAMS ((void));
|
||||
extern tree xref_tag PARAMS ((enum tree_code, tree));
|
||||
extern tree c_begin_compound_stmt PARAMS ((void));
|
||||
extern void c_expand_decl_stmt PARAMS ((tree));
|
||||
|
||||
/* in c-typeck.c */
|
||||
extern tree require_complete_type PARAMS ((tree));
|
||||
@ -268,7 +274,8 @@ extern void set_init_label PARAMS ((tree));
|
||||
extern void process_init_element PARAMS ((tree));
|
||||
extern void pedwarn_c99 PARAMS ((const char *, ...))
|
||||
ATTRIBUTE_PRINTF_1;
|
||||
extern tree c_expand_start_case PARAMS ((tree));
|
||||
extern tree c_start_case PARAMS ((tree));
|
||||
extern void c_finish_case PARAMS ((void));
|
||||
|
||||
/* Set to 0 at beginning of a function definition, set to 1 if
|
||||
a return statement that specifies a return value is seen. */
|
||||
|
148
gcc/c-typeck.c
148
gcc/c-typeck.c
@ -4999,7 +4999,8 @@ start_init (decl, asmspec_tree, top_level)
|
||||
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
|
||||
locus = IDENTIFIER_POINTER (DECL_NAME (decl));
|
||||
constructor_incremental |= TREE_STATIC (decl);
|
||||
constructor_incremental
|
||||
|= (TREE_STATIC (decl) && !DECL_CONTEXT (decl));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6541,7 +6542,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|
||||
if (TREE_CODE (string) == ADDR_EXPR)
|
||||
string = TREE_OPERAND (string, 0);
|
||||
if (TREE_CODE (string) != STRING_CST)
|
||||
if (last_tree && TREE_CODE (string) != STRING_CST)
|
||||
{
|
||||
error ("asm template is not a string constant");
|
||||
return;
|
||||
@ -6567,7 +6568,8 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|| TREE_CODE (output) == FIX_CEIL_EXPR)
|
||||
output = TREE_OPERAND (output, 0);
|
||||
|
||||
lvalue_or_else (o[i], "invalid lvalue in asm statement");
|
||||
if (last_tree)
|
||||
lvalue_or_else (o[i], "invalid lvalue in asm statement");
|
||||
}
|
||||
|
||||
/* Perform default conversions on array and function inputs. */
|
||||
@ -6578,6 +6580,14 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|
||||
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
|
||||
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
|
||||
|
||||
if (last_tree)
|
||||
{
|
||||
add_stmt (build_stmt (ASM_STMT,
|
||||
vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
|
||||
string, outputs, inputs, clobbers));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate the ASM_OPERANDS insn;
|
||||
store into the TREE_VALUEs of OUTPUTS some trees for
|
||||
where the values were actually stored. */
|
||||
@ -6703,53 +6713,115 @@ c_expand_return (retval)
|
||||
current_function_returns_value = 1;
|
||||
}
|
||||
|
||||
genrtl_return_stmt (build_return_stmt (retval));
|
||||
add_stmt (build_return_stmt (retval));
|
||||
}
|
||||
|
||||
/* Start a C switch statement, testing expression EXP.
|
||||
Return EXP if it is valid, an error node otherwise. */
|
||||
struct c_switch {
|
||||
/* The SWITCH_STMT being built. */
|
||||
tree switch_stmt;
|
||||
/* A splay-tree mapping the low element of a case range to the high
|
||||
element, or NULL_TREE if there is no high element. Used to
|
||||
determine whether or not a new case label duplicates an old case
|
||||
label. We need a tree, rather than simply a hash table, because
|
||||
of the GNU case range extension. */
|
||||
splay_tree cases;
|
||||
/* The next node on the stack. */
|
||||
struct c_switch *next;
|
||||
};
|
||||
|
||||
/* A stack of the currently active switch statements. The innermost
|
||||
switch statement is on the top of the stack. There is no need to
|
||||
mark the stack for garbage collection because it is only active
|
||||
during the processing of the body of a function, and we never
|
||||
collect at that point. */
|
||||
|
||||
static struct c_switch *switch_stack;
|
||||
|
||||
/* Start a C switch statement, testing expression EXP. Return the new
|
||||
SWITCH_STMT. */
|
||||
|
||||
tree
|
||||
c_expand_start_case (exp)
|
||||
c_start_case (exp)
|
||||
tree exp;
|
||||
{
|
||||
register enum tree_code code;
|
||||
tree type;
|
||||
struct c_switch *cs;
|
||||
|
||||
if (TREE_CODE (exp) == ERROR_MARK)
|
||||
return exp;
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
205
gcc/cp/decl.c
205
gcc/cp/decl.c
@ -159,7 +159,6 @@ static void mark_named_label_lists PARAMS ((void *, void *));
|
||||
static void mark_cp_function_context PARAMS ((struct function *));
|
||||
static void mark_saved_scope PARAMS ((void *));
|
||||
static void mark_lang_function PARAMS ((struct cp_language_function *));
|
||||
static void mark_stmt_tree PARAMS ((stmt_tree));
|
||||
static void save_function_data PARAMS ((tree));
|
||||
static void check_function_type PARAMS ((tree, tree));
|
||||
static void destroy_local_var PARAMS ((tree));
|
||||
@ -176,7 +175,6 @@ static tree check_special_function_return_type
|
||||
PARAMS ((special_function_kind, tree, tree, tree));
|
||||
static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
|
||||
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
|
||||
static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
|
||||
static void store_parm_decls PARAMS ((tree));
|
||||
|
||||
#if defined (DEBUG_CP_BINDING_LEVELS)
|
||||
@ -2411,16 +2409,6 @@ pop_nested_namespace (ns)
|
||||
scope isn't enough, because more binding levels may be pushed. */
|
||||
struct saved_scope *scope_chain;
|
||||
|
||||
/* Mark ST for GC. */
|
||||
|
||||
static void
|
||||
mark_stmt_tree (st)
|
||||
stmt_tree st;
|
||||
{
|
||||
ggc_mark_tree (st->x_last_stmt);
|
||||
ggc_mark_tree (st->x_last_expr_type);
|
||||
}
|
||||
|
||||
/* Mark ARG (which is really a struct saved_scope **) for GC. */
|
||||
|
||||
static void
|
||||
@ -5156,21 +5144,6 @@ struct cp_switch
|
||||
|
||||
static struct cp_switch *switch_stack;
|
||||
|
||||
static int
|
||||
case_compare (k1, k2)
|
||||
splay_tree_key k1;
|
||||
splay_tree_key k2;
|
||||
{
|
||||
/* Consider a NULL key (such as arises with a `default' label) to be
|
||||
smaller than anything else. */
|
||||
if (!k1)
|
||||
return k2 ? -1 : 0;
|
||||
else if (!k2)
|
||||
return k1 ? 1 : 0;
|
||||
|
||||
return tree_int_cst_compare ((tree) k1, (tree) k2);
|
||||
}
|
||||
|
||||
/* Called right after a switch-statement condition is parsed.
|
||||
SWITCH_STMT is the switch statement being parsed. */
|
||||
|
||||
@ -5206,12 +5179,7 @@ finish_case_label (low_value, high_value)
|
||||
tree low_value;
|
||||
tree high_value;
|
||||
{
|
||||
tree label;
|
||||
tree cleanup;
|
||||
tree type;
|
||||
tree cond;
|
||||
tree case_label;
|
||||
splay_tree_node node;
|
||||
|
||||
if (! switch_stack)
|
||||
{
|
||||
@ -5225,13 +5193,13 @@ finish_case_label (low_value, high_value)
|
||||
return;
|
||||
}
|
||||
|
||||
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
DECL_CONTEXT (label) = current_function_decl;
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
tree label;
|
||||
|
||||
/* For templates, just add the case label; we'll do semantic
|
||||
analysis at instantiation-time. */
|
||||
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
|
||||
add_stmt (build_case_label (low_value, high_value, label));
|
||||
return;
|
||||
}
|
||||
@ -5240,124 +5208,8 @@ finish_case_label (low_value, high_value)
|
||||
cond = SWITCH_COND (switch_stack->switch_stmt);
|
||||
if (cond && TREE_CODE (cond) == TREE_LIST)
|
||||
cond = TREE_VALUE (cond);
|
||||
/* If there was an error processing the switch condition, bail now
|
||||
before we get more confused. */
|
||||
if (!cond || cond == error_mark_node)
|
||||
return;
|
||||
type = TREE_TYPE (cond);
|
||||
|
||||
if ((low_value && TREE_TYPE (low_value)
|
||||
&& POINTER_TYPE_P (TREE_TYPE (low_value)))
|
||||
|| (high_value && TREE_TYPE (high_value)
|
||||
&& POINTER_TYPE_P (TREE_TYPE (high_value))))
|
||||
error ("pointers are not permitted as case values");
|
||||
|
||||
/* Case ranges are a GNU extension. */
|
||||
if (high_value && pedantic)
|
||||
pedwarn ("ISO C++ forbids range expressions in switch statement");
|
||||
|
||||
if (low_value)
|
||||
{
|
||||
low_value = check_case_value (low_value);
|
||||
low_value = convert_and_check (type, low_value);
|
||||
}
|
||||
if (high_value)
|
||||
{
|
||||
high_value = check_case_value (high_value);
|
||||
high_value = convert_and_check (type, high_value);
|
||||
}
|
||||
|
||||
/* If an error has occurred, bail out now. */
|
||||
if (low_value == error_mark_node || high_value == error_mark_node)
|
||||
return;
|
||||
|
||||
/* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
|
||||
really a case range, even though it was written that way. Remove
|
||||
the HIGH_VALUE to simplify later processing. */
|
||||
if (tree_int_cst_equal (low_value, high_value))
|
||||
high_value = NULL_TREE;
|
||||
if (low_value && high_value
|
||||
&& !tree_int_cst_lt (low_value, high_value))
|
||||
warning ("empty range specified");
|
||||
|
||||
/* Look up the LOW_VALUE in the table of case labels we already
|
||||
have. */
|
||||
node = splay_tree_lookup (switch_stack->cases, (splay_tree_key) low_value);
|
||||
/* If there was not an exact match, check for overlapping ranges.
|
||||
There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
|
||||
that's a `default' label and the only overlap is an exact match. */
|
||||
if (!node && (low_value || high_value))
|
||||
{
|
||||
splay_tree_node low_bound;
|
||||
splay_tree_node high_bound;
|
||||
|
||||
/* Even though there wasn't an exact match, there might be an
|
||||
overlap between this case range and another case range.
|
||||
Since we've (inductively) not allowed any overlapping case
|
||||
ranges, we simply need to find the greatest low case label
|
||||
that is smaller that LOW_VALUE, and the smallest low case
|
||||
label that is greater than LOW_VALUE. If there is an overlap
|
||||
it will occur in one of these two ranges. */
|
||||
low_bound = splay_tree_predecessor (switch_stack->cases,
|
||||
(splay_tree_key) low_value);
|
||||
high_bound = splay_tree_successor (switch_stack->cases,
|
||||
(splay_tree_key) low_value);
|
||||
|
||||
/* Check to see if the LOW_BOUND overlaps. It is smaller than
|
||||
the LOW_VALUE, so there is no need to check unless the
|
||||
LOW_BOUND is in fact itself a case range. */
|
||||
if (low_bound
|
||||
&& CASE_HIGH ((tree) low_bound->value)
|
||||
&& tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
|
||||
low_value) >= 0)
|
||||
node = low_bound;
|
||||
/* Check to see if the HIGH_BOUND overlaps. The low end of that
|
||||
range is bigger than the low end of the current range, so we
|
||||
are only interested if the current range is a real range, and
|
||||
not an ordinary case label. */
|
||||
else if (high_bound
|
||||
&& high_value
|
||||
&& (tree_int_cst_compare ((tree) high_bound->key,
|
||||
high_value)
|
||||
<= 0))
|
||||
node = high_bound;
|
||||
}
|
||||
/* If there was an overlap, issue an error. */
|
||||
if (node)
|
||||
{
|
||||
tree duplicate = CASE_LABEL_DECL ((tree) node->value);
|
||||
|
||||
if (high_value)
|
||||
{
|
||||
error ("duplicate (or overlapping) case value");
|
||||
cp_error_at ("this is the first entry overlapping that value",
|
||||
duplicate);
|
||||
}
|
||||
else if (low_value)
|
||||
{
|
||||
cp_error ("duplicate case value `%E'", low_value) ;
|
||||
cp_error_at ("previously used here", duplicate);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("multiple default labels in one switch");
|
||||
cp_error_at ("this is the first default label", duplicate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup = last_cleanup_this_contour ();
|
||||
if (cleanup)
|
||||
{
|
||||
static int explained = 0;
|
||||
cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
|
||||
warning ("where case label appears here");
|
||||
if (!explained)
|
||||
{
|
||||
warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
|
||||
explained = 1;
|
||||
}
|
||||
}
|
||||
c_add_case_label (switch_stack->cases, cond, low_value, high_value);
|
||||
|
||||
check_switch_goto (switch_stack->level);
|
||||
|
||||
@ -5365,16 +5217,6 @@ finish_case_label (low_value, high_value)
|
||||
own new (temporary) binding contour. */
|
||||
current_binding_level->more_cleanups_ok = 0;
|
||||
current_function_return_value = NULL_TREE;
|
||||
|
||||
/* Add a representation for the case label to the statement
|
||||
tree. */
|
||||
case_label = build_case_label (low_value, high_value, label);
|
||||
add_stmt (case_label);
|
||||
|
||||
/* Register this case label in the splay tree. */
|
||||
splay_tree_insert (switch_stack->cases,
|
||||
(splay_tree_key) low_value,
|
||||
(splay_tree_value) case_label);
|
||||
}
|
||||
|
||||
/* Return the list of declarations of the current level.
|
||||
@ -6462,11 +6304,11 @@ init_decl_processing ()
|
||||
/* Create all the identifiers we need. */
|
||||
initialize_predefined_identifiers ();
|
||||
|
||||
/* Let the back-end now how to save and restore language-specific
|
||||
per-function globals. */
|
||||
/* Fill in back-end hooks. */
|
||||
init_lang_status = &push_cp_function_context;
|
||||
free_lang_status = &pop_cp_function_context;
|
||||
mark_lang_status = &mark_cp_function_context;
|
||||
lang_safe_from_p = &c_safe_from_p;
|
||||
|
||||
cp_parse_init ();
|
||||
init_decl2 ();
|
||||
@ -13557,7 +13399,7 @@ build_enumerator (name, value, enumtype)
|
||||
|
||||
if (context && context == current_class_type)
|
||||
/* This enum declaration is local to the class. We need the full
|
||||
lang_decl so that we can record DECL_CLASS_CONTEXT, for example. */
|
||||
lang_decl so that we can record DECL_CLASS_CONTEXT, for example. */
|
||||
decl = build_lang_decl (CONST_DECL, name, type);
|
||||
else
|
||||
/* It's a global enum, or it's local to a function. (Note local to
|
||||
@ -14696,31 +14538,6 @@ maybe_build_cleanup (decl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Expand a C++ expression at the statement level.
|
||||
This is needed to ferret out nodes which have UNKNOWN_TYPE.
|
||||
The C++ type checker should get all of these out when
|
||||
expressions are combined with other, type-providing, expressions,
|
||||
leaving only orphan expressions, such as:
|
||||
|
||||
&class::bar; / / takes its address, but does nothing with it. */
|
||||
|
||||
void
|
||||
cplus_expand_expr_stmt (exp)
|
||||
tree exp;
|
||||
{
|
||||
#if 0
|
||||
/* We should do this eventually, but right now this causes regex.o from
|
||||
libg++ to miscompile, and tString to core dump. */
|
||||
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
|
||||
#endif
|
||||
|
||||
/* If we don't do this, we end up down inside expand_expr
|
||||
trying to do TYPE_MODE on the ERROR_MARK, and really
|
||||
go outside the bounds of the type. */
|
||||
if (exp != error_mark_node)
|
||||
expand_expr_stmt (exp);
|
||||
}
|
||||
|
||||
/* When a stmt has been parsed, this function is called. */
|
||||
|
||||
void
|
||||
@ -14801,17 +14618,17 @@ mark_lang_function (p)
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
mark_c_language_function (&p->base);
|
||||
|
||||
ggc_mark_tree (p->x_ctor_label);
|
||||
ggc_mark_tree (p->x_dtor_label);
|
||||
ggc_mark_tree (p->x_current_class_ptr);
|
||||
ggc_mark_tree (p->x_current_class_ref);
|
||||
ggc_mark_tree (p->x_eh_spec_try_block);
|
||||
ggc_mark_tree (p->x_scope_stmt_stack);
|
||||
|
||||
ggc_mark_rtx (p->x_result_rtx);
|
||||
|
||||
mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
|
||||
mark_stmt_tree (&p->base.x_stmt_tree);
|
||||
mark_binding_level (&p->bindings);
|
||||
}
|
||||
|
||||
@ -14872,13 +14689,13 @@ lang_mark_tree (t)
|
||||
if (ld)
|
||||
{
|
||||
ggc_mark (ld);
|
||||
c_mark_lang_decl (&ld->decl_flags.base);
|
||||
if (!DECL_GLOBAL_CTOR_P (t)
|
||||
&& !DECL_GLOBAL_DTOR_P (t)
|
||||
&& !DECL_THUNK_P (t))
|
||||
ggc_mark_tree (ld->decl_flags.u2.access);
|
||||
else if (DECL_THUNK_P (t))
|
||||
ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
|
||||
ggc_mark_tree (ld->decl_flags.context);
|
||||
if (TREE_CODE (t) != NAMESPACE_DECL)
|
||||
ggc_mark_tree (ld->decl_flags.u.template_info);
|
||||
else
|
||||
@ -14886,7 +14703,7 @@ lang_mark_tree (t)
|
||||
if (CAN_HAVE_FULL_LANG_DECL_P (t))
|
||||
{
|
||||
ggc_mark_tree (ld->befriending_classes);
|
||||
ggc_mark_tree (ld->saved_tree);
|
||||
ggc_mark_tree (ld->context);
|
||||
ggc_mark_tree (ld->cloned_function);
|
||||
if (!DECL_OVERLOADED_OPERATOR_P (t))
|
||||
ggc_mark_tree (ld->u2.vtt_parm);
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
21
gcc/expr.c
21
gcc/expr.c
@ -85,6 +85,15 @@ Boston, MA 02111-1307, USA. */
|
||||
#define CASE_VECTOR_PC_RELATIVE 0
|
||||
#endif
|
||||
|
||||
/* Hook called by safe_from_p for language-specific tree codes. It is
|
||||
up to the language front-end to install a hook if it has any such
|
||||
codes that safe_from_p needs to know about. Since same_from_p will
|
||||
recursively explore the TREE_OPERANDs of an expression, this hook
|
||||
should not reexamine those pieces. This routine may recursively
|
||||
call safe_from_p; it should always pass `0' as the TOP_P
|
||||
parameter. */
|
||||
int (*lang_safe_from_p) PARAMS ((rtx, tree));
|
||||
|
||||
/* If this is nonzero, we do not bother generating VOLATILE
|
||||
around volatile memory references, and we are willing to
|
||||
output indirect addresses. If cse is to follow, we reject
|
||||
@ -168,7 +177,6 @@ static enum memory_use_mode
|
||||
get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
|
||||
static tree save_noncopied_parts PARAMS ((tree, tree));
|
||||
static tree init_noncopied_parts PARAMS ((tree, tree));
|
||||
static int safe_from_p PARAMS ((rtx, tree, int));
|
||||
static int fixed_type_p PARAMS ((tree));
|
||||
static rtx var_rtx PARAMS ((tree));
|
||||
static int readonly_fields_p PARAMS ((tree));
|
||||
@ -5396,7 +5404,7 @@ init_noncopied_parts (lhs, list)
|
||||
It is always safe for this routine to return zero since it merely
|
||||
searches for optimization opportunities. */
|
||||
|
||||
static int
|
||||
int
|
||||
safe_from_p (x, exp, top_p)
|
||||
rtx x;
|
||||
tree exp;
|
||||
@ -5595,11 +5603,18 @@ safe_from_p (x, exp, top_p)
|
||||
if (exp_rtl)
|
||||
break;
|
||||
|
||||
nops = TREE_CODE_LENGTH (TREE_CODE (exp));
|
||||
nops = first_rtl_op (TREE_CODE (exp));
|
||||
for (i = 0; i < nops; i++)
|
||||
if (TREE_OPERAND (exp, i) != 0
|
||||
&& ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
|
||||
return 0;
|
||||
|
||||
/* If this is a language-specific tree code, it may require
|
||||
special handling. */
|
||||
if (TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE
|
||||
&& lang_safe_from_p
|
||||
&& !(*lang_safe_from_p) (x, exp))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we have an rtl, find any enclosed object. Then see if we conflict
|
||||
|
11
gcc/expr.h
11
gcc/expr.h
@ -1257,6 +1257,17 @@ extern rtx (*lang_expand_expr) PARAMS ((union tree_node *, rtx,
|
||||
such codes that output_constant needs to know about. Returns a
|
||||
language-independent constant equivalent to its input. */
|
||||
extern tree (*lang_expand_constant) PARAMS ((tree));
|
||||
|
||||
extern int safe_from_p PARAMS ((rtx, tree, int));
|
||||
|
||||
/* Hook called by safe_from_p for language-specific tree codes. It is
|
||||
up to the language front-end to install a hook if it has any such
|
||||
codes that safe_from_p needs to know about. Since same_from_p will
|
||||
recursively explore the TREE_OPERANDs of an expression, this hook
|
||||
should not reexamine those pieces. This routine may recursively
|
||||
call safe_from_p; it should always pass `0' as the TOP_P
|
||||
parameter. */
|
||||
extern int (*lang_safe_from_p) PARAMS ((rtx, tree));
|
||||
#endif
|
||||
|
||||
extern void init_all_optabs PARAMS ((void));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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>.
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user