OSDN Git Service

* tree.c (walk_tree): Expose tail recursion.
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Sep 2000 05:52:51 +0000 (05:52 +0000)
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Sep 2000 05:52:51 +0000 (05:52 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36178 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/cp/tree.c

index 32b7c08..d0a4851 100644 (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.
index 44c7168..0a62dfe 100644 (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));
index 7c46d1d..295c37a 100644 (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)
     {
index 0c51f54..0f88669 100644 (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