This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C/C++ PATCH: Move statement-tree facilities to C
- To: gcc-patches at gcc dot gnu dot org
- Subject: C/C++ PATCH: Move statement-tree facilities to C
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 06 Sep 2000 18:37:00 -0700
- Organization: CodeSourcery, LLC
As part of the preparation for C function-at-a-time mode, this patch
moves a bunch of g++'s statement-tree facilities into c-common and
related files.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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 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.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.c,v
retrieving revision 1.146
diff -c -p -r1.146 c-common.c
*** c-common.c 2000/09/01 22:09:55 1.146
--- c-common.c 2000/09/07 01:15:38
*************** tree *ridpointers;
*** 146,151 ****
--- 146,155 ----
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;
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3970,3975 ****
--- 3974,3982 ----
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,
*************** expand_tree_builtin (function, params, c
*** 4476,4481 ****
--- 4483,4593 ----
}
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. */
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.33
diff -c -p -r1.33 c-common.h
*** c-common.h 2000/09/06 21:24:56 1.33
--- c-common.h 2000/09/07 01:15:39
*************** enum c_tree_index
*** 124,129 ****
--- 124,131 ----
CTI_PRETTY_FUNCTION_ID,
CTI_FUNC_ID,
+ CTI_VOID_ZERO,
+
CTI_MAX
};
*************** enum c_tree_index
*** 164,169 ****
--- 166,174 ----
#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
*************** typedef enum c_language_kind
*** 175,180 ****
--- 180,247 ----
}
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. */
*************** extern tree build_va_arg PARAMS ((tree
*** 313,321 ****
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. */
/* IF_STMT accessors. These give access to the condtion of the if
statement, the then block of the if statement, and the else block
--- 380,393 ----
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. */
! /* 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
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.151
diff -c -p -r1.151 c-decl.c
*** c-decl.c 2000/09/06 06:06:46 1.151
--- c-decl.c 2000/09/07 01:15:43
*************** finish_function (nested)
*** 6746,6753 ****
that keep track of the progress of compilation of the current function.
Used for nested functions. */
! struct language_function
{
tree named_labels;
tree shadowed_labels;
int returns_value;
--- 6746,6754 ----
that keep track of the progress of compilation of the current function.
Used for nested functions. */
! struct c_language_function
{
+ struct language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
*************** void
*** 6764,6772 ****
push_c_function_context (f)
struct function *f;
{
! struct language_function *p;
! p = (struct language_function *) xmalloc (sizeof (struct language_function));
! f->language = p;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
--- 6765,6774 ----
push_c_function_context (f)
struct function *f;
{
! 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;
*************** void
*** 6783,6789 ****
pop_c_function_context (f)
struct function *f;
{
! struct language_function *p = f->language;
tree link;
/* Bring back all the labels that were shadowed. */
--- 6785,6792 ----
pop_c_function_context (f)
struct function *f;
{
! struct c_language_function *p
! = (struct c_language_function *) f->language;
tree link;
/* Bring back all the labels that were shadowed. */
*************** void
*** 6819,6825 ****
mark_c_function_context (f)
struct function *f;
{
! struct language_function *p = f->language;
if (p == 0)
return;
--- 6822,6829 ----
mark_c_function_context (f)
struct function *f;
{
! struct c_language_function *p
! = (struct c_language_function *) f->language;
if (p == 0)
return;
*************** int
*** 6882,6887 ****
--- 6886,6901 ----
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
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-semantics.c,v
retrieving revision 1.4
diff -c -p -r1.4 c-semantics.c
*** c-semantics.c 2000/07/23 19:59:40 1.4
--- c-semantics.c 2000/09/07 01:15:43
*************** Boston, MA 02111-1307, USA. */
*** 36,41 ****
--- 36,154 ----
#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. */
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.336
diff -c -p -r1.336 class.c
*** class.c 2000/09/06 08:53:44 1.336
--- class.c 2000/09/07 01:15:49
*************** finish_struct (t, attributes)
*** 5268,5274 ****
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
! add_tree (build_min (TAG_DEFN, t));
}
return t;
--- 5268,5274 ----
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
! add_stmt (build_min (TAG_DEFN, t));
}
return t;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.523
diff -c -p -r1.523 cp-tree.h
*** cp-tree.h 2000/09/06 21:24:57 1.523
--- cp-tree.h 2000/09/07 01:15:53
*************** enum cp_tree_index
*** 554,560 ****
CPTI_JAVA_CHAR_TYPE,
CPTI_JAVA_BOOLEAN_TYPE,
- CPTI_VOID_ZERO,
CPTI_WCHAR_DECL,
CPTI_VTABLE_ENTRY_TYPE,
CPTI_DELTA_TYPE,
--- 554,559 ----
*************** extern tree cp_global_trees[CPTI_MAX];
*** 647,653 ****
#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'
--- 646,651 ----
*************** extern tree cp_global_trees[CPTI_MAX];
*** 779,801 ****
/* 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;
--- 777,782 ----
*************** struct saved_scope {
*** 819,825 ****
int x_processing_explicit_instantiation;
int need_pop_function_context;
! struct stmt_tree x_stmt_tree;
struct binding_level *class_bindings;
struct binding_level *bindings;
--- 800,806 ----
int x_processing_explicit_instantiation;
int need_pop_function_context;
! struct stmt_tree_s x_stmt_tree;
struct binding_level *class_bindings;
struct binding_level *bindings;
*************** extern struct saved_scope *scope_chain;
*** 885,892 ****
/* Global state pertinent to the current function. */
! struct language_function
{
tree x_ctor_label;
tree x_dtor_label;
tree x_current_class_ptr;
--- 866,875 ----
/* Global state pertinent to the current function. */
! struct cp_language_function
{
+ struct language_function base;
+
tree x_ctor_label;
tree x_dtor_label;
tree x_current_class_ptr;
*************** struct language_function
*** 907,914 ****
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;
--- 890,895 ----
*************** struct language_function
*** 918,924 ****
/* The current C++-specific per-function global variables. */
! #define cp_function_chain (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. */
--- 899,906 ----
/* The current C++-specific per-function global variables. */
! #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. */
*************** struct language_function
*** 939,962 ****
#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. */
--- 921,926 ----
*************** struct lang_decl
*** 1912,1918 ****
{
tree sorted_fields;
struct pending_inline *pending_inline_info;
! struct language_function *saved_language_function;
} u;
union {
--- 1876,1882 ----
{
tree sorted_fields;
struct pending_inline *pending_inline_info;
! struct cp_language_function *saved_language_function;
} u;
union {
*************** struct lang_decl
*** 2461,2469 ****
#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
--- 2425,2430 ----
*************** extern void do_decl_instantiation PARAM
*** 4249,4255 ****
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));
--- 4210,4215 ----
*************** extern void add_decl_stmt
*** 4427,4434 ****
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));
--- 4387,4392 ----
*************** extern void debug_binfo PARAMS ((tree
*** 4512,4526 ****
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 *,
htab_t));
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 *));
--- 4470,4480 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.683
diff -c -p -r1.683 decl.c
*** decl.c 2000/09/06 21:24:57 1.683
--- decl.c 2000/09/07 01:16:01
*************** static void mark_binding_level PARAMS ((
*** 169,176 ****
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 save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree));
static void destroy_local_var PARAMS ((tree));
--- 169,176 ----
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));
static void destroy_local_var PARAMS ((tree));
*************** tree error_mark_list;
*** 200,206 ****
C++ extensions
tree wchar_decl_node;
- tree void_zero_node;
tree vtable_entry_type;
tree delta_type_node;
--- 200,205 ----
*************** struct saved_scope *scope_chain;
*** 2453,2459 ****
static void
mark_stmt_tree (st)
! struct stmt_tree *st;
{
ggc_mark_tree (st->x_last_stmt);
ggc_mark_tree (st->x_last_expr_type);
--- 2452,2458 ----
static void
mark_stmt_tree (st)
! stmt_tree st;
{
ggc_mark_tree (st->x_last_stmt);
ggc_mark_tree (st->x_last_expr_type);
*************** init_decl_processing ()
*** 6471,6480 ****
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,
--- 6470,6475 ----
*************** initialize_local_var (decl, init, flags)
*** 7965,7976 ****
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;
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;
}
/* Set this to 0 so we can tell whether an aggregate which was
--- 7960,7972 ----
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;
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;
}
/* Set this to 0 so we can tell whether an aggregate which was
*************** finish_enum (enumtype)
*** 13244,13250 ****
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
! add_tree (build_min (TAG_DEFN, enumtype));
}
else
{
--- 13240,13246 ----
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
! add_stmt (build_min (TAG_DEFN, enumtype));
}
else
{
*************** static void
*** 14037,14043 ****
save_function_data (decl)
tree decl;
{
! struct language_function *f;
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
--- 14033,14039 ----
save_function_data (decl)
tree decl;
{
! 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. */
*************** save_function_data (decl)
*** 14045,14059 ****
19990908);
/* Make a copy. */
! f = ((struct language_function *)
! xmalloc (sizeof (struct language_function)));
bcopy ((char *) cp_function_chain, (char *) f,
! sizeof (struct 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->x_result_rtx = NULL_RTX;
f->x_named_label_uses = NULL;
f->bindings = NULL;
--- 14041,14055 ----
19990908);
/* Make a copy. */
! f = ((struct cp_language_function *)
! xmalloc (sizeof (struct cp_language_function)));
bcopy ((char *) cp_function_chain, (char *) f,
! sizeof (struct cp_language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
! 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;
*************** finish_constructor_body ()
*** 14075,14081 ****
{
/* Any return from a constructor will end up here. */
if (ctor_label)
! add_tree (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. */
--- 14071,14077 ----
{
/* Any return from a constructor will end up here. */
if (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. */
*************** finish_constructor_body ()
*** 14084,14090 ****
constructor to a return of `this'. */
finish_return_stmt (NULL_TREE);
/* Mark the end of the constructor. */
! add_tree (build_stmt (CTOR_STMT));
}
/* At the end of every destructor we generate code to restore virtual
--- 14080,14086 ----
constructor to a return of `this'. */
finish_return_stmt (NULL_TREE);
/* Mark the end of the constructor. */
! add_stmt (build_stmt (CTOR_STMT));
}
/* At the end of every destructor we generate code to restore virtual
*************** finish_destructor_body ()
*** 14103,14109 ****
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));
/* Generate the code to call destructor on base class. If this
destructor belongs to a class with virtual functions, then set
--- 14099,14105 ----
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Any return from a destructor will end up here. */
! 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
*************** static void
*** 14896,14905 ****
push_cp_function_context (f)
struct function *f;
{
! struct language_function *p
! = ((struct language_function *)
! xcalloc (1, sizeof (struct language_function)));
! f->language = p;
/* It takes an explicit call to expand_body to generate RTL for a
function. */
--- 14892,14901 ----
push_cp_function_context (f)
struct function *f;
{
! 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. */
*************** push_cp_function_context (f)
*** 14907,14913 ****
/* Whenever we start a new function, we destroy temporaries in the
usual way. */
! current_stmt_tree->stmts_are_full_exprs_p = 1;
}
/* Free the language-specific parts of F, now that we've finished
--- 14903,14909 ----
/* Whenever we start a new function, we destroy temporaries in the
usual way. */
! current_stmt_tree ()->stmts_are_full_exprs_p = 1;
}
/* Free the language-specific parts of F, now that we've finished
*************** pop_cp_function_context (f)
*** 14926,14932 ****
static void
mark_lang_function (p)
! struct language_function *p;
{
if (!p)
return;
--- 14922,14928 ----
static void
mark_lang_function (p)
! struct cp_language_function *p;
{
if (!p)
return;
*************** mark_lang_function (p)
*** 14941,14947 ****
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_binding_level (&p->bindings);
}
--- 14937,14943 ----
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);
}
*************** static void
*** 14951,14957 ****
mark_cp_function_context (f)
struct function *f;
{
! mark_lang_function (f->language);
}
void
--- 14947,14953 ----
mark_cp_function_context (f)
struct function *f;
{
! mark_lang_function ((struct cp_language_function *) f->language);
}
void
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.216
diff -c -p -r1.216 init.c
*** init.c 2000/09/06 09:04:00 1.216
--- init.c 2000/09/07 01:16:04
*************** build_aggr_init (exp, init, flags)
*** 1228,1238 ****
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;
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;
TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
--- 1228,1238 ----
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;
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;
TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
*************** build_vec_init (decl, base, maxindex, in
*** 2873,2879 ****
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p ();
! 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);
--- 2873,2879 ----
begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p ();
! 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);
*************** build_vec_init (decl, base, maxindex, in
*** 3035,3043 ****
}
else
{
! current_stmt_tree->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
! current_stmt_tree->stmts_are_full_exprs_p = 0;
}
finish_expr_stmt (build_modify_expr
--- 3035,3043 ----
}
else
{
! current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init);
! current_stmt_tree ()->stmts_are_full_exprs_p = 0;
}
finish_expr_stmt (build_modify_expr
*************** build_vec_init (decl, base, maxindex, in
*** 3087,3093 ****
finish_expr_stmt (rval);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
! current_stmt_tree->stmts_are_full_exprs_p = destroy_temps;
return stmt_expr;
}
--- 3087,3093 ----
finish_expr_stmt (rval);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
! current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
return stmt_expr;
}
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.168
diff -c -p -r1.168 semantics.c
*** semantics.c 2000/09/06 21:24:58 1.168
--- semantics.c 2000/09/07 01:16:07
***************
*** 48,74 ****
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); \
} while (0)
/* Finish processing the COND, the SUBSTMT condition for STMT. */
--- 48,67 ----
static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree));
/* 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; \
! last_tree = stmt; \
} while (0)
/* Finish processing the COND, the SUBSTMT condition for STMT. */
*************** set_current_function_name_declared (i)
*** 107,114 ****
int
stmts_are_full_exprs_p ()
{
! return current_stmt_tree->stmts_are_full_exprs_p;
}
/* One if we have already declared __FUNCTION__ (and related
--- 100,119 ----
int
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
*************** do_pushlevel ()
*** 170,189 ****
}
}
- /* 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
--- 175,180 ----
*************** finish_goto_stmt (destination)
*** 207,213 ****
check_goto (destination);
! add_tree (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
--- 198,204 ----
check_goto (destination);
! add_stmt (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
*************** finish_expr_stmt (expr)
*** 251,257 ****
if (!processing_template_decl)
expr = break_out_cleanups (expr);
! add_tree (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
--- 242,248 ----
if (!processing_template_decl)
expr = break_out_cleanups (expr);
! add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
*************** begin_if_stmt ()
*** 271,277 ****
tree r;
do_pushlevel ();
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
! add_tree (r);
return r;
}
--- 262,268 ----
tree r;
do_pushlevel ();
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
! add_stmt (r);
return r;
}
*************** finish_then_clause (if_stmt)
*** 295,301 ****
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
! SET_LAST_STMT (if_stmt);
return if_stmt;
}
--- 286,292 ----
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
! last_tree = if_stmt;
return if_stmt;
}
*************** begin_while_stmt ()
*** 346,352 ****
{
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
! add_tree (r);
do_pushlevel ();
return r;
}
--- 337,343 ----
{
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
! add_stmt (r);
do_pushlevel ();
return r;
}
*************** tree
*** 382,388 ****
begin_do_stmt ()
{
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
! add_tree (r);
return r;
}
--- 373,379 ----
begin_do_stmt ()
{
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
! add_stmt (r);
return r;
}
*************** finish_return_stmt (expr)
*** 440,446 ****
return;
}
}
! add_tree (build_stmt (RETURN_STMT, expr));
finish_stmt ();
}
--- 431,437 ----
return;
}
}
! add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
}
*************** begin_for_stmt ()
*** 454,460 ****
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);
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
--- 445,451 ----
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
! add_stmt (r);
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
*************** finish_for_stmt (for_stmt)
*** 521,527 ****
void
finish_break_stmt ()
{
! add_tree (build_stmt (BREAK_STMT));
}
/* Finish a continue-statement. */
--- 512,518 ----
void
finish_break_stmt ()
{
! add_stmt (build_stmt (BREAK_STMT));
}
/* Finish a continue-statement. */
*************** finish_break_stmt ()
*** 529,535 ****
void
finish_continue_stmt ()
{
! add_tree (build_stmt (CONTINUE_STMT));
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
--- 520,526 ----
void
finish_continue_stmt ()
{
! add_stmt (build_stmt (CONTINUE_STMT));
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
*************** begin_switch_stmt ()
*** 540,546 ****
{
tree r;
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
! add_tree (r);
do_pushlevel ();
return r;
}
--- 531,537 ----
{
tree r;
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
! add_stmt (r);
do_pushlevel ();
return r;
}
*************** finish_case_label (low_value, high_value
*** 593,599 ****
{
/* Add a representation for the case label to the statement
tree. */
! add_tree (build_stmt (CASE_LABEL, low_value, high_value));
/* And warn about crossing initializations, etc. */
if (!processing_template_decl)
define_case_label ();
--- 584,590 ----
{
/* Add a representation for the case label to the statement
tree. */
! add_stmt (build_stmt (CASE_LABEL, low_value, high_value));
/* And warn about crossing initializations, etc. */
if (!processing_template_decl)
define_case_label ();
*************** tree
*** 649,655 ****
begin_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
! add_tree (r);
return r;
}
--- 640,646 ----
begin_try_block ()
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
! add_stmt (r);
return r;
}
*************** begin_function_try_block ()
*** 660,666 ****
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
! add_tree (r);
return r;
}
--- 651,657 ----
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
! add_stmt (r);
return r;
}
*************** begin_handler ()
*** 761,767 ****
{
tree r;
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
! add_tree (r);
do_pushlevel ();
return r;
}
--- 752,758 ----
{
tree r;
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
! add_stmt (r);
do_pushlevel ();
return r;
}
*************** void
*** 813,819 ****
begin_catch_block (type)
tree type;
{
! add_tree (build (START_CATCH_STMT, type));
}
/* Finish a handler, which may be given by HANDLER. The BLOCKs are
--- 804,810 ----
begin_catch_block (type)
tree type;
{
! add_stmt (build (START_CATCH_STMT, type));
}
/* Finish a handler, which may be given by HANDLER. The BLOCKs are
*************** begin_compound_stmt (has_no_scope)
*** 861,867 ****
if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
is_try = 1;
! add_tree (r);
if (has_no_scope)
COMPOUND_STMT_NO_SCOPE (r) = 1;
--- 852,858 ----
if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
is_try = 1;
! add_stmt (r);
if (has_no_scope)
COMPOUND_STMT_NO_SCOPE (r) = 1;
*************** finish_asm_stmt (cv_qualifier, string, o
*** 957,963 ****
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
! add_tree (r);
}
/* Finish a label with the indicated NAME. */
--- 948,954 ----
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
! add_stmt (r);
}
/* Finish a label with the indicated NAME. */
*************** finish_label_stmt (name)
*** 967,973 ****
tree name;
{
tree decl = define_label (input_filename, lineno, name);
! add_tree (build_stmt (LABEL_STMT, decl));
}
/* Finish a series of declarations for local labels. G++ allows users
--- 958,964 ----
tree name;
{
tree decl = define_label (input_filename, lineno, name);
! add_stmt (build_stmt (LABEL_STMT, decl));
}
/* Finish a series of declarations for local labels. G++ allows users
*************** add_decl_stmt (decl)
*** 993,999 ****
/* We need the type to last until instantiation time. */
decl_stmt = build_stmt (DECL_STMT, decl);
! add_tree (decl_stmt);
}
/* Generate the RTL for a SUBOBJECT. */
--- 984,990 ----
/* 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. */
*************** finish_subobject (cleanup)
*** 1014,1020 ****
tree cleanup;
{
tree r = build_stmt (SUBOBJECT, cleanup);
! add_tree (r);
}
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
--- 1005,1011 ----
tree cleanup;
{
tree r = build_stmt (SUBOBJECT, cleanup);
! add_stmt (r);
}
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
*************** finish_decl_cleanup (decl, cleanup)
*** 1024,1030 ****
tree decl;
tree cleanup;
{
! add_tree (build_stmt (CLEANUP_STMT, decl, cleanup));
}
/* Generate the RTL for a RETURN_INIT. */
--- 1015,1021 ----
tree decl;
tree cleanup;
{
! add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
}
/* Generate the RTL for a RETURN_INIT. */
*************** finish_named_return_value (return_id, in
*** 1103,1112 ****
if (!processing_template_decl)
{
cp_finish_decl (decl, init, NULL_TREE, 0);
! add_tree (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
}
else
! add_tree (build_stmt (RETURN_INIT, return_id, init));
}
/* Don't use tree-inlining for functions with named return values.
--- 1094,1103 ----
if (!processing_template_decl)
{
cp_finish_decl (decl, init, NULL_TREE, 0);
! add_stmt (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
}
else
! add_stmt (build_stmt (RETURN_INIT, return_id, init));
}
/* Don't use tree-inlining for functions with named return values.
*************** setup_vtbl_ptr (member_init_list, base_i
*** 1192,1198 ****
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
if (processing_template_decl)
! add_tree (build_min_nt
(CTOR_INITIALIZER,
member_init_list, base_init_list));
else
--- 1183,1189 ----
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
if (processing_template_decl)
! add_stmt (build_min_nt
(CTOR_INITIALIZER,
member_init_list, base_init_list));
else
*************** setup_vtbl_ptr (member_init_list, base_i
*** 1202,1208 ****
/* Mark the beginning of the constructor. */
ctor_stmt = build_stmt (CTOR_STMT);
CTOR_BEGIN_P (ctor_stmt) = 1;
! add_tree (ctor_stmt);
/* And actually initialize the base-classes and members. */
emit_base_init (member_init_list, base_init_list);
--- 1193,1199 ----
/* Mark the beginning of the constructor. */
ctor_stmt = build_stmt (CTOR_STMT);
CTOR_BEGIN_P (ctor_stmt) = 1;
! add_stmt (ctor_stmt);
/* And actually initialize the base-classes and members. */
emit_base_init (member_init_list, base_init_list);
*************** add_scope_stmt (begin_p, partial_p)
*** 1299,1305 ****
}
/* Add the new statement to the statement-tree. */
! add_tree (ss);
return top;
}
--- 1290,1296 ----
}
/* Add the new statement to the statement-tree. */
! add_stmt (ss);
return top;
}
*************** finish_stmt_expr (rtl_expr)
*** 1391,1397 ****
/* Remove the compound statement from the tree structure; it is
now saved in the STMT_EXPR. */
! SET_LAST_STMT (rtl_expr);
TREE_CHAIN (last_tree) = NULL_TREE;
/* If we created a statement-tree for this statement-expression,
--- 1382,1388 ----
/* Remove the compound statement from the tree structure; it is
now saved in the STMT_EXPR. */
! last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
/* If we created a statement-tree for this statement-expression,
*************** finish_typeof (expr)
*** 2224,2326 ****
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. */
--- 2215,2220 ----
*************** prep_stmt (t)
*** 2330,2336 ****
{
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);
}
/* Generate RTL for the statement T, and its substatements, and any
--- 2224,2230 ----
{
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);
}
/* Generate RTL for the statement T, and its substatements, and any
*************** lang_expand_stmt (t)
*** 2454,2460 ****
}
/* Restore saved state. */
! 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);
--- 2348,2355 ----
}
/* Restore saved state. */
! 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);
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.214
diff -c -p -r1.214 tree.c
*** tree.c 2000/09/06 05:52:51 1.214
--- tree.c 2000/09/07 01:16:08
*************** static cp_lvalue_kind lvalue_p_1 PARAMS
*** 42,48 ****
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 *));
--- 42,47 ----
*************** static tree build_target_expr PARAMS ((t
*** 50,55 ****
--- 49,55 ----
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
*************** is_aggr_type_2 (t1, t2)
*** 1071,1103 ****
/* Returns non-zero if CODE is the code for a statement. */
! static 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 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:
--- 1071,1088 ----
/* Returns non-zero if CODE is the code for a statement. */
! int
! cp_statement_code_p (code)
enum tree_code code;
{
switch (code)
{
case SUBOBJECT:
case CLEANUP_STMT:
case START_CATCH_STMT:
case CTOR_STMT:
case SCOPE_STMT:
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:
case HANDLER:
*************** copy_template_template_parm (t, newargs)
*** 1223,1231 ****
/* 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. */
tree
walk_tree (tp, func, data, htab)
--- 1208,1216 ----
/* 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 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)
*************** walk_tree_without_duplicates (tp, func,
*** 1455,1527 ****
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
--- 1440,1445 ----
*************** init_tree ()
*** 2477,2482 ****
--- 2395,2401 ----
{
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 *),