From 11f53b6a0879e853b8aa3e12b81b56f1582c38f6 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Wed, 6 Sep 2000 05:52:51 +0000 Subject: [PATCH] tree.c (walk_tree): Expose tail recursion. * tree.c (walk_tree): Expose tail recursion. (walk_stmt_tree): New function. * cp-tree.h: Prototype walk_stmt_tree. * semantics.c (prune_unused_decls): Operate on SCOPE_STMTs not the BLOCKs directly. If a BLOCK has no variables after pruning, discard it. (finish_stmt_tree): Use walk_stmt_tree. No need to save and restore the line number. From-SVN: r36178 --- gcc/cp/ChangeLog | 11 +++++++++ gcc/cp/cp-tree.h | 3 +++ gcc/cp/semantics.c | 37 ++++++++++++++++------------- gcc/cp/tree.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 32b7c08..d0a4851 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2000-09-05 Zack Weinberg + + * tree.c (walk_tree): Expose tail recursion. + (walk_stmt_tree): New function. + * cp-tree.h: Prototype walk_stmt_tree. + * semantics.c (prune_unused_decls): Operate on SCOPE_STMTs not + the BLOCKs directly. If a BLOCK has no variables after + pruning, discard it. + (finish_stmt_tree): Use walk_stmt_tree. No need to save and + restore the line number. + 2000-09-05 Mark Mitchell * Makefile.in (CXX_TREE_H): Add dependency on HTAB_H. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 44c7168..0a62dfe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4543,6 +4543,9 @@ 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)); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 7c46d1d..295c37a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2274,21 +2274,28 @@ prune_unused_decls (tp, walk_subtrees, data) return prune_unused_decls (tp, walk_subtrees, data); } } - else if (TREE_CODE (t) == BLOCK) + else if (TREE_CODE (t) == SCOPE_STMT) { - /* walk_tree doesn't inspect BLOCK_VARS, so we must do it by hand. */ - tree *vp; + /* Remove all unused decls from the BLOCK of this SCOPE_STMT. */ + tree block = SCOPE_STMT_BLOCK (t); - for (vp = &BLOCK_VARS (t); *vp; ) + if (block) { - 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 */ + 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; } - if (BLOCK_VARS (t) == NULL_TREE) - TREE_USED (t) = 0; } return NULL_TREE; } @@ -2314,18 +2321,14 @@ finish_stmt_tree (t) tree *t; { tree stmt; - int old_lineno; /* 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_tree messes with - the line number, so save/restore it. */ - old_lineno = lineno; - walk_tree_without_duplicates (t, prune_unused_decls, NULL); - lineno = old_lineno; + /* Remove unused decls from the stmt tree. */ + walk_stmt_tree (t, prune_unused_decls, NULL); if (cfun) { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0c51f54..0f88669 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1319,7 +1319,8 @@ walk_tree (tp, func, data, htab) WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp))); } - WALK_SUBTREE (TREE_CHAIN (*tp)); + /* This can be tail-recursion optimized if we write it this way. */ + return walk_tree (&TREE_CHAIN (*tp), func, data, htab); } /* We didn't find what we were looking for. */ @@ -1454,6 +1455,73 @@ 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 -- 2.7.4