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
This commit is contained in:
Zack Weinberg 2000-09-06 05:52:51 +00:00 committed by Zack Weinberg
parent 3392dafcfd
commit 11f53b6a08
4 changed files with 103 additions and 18 deletions

View File

@ -1,3 +1,14 @@
2000-09-05 Zack Weinberg <zack@wolery.cumb.org>
* 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 <mark@codesourcery.com>
* Makefile.in (CXX_TREE_H): Add dependency on HTAB_H.

View File

@ -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));

View File

@ -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)
{

View File

@ -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