Move statement-tree facilities from C++ to C front-end.

* c-common.h (c_tree_index): Add CTI_VOID_ZERO.
	(void_zero_node): New macro.
	(struct stmt_tree_s): New type.
	(stmt_tree): New typedef.
	(struct language_function): New type.
	(last_tree): New macro.
	(last_expr_type): Likewise.
	(walk_tree_fn): New typedef.
	(current_stmt_tree): New function.
	(begin_stmt_tree): Likewise.
	(add_stmt): Likewise.
	(finish_stmt_tree): Likewise.
	(statement_code_p): Likewise.
	(lang_statement_code_p): New variable.
	(walk_stmt_tree): New function.
	(STMT_IS_FULL_EXPR_P): New macro.
	* c-common.c (lang_statement_code_p): New variable.
	(c_common_nodes_and_builtins): Initialize void_zero_node.
	(statement_code_p): New function.
	(walk_stmt_tree): Likewise.
	* c-decl.c (language_function): Rename to ...
	(c_language_function): ... this.  Include language_function.
	(push_c_function_context): Adjust accordingly.
	(pop_c_function_context): Likewise.
	(mark_c_function_context): Likewise.
	(current_stmt_tree): Define.
	* c-semantics.c (begin_stmt_tree): New function.
	(add_stmt): Likewise.
	(prune_unused_decls): Likewise.
	(finish_stmt_tree): Likewise.

	Move statement-tree facilities from C++ to C front-end.
	* cp-tree.h (cp_tree_index): Remove CPTI_VOID_ZERO.
	(void_zero_node): Remove.
	(stmt_tree): Likewise.
	(scope_chain): Adjust.
	(language_function): Rename to cp_language_function.
	(cp_function_chain): Adjust.
	(current_stmt_tree): Remove.
	(last_tree): Likewise.
	(last_expr_type): Likewise.
	(struct lang_decl): Adjust.
	(STMT_IS_FULL_EXPR_P): Remove.
	(add_tree): Remove.
	(begin_stmt_tree): Likewise.
	(finish_stmt_tree): Likewise.
	(walk_tree_fn): Likewise.
	(walk_stmt_tree): Likewise.
	* class.c (finish_struct): Replace use of add_tree with add_stmt.
	* decl.c (mark_stmt_tree): Adjust type.
	(init_decl_processing): Don't build void_zero_node.
	(initialize_local_var): Adjust usage of current_stmt_tree.
	(finish_enum): Use add_stmt, not add_tree.
	(save_function_data): Adjust use of language_function.
	(finish_constructor_body): Use add_stmt, not add_tree.
	(finish_destructor_body): Likewise.
	(push_cp_function_context): Adjust use of language_function.
	(pop_cp_function_context): Likewise.
	(mark_lang_function): Likewise.
	(mark_cp_function_context): Likewise.
	* init.c (build_aggr_init): Adjust use of current_stmt_tree.
	(build_vec_init): Likewise.
	* semantics.c (SET_LAST_STMT): Remove.
	(RECHAIN_STMTS): Don't use it.
	(stmts_are_full_exprs_p): Adjust use of current_stmt_tree.
	(current_stmt_tree): Define.
	(add_tree): Remove.
	(finish_goto_stmt): Use add_stmt, not add_tree.
	(finish_expr_stmt): Likewise.
	(begin_if_stmt): Likewise.
	(finish_then_clause): Likewise.
	(begin_while_stmt): Likewise.
	(begin_do_stmt): Likewise.
	(finish_return_stmt): Likewise.
	(begin_for_stmt): Likewise.
	(finish_break_stmt): Likewise.
	(finish_continue_stmt): Likewise.
	(begin_switch_stmt): Likewise.
	(finish_case_label): Likewise.
	(begin_try_block): Likewise.
	(begin_function_try_block): Likewise.
	(begin_handler): Likewise.
	(begin_catch_block): Likewise.
	(begin_compound_stmt): Likewise.
	(begin_asm_stmt): Likewise.
	(finish_asm_stmt): Likewise.
	(finish_label_stmt): Likewise.
	(add_decl_stmt): Likewise.
	(finish_subobject): Likewise.
	(finish_decl_cleanup): Likewise.
	(finish_named_return_value): Likewise.
	(setup_vtbl_ptr): Likewise.
	(add_scope_stmt): Likewise.
	(finish_stmt_expr): Likewise.
	(prune_unused_decls): Remove.
	(begin_stmt_tree): Likewise.
	(finish_stmt_tree): Likewise.
	(prep_stmt): Adjust use of current_stmt_tree.
	(lang_expand_stmt): Likewise.
	* tree.c (statement_code_p): Remove.
	(cp_statement_code_p): New function.
	(walk_stmt_tree): Remove.
	(init_tree): Set lang_statement_code_p.

From-SVN: r36221
This commit is contained in:
Mark Mitchell 2000-09-07 01:36:11 +00:00 committed by Mark Mitchell
parent 4f4b88d083
commit ae499ccea4
14 changed files with 524 additions and 340 deletions

View File

@ -1,3 +1,37 @@
2000-09-06 Mark Mitchell <mark@codesourcery.com>
Move statement-tree facilities from C++ to C front-end.
* c-common.h (c_tree_index): Add CTI_VOID_ZERO.
(void_zero_node): New macro.
(struct stmt_tree_s): New type.
(stmt_tree): New typedef.
(struct language_function): New type.
(last_tree): New macro.
(last_expr_type): Likewise.
(walk_tree_fn): New typedef.
(current_stmt_tree): New function.
(begin_stmt_tree): Likewise.
(add_stmt): Likewise.
(finish_stmt_tree): Likewise.
(statement_code_p): Likewise.
(lang_statement_code_p): New variable.
(walk_stmt_tree): New function.
(STMT_IS_FULL_EXPR_P): New macro.
* c-common.c (lang_statement_code_p): New variable.
(c_common_nodes_and_builtins): Initialize void_zero_node.
(statement_code_p): New function.
(walk_stmt_tree): Likewise.
* c-decl.c (language_function): Rename to ...
(c_language_function): ... this. Include language_function.
(push_c_function_context): Adjust accordingly.
(pop_c_function_context): Likewise.
(mark_c_function_context): Likewise.
(current_stmt_tree): Define.
* c-semantics.c (begin_stmt_tree): New function.
(add_stmt): Likewise.
(prune_unused_decls): Likewise.
(finish_stmt_tree): Likewise.
2000-09-06 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
* flow.c (insn_dead_p): Detect dead memory stores with auto increments.

View File

@ -144,6 +144,10 @@ tree *ridpointers;
tree (*make_fname_decl) PARAMS ((tree, const char *, int));
/* If non-NULL, the address of a language-specific function that
returns 1 for language-specific statement codes. */
int (*lang_statement_code_p) PARAMS ((enum tree_code));
/* Nonzero means the expression being parsed will never be evaluated.
This is a count, since unevaluated expressions can nest. */
int skip_evaluation;
@ -3870,6 +3874,9 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
sizetype,
endlink))));
void_zero_node = build_int_2 (0, 0);
TREE_TYPE (void_zero_node) = void_type_node;
/* Prototype for strcpy. */
string_ftype_ptr_ptr
= build_function_type (string_type_node,
@ -4378,6 +4385,111 @@ expand_tree_builtin (function, params, coerced_params)
return NULL_TREE;
}
/* Returns non-zero if CODE is the code for a statement. */
int
statement_code_p (code)
enum tree_code code;
{
switch (code)
{
case EXPR_STMT:
case COMPOUND_STMT:
case DECL_STMT:
case IF_STMT:
case FOR_STMT:
case WHILE_STMT:
case DO_STMT:
case RETURN_STMT:
case BREAK_STMT:
case CONTINUE_STMT:
case SWITCH_STMT:
case GOTO_STMT:
case LABEL_STMT:
case ASM_STMT:
case CASE_LABEL:
return 1;
default:
if (lang_statement_code_p)
return (*lang_statement_code_p) (code);
return 0;
}
}
/* Walk the statemen tree, rooted at *tp. Apply FUNC to all the
sub-trees of *TP in a pre-order traversal. FUNC is called with the
DATA and the address of each sub-tree. If FUNC returns a non-NULL
value, the traversal is aborted, and the value returned by FUNC is
returned. If FUNC sets WALK_SUBTREES to zero, then the subtrees of
the node being visited are not walked.
We don't need a without_duplicates variant of this one because the
statement tree is a tree, not a graph. */
tree
walk_stmt_tree (tp, func, data)
tree *tp;
walk_tree_fn func;
void *data;
{
enum tree_code code;
int walk_subtrees;
tree result;
int i, len;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_stmt_tree (&(NODE), func, data); \
if (result) \
return result; \
} \
while (0)
/* Skip empty subtrees. */
if (!*tp)
return NULL_TREE;
/* Skip subtrees below non-statement nodes. */
if (!statement_code_p (TREE_CODE (*tp)))
return NULL_TREE;
/* Call the function. */
walk_subtrees = 1;
result = (*func) (tp, &walk_subtrees, data);
/* If we found something, return it. */
if (result)
return result;
/* Even if we didn't, FUNC may have decided that there was nothing
interesting below this point in the tree. */
if (!walk_subtrees)
return NULL_TREE;
/* FUNC may have modified the tree, recheck that we're looking at a
statement node. */
code = TREE_CODE (*tp);
if (!statement_code_p (code))
return NULL_TREE;
/* Walk over all the sub-trees of this operand. Statement nodes never
contain RTL, and we needn't worry about TARGET_EXPRs. */
len = TREE_CODE_LENGTH (code);
/* Go through the subtrees. We need to do this in forward order so
that the scope of a FOR_EXPR is handled properly. */
for (i = 0; i < len; ++i)
WALK_SUBTREE (TREE_OPERAND (*tp, i));
/* Finally visit the chain. This can be tail-recursion optimized if
we write it this way. */
return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
#undef WALK_SUBTREE
}
/* Tree code classes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,

View File

@ -147,6 +147,8 @@ enum c_tree_index
CTI_PRETTY_FUNCTION_ID,
CTI_FUNC_ID,
CTI_VOID_ZERO,
CTI_MAX
};
@ -187,6 +189,9 @@ enum c_tree_index
#define pretty_function_id_node c_global_trees[CTI_PRETTY_FUNCTION_ID]
#define func_id_node c_global_trees[CTI_FUNC_ID]
/* A node for `((void) 0)'. */
#define void_zero_node c_global_trees[CTI_VOID_ZERO]
extern tree c_global_trees[CTI_MAX];
typedef enum c_language_kind
@ -198,6 +203,68 @@ typedef enum c_language_kind
}
c_language_kind;
/* Information about a statement tree. */
struct stmt_tree_s {
/* The last statement added to the tree. */
tree x_last_stmt;
/* The type of the last expression statement. (This information is
needed to implement the statement-expression extension.) */
tree x_last_expr_type;
/* In C++, Non-zero if we should treat statements as full
expressions. In particular, this variable is no-zero if at the
end of a statement we should destroy any temporaries created
during that statement. Similarly, if, at the end of a block, we
should destroy any local variables in this block. Normally, this
variable is non-zero, since those are the normal semantics of
C++.
However, in order to represent aggregate initialization code as
tree structure, we use statement-expressions. The statements
within the statement expression should not result in cleanups
being run until the entire enclosing statement is complete.
This flag has no effect in C. */
int stmts_are_full_exprs_p;
};
typedef struct stmt_tree_s *stmt_tree;
/* Global state pertinent to the current function. Some C dialects
extend this structure with additional fields. */
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;
};
/* When building a statement-tree, this is the last statement added to
the tree. */
#define last_tree (current_stmt_tree ()->x_last_stmt)
/* The type of the last expression-statement we have seen. */
#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 void 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 *));
/* The variant of the C language being processed. Each C language
front-end defines this variable. */
@ -337,8 +404,13 @@ extern tree build_va_arg PARAMS ((tree, tree));
extern int self_promoting_args_p PARAMS ((tree));
extern tree simple_type_promotes_to PARAMS ((tree));
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
/* These macros provide convenient access to the various _STMT nodes. */
/* Nonzero if this statement should be considered a full-expression,
i.e., if temporaries created during this statement should have
their destructors run at the end of this statement. (In C, this
will always be false, since there are no destructors.) */
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
/* IF_STMT accessors. These give access to the condtion of the if
statement, the then block of the if statement, and the else block

View File

@ -6761,8 +6761,9 @@ finish_function (nested)
that keep track of the progress of compilation of the current function.
Used for nested functions. */
struct language_function
struct c_language_function
{
struct language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
@ -6779,9 +6780,10 @@ void
push_c_function_context (f)
struct function *f;
{
struct language_function *p;
p = (struct language_function *) xmalloc (sizeof (struct language_function));
f->language = p;
struct c_language_function *p;
p = ((struct c_language_function *)
xmalloc (sizeof (struct c_language_function)));
f->language = (struct language_function *) p;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
@ -6798,7 +6800,8 @@ void
pop_c_function_context (f)
struct function *f;
{
struct language_function *p = f->language;
struct c_language_function *p
= (struct c_language_function *) f->language;
tree link;
/* Bring back all the labels that were shadowed. */
@ -6834,7 +6837,8 @@ void
mark_c_function_context (f)
struct function *f;
{
struct language_function *p = f->language;
struct c_language_function *p
= (struct c_language_function *) f->language;
if (p == 0)
return;
@ -6899,6 +6903,16 @@ stmts_are_full_exprs_p ()
return 0;
}
/* Returns the stmt_tree (if any) to which statements are currently
being added. If there is no active statement-tree, NULL is
returned. */
stmt_tree
current_stmt_tree ()
{
return cfun ? &cfun->language->x_stmt_tree : NULL;
}
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
C. */

View File

@ -36,6 +36,119 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "timevar.h"
static tree prune_unused_decls PARAMS ((tree *, int *, void *));
/* Create an empty statement tree rooted at T. */
void
begin_stmt_tree (t)
tree *t;
{
/* We create a trivial EXPR_STMT so that last_tree is never NULL in
what follows. We remove the extraneous statement in
finish_stmt_tree. */
*t = build_nt (EXPR_STMT, void_zero_node);
last_tree = *t;
last_expr_type = NULL_TREE;
}
/* T is a statement. Add it to the statement-tree. */
void
add_stmt (t)
tree t;
{
/* Add T to the statement-tree. */
TREE_CHAIN (last_tree) = t;
last_tree = t;
/* When we expand a statement-tree, we must know whether or not the
statements are full-expresions. We record that fact here. */
STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
}
/* 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
which TREE_USED was false, but it turns out that there's tons of
variables for which TREE_USED is false but that are still in fact
used. */
static tree
prune_unused_decls (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
tree t = *tp;
if (t == NULL_TREE)
{
*walk_subtrees = 0;
return NULL_TREE;
}
if (TREE_CODE (t) == DECL_STMT)
{
tree d = DECL_STMT_DECL (t);
if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
{
*tp = TREE_CHAIN (t);
/* Recurse on the new value of tp, otherwise we will skip
the next statement. */
return prune_unused_decls (tp, walk_subtrees, data);
}
}
else if (TREE_CODE (t) == SCOPE_STMT)
{
/* Remove all unused decls from the BLOCK of this SCOPE_STMT. */
tree block = SCOPE_STMT_BLOCK (t);
if (block)
{
tree *vp;
for (vp = &BLOCK_VARS (block); *vp; )
{
tree v = *vp;
if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
*vp = TREE_CHAIN (v); /* drop */
else
vp = &TREE_CHAIN (v); /* advance */
}
/* If there are now no variables, the entire BLOCK can be dropped.
(This causes SCOPE_NULLIFIED_P (t) to be true.) */
if (BLOCK_VARS (block) == NULL_TREE)
SCOPE_STMT_BLOCK (t) = NULL_TREE;
}
}
return NULL_TREE;
}
/* Finish the statement tree rooted at T. */
void
finish_stmt_tree (t)
tree *t;
{
tree stmt;
/* Remove the fake extra statement added in begin_stmt_tree. */
stmt = TREE_CHAIN (*t);
*t = stmt;
last_tree = NULL_TREE;
/* Remove unused decls from the stmt tree. */
walk_stmt_tree (t, prune_unused_decls, NULL);
if (cfun)
{
/* The line-number recorded in the outermost statement in a function
is the line number of the end of the function. */
STMT_LINENO (stmt) = lineno;
STMT_LINENO_FOR_FN_P (stmt) = 1;
}
}
/* Build a generic statement based on the given type of node and
arguments. Similar to `build_nt', except that we set
TREE_COMPLEXITY to be the current line number. */

View File

@ -1,3 +1,78 @@
2000-09-06 Mark Mitchell <mark@codesourcery.com>
Move statement-tree facilities from C++ to C front-end.
* cp-tree.h (cp_tree_index): Remove CPTI_VOID_ZERO.
(void_zero_node): Remove.
(stmt_tree): Likewise.
(scope_chain): Adjust.
(language_function): Rename to cp_language_function.
(cp_function_chain): Adjust.
(current_stmt_tree): Remove.
(last_tree): Likewise.
(last_expr_type): Likewise.
(struct lang_decl): Adjust.
(STMT_IS_FULL_EXPR_P): Remove.
(add_tree): Remove.
(begin_stmt_tree): Likewise.
(finish_stmt_tree): Likewise.
(walk_tree_fn): Likewise.
(walk_stmt_tree): Likewise.
* class.c (finish_struct): Replace use of add_tree with add_stmt.
* decl.c (mark_stmt_tree): Adjust type.
(init_decl_processing): Don't build void_zero_node.
(initialize_local_var): Adjust usage of current_stmt_tree.
(finish_enum): Use add_stmt, not add_tree.
(save_function_data): Adjust use of language_function.
(finish_constructor_body): Use add_stmt, not add_tree.
(finish_destructor_body): Likewise.
(push_cp_function_context): Adjust use of language_function.
(pop_cp_function_context): Likewise.
(mark_lang_function): Likewise.
(mark_cp_function_context): Likewise.
* init.c (build_aggr_init): Adjust use of current_stmt_tree.
(build_vec_init): Likewise.
* semantics.c (SET_LAST_STMT): Remove.
(RECHAIN_STMTS): Don't use it.
(stmts_are_full_exprs_p): Adjust use of current_stmt_tree.
(current_stmt_tree): Define.
(add_tree): Remove.
(finish_goto_stmt): Use add_stmt, not add_tree.
(finish_expr_stmt): Likewise.
(begin_if_stmt): Likewise.
(finish_then_clause): Likewise.
(begin_while_stmt): Likewise.
(begin_do_stmt): Likewise.
(finish_return_stmt): Likewise.
(begin_for_stmt): Likewise.
(finish_break_stmt): Likewise.
(finish_continue_stmt): Likewise.
(begin_switch_stmt): Likewise.
(finish_case_label): Likewise.
(begin_try_block): Likewise.
(begin_function_try_block): Likewise.
(begin_handler): Likewise.
(begin_catch_block): Likewise.
(begin_compound_stmt): Likewise.
(begin_asm_stmt): Likewise.
(finish_asm_stmt): Likewise.
(finish_label_stmt): Likewise.
(add_decl_stmt): Likewise.
(finish_subobject): Likewise.
(finish_decl_cleanup): Likewise.
(finish_named_return_value): Likewise.
(setup_vtbl_ptr): Likewise.
(add_scope_stmt): Likewise.
(finish_stmt_expr): Likewise.
(prune_unused_decls): Remove.
(begin_stmt_tree): Likewise.
(finish_stmt_tree): Likewise.
(prep_stmt): Adjust use of current_stmt_tree.
(lang_expand_stmt): Likewise.
* tree.c (statement_code_p): Remove.
(cp_statement_code_p): New function.
(walk_stmt_tree): Remove.
(init_tree): Set lang_statement_code_p.
2000-09-06 Zack Weinberg <zack@wolery.cumb.org>
Integrated preprocessor.

View File

@ -5265,7 +5265,7 @@ finish_struct (t, attributes)
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
add_tree (build_min (TAG_DEFN, t));
add_stmt (build_min (TAG_DEFN, t));
}
return t;

View File

@ -559,7 +559,6 @@ enum cp_tree_index
CPTI_JAVA_CHAR_TYPE,
CPTI_JAVA_BOOLEAN_TYPE,
CPTI_VOID_ZERO,
CPTI_WCHAR_DECL,
CPTI_VTABLE_ENTRY_TYPE,
CPTI_DELTA_TYPE,
@ -652,7 +651,6 @@ extern tree cp_global_trees[CPTI_MAX];
#define java_char_type_node cp_global_trees[CPTI_JAVA_CHAR_TYPE]
#define java_boolean_type_node cp_global_trees[CPTI_JAVA_BOOLEAN_TYPE]
#define void_zero_node cp_global_trees[CPTI_VOID_ZERO]
#define wchar_decl_node cp_global_trees[CPTI_WCHAR_DECL]
#define vtable_entry_type cp_global_trees[CPTI_VTABLE_ENTRY_TYPE]
/* The type used to represent an offset by which to adjust the `this'
@ -784,23 +782,6 @@ extern tree cp_global_trees[CPTI_MAX];
/* Global state. */
struct stmt_tree {
tree x_last_stmt;
tree x_last_expr_type;
/* Non-zero if we should treat statements as full expressions. In
particular, this variable is no-zero if at the end of a statement
we should destroy any temporaries created during that statement.
Similarly, if, at the end of a block, we should destroy any local
variables in this block. Normally, this variable is non-zero,
since those are the normal semantics of C++.
However, in order to represent aggregate initialization code as
tree structure, we use statement-expressions. The statements
within the statement expression should not result in cleanups being
run until the entire enclosing statement is complete. */
int stmts_are_full_exprs_p;
};
struct saved_scope {
tree old_bindings;
tree old_namespace;
@ -824,7 +805,7 @@ struct saved_scope {
int x_processing_explicit_instantiation;
int need_pop_function_context;
struct stmt_tree x_stmt_tree;
struct stmt_tree_s x_stmt_tree;
struct binding_level *class_bindings;
struct binding_level *bindings;
@ -890,8 +871,10 @@ extern struct saved_scope *scope_chain;
/* Global state pertinent to the current function. */
struct language_function
struct cp_language_function
{
struct language_function base;
tree x_ctor_label;
tree x_dtor_label;
tree x_current_class_ptr;
@ -912,8 +895,6 @@ struct language_function
int name_declared;
int vtbls_set_up_p;
struct stmt_tree x_stmt_tree;
struct named_label_use_list *x_named_label_uses;
struct named_label_list *x_named_labels;
struct binding_level *bindings;
@ -923,7 +904,8 @@ struct language_function
/* The current C++-specific per-function global variables. */
#define cp_function_chain (cfun->language)
#define cp_function_chain \
((struct cp_language_function *) (cfun->language))
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
@ -944,24 +926,6 @@ struct language_function
#define current_class_ref \
(cfun ? cp_function_chain->x_current_class_ref : NULL_TREE)
/* Information about the current statement tree. */
#define current_stmt_tree \
(cfun \
? &cp_function_chain->x_stmt_tree \
: &scope_chain->x_stmt_tree)
/* When building a statement-tree, this is the last statement added to
the tree. */
#define last_tree current_stmt_tree->x_last_stmt
/* The type of the last expression-statement we have seen. This is
required because the type of a statement-expression is the type of
the last expression statement. */
#define last_expr_type current_stmt_tree->x_last_expr_type
/* The TRY_BLOCK for the exception-specifiers for the current
function, if any. */
@ -1927,7 +1891,7 @@ struct lang_decl
{
tree sorted_fields;
struct unparsed_text *pending_inline_info;
struct language_function *saved_language_function;
struct cp_language_function *saved_language_function;
} u;
union {
@ -2474,9 +2438,6 @@ struct lang_decl
#define AGGR_INIT_VIA_CTOR_P(NODE) \
TREE_LANG_FLAG_0 (AGGR_INIT_EXPR_CHECK (NODE))
/* Nonzero if this statement should be considered a full-expression. */
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
/* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
TEMPLATE_DECL. This macro determines whether or not a given class
type is really a template type, as opposed to an instantiation or
@ -4231,7 +4192,6 @@ extern void do_decl_instantiation PARAMS ((tree, tree, tree));
extern void do_type_instantiation PARAMS ((tree, tree, int));
extern tree instantiate_decl PARAMS ((tree, int));
extern tree get_bindings PARAMS ((tree, tree, tree));
extern void add_tree PARAMS ((tree));
extern void add_maybe_template PARAMS ((tree, tree));
extern void pop_tinst_level PARAMS ((void));
extern int more_specialized_class PARAMS ((tree, tree));
@ -4409,8 +4369,6 @@ 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 begin_stmt_tree PARAMS ((tree *));
extern void finish_stmt_tree PARAMS ((tree *));
extern void prep_stmt PARAMS ((tree));
extern tree add_scope_stmt PARAMS ((int, int));
extern void do_pushlevel PARAMS ((void));
@ -4494,7 +4452,6 @@ extern void debug_binfo PARAMS ((tree));
extern tree build_dummy_object PARAMS ((tree));
extern tree maybe_dummy_object PARAMS ((tree, tree *));
extern int is_dummy_object PARAMS ((tree));
typedef tree (*walk_tree_fn) PARAMS ((tree *, int *, void *));
extern tree walk_tree PARAMS ((tree *,
walk_tree_fn,
void *,
@ -4502,9 +4459,6 @@ extern tree walk_tree PARAMS ((tree *,
extern tree walk_tree_without_duplicates PARAMS ((tree *,
walk_tree_fn,
void *));
extern tree walk_stmt_tree PARAMS ((tree *,
walk_tree_fn,
void *));
extern tree copy_tree_r PARAMS ((tree *, int *, void *));
extern int cp_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
extern tree make_ptrmem_cst PARAMS ((tree, tree));

View File

@ -169,8 +169,8 @@ static void mark_binding_level PARAMS ((void *));
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 language_function *));
static void mark_stmt_tree PARAMS ((struct stmt_tree *));
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));
static void destroy_local_var PARAMS ((tree));
@ -200,7 +200,6 @@ tree error_mark_list;
C++ extensions
tree wchar_decl_node;
tree void_zero_node;
tree vtable_entry_type;
tree delta_type_node;
@ -2453,7 +2452,7 @@ struct saved_scope *scope_chain;
static void
mark_stmt_tree (st)
struct stmt_tree *st;
stmt_tree st;
{
ggc_mark_tree (st->x_last_stmt);
ggc_mark_tree (st->x_last_expr_type);
@ -6471,10 +6470,6 @@ init_decl_processing ()
void_list_node = build_tree_list (NULL_TREE, void_type_node);
TREE_PARMLIST (void_list_node) = 1;
/* Used for expressions that do nothing, but are not errors. */
void_zero_node = build_int_2 (0, 0);
TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
= build_pointer_type (build_qualified_type (char_type_node,
@ -7965,12 +7960,13 @@ initialize_local_var (decl, init, flags)
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree->stmts_are_full_exprs_p = 1;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
if (building_stmt_tree ())
finish_expr_stmt (build_aggr_init (decl, init, flags));
else
genrtl_expr_stmt (build_aggr_init (decl, init, flags));
current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
}
/* Set this to 0 so we can tell whether an aggregate which was
@ -13244,7 +13240,7 @@ finish_enum (enumtype)
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
add_tree (build_min (TAG_DEFN, enumtype));
add_stmt (build_min (TAG_DEFN, enumtype));
}
else
{
@ -14037,7 +14033,7 @@ static void
save_function_data (decl)
tree decl;
{
struct language_function *f;
struct cp_language_function *f;
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
@ -14045,15 +14041,15 @@ save_function_data (decl)
19990908);
/* Make a copy. */
f = ((struct language_function *)
xmalloc (sizeof (struct language_function)));
f = ((struct cp_language_function *)
xmalloc (sizeof (struct cp_language_function)));
bcopy ((char *) cp_function_chain, (char *) f,
sizeof (struct language_function));
sizeof (struct cp_language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
f->x_stmt_tree.x_last_stmt = NULL_TREE;
f->x_stmt_tree.x_last_expr_type = NULL_TREE;
f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
f->x_result_rtx = NULL_RTX;
f->x_named_label_uses = NULL;
f->bindings = NULL;
@ -14075,7 +14071,7 @@ finish_constructor_body ()
{
/* Any return from a constructor will end up here. */
if (ctor_label)
add_tree (build_stmt (LABEL_STMT, ctor_label));
add_stmt (build_stmt (LABEL_STMT, ctor_label));
/* Clear CTOR_LABEL so that finish_return_stmt knows to really
generate the return, rather than a goto to CTOR_LABEL. */
@ -14084,7 +14080,7 @@ finish_constructor_body ()
constructor to a return of `this'. */
finish_return_stmt (NULL_TREE);
/* Mark the end of the constructor. */
add_tree (build_stmt (CTOR_STMT));
add_stmt (build_stmt (CTOR_STMT));
}
/* At the end of every destructor we generate code to restore virtual
@ -14103,7 +14099,7 @@ finish_destructor_body ()
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Any return from a destructor will end up here. */
add_tree (build_stmt (LABEL_STMT, dtor_label));
add_stmt (build_stmt (LABEL_STMT, dtor_label));
/* Generate the code to call destructor on base class. If this
destructor belongs to a class with virtual functions, then set
@ -14896,10 +14892,10 @@ static void
push_cp_function_context (f)
struct function *f;
{
struct language_function *p
= ((struct language_function *)
xcalloc (1, sizeof (struct language_function)));
f->language = p;
struct cp_language_function *p
= ((struct cp_language_function *)
xcalloc (1, sizeof (struct cp_language_function)));
f->language = (struct language_function *) p;
/* It takes an explicit call to expand_body to generate RTL for a
function. */
@ -14907,7 +14903,7 @@ push_cp_function_context (f)
/* Whenever we start a new function, we destroy temporaries in the
usual way. */
current_stmt_tree->stmts_are_full_exprs_p = 1;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
}
/* Free the language-specific parts of F, now that we've finished
@ -14926,7 +14922,7 @@ pop_cp_function_context (f)
static void
mark_lang_function (p)
struct language_function *p;
struct cp_language_function *p;
{
if (!p)
return;
@ -14941,7 +14937,7 @@ mark_lang_function (p)
ggc_mark_rtx (p->x_result_rtx);
mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
mark_stmt_tree (&p->x_stmt_tree);
mark_stmt_tree (&p->base.x_stmt_tree);
mark_binding_level (&p->bindings);
}
@ -14951,7 +14947,7 @@ static void
mark_cp_function_context (f)
struct function *f;
{
mark_lang_function (f->language);
mark_lang_function ((struct cp_language_function *) f->language);
}
void

View File

@ -1228,11 +1228,11 @@ build_aggr_init (exp, init, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p ();
current_stmt_tree->stmts_are_full_exprs_p = 0;
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
init, LOOKUP_NORMAL|flags);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
current_stmt_tree->stmts_are_full_exprs_p = destroy_temps;
current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
@ -2873,7 +2873,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p ();
current_stmt_tree->stmts_are_full_exprs_p = 0;
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
rval = get_temp_regvar (ptype,
cp_convert (ptype, default_conversion (base)));
base = get_temp_regvar (ptype, rval);
@ -3035,9 +3035,9 @@ build_vec_init (decl, base, maxindex, init, from_array)
}
else
{
current_stmt_tree->stmts_are_full_exprs_p = 1;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
current_stmt_tree->stmts_are_full_exprs_p = 0;
current_stmt_tree ()->stmts_are_full_exprs_p = 0;
}
finish_expr_stmt (build_modify_expr
@ -3087,7 +3087,7 @@ build_vec_init (decl, base, maxindex, init, from_array)
finish_expr_stmt (rval);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
current_stmt_tree->stmts_are_full_exprs_p = destroy_temps;
current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
return stmt_expr;
}

View File

@ -48,27 +48,20 @@
static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static tree prune_unused_decls PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree));
/* Record the fact that STMT was the last statement added to the
statement tree. */
#define SET_LAST_STMT(stmt) \
(current_stmt_tree->x_last_stmt = (stmt))
/* When parsing a template, LAST_TREE contains the last statement
parsed. These are chained together through the TREE_CHAIN field,
but often need to be re-organized since the parse is performed
bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
STMT. */
#define RECHAIN_STMTS(stmt, substmt) \
do { \
substmt = TREE_CHAIN (stmt); \
TREE_CHAIN (stmt) = NULL_TREE; \
SET_LAST_STMT (stmt); \
#define RECHAIN_STMTS(stmt, substmt) \
do { \
substmt = TREE_CHAIN (stmt); \
TREE_CHAIN (stmt) = NULL_TREE; \
last_tree = stmt; \
} while (0)
/* Finish processing the COND, the SUBSTMT condition for STMT. */
@ -108,7 +101,19 @@ set_current_function_name_declared (i)
int
stmts_are_full_exprs_p ()
{
return current_stmt_tree->stmts_are_full_exprs_p;
return current_stmt_tree ()->stmts_are_full_exprs_p;
}
/* Returns the stmt_tree (if any) to which statements are currently
being added. If there is no active statement-tree, NULL is
returned. */
stmt_tree
current_stmt_tree ()
{
return (cfun
? &cfun->language->x_stmt_tree
: &scope_chain->x_stmt_tree);
}
/* One if we have already declared __FUNCTION__ (and related
@ -170,20 +175,6 @@ do_pushlevel ()
}
}
/* T is a statement. Add it to the statement-tree. */
void
add_tree (t)
tree t;
{
/* Add T to the statement-tree. */
TREE_CHAIN (last_tree) = t;
SET_LAST_STMT (t);
/* When we expand a statement-tree, we must know whether or not the
statements are full-expresions. We record that fact here. */
STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
}
/* Finish a goto-statement. */
void
@ -207,7 +198,7 @@ finish_goto_stmt (destination)
check_goto (destination);
add_tree (build_stmt (GOTO_STMT, destination));
add_stmt (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
@ -251,7 +242,7 @@ finish_expr_stmt (expr)
if (!processing_template_decl)
expr = break_out_cleanups (expr);
add_tree (build_stmt (EXPR_STMT, expr));
add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
@ -271,7 +262,7 @@ begin_if_stmt ()
tree r;
do_pushlevel ();
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
return r;
}
@ -295,7 +286,7 @@ finish_then_clause (if_stmt)
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
SET_LAST_STMT (if_stmt);
last_tree = if_stmt;
return if_stmt;
}
@ -346,7 +337,7 @@ begin_while_stmt ()
{
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
do_pushlevel ();
return r;
}
@ -382,7 +373,7 @@ tree
begin_do_stmt ()
{
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
return r;
}
@ -440,7 +431,7 @@ finish_return_stmt (expr)
return;
}
}
add_tree (build_stmt (RETURN_STMT, expr));
add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
}
@ -454,7 +445,7 @@ begin_for_stmt ()
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
add_tree (r);
add_stmt (r);
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
@ -521,7 +512,7 @@ finish_for_stmt (for_stmt)
void
finish_break_stmt ()
{
add_tree (build_stmt (BREAK_STMT));
add_stmt (build_stmt (BREAK_STMT));
}
/* Finish a continue-statement. */
@ -529,7 +520,7 @@ finish_break_stmt ()
void
finish_continue_stmt ()
{
add_tree (build_stmt (CONTINUE_STMT));
add_stmt (build_stmt (CONTINUE_STMT));
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
@ -540,7 +531,7 @@ begin_switch_stmt ()
{
tree r;
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
do_pushlevel ();
return r;
}
@ -593,7 +584,7 @@ finish_case_label (low_value, high_value)
{
/* Add a representation for the case label to the statement
tree. */
add_tree (build_stmt (CASE_LABEL, low_value, high_value));
add_stmt (build_stmt (CASE_LABEL, low_value, high_value));
/* And warn about crossing initializations, etc. */
if (!processing_template_decl)
define_case_label ();
@ -649,7 +640,7 @@ tree
begin_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
return r;
}
@ -660,7 +651,7 @@ begin_function_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
add_tree (r);
add_stmt (r);
return r;
}
@ -761,7 +752,7 @@ begin_handler ()
{
tree r;
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
add_tree (r);
add_stmt (r);
do_pushlevel ();
return r;
}
@ -813,7 +804,7 @@ void
begin_catch_block (type)
tree type;
{
add_tree (build (START_CATCH_STMT, type));
add_stmt (build (START_CATCH_STMT, type));
}
/* Finish a handler, which may be given by HANDLER. The BLOCKs are
@ -861,7 +852,7 @@ begin_compound_stmt (has_no_scope)
if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
is_try = 1;
add_tree (r);
add_stmt (r);
if (has_no_scope)
COMPOUND_STMT_NO_SCOPE (r) = 1;
@ -957,7 +948,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
add_tree (r);
add_stmt (r);
}
/* Finish a label with the indicated NAME. */
@ -967,7 +958,7 @@ finish_label_stmt (name)
tree name;
{
tree decl = define_label (input_filename, lineno, name);
add_tree (build_stmt (LABEL_STMT, decl));
add_stmt (build_stmt (LABEL_STMT, decl));
}
/* Finish a series of declarations for local labels. G++ allows users
@ -993,7 +984,7 @@ add_decl_stmt (decl)
/* We need the type to last until instantiation time. */
decl_stmt = build_stmt (DECL_STMT, decl);
add_tree (decl_stmt);
add_stmt (decl_stmt);
}
/* Generate the RTL for a SUBOBJECT. */
@ -1014,7 +1005,7 @@ finish_subobject (cleanup)
tree cleanup;
{
tree r = build_stmt (SUBOBJECT, cleanup);
add_tree (r);
add_stmt (r);
}
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
@ -1024,7 +1015,7 @@ finish_decl_cleanup (decl, cleanup)
tree decl;
tree cleanup;
{
add_tree (build_stmt (CLEANUP_STMT, decl, cleanup));
add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
}
/* Generate the RTL for a RETURN_INIT. */
@ -1103,10 +1094,10 @@ finish_named_return_value (return_id, init)
if (!processing_template_decl)
{
cp_finish_decl (decl, init, NULL_TREE, 0);
add_tree (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
add_stmt (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
}
else
add_tree (build_stmt (RETURN_INIT, return_id, init));
add_stmt (build_stmt (RETURN_INIT, return_id, init));
}
/* Don't use tree-inlining for functions with named return values.
@ -1192,7 +1183,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
if (processing_template_decl)
add_tree (build_min_nt
add_stmt (build_min_nt
(CTOR_INITIALIZER,
member_init_list, base_init_list));
else
@ -1202,7 +1193,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
/* Mark the beginning of the constructor. */
ctor_stmt = build_stmt (CTOR_STMT);
CTOR_BEGIN_P (ctor_stmt) = 1;
add_tree (ctor_stmt);
add_stmt (ctor_stmt);
/* And actually initialize the base-classes and members. */
emit_base_init (member_init_list, base_init_list);
@ -1299,7 +1290,7 @@ add_scope_stmt (begin_p, partial_p)
}
/* Add the new statement to the statement-tree. */
add_tree (ss);
add_stmt (ss);
return top;
}
@ -1391,7 +1382,7 @@ finish_stmt_expr (rtl_expr)
/* Remove the compound statement from the tree structure; it is
now saved in the STMT_EXPR. */
SET_LAST_STMT (rtl_expr);
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
/* If we created a statement-tree for this statement-expression,
@ -2223,103 +2214,6 @@ finish_typeof (expr)
return TREE_TYPE (expr);
}
/* 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
which TREE_USED was false, but it turns out that there's tons of
variables for which TREE_USED is false but that are still in fact
used. */
static tree
prune_unused_decls (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
tree t = *tp;
if (t == NULL_TREE)
{
*walk_subtrees = 0;
return NULL_TREE;
}
if (TREE_CODE (t) == DECL_STMT)
{
tree d = DECL_STMT_DECL (t);
if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
{
*tp = TREE_CHAIN (t);
/* Recurse on the new value of tp, otherwise we will skip
the next statement. */
return prune_unused_decls (tp, walk_subtrees, data);
}
}
else if (TREE_CODE (t) == SCOPE_STMT)
{
/* Remove all unused decls from the BLOCK of this SCOPE_STMT. */
tree block = SCOPE_STMT_BLOCK (t);
if (block)
{
tree *vp;
for (vp = &BLOCK_VARS (block); *vp; )
{
tree v = *vp;
if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
*vp = TREE_CHAIN (v); /* drop */
else
vp = &TREE_CHAIN (v); /* advance */
}
/* If there are now no variables, the entire BLOCK can be dropped.
(This causes SCOPE_NULLIFIED_P (t) to be true.) */
if (BLOCK_VARS (block) == NULL_TREE)
SCOPE_STMT_BLOCK (t) = NULL_TREE;
}
}
return NULL_TREE;
}
/* Create an empty statement tree rooted at T. */
void
begin_stmt_tree (t)
tree *t;
{
/* We create a trivial EXPR_STMT so that last_tree is never NULL in
what follows. We remove the extraneous statement in
finish_stmt_tree. */
*t = build_nt (EXPR_STMT, void_zero_node);
SET_LAST_STMT (*t);
last_expr_type = NULL_TREE;
}
/* Finish the statement tree rooted at T. */
void
finish_stmt_tree (t)
tree *t;
{
tree stmt;
/* Remove the fake extra statement added in begin_stmt_tree. */
stmt = TREE_CHAIN (*t);
*t = stmt;
SET_LAST_STMT (NULL_TREE);
/* Remove unused decls from the stmt tree. */
walk_stmt_tree (t, prune_unused_decls, NULL);
if (cfun)
{
/* The line-number recorded in the outermost statement in a function
is the line number of the end of the function. */
STMT_LINENO (stmt) = lineno;
STMT_LINENO_FOR_FN_P (stmt) = 1;
}
}
/* We're about to expand T, a statement. Set up appropriate context
for the substitution. */
@ -2329,7 +2223,7 @@ prep_stmt (t)
{
if (!STMT_LINENO_FOR_FN_P (t))
lineno = STMT_LINENO (t);
current_stmt_tree->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
}
/* Generate RTL for the statement T, and its substatements, and any
@ -2453,7 +2347,8 @@ lang_expand_stmt (t)
}
/* Restore saved state. */
current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
/* Go on to the next statement in this scope. */
t = TREE_CHAIN (t);

View File

@ -42,7 +42,6 @@ static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
static tree no_linkage_helper PARAMS ((tree *, int *, void *));
static tree build_srcloc PARAMS ((const char *, int));
static void mark_list_hash PARAMS ((void *));
static int statement_code_p PARAMS ((enum tree_code));
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
static tree cp_unsave_r PARAMS ((tree *, int *, void *));
static void cp_unsave PARAMS ((tree *));
@ -50,6 +49,7 @@ static tree build_target_expr PARAMS ((tree, tree));
static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
static tree find_tree_r PARAMS ((tree *, int *, void *));
extern int cp_statement_code_p PARAMS ((enum tree_code));
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
@ -1071,33 +1071,18 @@ is_aggr_type_2 (t1, t2)
/* Returns non-zero if CODE is the code for a statement. */
static int
statement_code_p (code)
int
cp_statement_code_p (code)
enum tree_code code;
{
switch (code)
{
case EXPR_STMT:
case COMPOUND_STMT:
case DECL_STMT:
case IF_STMT:
case FOR_STMT:
case WHILE_STMT:
case DO_STMT:
case RETURN_STMT:
case BREAK_STMT:
case CONTINUE_STMT:
case SWITCH_STMT:
case GOTO_STMT:
case LABEL_STMT:
case ASM_STMT:
case SUBOBJECT:
case CLEANUP_STMT:
case START_CATCH_STMT:
case CTOR_STMT:
case SCOPE_STMT:
case CTOR_INITIALIZER:
case CASE_LABEL:
case RETURN_INIT:
case TRY_BLOCK:
case HANDLER:
@ -1223,9 +1208,9 @@ copy_template_template_parm (t, newargs)
/* Apply FUNC to all the sub-trees of TP in a pre-order traversal.
FUNC is called with the DATA and the address of each sub-tree. If
FUNC returns a non-NULL value, the traversal is aborted, and the
value returned by FUNC is returned. The FLAGS govern the way in
which nodes are walked. If HTAB is non-NULL it is used to record
the nodes visited, and to avoid visiting a node more than once. */
value returned by FUNC is returned. If HTAB is non-NULL it is used
to record the nodes visited, and to avoid visiting a node more than
once. */
tree
walk_tree (tp, func, data, htab)
@ -1455,73 +1440,6 @@ walk_tree_without_duplicates (tp, func, data)
return result;
}
/* Like walk_tree, but only examines statement nodes. We don't need a
without_duplicates variant of this one because the statement tree is
a tree, not a graph. */
tree
walk_stmt_tree (tp, func, data)
tree *tp;
walk_tree_fn func;
void *data;
{
enum tree_code code;
int walk_subtrees;
tree result;
int i, len;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_stmt_tree (&(NODE), func, data); \
if (result) \
return result; \
} \
while (0)
/* Skip empty subtrees. */
if (!*tp)
return NULL_TREE;
/* Skip subtrees below non-statement nodes. */
if (!statement_code_p (TREE_CODE (*tp)))
return NULL_TREE;
/* Call the function. */
walk_subtrees = 1;
result = (*func) (tp, &walk_subtrees, data);
/* If we found something, return it. */
if (result)
return result;
/* Even if we didn't, FUNC may have decided that there was nothing
interesting below this point in the tree. */
if (!walk_subtrees)
return NULL_TREE;
/* FUNC may have modified the tree, recheck that we're looking at a
statement node. */
code = TREE_CODE (*tp);
if (!statement_code_p (code))
return NULL_TREE;
/* Walk over all the sub-trees of this operand. Statement nodes never
contain RTL, and we needn't worry about TARGET_EXPRs. */
len = TREE_CODE_LENGTH (code);
/* Go through the subtrees. We need to do this in forward order so
that the scope of a FOR_EXPR is handled properly. */
for (i = 0; i < len; ++i)
WALK_SUBTREE (TREE_OPERAND (*tp, i));
/* Finally visit the chain. This can be tail-recursion optimized if
we write it this way. */
return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
#undef WALK_SUBTREE
}
/* Called from count_trees via walk_tree. */
static tree
@ -2477,6 +2395,7 @@ init_tree ()
{
make_lang_type_fn = cp_make_lang_type;
lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p;
ggc_add_root (list_hash_table,
ARRAY_SIZE (list_hash_table),
sizeof (struct list_hash *),

View File

@ -1,5 +1,5 @@
/* This is part of libio/iostream, providing -*- C++ -*- input/output.
Copyright (C) 1993 Free Software Foundation
Copyright (C) 1993, 2000 Free Software Foundation
This file is part of the GNU IO Library. This library is free
software; you can redistribute it and/or modify it under the

View File

@ -1,5 +1,5 @@
/* Encoding of types for Objective C.
Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
Bitfield support by Ovidiu Predescu