* 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
+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.
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));
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;
}
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)
{
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. */
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