Makefile.in (typeck2.o): Depend on output.h.
authorMark Mitchell <mark@codesourcery.com>
Fri, 5 Nov 1999 09:26:11 +0000 (09:26 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 5 Nov 1999 09:26:11 +0000 (09:26 +0000)
* Makefile.in (typeck2.o): Depend on output.h.
* typeck2.c: Include output.h.

* decl.c (flag_ansi): Remove declaration.

* pt.c (tinst_level_tick): Make it static.
(last_template_error_tick): Likewise.

* cp-tree.h (mapcar): Remove declaration.
(search_tree): Likewise.
(walk_tree_fn): New typedef.
(walk_tree): New function.
* tree.c (bot_manip): Change prototype.  Adjust to be called via
walk_tree.
(bot_replace): Likewise.
(no_linkage_helper): Likewise.
(copy_tree_r): New function.
(search_tree): Rename, and adjust, to become ...
(walk_tree): New function.
(mapcar): Remove.
(target_remap): Remove.
(target_remap_count): Likewise.
(break_out_target_exprs): Use walk_tree.
* decl.c (local_variable_p): Change prototype.
(check_default_argument): Use walk_tree.
* pt.c (for_each_template_parm_r): New function, split out from ...
(for_each_template_parm): Here.  Use it, via walk_tree.

From-SVN: r30412

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/tree.c

index 19e5c975f29140f42e89140099e7847c58ee54c2..1882c28a5e4b5718d48aa77c0d11c887a3529489 100644 (file)
@@ -19,7 +19,7 @@
        (copy_tree_r): New function.
        (search_tree): Rename, and adjust, to become ...
        (walk_tree): New function.
-       (mapcar): Rtemove.
+       (mapcar): Remove.
        (target_remap): Remove.
        (target_remap_count): Likewise.
        (break_out_target_exprs): Use walk_tree.
index 882ca04c222c2d10e46bf465978d873117d9184a..6f8f1b7dbc008f5f658f1ee4906d0e6b4928e90c 100644 (file)
@@ -3986,7 +3986,6 @@ extern int varargs_function_p                     PROTO((tree));
 extern int really_overloaded_fn                        PROTO((tree));
 extern int cp_tree_equal                       PROTO((tree, tree));
 extern int can_free                            PROTO((struct obstack *, tree));
-extern tree mapcar                             PROTO((tree, tree (*) (tree)));
 extern tree no_linkage_check                   PROTO((tree));
 extern void debug_binfo                                PROTO((tree));
 extern void push_expression_obstack            PROTO((void));
@@ -3994,7 +3993,8 @@ extern void push_permanent_obstack              PROTO((void));
 extern tree build_dummy_object                 PROTO((tree));
 extern tree maybe_dummy_object                 PROTO((tree, tree *));
 extern int is_dummy_object                     PROTO((tree));
-extern tree search_tree                         PROTO((tree *, tree (*)(tree *)));
+typedef tree (*walk_tree_fn)                    PROTO((tree *, int *, void *));
+extern tree walk_tree                           PROTO((tree *, walk_tree_fn, void *));
 extern int cp_valid_lang_attribute             PROTO((tree, tree, tree, tree));
 extern tree make_ptrmem_cst                     PROTO((tree, tree));
 extern tree cp_build_qualified_type_real        PROTO((tree, int, int));
index 40d13967c0fe58c83b31ff24f53da30185dc4671..80aec15def56d44969dd24efbf905c28c3239cb2 100644 (file)
@@ -141,7 +141,7 @@ static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 static void push_binding PROTO((tree, tree, struct binding_level*));
 static int add_binding PROTO((tree, tree));
 static void pop_binding PROTO((tree, tree));
-static tree local_variable_p PROTO((tree *));
+static tree local_variable_p PROTO((tree *, int *, void *));
 static tree find_binding PROTO((tree, tree));
 static tree select_decl PROTO((tree, int));
 static int lookup_flags PROTO((int, int));
@@ -349,11 +349,6 @@ extern int flag_no_builtin;
 
 extern int flag_no_nonansi_builtin;
 
-/* Nonzero means enable obscure ANSI features and disable GNU extensions
-   that might cause ANSI-compliant code to be miscompiled.  */
-
-extern int flag_ansi;
-
 /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
    objects.  */
 extern int flag_huge_objects;
@@ -11189,8 +11184,10 @@ require_complete_types_for_parms (parms)
    NULL_TREE otherwise.  */
 
 static tree
-local_variable_p (tp)
+local_variable_p (tp, walk_subtrees, data)
      tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
 {
   tree t = *tp;
 
@@ -11272,7 +11269,7 @@ check_default_argument (decl, arg)
 
      The keyword `this' shall not be used in a default argument of a
      member function.  */
-  var = search_tree (&arg, local_variable_p);
+  var = walk_tree (&arg, local_variable_p, NULL);
   if (var)
     {
       cp_error ("default argument `%E' uses local variable `%D'",
index c96d0320435f2434b014819dc795dd772478739f..c70147d8fadc895b2f965e7e82696c0cd580fed2 100644 (file)
@@ -4032,83 +4032,56 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
     }
 }
 \f
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
-   TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
-   If FN returns non-zero, the iteration is terminated, and
-   for_each_template_parm returns 1.  Otherwise, the iteration
-   continues.  If FN never returns a non-zero value, the value
-   returned by for_each_template_parm is 0.  If FN is NULL, it is
-   considered to be the function which always returns 1.  */
-
-static int
-for_each_template_parm (t, fn, data)
-     tree t;
-     tree_fn_t fn;
-     void* data;
+struct pair_fn_data 
 {
-  if (!t)
-    return 0;
+  tree_fn_t fn;
+  void *data;
+};
+
+/* Called from for_each_template_parm via walk_tree.  */
 
+static tree
+for_each_template_parm_r (tp, walk_subtrees, d)
+     tree *tp;
+     int *walk_subtrees;
+     void *d;
+{
+  tree t = *tp;
+  struct pair_fn_data *pfd = (struct pair_fn_data *) d;
+  tree_fn_t fn = pfd->fn;
+  void *data = pfd->data;
+  
   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
       && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
-    return 1;
+    return error_mark_node;
 
   switch (TREE_CODE (t))
     {
-    case ARRAY_REF:
-    case OFFSET_REF:
-      return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
-             || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
-
-    case IDENTIFIER_NODE:
-      if (!IDENTIFIER_TEMPLATE (t))
-       return 0;
-      my_friendly_abort (42);
-
-      /* aggregates of tree nodes */
-    case TREE_VEC:
-      {
-       int i = TREE_VEC_LENGTH (t);
-       while (i--)
-         if (for_each_template_parm (TREE_VEC_ELT (t, i), fn, data))
-           return 1;
-       return 0;
-      }
-    case TREE_LIST:
-      if (for_each_template_parm (TREE_PURPOSE (t), fn, data)
-         || for_each_template_parm (TREE_VALUE (t), fn, data))
-       return 1;
-      return for_each_template_parm (TREE_CHAIN (t), fn, data);
-
-    case OVERLOAD:
-      if (for_each_template_parm (OVL_FUNCTION (t), fn, data))
-       return 1;
-      return for_each_template_parm (OVL_CHAIN (t), fn, data);
-
-      /* constructed type nodes */
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
-
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_FLAG (t))
-       return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
-                                      fn, data);
+       break;
       /* Fall through.  */
 
     case UNION_TYPE:
     case ENUMERAL_TYPE:
-      if (! TYPE_TEMPLATE_INFO (t))
-       return 0;
-      return for_each_template_parm (TREE_VALUE
-                                    (TYPE_TEMPLATE_INFO (t)),
-                                    fn, data);
+      if (!TYPE_TEMPLATE_INFO (t))
+       *walk_subtrees = 0;
+      else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
+                                      fn, data))
+       return error_mark_node;
+      break;
+
     case METHOD_TYPE:
+      /* Since we're not going to walk subtrees, we have to do this
+        explicitly here.  */
       if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
-       return 1;
-      /* Fall through.  */
+       return error_mark_node;
 
     case FUNCTION_TYPE:
+      /* Check the return type.  */
+      if (for_each_template_parm (TREE_TYPE (t), fn, data))
+       return error_mark_node;
+
       /* Check the parameter types.  Since default arguments are not
         instantiated until they are needed, the TYPE_ARG_TYPES may
         contain expressions that involve template parameters.  But,
@@ -4120,132 +4093,72 @@ for_each_template_parm (t, fn, data)
 
        for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
          if (for_each_template_parm (TREE_VALUE (parm), fn, data))
-           return 1;
-      }
-
-      /* Check the return type, too.  */
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
-
-    case ARRAY_TYPE:
-      if (for_each_template_parm (TYPE_DOMAIN (t), fn, data))
-       return 1;
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
-    case OFFSET_TYPE:
-      if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data))
-       return 1;
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
-
-      /* decl nodes */
-    case TYPE_DECL:
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
+           return error_mark_node;
 
-    case TEMPLATE_DECL:
-      /* A template template parameter is encountered */
-      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
-       return for_each_template_parm (TREE_TYPE (t), fn, data);
-      /* Already substituted template template parameter */
-      return 0;
-      
-    case CONST_DECL:
-      if (for_each_template_parm (DECL_INITIAL (t), fn, data))
-       return 1;
-      goto check_type_and_context;
+       /* Since we've already handled the TYPE_ARG_TYPES, we don't
+          want walk_tree walking into them itself.  */
+       *walk_subtrees = 0;
+      }
+      break;
 
     case FUNCTION_DECL:
     case VAR_DECL:
       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
          && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
-       return 1;
-      /* fall through */
+       return error_mark_node;
+      /* Fall through.  */
+
+    case CONST_DECL:
     case PARM_DECL:
-    check_type_and_context:
-      if (for_each_template_parm (TREE_TYPE (t), fn, data))
-       return 1;
       if (DECL_CONTEXT (t) 
          && for_each_template_parm (DECL_CONTEXT (t), fn, data))
-       return 1;
-      return 0;
-
-    case CALL_EXPR:
-      return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
-             || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
-       
-    case ADDR_EXPR:
-      return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
+       return error_mark_node;
+      break;
 
-      /* template parm nodes */
     case TEMPLATE_TEMPLATE_PARM:
       /* Record template parameters such as `T' inside `TT<T>'.  */
       if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)
          && for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
-       return 1;
+       return error_mark_node;
+      /* Fall through.  */
+
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_PARM_INDEX:
-      if (fn)
-       return (*fn)(t, data);
-      else
-       return 1;
-
-      /* simple type nodes */
-    case INTEGER_TYPE:
-      if (for_each_template_parm (TYPE_MIN_VALUE (t), fn, data))
-       return 1;
-      return for_each_template_parm (TYPE_MAX_VALUE (t), fn, data);
-
-    case REAL_TYPE:
-    case COMPLEX_TYPE:
-    case VOID_TYPE:
-    case BOOLEAN_TYPE:
-    case NAMESPACE_DECL:
-    case FIELD_DECL:
-      return 0;
-
-      /* constants */
-    case INTEGER_CST:
-    case REAL_CST:
-    case STRING_CST:
-      return 0;
-
-    case ERROR_MARK:
-      /* Non-error_mark_node ERROR_MARKs are bad things.  */
-      my_friendly_assert (t == error_mark_node, 274);
-      /* NOTREACHED */
-      return 0;
-
-    case PTRMEM_CST:
-      return for_each_template_parm (TREE_TYPE (t), fn, data);
-
-    case SCOPE_REF:
-      return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
+      if (fn && (*fn)(t, data))
+       return error_mark_node;
+      else if (!fn)
+       return error_mark_node;
+      break;
 
-    case CONSTRUCTOR:
-      if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
-       return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
-                                      (TREE_TYPE (t)), fn, data);
-      return for_each_template_parm (TREE_OPERAND (t, 1), fn, data);
+    case TEMPLATE_DECL:
+      /* A template template parameter is encountered */
+      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
+         && for_each_template_parm (TREE_TYPE (t), fn, data))
+       return error_mark_node;
 
-    case SIZEOF_EXPR:
-    case ALIGNOF_EXPR:
-      return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
+      /* Already substituted template template parameter */
+      *walk_subtrees = 0;
+      break;
 
     case TYPENAME_TYPE:
-      if (!fn)
-       return 1;
-      return (for_each_template_parm (TYPE_CONTEXT (t), fn, data)
-             || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t),
-                                        fn, data));
+      if (!fn || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, data))
+       return error_mark_node;
+      break;
 
+    case CONSTRUCTOR:
+      if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
+         && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
+                                    (TREE_TYPE (t)), fn, data))
+       return error_mark_node;
+      break;
+      
     case INDIRECT_REF:
     case COMPONENT_REF:
       /* If there's no type, then this thing must be some expression
         involving template parameters.  */
       if (!fn && !TREE_TYPE (t))
-       return 1;
-      if (TREE_CODE (t) == COMPONENT_REF)
-       return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
-               || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
-      else
-       return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
+       return error_mark_node;
+      break;
 
     case MODOP_EXPR:
     case CAST_EXPR:
@@ -4259,32 +4172,39 @@ for_each_template_parm (t, fn, data)
     case LOOKUP_EXPR:
     case PSEUDO_DTOR_EXPR:
       if (!fn)
-       return 1;
-      /* Fall through.  */
+       return error_mark_node;
+      break;
 
     default:
-      switch (TREE_CODE_CLASS (TREE_CODE (t)))
-       {
-       case '1':
-       case '2':
-       case 'e':
-       case '<':
-         {
-           int i;
-           for (i = first_rtl_op (TREE_CODE (t)); --i >= 0;)
-             if (for_each_template_parm (TREE_OPERAND (t, i), fn, data))
-               return 1;
-           return 0;
-         }
-       default:
-         break;
-       }
-      sorry ("testing %s for template parms",
-            tree_code_name [(int) TREE_CODE (t)]);
-      my_friendly_abort (82);
-      /* NOTREACHED */
-      return 0;
+      break;
     }
+
+  /* We didn't find any template parameters we liked.  */
+  return NULL_TREE;
+}
+
+/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
+   TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
+   If FN returns non-zero, the iteration is terminated, and
+   for_each_template_parm returns 1.  Otherwise, the iteration
+   continues.  If FN never returns a non-zero value, the value
+   returned by for_each_template_parm is 0.  If FN is NULL, it is
+   considered to be the function which always returns 1.  */
+
+static int
+for_each_template_parm (t, fn, data)
+     tree t;
+     tree_fn_t fn;
+     void* data;
+{
+  struct pair_fn_data pfd;
+
+  /* Set up.  */
+  pfd.fn = fn;
+  pfd.data = data;
+
+  /* Walk the tree.  */
+  return walk_tree (&t, for_each_template_parm_r, &pfd) != NULL_TREE;
 }
 
 int
@@ -4301,8 +4221,8 @@ extern int max_tinst_depth;
 #ifdef GATHER_STATISTICS
 int depth_reached;
 #endif
-int tinst_level_tick;
-int last_template_error_tick;
+static int tinst_level_tick;
+static int last_template_error_tick;
 
 /* Print out all the template instantiations that we are currently
    working on.  If ERR, we are being called from cp_thing, so do
index 0dbc539021adef09a10a716a310048de0942de5b..d1b725b2c321ec02cc7b92f6153ec414875453d7 100644 (file)
@@ -30,8 +30,8 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "splay-tree.h"
 
-static tree bot_manip PROTO((tree));
-static tree bot_replace PROTO((tree *));
+static tree bot_manip PROTO((tree *, int *, void *));
+static tree bot_replace PROTO((tree *, int *, void *));
 static tree build_cplus_array_type_1 PROTO((tree, tree));
 static void list_hash_add PROTO((int, tree));
 static int list_hash PROTO((tree, tree, tree));
@@ -39,9 +39,10 @@ static tree list_hash_lookup PROTO((int, tree, tree, tree));
 static void propagate_binfo_offsets PROTO((tree, tree));
 static int avoid_overlap PROTO((tree, tree));
 static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
-static tree no_linkage_helper PROTO((tree *));
+static tree no_linkage_helper PROTO((tree *, int *, void *));
 static tree build_srcloc PROTO((char *, int));
 static void mark_list_hash PROTO ((void *));
+static tree copy_tree_r PROTO ((tree *, int *, void *));
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
@@ -1524,221 +1525,181 @@ copy_template_template_parm (t)
   return t2;
 }
 
-/* Walk through the tree structure T, applying func.  If func ever returns
-   non-null, return that value.  */
+/* 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.  */
 
-tree
-search_tree (tp, func)
+tree 
+walk_tree (tp, func, data)
      tree *tp;
-     tree (*func) PROTO((tree *));
+     walk_tree_fn func;
+     void *data;
 {
-#define TRY(ARG) if (tmp=search_tree (&ARG, func), tmp != NULL_TREE) return tmp
-
-  tree t = *tp;
-  tree tmp;
-  enum tree_code code; 
+  enum tree_code code;
+  int walk_subtrees;
+  tree result;
   
-  if (t == NULL_TREE)
+#define WALK_SUBTREE(NODE)                     \
+  do                                           \
+    {                                          \
+      result = walk_tree (&(NODE), func, data);        \
+      if (result)                              \
+       return result;                          \
+    }                                          \
+  while (0)
+
+  /* Skip empty subtrees.  */
+  if (!*tp)
     return NULL_TREE;
-  
-  tmp = func (tp);
-  if (tmp)
-    return tmp;
 
-  /* Handle some common cases up front.  */
-  code = TREE_CODE (t);
-  if (TREE_CODE_CLASS (code) == '1')
+  /* 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;
+
+  code = TREE_CODE (*tp);
+
+  /* Handle commmon cases up front.  */
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+      || TREE_CODE_CLASS (code) == 'r')
     {
-      TRY (TREE_OPERAND (t, 0));
+      int i;
+
+      /* Walk over all the sub-trees of this operand.  */
+      for (i = first_rtl_op (code) - 1; i >= 0; --i)
+       WALK_SUBTREE (TREE_OPERAND (*tp, i));
+
+      /* We didn't find what we were looking for.  */
       return NULL_TREE;
     }
-  else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
+  else if (TREE_CODE_CLASS (code) == 'd')
     {
-      TRY (TREE_OPERAND (t, 0));
-      TRY (TREE_OPERAND (t, 1));
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      WALK_SUBTREE (DECL_INITIAL (*tp));
+      WALK_SUBTREE (DECL_SIZE (*tp));
+
+      /* We didn't find what we were looking for.  */
       return NULL_TREE;
     }
 
+  /* Not one of the easy cases.  We must explicitly go through the
+     children.  */
   switch (code)
     {
     case ERROR_MARK:
-      break;
-
     case IDENTIFIER_NODE:
+    case INTEGER_CST:
+    case REAL_CST:
+    case STRING_CST:
+    case DEFAULT_ARG:
+    case TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_PARM_INDEX:
+    case TEMPLATE_TYPE_PARM:
+    case REAL_TYPE:
+    case COMPLEX_TYPE:
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+    case TYPENAME_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+    case TYPEOF_TYPE:
+    case BLOCK:
+      /* None of thse have subtrees other than those already walked
+         above.  */
       break;
 
-    case VAR_DECL:
-    case FUNCTION_DECL:
-    case CONST_DECL:
-    case TEMPLATE_DECL:
-    case NAMESPACE_DECL:
-      break;
-
-    case TYPE_DECL:
-      TRY (TREE_TYPE (t));
+    case PTRMEM_CST:
+      WALK_SUBTREE (TREE_TYPE (*tp));
       break;
 
-    case PARM_DECL:
-      TRY (TREE_TYPE (t));
-      TRY (TREE_CHAIN (t));
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      WALK_SUBTREE (TREE_TYPE (*tp));
       break;
 
     case TREE_LIST:
-      TRY (TREE_PURPOSE (t));
-      TRY (TREE_VALUE (t));
-      TRY (TREE_CHAIN (t));
+      WALK_SUBTREE (TREE_PURPOSE (*tp));
+      WALK_SUBTREE (TREE_VALUE (*tp));
+      WALK_SUBTREE (TREE_CHAIN (*tp));
       break;
 
     case OVERLOAD:
-      TRY (OVL_FUNCTION (t));
-      TRY (OVL_CHAIN (t));
+      WALK_SUBTREE (OVL_FUNCTION (*tp));
+      WALK_SUBTREE (OVL_CHAIN (*tp));
       break;
 
     case TREE_VEC:
       {
-       int len = TREE_VEC_LENGTH (t);
-
-       t = copy_node (t);
+       int len = TREE_VEC_LENGTH (*tp);
        while (len--)
-         TRY (TREE_VEC_ELT (t, len));
+         WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
       }
       break;
 
-    case INTEGER_CST:
-    case REAL_CST:
-    case STRING_CST:
-    case DEFAULT_ARG:
-      break;
-
-    case PTRMEM_CST:
-      TRY (TREE_TYPE (t));
-      break;
-
-    case COND_EXPR:
-    case TARGET_EXPR:
-    case AGGR_INIT_EXPR:
-    case NEW_EXPR:
-      TRY (TREE_OPERAND (t, 0));
-      TRY (TREE_OPERAND (t, 1));
-      TRY (TREE_OPERAND (t, 2));
-      break;
-
-    case TRUTH_AND_EXPR:
-    case TRUTH_OR_EXPR:
-    case TRUTH_XOR_EXPR:
-    case TRUTH_ANDIF_EXPR:
-    case TRUTH_ORIF_EXPR:
-    case PREDECREMENT_EXPR:
-    case PREINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
-    case ARRAY_REF:
-    case SCOPE_REF:
-    case TRY_CATCH_EXPR:
-    case WITH_CLEANUP_EXPR:
-    case CALL_EXPR:
-    case COMPOUND_EXPR:
-    case MODIFY_EXPR:
-    case INIT_EXPR:
-    case OFFSET_REF:
-      TRY (TREE_OPERAND (t, 0));
-      TRY (TREE_OPERAND (t, 1));
-      break;
-
-    case SAVE_EXPR:
-    case ADDR_EXPR:
-    case INDIRECT_REF:
-    case TRUTH_NOT_EXPR:
-    case COMPONENT_REF:
-    case CLEANUP_POINT_EXPR:
-    case LOOKUP_EXPR:
-    case THROW_EXPR:
-    case EXIT_EXPR:
-    case LOOP_EXPR:
-    case BIT_FIELD_REF:
-    case VA_ARG_EXPR:
-      TRY (TREE_OPERAND (t, 0));
-      break;
-
-    case MODOP_EXPR:
-    case ARROW_EXPR:
-    case DOTSTAR_EXPR:
-    case TYPEID_EXPR:
-    case PSEUDO_DTOR_EXPR:
-      break;
-
     case COMPLEX_CST:
-      TRY (TREE_REALPART (t));
-      TRY (TREE_IMAGPART (t));
+      WALK_SUBTREE (TREE_REALPART (*tp));
+      WALK_SUBTREE (TREE_IMAGPART (*tp));
       break;
 
     case CONSTRUCTOR:
-      TRY (CONSTRUCTOR_ELTS (t));
-      break;
-
-    case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_PARM_INDEX:
-    case TEMPLATE_TYPE_PARM:
-      break;
-
-    case BIND_EXPR:
-    case STMT_EXPR:
-      break;
-
-    case REAL_TYPE:
-    case COMPLEX_TYPE:
-    case VOID_TYPE:
-    case BOOLEAN_TYPE:
-    case TYPENAME_TYPE:
-    case UNION_TYPE:
-    case ENUMERAL_TYPE:
-    case TYPEOF_TYPE:
+      WALK_SUBTREE (CONSTRUCTOR_ELTS (*tp));
       break;
 
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-      TRY (TREE_TYPE (t));
-      break;
+    case METHOD_TYPE:
+      WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
+      /* Fall through.  */
 
     case FUNCTION_TYPE:
-    case METHOD_TYPE:
-      TRY (TREE_TYPE (t));
-      TRY (TYPE_ARG_TYPES (t));
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      WALK_SUBTREE (TYPE_ARG_TYPES (*tp));
       break;
 
     case ARRAY_TYPE:
-      TRY (TREE_TYPE (t));
-      TRY (TYPE_DOMAIN (t));
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      WALK_SUBTREE (TYPE_DOMAIN (*tp));
       break;
 
     case INTEGER_TYPE:
-      TRY (TYPE_MAX_VALUE (t));
+      WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
+      WALK_SUBTREE (TYPE_MAX_VALUE (*tp));
       break;
 
     case OFFSET_TYPE:
-      TRY (TREE_TYPE (t));
-      TRY (TYPE_OFFSET_BASETYPE (t));
+      WALK_SUBTREE (TREE_TYPE (*tp));
+      WALK_SUBTREE (TYPE_OFFSET_BASETYPE (*tp));
       break;
 
     case RECORD_TYPE:
-      if (TYPE_PTRMEMFUNC_P (t))
-       TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
+      if (TYPE_PTRMEMFUNC_P (*tp))
+       WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
       break;
       
     default:
       my_friendly_abort (19990803);
     }
 
+  /* We didn't find what we were looking for.  */
   return NULL_TREE;
 
-#undef TRY
+#undef WALK_SUBTREE
 }
 
-/* Passed to search_tree.  Checks for the use of types with no linkage.  */
+/* Passed to walk_tree.  Checks for the use of types with no linkage.  */
 
 static tree
-no_linkage_helper (tp)
+no_linkage_helper (tp, walk_subtrees, data)
      tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
 {
   tree t = *tp;
 
@@ -1762,269 +1723,47 @@ no_linkage_check (t)
   if (processing_template_decl)
     return NULL_TREE;
 
-  t = search_tree (&t, no_linkage_helper);
+  t = walk_tree (&t, no_linkage_helper, NULL);
   if (t != error_mark_node)
     return t;
   return NULL_TREE;
 }
 
+/* Passed to walk_tree.  Copies the node pointed to, if appropriate.  */
 
-/* Make copies of all the nodes below T.  If FUNC is non-NULL, call it
-   for each node.  */
-
-tree
-mapcar (t, func)
-     tree t;
-     tree (*func) PROTO((tree));
-{
-  tree tmp;
-  enum tree_code code; 
-
-  if (t == NULL_TREE)
-    return t;
-
-  if (func) 
-    {
-      tmp = func (t);
-      if (tmp)
-       return tmp;
-    }
-
-  /* Handle some common cases up front.  */
-  code = TREE_CODE (t);
-  if (TREE_CODE_CLASS (code) == '1')
-    {
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      return t;
-    }
-  else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
-    {
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      return t;
-    }
-
-  switch (TREE_CODE (t))
+static tree
+copy_tree_r (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  enum tree_code code = TREE_CODE (*tp);
+
+  /* We make copies of most nodes.  */
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+      || TREE_CODE_CLASS (code) == 'r'
+      || TREE_CODE_CLASS (code) == 'c'
+      || code == PARM_DECL
+      || code == TREE_LIST
+      || code == TREE_VEC
+      || code == OVERLOAD)
     {
-    case ERROR_MARK:
-      return error_mark_node;
-
-    case VAR_DECL:
-    case FUNCTION_DECL:
-    case CONST_DECL:
-      /* Rather than aborting, return error_mark_node.  This allows us
-        to report a sensible error message on code like this:
-
-        void g() { int i; f<i>(7); } 
-
-         In a case like:
-
-           void g() { const int i = 7; f<i>(7); }
-
-        however, we must actually return the constant initializer.  */
-      if (TREE_READONLY_DECL_P (t))
-       {
-         tmp = decl_constant_value (t);
-         if (tmp != t)
-           return mapcar (tmp, func);
-       }
-      return error_mark_node;
-
-    case PARM_DECL:
-      {
-       tree chain = TREE_CHAIN (t);
-       t = copy_node (t);
-       TREE_CHAIN (t) = mapcar (chain, func);
-       TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-       DECL_INITIAL (t) = mapcar (DECL_INITIAL (t), func);
-       DECL_SIZE (t) = mapcar (DECL_SIZE (t), func);
-       return t;
-      }
-
-    case TREE_LIST:
-      {
-       tree chain = TREE_CHAIN (t);
-       t = copy_node (t);
-       TREE_PURPOSE (t) = mapcar (TREE_PURPOSE (t), func);
-       TREE_VALUE (t) = mapcar (TREE_VALUE (t), func);
-       TREE_CHAIN (t) = mapcar (chain, func);
-       return t;
-      }
-
-    case OVERLOAD:
-      {
-       tree chain = OVL_CHAIN (t);
-       t = copy_node (t);
-       OVL_FUNCTION (t) = mapcar (OVL_FUNCTION (t), func);
-       OVL_CHAIN (t) = mapcar (chain, func);
-       return t;
-      }
-
-    case TREE_VEC:
-      {
-       int len = TREE_VEC_LENGTH (t);
-
-       t = copy_node (t);
-       while (len--)
-         TREE_VEC_ELT (t, len) = mapcar (TREE_VEC_ELT (t, len), func);
-       return t;
-      }
+      /* Because the chain gets clobbered when we make a copy, we save it
+        here.  */
+      tree chain = TREE_CHAIN (*tp);
 
-    case INTEGER_CST:
-    case REAL_CST:
-    case STRING_CST:
-      return copy_node (t);
-
-    case PTRMEM_CST:
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func);
-      return t;
-
-    case COND_EXPR:
-    case TARGET_EXPR:
-    case AGGR_INIT_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
-      return t;
-
-    case TRUTH_AND_EXPR:
-    case TRUTH_OR_EXPR:
-    case TRUTH_XOR_EXPR:
-    case TRUTH_ANDIF_EXPR:
-    case TRUTH_ORIF_EXPR:
-    case PREDECREMENT_EXPR:
-    case PREINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
-    case ARRAY_REF:
-    case SCOPE_REF:
-    case TRY_CATCH_EXPR:
-    case WITH_CLEANUP_EXPR:
-    case COMPOUND_EXPR:
-    case MODIFY_EXPR:
-    case INIT_EXPR:
-    case OFFSET_REF:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      return t;
-
-    case CALL_EXPR:
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      TREE_OPERAND (t, 2) = NULL_TREE;
-      return t;
+      /* Copy the node.  */
+      *tp = copy_node (*tp);
 
-    case SAVE_EXPR:
-    case ADDR_EXPR:
-    case INDIRECT_REF:
-    case TRUTH_NOT_EXPR:
-    case COMPONENT_REF:
-    case CLEANUP_POINT_EXPR:
-    case THROW_EXPR:
-    case STMT_EXPR:
-    case VA_ARG_EXPR:
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      return t;
-
-    case POINTER_TYPE:
-      tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-    case REFERENCE_TYPE:
-      tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-    case FUNCTION_TYPE:
-      tmp = build_function_type (mapcar (TREE_TYPE (t), func),
-                                mapcar (TYPE_ARG_TYPES (t), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-    case ARRAY_TYPE:
-      tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func),
-                                   mapcar (TYPE_DOMAIN (t), func));
-      return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t));
-    case INTEGER_TYPE:
-      tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-    case OFFSET_TYPE:
-      tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
-                              mapcar (TREE_TYPE (t), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-    case METHOD_TYPE:
-      tmp = build_cplus_method_type
-       (mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func),
-        mapcar (TREE_TYPE (t), func),
-        mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
-      return cp_build_qualified_type (tmp, TYPE_QUALS (t));
-
-    case COMPLEX_CST:
-      t = copy_node (t);
-      TREE_REALPART (t) = mapcar (TREE_REALPART (t), func);
-      TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func);
-      return t;
-
-    case CONSTRUCTOR:
-      t = copy_node (t);
-      CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
-      return t;
-
-    case TEMPLATE_TEMPLATE_PARM:
-      return copy_template_template_parm (t);
-
-    case BIND_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      TREE_OPERAND (t, 2) = NULL_TREE;
-      return t;
-
-    case NEW_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
-      return t;
-
-    case BIT_FIELD_REF:
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
-      TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
-      return t;
-      
-    case LOOKUP_EXPR:
-    case EXIT_EXPR:
-    case LOOP_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      return t;
-
-    case RTL_EXPR:
-      t = copy_node (t);
-      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
-      return t;
-
-    case RECORD_TYPE:
-      if (TYPE_PTRMEMFUNC_P (t))
-       return build_ptrmemfunc_type
-         (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func));
-      /* else fall through */
-
-    default:
-      my_friendly_abort (19990815);
+      /* Now, restore the chain, if appropriate.  That will cause
+        walk_tree to walk into the chain as well.  */
+      if (code == PARM_DECL || code == TREE_LIST || code == OVERLOAD)
+       TREE_CHAIN (*tp) = chain;
     }
-  my_friendly_abort (107);
-  /* NOTREACHED */
+  else if (code == TEMPLATE_TEMPLATE_PARM)
+    /* These must be copied specially.  */
+    *tp = copy_template_template_parm (*tp);
+
   return NULL_TREE;
 }
 
@@ -2092,24 +1831,23 @@ array_type_nelts_total (type)
   return sz;
 }
 
-/* When we parse a default argument expression, we may create
-   temporary variables via TARGET_EXPRs.  When we actually use the
-   default-argument expression, we make a copy of the expression, but
-   we must relpace the temporaries with appropriate local versions.  */
-
-/* A map from VAR_DECLs declared in TARGET_EXPRs in a default argument
-   to corresponding "instantiations" of those variables.  */
-static splay_tree target_remap;
-static int target_remap_count;
-
 /* Called from break_out_target_exprs via mapcar.  */
 
 static tree
-bot_manip (t)
-     tree t;
+bot_manip (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees;
+     void *data;
 {
+  splay_tree target_remap = ((splay_tree) data);
+  tree t = *tp;
+
   if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t))
-    return t;
+    {
+      /* There can't be any TARGET_EXPRs below this point.  */
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
   else if (TREE_CODE (t) == TARGET_EXPR)
     {
       tree u;
@@ -2131,20 +1869,34 @@ bot_manip (t)
       splay_tree_insert (target_remap, 
                         (splay_tree_key) TREE_OPERAND (t, 0), 
                         (splay_tree_value) TREE_OPERAND (u, 0));
-      return u;
+
+      /* Replace the old expression with the new version.  */
+      *tp = u;
+      /* We don't have to go below this point; the recursive call to
+        break_out_target_exprs will have handled anything below this
+        point.  */
+      *walk_subtrees = 0;
+      return NULL_TREE;
     }
   else if (TREE_CODE (t) == CALL_EXPR)
     mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
 
-  return NULL_TREE;
+  /* Make a copy of this node.  */
+  return copy_tree_r (tp, walk_subtrees, NULL);
 }
   
-/* Replace all remapped VAR_DECLs in T with their new equivalents.  */
+/* Replace all remapped VAR_DECLs in T with their new equivalents.
+   DATA is really a splay-tree mapping old variables to new
+   variables.  */
 
 static tree
-bot_replace (t)
+bot_replace (t, walk_subtrees, data)
      tree *t;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data;
 {
+  splay_tree target_remap = ((splay_tree) data);
+
   if (TREE_CODE (*t) == VAR_DECL)
     {
       splay_tree_node n = splay_tree_lookup (target_remap,
@@ -2156,18 +1908,24 @@ bot_replace (t)
   return NULL_TREE;
 }
        
-/* Actually, we'll just clean out the target exprs for the moment.  */
+/* When we parse a default argument expression, we may create
+   temporary variables via TARGET_EXPRs.  When we actually use the
+   default-argument expression, we make a copy of the expression, but
+   we must replace the temporaries with appropriate local versions.  */
 
 tree
 break_out_target_exprs (t)
      tree t;
 {
+  static int target_remap_count;
+  static splay_tree target_remap;
+
   if (!target_remap_count++)
     target_remap = splay_tree_new (splay_tree_compare_pointers, 
                                   /*splay_tree_delete_key_fn=*/NULL, 
                                   /*splay_tree_delete_value_fn=*/NULL);
-  t = mapcar (t, bot_manip);
-  search_tree (&t, bot_replace);
+  walk_tree (&t, bot_manip, target_remap);
+  walk_tree (&t, bot_replace, target_remap);
 
   if (!--target_remap_count)
     {