OSDN Git Service

2004-08-20 Andreas Tobler <a.tobler@schweiz.ch>
[pf3gnuchains/gcc-fork.git] / gcc / cp / tree.c
index a5858bf..703d963 100644 (file)
@@ -35,36 +35,30 @@ Boston, MA 02111-1307, USA.  */
 #include "tree-inline.h"
 #include "target.h"
 
-static tree bot_manip PARAMS ((tree *, int *, void *));
-static tree bot_replace PARAMS ((tree *, int *, void *));
-static tree build_cplus_array_type_1 PARAMS ((tree, tree));
-static int list_hash_eq PARAMS ((const void *, const void *));
-static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
-static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int));
-static tree no_linkage_helper PARAMS ((tree *, int *, void *));
-static tree build_srcloc PARAMS ((const char *, int));
-static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
-static tree cp_unsave_r PARAMS ((tree *, int *, void *));
-static tree build_target_expr PARAMS ((tree, tree));
-static tree count_trees_r PARAMS ((tree *, int *, void *));
-static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
-static tree find_tree_r PARAMS ((tree *, int *, void *));
-extern int cp_statement_code_p PARAMS ((enum tree_code));
-
-static tree handle_java_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_com_interface_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree bot_manip (tree *, int *, void *);
+static tree bot_replace (tree *, int *, void *);
+static tree build_cplus_array_type_1 (tree, tree);
+static int list_hash_eq (const void *, const void *);
+static hashval_t list_hash_pieces (tree, tree, tree);
+static hashval_t list_hash (const void *);
+static cp_lvalue_kind lvalue_p_1 (tree, int);
+static tree build_target_expr (tree, tree);
+static tree count_trees_r (tree *, int *, void *);
+static tree verify_stmt_tree_r (tree *, int *, void *);
+static tree find_tree_r (tree *, int *, void *);
+static tree build_local_temp (tree);
+
+static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
+static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
+static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
 
 /* If REF is an lvalue, returns the kind of lvalue that REF is.
    Otherwise, returns clk_none.  If TREAT_CLASS_RVALUES_AS_LVALUES is
    nonzero, rvalues of class type are considered lvalues.  */
 
 static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
-     tree ref;
-     int treat_class_rvalues_as_lvalues;
-     int allow_cast_as_lvalue;
+lvalue_p_1 (tree ref,
+            int treat_class_rvalues_as_lvalues)
 {
   cp_lvalue_kind op1_lvalue_kind = clk_none;
   cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -82,39 +76,36 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case SAVE_EXPR:
-    case UNSAVE_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 0),
-                        treat_class_rvalues_as_lvalues,
-                        allow_cast_as_lvalue);
-
-    case NOP_EXPR:
-      if (allow_cast_as_lvalue)
-       return lvalue_p_1 (TREE_OPERAND (ref, 0),
-                          treat_class_rvalues_as_lvalues,
-                          allow_cast_as_lvalue);
-      else
-       return clk_none;
+                        treat_class_rvalues_as_lvalues);
 
     case COMPONENT_REF:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues,
-                                   allow_cast_as_lvalue);
-      if (op1_lvalue_kind 
+                                   treat_class_rvalues_as_lvalues);
+      /* In an expression of the form "X.Y", the packed-ness of the
+        expression does not depend on "X".  */
+      op1_lvalue_kind &= ~clk_packed;
+      /* Look at the member designator.  */
+      if (!op1_lvalue_kind
          /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
-            situations.  */
-         && TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
-         && DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
+            situations.  */
+         || TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+       ;
+      else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
        {
          /* Clear the ordinary bit.  If this object was a class
             rvalue we want to preserve that information.  */
          op1_lvalue_kind &= ~clk_ordinary;
-         /* The lvalue is for a btifield.  */
+         /* The lvalue is for a bitfield.  */
          op1_lvalue_kind |= clk_bitfield;
        }
+      else if (DECL_PACKED (TREE_OPERAND (ref, 1)))
+       op1_lvalue_kind |= clk_packed;
+
       return op1_lvalue_kind;
 
     case STRING_CST:
@@ -136,27 +127,19 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
       /* A currently unresolved scope ref.  */
     case SCOPE_REF:
       abort ();
-    case OFFSET_REF:
-      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
-       return clk_ordinary;
-      /* Fall through.  */
     case MAX_EXPR:
     case MIN_EXPR:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
-                                   treat_class_rvalues_as_lvalues,
-                                   allow_cast_as_lvalue);
+                                   treat_class_rvalues_as_lvalues);
       op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues,
-                                   allow_cast_as_lvalue);
+                                   treat_class_rvalues_as_lvalues);
       break;
 
     case COND_EXPR:
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
-                                   treat_class_rvalues_as_lvalues,
-                                   allow_cast_as_lvalue);
+                                   treat_class_rvalues_as_lvalues);
       op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
-                                   treat_class_rvalues_as_lvalues,
-                                   allow_cast_as_lvalue);
+                                   treat_class_rvalues_as_lvalues);
       break;
 
     case MODIFY_EXPR:
@@ -164,8 +147,7 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
 
     case COMPOUND_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 1),
-                        treat_class_rvalues_as_lvalues,
-                        allow_cast_as_lvalue);
+                        treat_class_rvalues_as_lvalues);
 
     case TARGET_EXPR:
       return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
@@ -178,9 +160,17 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
     case FUNCTION_DECL:
       /* All functions (except non-static-member functions) are
         lvalues.  */
-      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) 
+      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
              ? clk_none : clk_ordinary);
 
+    case NON_DEPENDENT_EXPR:
+      /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
+        things like "&E" where "E" is an expression with a
+        non-dependent type work. It is safe to be lenient because an
+        error will be issued when the template is instantiated if "E"
+        is not an lvalue.  */
+      return clk_ordinary;
+
     default:
       break;
     }
@@ -200,87 +190,50 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
   return op1_lvalue_kind;
 }
 
-/* If REF is an lvalue, returns the kind of lvalue that REF is.
-   Otherwise, returns clk_none.  Lvalues can be assigned, unless they
-   have TREE_READONLY, or unless they are FUNCTION_DECLs.  Lvalues can
-   have their address taken, unless they have DECL_REGISTER.  */
-
-cp_lvalue_kind
-real_lvalue_p (ref)
-     tree ref;
-{
-  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
-}
-
 /* Returns the kind of lvalue that REF is, in the sense of
    [basic.lval].  This function should really be named lvalue_p; it
    computes the C++ definition of lvalue.  */
 
 cp_lvalue_kind
-real_non_cast_lvalue_p (tree ref)
+real_lvalue_p (tree ref)
 {
-  return lvalue_p_1 (ref, 
-                    /*treat_class_rvalues_as_lvalues=*/0, 
-                    /*allow_cast_as_lvalue=*/0);
+  return lvalue_p_1 (ref,
+                    /*treat_class_rvalues_as_lvalues=*/0);
 }
 
 /* This differs from real_lvalue_p in that class rvalues are
    considered lvalues.  */
 
 int
-lvalue_p (ref)
-     tree ref;
+lvalue_p (tree ref)
 {
-  return 
-    (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none);
-}
-
-int
-non_cast_lvalue_p (ref)
-     tree ref;
-{
-  return 
-    (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 0) != clk_none);
+  return
+    (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  */
 
 int
-lvalue_or_else (ref, string)
-     tree ref;
-     const char *string;
-{
-  int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1);
-  int win = (ret != clk_none);
-  if (! win)
-    error ("non-lvalue in %s", string);
-  return win;
-}
-
-int
-non_cast_lvalue_or_else (ref, string)
-     tree ref;
-     const char *string;
+lvalue_or_else (tree ref, const char* string)
 {
-  int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0);
-  int win = (ret != clk_none);
-  if (! win)
-    error ("non-lvalue in %s", string);
-  return win;
+  if (!lvalue_p (ref))
+    {
+      error ("non-lvalue in %s", string);
+      return 0;
+    }
+  return 1;
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
 
 static tree
-build_target_expr (decl, value)
-     tree decl;
-     tree value;
+build_target_expr (tree decl, tree value)
 {
   tree t;
 
-  t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value, 
-            cxx_maybe_build_cleanup (decl), NULL_TREE);
+  t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
+             cxx_maybe_build_cleanup (decl), NULL_TREE);
   /* We always set TREE_SIDE_EFFECTS so that expand_expr does not
      ignore the TARGET_EXPR.  If there really turn out to be no
      side-effects, then the optimizer should be able to get rid of
@@ -290,6 +243,19 @@ build_target_expr (decl, value)
   return t;
 }
 
+/* Return an undeclared local temporary of type TYPE for use in building a
+   TARGET_EXPR.  */
+
+static tree
+build_local_temp (tree type)
+{
+  tree slot = build_decl (VAR_DECL, NULL_TREE, type);
+  DECL_ARTIFICIAL (slot) = 1;
+  DECL_CONTEXT (slot) = current_function_decl;
+  layout_decl (slot, 0);
+  return slot;
+}
+
 /* INIT is a CALL_EXPR which needs info about its target.
    TYPE is the type that this initialization should appear to have.
 
@@ -298,9 +264,7 @@ build_target_expr (decl, value)
    and language-specific expression expanders.  */
 
 tree
-build_cplus_new (type, init)
-     tree type;
-     tree init;
+build_cplus_new (tree type, tree init)
 {
   tree fn;
   tree slot;
@@ -319,10 +283,7 @@ build_cplus_new (type, init)
             && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
             && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
 
-  slot = build (VAR_DECL, type);
-  DECL_ARTIFICIAL (slot) = 1;
-  DECL_CONTEXT (slot) = current_function_decl;
-  layout_decl (slot, 0);
+  slot = build_local_temp (type);
 
   /* We split the CALL_EXPR into its function and its arguments here.
      Then, in expand_expr, we put them back together.  The reason for
@@ -337,7 +298,8 @@ build_cplus_new (type, init)
      type, don't mess with AGGR_INIT_EXPR.  */
   if (is_ctor || TREE_ADDRESSABLE (type))
     {
-      rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
+      rval = build3 (AGGR_INIT_EXPR, void_type_node, fn,
+                    TREE_OPERAND (init, 1), slot);
       TREE_SIDE_EFFECTS (rval) = 1;
       AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
     }
@@ -353,172 +315,64 @@ build_cplus_new (type, init)
    indicated TYPE.  */
 
 tree
-build_target_expr_with_type (init, type)
-     tree init;
-     tree type;
+build_target_expr_with_type (tree init, tree type)
 {
   tree slot;
-  tree rval;
+
+  my_friendly_assert (!VOID_TYPE_P (type), 20040130);
 
   if (TREE_CODE (init) == TARGET_EXPR)
     return init;
+  else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)
+          && TREE_CODE (init) != COND_EXPR
+          && TREE_CODE (init) != CONSTRUCTOR
+          && TREE_CODE (init) != VA_ARG_EXPR)
+    /* We need to build up a copy constructor call.  COND_EXPR is a special
+       case because we already have copies on the arms and we don't want
+       another one here.  A CONSTRUCTOR is aggregate initialization, which
+       is handled separately.  A VA_ARG_EXPR is magic creation of an
+       aggregate; there's no additional work to be done.  */
+    return force_rvalue (init);
 
-  slot = build (VAR_DECL, type);
-  DECL_ARTIFICIAL (slot) = 1;
-  DECL_CONTEXT (slot) = current_function_decl;
-  layout_decl (slot, 0);
-  rval = build_target_expr (slot, init);
-
-  return rval;
-}
-
-/* Like build_target_expr_with_type, but use the type of INIT.  */
-
-tree
-get_target_expr (init)
-     tree init;
-{
-  return build_target_expr_with_type (init, TREE_TYPE (init));
+  slot = build_local_temp (type);
+  return build_target_expr (slot, init);
 }
 
-/* Recursively perform a preorder search EXP for CALL_EXPRs, making
-   copies where they are found.  Returns a deep copy all nodes transitively
-   containing CALL_EXPRs.  */
+/* Like the above function, but without the checking.  This function should
+   only be used by code which is deliberately trying to subvert the type
+   system, such as call_builtin_trap.  */
 
 tree
-break_out_calls (exp)
-     tree exp;
+force_target_expr (tree type, tree init)
 {
-  register tree t1, t2 = NULL_TREE;
-  register enum tree_code code;
-  register int changed = 0;
-  register int i;
-
-  if (exp == NULL_TREE)
-    return exp;
-
-  code = TREE_CODE (exp);
-
-  if (code == CALL_EXPR)
-    return copy_node (exp);
-
-  /* Don't try and defeat a save_expr, as it should only be done once.  */
-    if (code == SAVE_EXPR)
-       return exp;
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    default:
-      abort ();
-
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
-      return exp;
-
-    case 'd':  /* A decl node */
-      return exp;
-
-    case 'b':  /* A block node */
-      {
-       /* Don't know how to handle these correctly yet.   Must do a
-          break_out_calls on all DECL_INITIAL values for local variables,
-          and also break_out_calls on all sub-blocks and sub-statements.  */
-       abort ();
-      }
-      return exp;
+  tree slot;
 
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-      for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; i--)
-       {
-         t1 = break_out_calls (TREE_OPERAND (exp, i));
-         if (t1 != TREE_OPERAND (exp, i))
-           {
-             exp = copy_node (exp);
-             TREE_OPERAND (exp, i) = t1;
-           }
-       }
-      return exp;
-
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-      t2 = break_out_calls (TREE_OPERAND (exp, 1));
-      if (t2 != TREE_OPERAND (exp, 1))
-       changed = 1;
-    case '1':  /* a unary arithmetic expression */
-      t1 = break_out_calls (TREE_OPERAND (exp, 0));
-      if (t1 != TREE_OPERAND (exp, 0))
-       changed = 1;
-      if (changed)
-       {
-         if (TREE_CODE_LENGTH (code) == 1)
-           return build1 (code, TREE_TYPE (exp), t1);
-         else
-           return build (code, TREE_TYPE (exp), t1, t2);
-       }
-      return exp;
-    }
+  my_friendly_assert (!VOID_TYPE_P (type), 20040130);
 
+  slot = build_local_temp (type);
+  return build_target_expr (slot, init);
 }
-\f
-/* Construct, lay out and return the type of methods belonging to class
-   BASETYPE and whose arguments are described by ARGTYPES and whose values
-   are described by RETTYPE.  If each type exists already, reuse it.  */
+
+/* Like build_target_expr_with_type, but use the type of INIT.  */
 
 tree
-build_cplus_method_type (basetype, rettype, argtypes)
-     tree basetype, rettype, argtypes;
+get_target_expr (tree init)
 {
-  register tree t;
-  tree ptype;
-  int hashcode;
-
-  /* Make a node of the sort we want.  */
-  t = make_node (METHOD_TYPE);
-
-  TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
-  TREE_TYPE (t) = rettype;
-  ptype = build_pointer_type (basetype);
-
-  /* The actual arglist for this function includes a "hidden" argument
-     which is "this".  Put it into the list of argument types.  */
-  argtypes = tree_cons (NULL_TREE, ptype, argtypes);
-  TYPE_ARG_TYPES (t) = argtypes;
-  TREE_SIDE_EFFECTS (argtypes) = 1;  /* Mark first argtype as "artificial".  */
-
-  /* If we already have such a type, use the old one and free this one.
-     Note that it also frees up the above cons cell if found.  */
-  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
-    type_hash_list (argtypes);
-
-  t = type_hash_canon (hashcode, t);
-
-  if (!COMPLETE_TYPE_P (t))
-    layout_type (t);
-
-  return t;
+  return build_target_expr_with_type (init, TREE_TYPE (init));
 }
 
+\f
 static tree
-build_cplus_array_type_1 (elt_type, index_type)
-     tree elt_type;
-     tree index_type;
+build_cplus_array_type_1 (tree elt_type, tree index_type)
 {
   tree t;
 
   if (elt_type == error_mark_node || index_type == error_mark_node)
     return error_mark_node;
 
-  /* Don't do the minimal thing just because processing_template_decl is
-     set; we want to give string constants the right type immediately, so
-     we don't have to fix them up at instantiation time.  */
-  if ((processing_template_decl
-       && index_type && TYPE_MAX_VALUE (index_type)
-       && TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
-      || uses_template_parms (elt_type) 
-      || uses_template_parms (index_type))
+  if (dependent_type_p (elt_type)
+      || (index_type
+         && value_dependent_expression_p (TYPE_MAX_VALUE (index_type))))
     {
       t = make_node (ARRAY_TYPE);
       TREE_TYPE (t) = elt_type;
@@ -529,30 +383,26 @@ build_cplus_array_type_1 (elt_type, index_type)
 
   /* Push these needs up so that initialization takes place
      more easily.  */
-  TYPE_NEEDS_CONSTRUCTING (t) 
+  TYPE_NEEDS_CONSTRUCTING (t)
     = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
-  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+  TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
     = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
   return t;
 }
 
 tree
-build_cplus_array_type (elt_type, index_type)
-     tree elt_type;
-     tree index_type;
+build_cplus_array_type (tree elt_type, tree index_type)
 {
   tree t;
   int type_quals = cp_type_quals (elt_type);
-  int cv_quals = type_quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
-  int other_quals = type_quals & ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
 
-  if (cv_quals)
-    elt_type = cp_build_qualified_type (elt_type, other_quals);
+  if (type_quals != TYPE_UNQUALIFIED)
+    elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
 
   t = build_cplus_array_type_1 (elt_type, index_type);
 
-  if (cv_quals)
-    t = cp_build_qualified_type (t, cv_quals);
+  if (type_quals != TYPE_UNQUALIFIED)
+    t = cp_build_qualified_type (t, type_quals);
 
   return t;
 }
@@ -560,7 +410,7 @@ build_cplus_array_type (elt_type, index_type)
 /* Make a variant of TYPE, qualified with the TYPE_QUALS.  Handles
    arrays correctly.  In particular, if TYPE is an array of T's, and
    TYPE_QUALS is non-empty, returns an array of qualified T's.
-  
+
    FLAGS determines how to deal with illformed qualifications. If
    tf_ignore_bad_quals is set, then bad qualifications are dropped
    (this is permitted if TYPE was introduced via a typedef or template
@@ -574,22 +424,16 @@ build_cplus_array_type (elt_type, index_type)
    via a typedef or template type argument. [dcl.ref] No such
    dispensation is provided for qualifying a function type.  [dcl.fct]
    DR 295 queries this and the proposed resolution brings it into line
-   with qualifiying a reference.  We implement the DR.  We also behave
+   with qualifying a reference.  We implement the DR.  We also behave
    in a similar manner for restricting non-pointer types.  */
+
 tree
-cp_build_qualified_type_real (type, type_quals, complain)
-     tree type;
-     int type_quals;
-     tsubst_flags_t complain;
+cp_build_qualified_type_real (tree type,
+                              int type_quals,
+                              tsubst_flags_t complain)
 {
   tree result;
   int bad_quals = TYPE_UNQUALIFIED;
-  /* We keep bad function qualifiers separate, so that we can decide
-     whether to implement DR 295 or not. DR 295 break existing code,
-     unfortunately. Remove this variable to implement the defect
-     report.  */
-  int bad_func_quals = TYPE_UNQUALIFIED;
 
   if (type == error_mark_node)
     return type;
@@ -597,61 +441,13 @@ cp_build_qualified_type_real (type, type_quals, complain)
   if (type_quals == cp_type_quals (type))
     return type;
 
-  /* A reference, fucntion or method type shall not be cv qualified.
-     [dcl.ref], [dct.fct]  */
-  if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
-      && (TREE_CODE (type) == REFERENCE_TYPE
-         || TREE_CODE (type) == FUNCTION_TYPE
-         || TREE_CODE (type) == METHOD_TYPE))
-    {
-      bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-      if (TREE_CODE (type) != REFERENCE_TYPE)
-       bad_func_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-      type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-    }
-  
-  /* A restrict-qualified type must be a pointer (or reference)
-     to object or incomplete type.  */
-  if ((type_quals & TYPE_QUAL_RESTRICT)
-      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (type) != TYPENAME_TYPE
-      && !POINTER_TYPE_P (type))
-    {
-      bad_quals |= TYPE_QUAL_RESTRICT;
-      type_quals &= ~TYPE_QUAL_RESTRICT;
-    }
-
-  if (bad_quals == TYPE_UNQUALIFIED)
-    /*OK*/;
-  else if (!(complain & (tf_error | tf_ignore_bad_quals)))
-    return error_mark_node;
-  else if (bad_func_quals && !(complain & tf_error))
-    return error_mark_node;
-  else
-    {
-      if (complain & tf_ignore_bad_quals)
-       /* We're not going to warn about constifying things that can't
-          be constified.  */
-       bad_quals &= ~TYPE_QUAL_CONST;
-      bad_quals |= bad_func_quals;
-      if (bad_quals)
-       {
-         tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
-         if (!(complain & tf_ignore_bad_quals)
-             || bad_func_quals)
-           error ("`%V' qualifiers cannot be applied to `%T'",
-                  bad_type, type);
-       }
-    }
-  
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
       /* In C++, the qualification really applies to the array element
         type.  Obtain the appropriately qualified element type.  */
       tree t;
-      tree element_type 
-       = cp_build_qualified_type_real (TREE_TYPE (type), 
+      tree element_type
+       = cp_build_qualified_type_real (TREE_TYPE (type),
                                        type_quals,
                                        complain);
 
@@ -660,11 +456,11 @@ cp_build_qualified_type_real (type, type_quals, complain)
 
       /* See if we already have an identically qualified type.  */
       for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-       if (cp_type_quals (t) == type_quals 
+       if (cp_type_quals (t) == type_quals
            && TYPE_NAME (t) == TYPE_NAME (type)
            && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
          break;
-         
+
       if (!t)
        {
          /* Make a new array type, just like the old one, but with the
@@ -675,14 +471,14 @@ cp_build_qualified_type_real (type, type_quals, complain)
 
       /* Even if we already had this variant, we update
         TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
-        they changed since the variant was originally created.  
-        
+        they changed since the variant was originally created.
+
         This seems hokey; if there is some way to use a previous
         variant *without* coming through here,
         TYPE_NEEDS_CONSTRUCTING will never be updated.  */
-      TYPE_NEEDS_CONSTRUCTING (t) 
+      TYPE_NEEDS_CONSTRUCTING (t)
        = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (element_type));
-      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) 
+      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
        = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
       return t;
     }
@@ -698,7 +494,49 @@ cp_build_qualified_type_real (type, type_quals, complain)
       t = cp_build_qualified_type_real (t, type_quals, complain);
       return build_ptrmemfunc_type (t);
     }
-  
+
+  /* A reference, function or method type shall not be cv qualified.
+     [dcl.ref], [dct.fct]  */
+  if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
+      && (TREE_CODE (type) == REFERENCE_TYPE
+         || TREE_CODE (type) == FUNCTION_TYPE
+         || TREE_CODE (type) == METHOD_TYPE))
+    {
+      bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
+      type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
+    }
+
+  /* A restrict-qualified type must be a pointer (or reference)
+     to object or incomplete type.  */
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
+      && TREE_CODE (type) != TYPENAME_TYPE
+      && !POINTER_TYPE_P (type))
+    {
+      bad_quals |= TYPE_QUAL_RESTRICT;
+      type_quals &= ~TYPE_QUAL_RESTRICT;
+    }
+
+  if (bad_quals == TYPE_UNQUALIFIED)
+    /*OK*/;
+  else if (!(complain & (tf_error | tf_ignore_bad_quals)))
+    return error_mark_node;
+  else
+    {
+      if (complain & tf_ignore_bad_quals)
+       /* We're not going to warn about constifying things that can't
+          be constified.  */
+       bad_quals &= ~TYPE_QUAL_CONST;
+      if (bad_quals)
+       {
+         tree bad_type = build_qualified_type (ptr_type_node, bad_quals);
+
+         if (!(complain & tf_ignore_bad_quals))
+           error ("`%V' qualifiers cannot be applied to `%T'",
+                  bad_type, type);
+       }
+    }
+
   /* Retrieve (or create) the appropriately qualified variant.  */
   result = build_qualified_type (type, type_quals);
 
@@ -706,7 +544,7 @@ cp_build_qualified_type_real (type, type_quals, complain)
      then we need to unshare the record that holds the cached
      pointer-to-member-function type, because these will be distinct
      between the unqualified and qualified types.  */
-  if (result != type 
+  if (result != type
       && TREE_CODE (type) == POINTER_TYPE
       && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
     TYPE_LANG_SPECIFIC (result) = NULL;
@@ -720,89 +558,92 @@ cp_build_qualified_type_real (type, type_quals, complain)
    compatible types.  */
 
 tree
-canonical_type_variant (t)
-     tree t;
+canonical_type_variant (tree t)
 {
   return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
 }
 \f
-/* Makes new binfos for the indirect bases under BINFO. T is the most
-   derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make
-   point to this binfo. We return the last BINFO created.
-
-   The CLASSTYPE_VBASECLASSES list of T is constructed in reverse
-   order (pre-order, depth-first, right-to-left). You must nreverse it.
+/* Makes a copy of BINFO and TYPE, which is to be inherited into a
+   graph dominated by T.  If BINFO is NULL, TYPE is a dependent base,
+   and we do a shallow copy.  If BINFO is non-NULL, we do a deep copy.
+   VIRT indicates whether TYPE is inherited virtually or not.
+   IGO_PREV points at the previous binfo of the inheritance graph
+   order chain.  The newly copied binfo's TREE_CHAIN forms this
+   ordering.
+
+   The CLASSTYPE_VBASECLASSES vector of T is constructed in the
+   correct order. That is in the order the bases themselves should be
+   constructed in.
 
    The BINFO_INHERITANCE of a virtual base class points to the binfo
-   og the most derived type.
-
-   The binfo's TREE_CHAIN is set to inheritance graph order, but bases
-   for non-class types are not included (i.e. those which are
-   dependent bases in non-instantiated templates).  */
+   of the most derived type. ??? We could probably change this so that
+   BINFO_INHERITANCE becomes synonymous with BINFO_PRIMARY, and hence
+   remove a field.  They currently can only differ for primary virtual
+   virtual bases.  */
 
 tree
-copy_base_binfos (binfo, t, prev)
-     tree binfo, t, prev;
-{
-  tree binfos = BINFO_BASETYPES (binfo);
-  int n, ix;
-
-  if (prev)
-    TREE_CHAIN (prev) = binfo;
-  prev = binfo;
-  
-  if (binfos == NULL_TREE)
-    return prev;
-
-  n = TREE_VEC_LENGTH (binfos);
-  
-  /* Now copy the structure beneath BINFO.  */
-  for (ix = 0; ix != n; ix++)
+copy_binfo (tree binfo, tree type, tree t, tree *igo_prev, int virt)
+{
+  tree new_binfo;
+
+  if (virt)
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, ix);
-      tree new_binfo = NULL_TREE;
+      /* See if we've already made this virtual base.  */
+      new_binfo = binfo_for_vbase (type, t);
+      if (new_binfo)
+       return new_binfo;
+    }
 
-      if (!CLASS_TYPE_P (BINFO_TYPE (base_binfo)))
-       {
-         my_friendly_assert (binfo == TYPE_BINFO (t), 20030204);
-         
-         new_binfo = base_binfo;
-         TREE_CHAIN (prev) = new_binfo;
-         prev = new_binfo;
-         BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
-         BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
-       }
-      else if (TREE_VIA_VIRTUAL (base_binfo))
-       {
-         new_binfo = purpose_member (BINFO_TYPE (base_binfo),
-                                     CLASSTYPE_VBASECLASSES (t));
-         if (new_binfo)
-           new_binfo = TREE_VALUE (new_binfo);
-       }
-      
-      if (!new_binfo)
+  new_binfo = make_tree_binfo (binfo ? BINFO_N_BASE_BINFOS (binfo) : 0);
+  BINFO_TYPE (new_binfo) = type;
+
+  /* Chain it into the inheritance graph.  */
+  TREE_CHAIN (*igo_prev) = new_binfo;
+  *igo_prev = new_binfo;
+
+  if (binfo)
+    {
+      int ix;
+      tree base_binfo;
+
+      my_friendly_assert (!BINFO_DEPENDENT_BASE_P (binfo), 20040712);
+      my_friendly_assert (type == BINFO_TYPE (binfo), 20040714);
+
+      BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo);
+      BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (binfo);
+
+      /* We do not need to copy the accesses, as they are read only.  */
+      BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (binfo);
+
+      /* Recursively copy base binfos of BINFO.  */
+      for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
        {
-         new_binfo = make_binfo (BINFO_OFFSET (base_binfo),
-                                 base_binfo, NULL_TREE,
-                                 BINFO_VIRTUALS (base_binfo));
-         prev = copy_base_binfos (new_binfo, t, prev);
-         if (TREE_VIA_VIRTUAL (base_binfo))
-           {
-             CLASSTYPE_VBASECLASSES (t)
-               = tree_cons (BINFO_TYPE (new_binfo), new_binfo,
-                            CLASSTYPE_VBASECLASSES (t));
-             TREE_VIA_VIRTUAL (new_binfo) = 1;
-             BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
-           }
-         else
-           BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+         tree new_base_binfo;
+
+         my_friendly_assert (!BINFO_DEPENDENT_BASE_P (base_binfo), 20040713);
+         new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo),
+                                      t, igo_prev,
+                                      BINFO_VIRTUAL_P (base_binfo));
+
+         if (!BINFO_INHERITANCE_CHAIN (new_base_binfo))
+           BINFO_INHERITANCE_CHAIN (new_base_binfo) = new_binfo;
+         BINFO_BASE_APPEND (new_binfo, new_base_binfo);
        }
-      TREE_VEC_ELT (binfos, ix) = new_binfo;
     }
+  else
+    BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
 
-  return prev;
-}
+  if (virt)
+    {
+      /* Push it onto the list after any virtual bases it contains
+        will have been pushed.  */
+      VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo);
+      BINFO_VIRTUAL_P (new_binfo) = 1;
+      BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
+    }
 
+  return new_binfo;
+}
 \f
 /* Hashing of lists so that we don't make duplicates.
    The entry point is `list_hash_canon'.  */
@@ -815,7 +656,7 @@ copy_base_binfos (binfo, t, prev)
 
 static GTY ((param_is (union tree_node))) htab_t list_hash_table;
 
-struct list_proxy 
+struct list_proxy
 {
   tree purpose;
   tree value;
@@ -826,9 +667,7 @@ struct list_proxy
    for a node we are thinking about adding).  */
 
 static int
-list_hash_eq (entry, data)
-     const void *entry;
-     const void *data;
+list_hash_eq (const void* entry, const void* data)
 {
   tree t = (tree) entry;
   struct list_proxy *proxy = (struct list_proxy *) data;
@@ -843,22 +682,19 @@ list_hash_eq (entry, data)
    TREE_COMMON slots), by adding the hash codes of the individual entries.  */
 
 static hashval_t
-list_hash_pieces (purpose, value, chain)
-     tree purpose;
-     tree value;
-     tree chain;
+list_hash_pieces (tree purpose, tree value, tree chain)
 {
   hashval_t hashcode = 0;
-  
+
   if (chain)
-    hashcode += TYPE_HASH (chain);
-  
+    hashcode += TREE_HASH (chain);
+
   if (value)
-    hashcode += TYPE_HASH (value);
+    hashcode += TREE_HASH (value);
   else
     hashcode += 1007;
   if (purpose)
-    hashcode += TYPE_HASH (purpose);
+    hashcode += TREE_HASH (purpose);
   else
     hashcode += 1009;
   return hashcode;
@@ -867,12 +703,11 @@ list_hash_pieces (purpose, value, chain)
 /* Hash an already existing TREE_LIST.  */
 
 static hashval_t
-list_hash (p)
-     const void *p;
+list_hash (const void* p)
 {
   tree t = (tree) p;
-  return list_hash_pieces (TREE_PURPOSE (t), 
-                          TREE_VALUE (t), 
+  return list_hash_pieces (TREE_PURPOSE (t),
+                          TREE_VALUE (t),
                           TREE_CHAIN (t));
 }
 
@@ -881,11 +716,10 @@ list_hash (p)
    new one, and record it as the canonical object.  */
 
 tree
-hash_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
+hash_tree_cons (tree purpose, tree value, tree chain)
 {
   int hashcode = 0;
-  PTR* slot;
+  void **slot;
   struct list_proxy proxy;
 
   /* Hash the list node.  */
@@ -900,15 +734,14 @@ hash_tree_cons (purpose, value, chain)
                                   INSERT);
   /* If not, create a new node.  */
   if (!*slot)
-    *slot = (PTR) tree_cons (purpose, value, chain);
+    *slot = tree_cons (purpose, value, chain);
   return *slot;
 }
 
 /* Constructor for hashed lists.  */
 
 tree
-hash_tree_chain (value, chain)
-     tree value, chain;
+hash_tree_chain (tree value, tree chain)
 {
   return hash_tree_cons (NULL_TREE, value, chain);
 }
@@ -916,8 +749,7 @@ hash_tree_chain (value, chain)
 /* Similar, but used for concatenating two lists.  */
 
 tree
-hash_chainon (list1, list2)
-     tree list1, list2;
+hash_chainon (tree list1, tree list2)
 {
   if (list2 == 0)
     return list1;
@@ -929,68 +761,16 @@ hash_chainon (list1, list2)
                          hash_chainon (TREE_CHAIN (list1), list2));
 }
 \f
-/* Build an association between TYPE and some parameters:
-
-   OFFSET is the offset added to `this' to convert it to a pointer
-   of type `TYPE *'
-
-   BINFO is the base binfo to use, if we are deriving from one.  This
-   is necessary, as we want specialized parent binfos from base
-   classes, so that the VTABLE_NAMEs of bases are for the most derived
-   type, instead of the simple type.
-
-   VTABLE is the virtual function table with which to initialize
-   sub-objects of type TYPE.
-
-   VIRTUALS are the virtual functions sitting in VTABLE.  */
-
-tree
-make_binfo (offset, binfo, vtable, virtuals)
-     tree offset, binfo;
-     tree vtable, virtuals;
-{
-  tree new_binfo = make_tree_vec (BINFO_LANG_ELTS);
-  tree type;
-
-  if (TREE_CODE (binfo) == TREE_VEC)
-    {
-      type = BINFO_TYPE (binfo);
-      BINFO_DEPENDENT_BASE_P (new_binfo) = BINFO_DEPENDENT_BASE_P (binfo);
-    }
-  else
-    {
-      type = binfo;
-      binfo = NULL_TREE;
-      BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
-    }
-
-  TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
-  BINFO_OFFSET (new_binfo) = offset;
-  BINFO_VTABLE (new_binfo) = vtable;
-  BINFO_VIRTUALS (new_binfo) = virtuals;
-
-  if (binfo && !BINFO_DEPENDENT_BASE_P (binfo)
-      && BINFO_BASETYPES (binfo) != NULL_TREE)
-    {
-      BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));
-      /* We do not need to copy the accesses, as they are read only.  */
-      BINFO_BASEACCESSES (new_binfo) = BINFO_BASEACCESSES (binfo);
-    }
-  return new_binfo;
-}
-
 void
-debug_binfo (elem)
-     tree elem;
+debug_binfo (tree elem)
 {
   HOST_WIDE_INT n;
   tree virtuals;
 
-  fprintf (stderr, "type \"%s\", offset = ",
-          TYPE_NAME_STRING (BINFO_TYPE (elem)));
-  fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
+  fprintf (stderr, "type \"%s\", offset = " HOST_WIDE_INT_PRINT_DEC
+          "\nvtable type:\n",
+          TYPE_NAME_STRING (BINFO_TYPE (elem)),
           TREE_INT_CST_LOW (BINFO_OFFSET (elem)));
-  fprintf (stderr, "\nvtable type:\n");
   debug_tree (BINFO_TYPE (elem));
   if (BINFO_VTABLE (elem))
     fprintf (stderr, "vtable decl \"%s\"\n",
@@ -1013,8 +793,7 @@ debug_binfo (elem)
 }
 
 int
-count_functions (t)
-     tree t;
+count_functions (tree t)
 {
   int i;
   if (TREE_CODE (t) == FUNCTION_DECL)
@@ -1031,8 +810,7 @@ count_functions (t)
 }
 
 int
-is_overloaded_fn (x)
-     tree x;
+is_overloaded_fn (tree x)
 {
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (x) == OFFSET_REF)
@@ -1046,23 +824,21 @@ is_overloaded_fn (x)
 }
 
 int
-really_overloaded_fn (x)
-     tree x;
-{     
+really_overloaded_fn (tree x)
+{
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (x) == OFFSET_REF)
     x = TREE_OPERAND (x, 1);
   if (BASELINK_P (x))
     x = BASELINK_FUNCTIONS (x);
-  
+
   return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x))
          || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
          || TREE_CODE (x) == TEMPLATE_ID_EXPR);
 }
 
 tree
-get_first_fn (from)
-     tree from;
+get_first_fn (tree from)
 {
   my_friendly_assert (is_overloaded_fn (from), 9);
   /* A baselink is also considered an overloaded function.  */
@@ -1075,8 +851,7 @@ get_first_fn (from)
    member function.  */
 
 int
-bound_pmf_p (t)
-     tree t;
+bound_pmf_p (tree t)
 {
   return (TREE_CODE (t) == OFFSET_REF
          && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
@@ -1085,15 +860,13 @@ bound_pmf_p (t)
 /* Return a new OVL node, concatenating it with the old one.  */
 
 tree
-ovl_cons (decl, chain)
-     tree decl;
-     tree chain;
+ovl_cons (tree decl, tree chain)
 {
   tree result = make_node (OVERLOAD);
   TREE_TYPE (result) = unknown_type_node;
   OVL_FUNCTION (result) = decl;
   TREE_CHAIN (result) = chain;
-  
+
   return result;
 }
 
@@ -1101,9 +874,7 @@ ovl_cons (decl, chain)
    just return it; otherwise, ovl_cons the _DECLs */
 
 tree
-build_overload (decl, chain)
-     tree decl;
-     tree chain;
+build_overload (tree decl, tree chain)
 {
   if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
     return decl;
@@ -1112,42 +883,11 @@ build_overload (decl, chain)
   return ovl_cons (decl, chain);
 }
 
-int
-is_aggr_type_2 (t1, t2)
-     tree t1, t2;
-{
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return 0;
-  return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
-}
-
-/* Returns nonzero if CODE is the code for a statement.  */
-
-int
-cp_statement_code_p (code)
-     enum tree_code code;
-{
-  switch (code)
-    {
-    case CTOR_INITIALIZER:
-    case TRY_BLOCK:
-    case HANDLER:
-    case EH_SPEC_BLOCK:
-    case USING_STMT:
-    case TAG_DEFN:
-      return 1;
-
-    default:
-      return 0;
-    }
-}
 \f
 #define PRINT_RING_SIZE 4
 
 const char *
-cxx_printable_name (decl, v)
-     tree decl;
-     int v;
+cxx_printable_name (tree decl, int v)
 {
   static tree decl_ring[PRINT_RING_SIZE];
   static char *print_ring[PRINT_RING_SIZE];
@@ -1191,15 +931,13 @@ cxx_printable_name (decl, v)
    listed in RAISES.  */
 
 tree
-build_exception_variant (type, raises)
-     tree type;
-     tree raises;
+build_exception_variant (tree type, tree raises)
 {
   tree v = TYPE_MAIN_VARIANT (type);
   int type_quals = TYPE_QUALS (type);
 
   for (; v; v = TYPE_NEXT_VARIANT (v))
-    if (TYPE_QUALS (v) == type_quals
+    if (check_qualified_type (v, type, type_quals)
         && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
       return v;
 
@@ -1214,9 +952,7 @@ build_exception_variant (type, raises)
    arguments.  */
 
 tree
-bind_template_template_parm (t, newargs)
-     tree t;
-     tree newargs;
+bind_template_template_parm (tree t, tree newargs)
 {
   tree decl = TYPE_NAME (t);
   tree t2;
@@ -1229,7 +965,7 @@ bind_template_template_parm (t, newargs)
   TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
   TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
-    = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), 
+    = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
                 newargs, NULL_TREE);
 
   TREE_TYPE (decl) = t2;
@@ -1243,12 +979,13 @@ bind_template_template_parm (t, newargs)
 /* Called from count_trees via walk_tree.  */
 
 static tree
-count_trees_r (tp, walk_subtrees, data)
-     tree *tp ATTRIBUTE_UNUSED;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+count_trees_r (tree *tp, int *walk_subtrees, void *data)
 {
-  ++ *((int*) data);
+  ++*((int *) data);
+
+  if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+
   return NULL_TREE;
 }
 
@@ -1256,34 +993,32 @@ count_trees_r (tp, walk_subtrees, data)
    representation.  */
 
 int
-count_trees (t)
-     tree t;
+count_trees (tree t)
 {
   int n_trees = 0;
   walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
   return n_trees;
-}  
+}
 
 /* Called from verify_stmt_tree via walk_tree.  */
 
 static tree
-verify_stmt_tree_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+verify_stmt_tree_r (tree* tp,
+                    int* walk_subtrees ATTRIBUTE_UNUSED ,
+                    void* data)
 {
   tree t = *tp;
   htab_t *statements = (htab_t *) data;
   void **slot;
 
-  if (!statement_code_p (TREE_CODE (t)))
+  if (!STATEMENT_CODE_P (TREE_CODE (t)))
     return NULL_TREE;
 
   /* If this statement is already present in the hash table, then
      there is a circularity in the statement tree.  */
   if (htab_find (*statements, t))
     abort ();
-  
+
   slot = htab_find_slot (*statements, t, INSERT);
   *slot = t;
 
@@ -1295,8 +1030,7 @@ verify_stmt_tree_r (tp, walk_subtrees, data)
    circularities.  */
 
 void
-verify_stmt_tree (t)
-     tree t;
+verify_stmt_tree (tree t)
 {
   htab_t statements;
   statements = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
@@ -1307,10 +1041,9 @@ verify_stmt_tree (t)
 /* Called from find_tree via walk_tree.  */
 
 static tree
-find_tree_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+find_tree_r (tree* tp,
+             int* walk_subtrees ATTRIBUTE_UNUSED ,
+             void* data)
 {
   if (*tp == (tree) data)
     return (tree) data;
@@ -1321,47 +1054,80 @@ find_tree_r (tp, walk_subtrees, data)
 /* Returns X if X appears in the tree structure rooted at T.  */
 
 tree
-find_tree (t, x)
-     tree t;
-     tree x;
+find_tree (tree t, tree x)
 {
   return walk_tree_without_duplicates (&t, find_tree_r, x);
 }
 
-/* Passed to walk_tree.  Checks for the use of types with no linkage.  */
-
-static tree
-no_linkage_helper (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
-{
-  tree t = *tp;
-
-  if (TYPE_P (t)
-      && (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
-      && (decl_function_context (TYPE_MAIN_DECL (t))
-         || TYPE_ANONYMOUS_P (t)))
-    return t;
-  return NULL_TREE;
-}
-
 /* Check if the type T depends on a type with no linkage and if so, return
-   it.  */
+   it.  If RELAXED_P then do not consider a class type declared within
+   a TREE_PUBLIC function to have no linkage.  */
 
 tree
-no_linkage_check (t)
-     tree t;
+no_linkage_check (tree t, bool relaxed_p)
 {
+  tree r;
+
   /* There's no point in checking linkage on template functions; we
      can't know their complete types.  */
   if (processing_template_decl)
     return NULL_TREE;
 
-  t = walk_tree_without_duplicates (&t, no_linkage_helper, NULL);
-  if (t != error_mark_node)
-    return t;
-  return NULL_TREE;
+  switch (TREE_CODE (t))
+    {
+      tree fn;
+
+    case RECORD_TYPE:
+      if (TYPE_PTRMEMFUNC_P (t))
+       goto ptrmem;
+      /* Fall through.  */
+    case UNION_TYPE:
+      if (!CLASS_TYPE_P (t))
+       return NULL_TREE;
+      /* Fall through.  */
+    case ENUMERAL_TYPE:
+      if (TYPE_ANONYMOUS_P (t))
+       return t;
+      fn = decl_function_context (TYPE_MAIN_DECL (t));
+      if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
+       return t;
+      return NULL_TREE;
+
+    case ARRAY_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      return no_linkage_check (TREE_TYPE (t), relaxed_p);
+
+    case OFFSET_TYPE:
+    ptrmem:
+      r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t),
+                           relaxed_p);
+      if (r)
+       return r;
+      return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
+
+    case METHOD_TYPE:
+      r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
+      if (r)
+       return r;
+      /* Fall through.  */
+    case FUNCTION_TYPE:
+      {
+       tree parm;
+       for (parm = TYPE_ARG_TYPES (t);
+            parm && parm != void_list_node;
+            parm = TREE_CHAIN (parm))
+         {
+           r = no_linkage_check (TREE_VALUE (parm), relaxed_p);
+           if (r)
+             return r;
+         }
+       return no_linkage_check (TREE_TYPE (t), relaxed_p);
+      }
+
+    default:
+      return NULL_TREE;
+    }
 }
 
 #ifdef GATHER_STATISTICS
@@ -1369,7 +1135,7 @@ extern int depth_reached;
 #endif
 
 void
-cxx_print_statistics ()
+cxx_print_statistics (void)
 {
   print_search_statistics ();
   print_class_statistics ();
@@ -1384,12 +1150,11 @@ cxx_print_statistics ()
    array.  */
 
 tree
-array_type_nelts_top (type)
-     tree type;
+array_type_nelts_top (tree type)
 {
-  return fold (build (PLUS_EXPR, sizetype,
-                     array_type_nelts (type),
-                     integer_one_node));
+  return fold (build2 (PLUS_EXPR, sizetype,
+                      array_type_nelts (type),
+                      integer_one_node));
 }
 
 /* Return, as an INTEGER_CST node, the number of elements for TYPE
@@ -1397,15 +1162,14 @@ array_type_nelts_top (type)
    ARRAY_TYPEs that are clumped together.  */
 
 tree
-array_type_nelts_total (type)
-     tree type;
+array_type_nelts_total (tree type)
 {
   tree sz = array_type_nelts_top (type);
   type = TREE_TYPE (type);
   while (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree n = array_type_nelts_top (type);
-      sz = fold (build (MULT_EXPR, sizetype, sz, n));
+      sz = fold (build2 (MULT_EXPR, sizetype, sz, n));
       type = TREE_TYPE (type);
     }
   return sz;
@@ -1414,15 +1178,12 @@ array_type_nelts_total (type)
 /* Called from break_out_target_exprs via mapcar.  */
 
 static tree
-bot_manip (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees;
-     void *data;
+bot_manip (tree* tp, int* walk_subtrees, void* data)
 {
   splay_tree target_remap = ((splay_tree) data);
   tree t = *tp;
 
-  if (TREE_CONSTANT (t))
+  if (!TYPE_P (t) && TREE_CONSTANT (t))
     {
       /* There can't be any TARGET_EXPRs or their slot variables below
          this point.  We used to check !TREE_SIDE_EFFECTS, but then we
@@ -1440,15 +1201,15 @@ bot_manip (tp, walk_subtrees, data)
          u = build_cplus_new
            (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
        }
-      else 
+      else
        {
          u = build_target_expr_with_type
            (break_out_target_exprs (TREE_OPERAND (t, 1)), TREE_TYPE (t));
        }
 
       /* Map the old variable to the new one.  */
-      splay_tree_insert (target_remap, 
-                        (splay_tree_key) TREE_OPERAND (t, 0), 
+      splay_tree_insert (target_remap,
+                        (splay_tree_key) TREE_OPERAND (t, 0),
                         (splay_tree_value) TREE_OPERAND (u, 0));
 
       /* Replace the old expression with the new version.  */
@@ -1465,16 +1226,15 @@ bot_manip (tp, walk_subtrees, data)
   /* 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.
    DATA is really a splay-tree mapping old variables to new
    variables.  */
 
 static tree
-bot_replace (t, walk_subtrees, data)
-     tree *t;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
+bot_replace (tree* t,
+             int* walk_subtrees ATTRIBUTE_UNUSED ,
+             void* data)
 {
   splay_tree target_remap = ((splay_tree) data);
 
@@ -1488,22 +1248,21 @@ bot_replace (t, walk_subtrees, data)
 
   return NULL_TREE;
 }
-       
+
 /* 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;
+break_out_target_exprs (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, 
+    target_remap = splay_tree_new (splay_tree_compare_pointers,
+                                  /*splay_tree_delete_key_fn=*/NULL,
                                   /*splay_tree_delete_value_fn=*/NULL);
   walk_tree (&t, bot_manip, target_remap, NULL);
   walk_tree (&t, bot_replace, target_remap, NULL);
@@ -1517,25 +1276,21 @@ break_out_target_exprs (t)
   return t;
 }
 
-/* Obstack used for allocating nodes in template function and variable
-   definitions.  */
-
-/* Similar to `build_nt', except that we set TREE_COMPLEXITY to be the
-   current line number.  */
+/* Similar to `build_nt', but for template definitions of dependent
+   expressions  */
 
 tree
-build_min_nt VPARAMS ((enum tree_code code, ...))
+build_min_nt (enum tree_code code, ...)
 {
-  register tree t;
-  register int length;
-  register int i;
+  tree t;
+  int length;
+  int i;
+  va_list p;
 
-  VA_OPEN (p, code);
-  VA_FIXEDARG (p, enum tree_code, code);
+  va_start (p, code);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
-  TREE_COMPLEXITY (t) = lineno;
 
   for (i = 0; i < length; i++)
     {
@@ -1543,62 +1298,74 @@ build_min_nt VPARAMS ((enum tree_code code, ...))
       TREE_OPERAND (t, i) = x;
     }
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 
-/* Similar to `build', except we set TREE_COMPLEXITY to the current
-   line-number.  */
+/* Similar to `build', but for template definitions.  */
 
 tree
-build_min VPARAMS ((enum tree_code code, tree tt, ...))
+build_min (enum tree_code code, tree tt, ...)
 {
-  register tree t;
-  register int length;
-  register int i;
+  tree t;
+  int length;
+  int i;
+  va_list p;
 
-  VA_OPEN (p, tt);
-  VA_FIXEDARG (p, enum tree_code, code);
-  VA_FIXEDARG (p, tree, tt);
+  va_start (p, tt);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = tt;
-  TREE_COMPLEXITY (t) = lineno;
 
   for (i = 0; i < length; i++)
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
+      if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
+       TREE_SIDE_EFFECTS (t) = 1;
     }
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 
-/* Returns an INTEGER_CST (of type `int') corresponding to I.
-   Multiple calls with the same value of I may or may not yield the
-   same node; therefore, callers should never modify the node
-   returned.  */
-
-static GTY(()) tree shared_int_cache[256];
+/* Similar to `build', but for template definitions of non-dependent
+   expressions. NON_DEP is the non-dependent expression that has been
+   built.  */
 
 tree
-build_shared_int_cst (i)
-     int i;
+build_min_non_dep (enum tree_code code, tree non_dep, ...)
 {
-  if (i >= 256)
-    return build_int_2 (i, 0);
-  
-  if (!shared_int_cache[i])
-    shared_int_cache[i] = build_int_2 (i, 0);
-  
-  return shared_int_cache[i];
+  tree t;
+  int length;
+  int i;
+  va_list p;
+
+  va_start (p, non_dep);
+
+  t = make_node (code);
+  length = TREE_CODE_LENGTH (code);
+  TREE_TYPE (t) = TREE_TYPE (non_dep);
+  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
+
+  for (i = 0; i < length; i++)
+    {
+      tree x = va_arg (p, tree);
+      TREE_OPERAND (t, i) = x;
+    }
+
+  if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
+    /* This should not be considered a COMPOUND_EXPR, because it
+       resolves to an overload.  */
+    COMPOUND_EXPR_OVERLOADED (t) = 1;
+
+  va_end (p);
+  return t;
 }
 
 tree
-get_type_decl (t)
-     tree t;
+get_type_decl (tree t)
 {
   if (TREE_CODE (t) == TYPE_DECL)
     return t;
@@ -1606,36 +1373,18 @@ get_type_decl (t)
     return TYPE_STUB_DECL (t);
   if (t == error_mark_node)
     return t;
-  
+
   abort ();
 
   /* Stop compiler from complaining control reaches end of non-void function.  */
   return 0;
 }
 
-/* Return first vector element whose BINFO_TYPE is ELEM.
-   Return 0 if ELEM is not in VEC.  VEC may be NULL_TREE.  */
-
-tree
-vec_binfo_member (elem, vec)
-     tree elem, vec;
-{
-  int i;
-
-  if (vec)
-    for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
-      if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
-       return TREE_VEC_ELT (vec, i);
-
-  return NULL_TREE;
-}
-
 /* Returns the namespace that contains DECL, whether directly or
    indirectly.  */
 
 tree
-decl_namespace_context (decl)
-     tree decl;
+decl_namespace_context (tree decl)
 {
   while (1)
     {
@@ -1649,39 +1398,35 @@ decl_namespace_context (decl)
 }
 
 /* Return truthvalue of whether T1 is the same tree structure as T2.
-   Return 1 if they are the same.
-   Return 0 if they are understandably different.
-   Return -1 if either contains tree structure not understood by
-   this function.  */
+   Return 1 if they are the same. Return 0 if they are different.  */
 
-int
-cp_tree_equal (t1, t2)
-     tree t1, t2;
+bool
+cp_tree_equal (tree t1, tree t2)
 {
-  register enum tree_code code1, code2;
-  int cmp;
+  enum tree_code code1, code2;
 
   if (t1 == t2)
-    return 1;
-  if (t1 == 0 || t2 == 0)
-    return 0;
-
-  code1 = TREE_CODE (t1);
-  code2 = TREE_CODE (t2);
-
-  if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
-    {
-      if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
-       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      else
-       return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
-    }
-  else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
-          || code2 == NON_LVALUE_EXPR)
-    return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+    return true;
+  if (!t1 || !t2)
+    return false;
+
+  for (code1 = TREE_CODE (t1);
+       code1 == NOP_EXPR || code1 == CONVERT_EXPR
+        || code1 == NON_LVALUE_EXPR;
+       code1 = TREE_CODE (t1))
+    t1 = TREE_OPERAND (t1, 0);
+  for (code2 = TREE_CODE (t2);
+       code2 == NOP_EXPR || code2 == CONVERT_EXPR
+        || code1 == NON_LVALUE_EXPR;
+       code2 = TREE_CODE (t2))
+    t2 = TREE_OPERAND (t2, 0);
+
+  /* They might have become equal now.  */
+  if (t1 == t2)
+    return true;
 
   if (code1 != code2)
-    return 0;
+    return false;
 
   switch (code1)
     {
@@ -1695,7 +1440,7 @@ cp_tree_equal (t1, t2)
     case STRING_CST:
       return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
        && !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
-                 TREE_STRING_LENGTH (t1));
+                   TREE_STRING_LENGTH (t1));
 
     case CONSTRUCTOR:
       /* We need to do this when determining whether or not two
@@ -1704,61 +1449,62 @@ cp_tree_equal (t1, t2)
       if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
            /* The first operand is RTL.  */
            && TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
-       return 0;
+       return false;
       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
 
     case TREE_LIST:
-      cmp = cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
-      if (cmp <= 0)
-       return cmp;
-      cmp = cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2));
-      if (cmp <= 0)
-       return cmp;
+      if (!cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+       return false;
+      if (!cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+       return false;
       return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
 
     case SAVE_EXPR:
       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     case CALL_EXPR:
-      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
-      return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+       return false;
+      return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
 
     case TARGET_EXPR:
-      /* Special case: if either target is an unallocated VAR_DECL,
-        it means that it's going to be unified with whatever the
-        TARGET_EXPR is really supposed to initialize, so treat it
-        as being equivalent to anything.  */
-      if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
-          && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
-          && !DECL_RTL_SET_P (TREE_OPERAND (t1, 0)))
-         || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
-             && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
-             && !DECL_RTL_SET_P (TREE_OPERAND (t2, 0))))
-       cmp = 1;
-      else
-       cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
-      return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      {
+       tree o1 = TREE_OPERAND (t1, 0);
+       tree o2 = TREE_OPERAND (t2, 0);
+
+       /* Special case: if either target is an unallocated VAR_DECL,
+          it means that it's going to be unified with whatever the
+          TARGET_EXPR is really supposed to initialize, so treat it
+          as being equivalent to anything.  */
+       if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE
+           && !DECL_RTL_SET_P (o1))
+         /*Nop*/;
+       else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
+                && !DECL_RTL_SET_P (o2))
+         /*Nop*/;
+       else if (!cp_tree_equal (o1, o2))
+         return false;
+
+       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+      }
 
     case WITH_CLEANUP_EXPR:
-      cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      if (cmp <= 0)
-       return cmp;
+      if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+       return false;
       return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
 
     case COMPONENT_REF:
-      if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
-       return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      return 0;
+      if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
+       return false;
+      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     case VAR_DECL:
     case PARM_DECL:
     case CONST_DECL:
     case FUNCTION_DECL:
-      return 0;
+    case TEMPLATE_DECL:
+    case IDENTIFIER_NODE:
+      return false;
 
     case TEMPLATE_PARM_INDEX:
       return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
@@ -1766,19 +1512,51 @@ cp_tree_equal (t1, t2)
              && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
                              TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
 
+    case TEMPLATE_ID_EXPR:
+      {
+       unsigned ix;
+       tree vec1, vec2;
+
+       if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+         return false;
+       vec1 = TREE_OPERAND (t1, 1);
+       vec2 = TREE_OPERAND (t2, 1);
+
+       if (!vec1 || !vec2)
+         return !vec1 && !vec2;
+
+       if (TREE_VEC_LENGTH (vec1) != TREE_VEC_LENGTH (vec2))
+         return false;
+
+       for (ix = TREE_VEC_LENGTH (vec1); ix--;)
+         if (!cp_tree_equal (TREE_VEC_ELT (vec1, ix),
+                             TREE_VEC_ELT (vec2, ix)))
+           return false;
+
+       return true;
+      }
+
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
-      if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
-       return 0;
-      if (TYPE_P (TREE_OPERAND (t1, 0)))
-       return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
-      break;
+      {
+       tree o1 = TREE_OPERAND (t1, 0);
+       tree o2 = TREE_OPERAND (t2, 0);
+
+       if (TREE_CODE (o1) != TREE_CODE (o2))
+         return false;
+       if (TYPE_P (o1))
+         return same_type_p (o1, o2);
+       else
+         return cp_tree_equal (o1, o2);
+      }
 
     case PTRMEM_CST:
       /* Two pointer-to-members are the same if they point to the same
         field or function in the same class.  */
-      return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
-             && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
+      if (PTRMEM_CST_MEMBER (t1) != PTRMEM_CST_MEMBER (t2))
+       return false;
+
+      return same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2));
 
     default:
       break;
@@ -1794,65 +1572,28 @@ cp_tree_equal (t1, t2)
     case 's':
       {
        int i;
-       
-       cmp = 1;
-       for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
-         {
-           cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
-           if (cmp <= 0)
-             return cmp;
-         }
-       return cmp;
-      }
-    
-      case 't':
-       return same_type_p (t1, t2) ? 1 : 0;
-    }
 
-  return -1;
-}
-
-/* Build a wrapper around a 'struct z_candidate' so we can use it as a
-   tree.  */
-
-tree
-build_zc_wrapper (ptr)
-     struct z_candidate *ptr;
-{
-  tree t = make_node (WRAPPER);
-  WRAPPER_ZC (t) = ptr;
-  return t;
-}
-
-static tree
-build_srcloc (file, line)
-     const char *file;
-     int line;
-{
-  tree t;
+       for (i = 0; i < TREE_CODE_LENGTH (code1); ++i)
+         if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
+           return false;
 
-  t = make_node (SRCLOC);
-  SRCLOC_FILE (t) = file;
-  SRCLOC_LINE (t) = line;
+       return true;
+      }
 
-  return t;
-}
+    case 't':
+      return same_type_p (t1, t2);
+    }
 
-tree
-build_srcloc_here ()
-{
-  return build_srcloc (input_filename, lineno);
+  my_friendly_assert (0, 20030617);
+  return false;
 }
 
 /* The type of ARG when used as an lvalue.  */
 
 tree
-lvalue_type (arg)
-     tree arg;
+lvalue_type (tree arg)
 {
   tree type = TREE_TYPE (arg);
-  if (TREE_CODE (arg) == OVERLOAD)
-    type = unknown_type_node;
   return type;
 }
 
@@ -1860,12 +1601,14 @@ lvalue_type (arg)
    reference types.  */
 
 tree
-error_type (arg)
-     tree arg;
+error_type (tree arg)
 {
   tree type = TREE_TYPE (arg);
+
   if (TREE_CODE (type) == ARRAY_TYPE)
     ;
+  else if (TREE_CODE (type) == ERROR_MARK)
+    ;
   else if (real_lvalue_p (arg))
     type = build_reference_type (lvalue_type (arg));
   else if (IS_AGGR_TYPE (type))
@@ -1877,8 +1620,7 @@ error_type (arg)
 /* Does FUNCTION use a variable-length argument list?  */
 
 int
-varargs_function_p (function)
-     tree function;
+varargs_function_p (tree function)
 {
   tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
   for (; parm; parm = TREE_CHAIN (parm))
@@ -1890,8 +1632,7 @@ varargs_function_p (function)
 /* Returns 1 if decl is a member of a class.  */
 
 int
-member_p (decl)
-     tree decl;
+member_p (tree decl)
 {
   const tree ctx = DECL_CONTEXT (decl);
   return (ctx && TYPE_P (ctx));
@@ -1901,8 +1642,7 @@ member_p (decl)
    object that the access is against.  */
 
 tree
-build_dummy_object (type)
-     tree type;
+build_dummy_object (tree type)
 {
   tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
   return build_indirect_ref (decl, NULL);
@@ -1913,13 +1653,11 @@ build_dummy_object (type)
    binfo path from current_class_type to TYPE, or 0.  */
 
 tree
-maybe_dummy_object (type, binfop)
-     tree type;
-     tree *binfop;
+maybe_dummy_object (tree type, tree* binfop)
 {
   tree decl, context;
   tree binfo;
-  
+
   if (current_class_type
       && (binfo = lookup_base (current_class_type, type,
                               ba_ignore | ba_quiet, NULL)))
@@ -1933,7 +1671,7 @@ maybe_dummy_object (type, binfop)
 
   if (binfop)
     *binfop = binfo;
-  
+
   if (current_class_ref && context == current_class_type
       /* Kludge: Make sure that current_class_type is actually
          correct.  It might not be if we're in the middle of
@@ -1950,8 +1688,7 @@ maybe_dummy_object (type, binfop)
 /* Returns 1 if OB is a placeholder object, or a pointer to one.  */
 
 int
-is_dummy_object (ob)
-     tree ob;
+is_dummy_object (tree ob)
 {
   if (TREE_CODE (ob) == INDIRECT_REF)
     ob = TREE_OPERAND (ob, 0);
@@ -1962,8 +1699,7 @@ is_dummy_object (ob)
 /* Returns 1 iff type T is a POD type, as defined in [basic.types].  */
 
 int
-pod_type_p (t)
-     tree t;
+pod_type_p (tree t)
 {
   t = strip_array_types (t);
 
@@ -1975,11 +1711,12 @@ pod_type_p (t)
     return 1;
   if (TYPE_PTR_P (t))
     return 1; /* pointer to non-member */
-  if (TYPE_PTRMEM_P (t))
-    return 1; /* pointer to member object */
-  if (TYPE_PTRMEMFUNC_P (t))
-    return 1; /* pointer to member function */
-  
+  if (TYPE_PTR_TO_MEMBER_P (t))
+    return 1; /* pointer to member */
+
+  if (TREE_CODE (t) == VECTOR_TYPE)
+    return 1; /* vectors are (small) arrays if scalars */
+
   if (! CLASS_TYPE_P (t))
     return 0; /* other non-class type (reference or function) */
   if (CLASSTYPE_NON_POD_P (t))
@@ -1991,8 +1728,7 @@ pod_type_p (t)
    zeros in it.  */
 
 int
-zero_init_p (t)
-     tree t;
+zero_init_p (tree t)
 {
   t = strip_array_types (t);
 
@@ -2024,19 +1760,18 @@ const struct attribute_spec cxx_attribute_table[] =
 /* Handle a "java_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags;
-     bool *no_add_attrs;
+handle_java_interface_attribute (tree* node,
+                                 tree name,
+                                 tree args ATTRIBUTE_UNUSED ,
+                                 int flags,
+                                 bool* no_add_attrs)
 {
   if (DECL_P (*node)
       || !CLASS_TYPE_P (*node)
       || !TYPE_FOR_JAVA (*node))
     {
-      error ("`%s' attribute can only be applied to Java class definitions",
-            IDENTIFIER_POINTER (name));
+      error ("`%E' attribute can only be applied to Java class definitions",
+            name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2050,12 +1785,11 @@ handle_java_interface_attribute (node, name, args, flags, no_add_attrs)
 /* Handle a "com_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+handle_com_interface_attribute (tree* node,
+                                tree name,
+                                tree args ATTRIBUTE_UNUSED ,
+                                int flags ATTRIBUTE_UNUSED ,
+                                bool* no_add_attrs)
 {
   static int warned;
 
@@ -2065,14 +1799,14 @@ handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
       || !CLASS_TYPE_P (*node)
       || *node != TYPE_MAIN_VARIANT (*node))
     {
-      warning ("`%s' attribute can only be applied to class definitions",
-              IDENTIFIER_POINTER (name));
+      warning ("`%E' attribute can only be applied to class definitions",
+              name);
       return NULL_TREE;
     }
 
   if (!warned++)
-    warning ("`%s' is obsolete; g++ vtables are now COM-compatible by default",
-            IDENTIFIER_POINTER (name));
+    warning ("`%E' is obsolete; g++ vtables are now COM-compatible by default",
+            name);
 
   return NULL_TREE;
 }
@@ -2080,12 +1814,11 @@ handle_com_interface_attribute (node, name, args, flags, no_add_attrs)
 /* Handle an "init_priority" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
-handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
+handle_init_priority_attribute (tree* node,
+                                tree name,
+                                tree args,
+                                int flags ATTRIBUTE_UNUSED ,
+                                bool* no_add_attrs)
 {
   tree initp_expr = TREE_VALUE (args);
   tree decl = *node;
@@ -2093,7 +1826,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
   int pri;
 
   STRIP_NOPS (initp_expr);
-         
+
   if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
     {
       error ("requested init_priority is not an integer constant");
@@ -2102,7 +1835,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
     }
 
   pri = TREE_INT_CST_LOW (initp_expr);
-       
+
   type = strip_array_types (type);
 
   if (decl == NULL_TREE
@@ -2115,10 +1848,10 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
         first time control passes through that
         function. This is not precise enough to pin down an
         init_priority value, so don't allow it.  */
-      || current_function_decl) 
+      || current_function_decl)
     {
-      error ("can only use `%s' attribute on file-scope definitions of objects of class type",
-            IDENTIFIER_POINTER (name));
+      error ("can only use `%E' attribute on file-scope definitions "
+             "of objects of class type", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2134,7 +1867,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
      language and runtime support implementations.*/
   if (pri <= MAX_RESERVED_INIT_PRIORITY)
     {
-      warning 
+      warning
        ("requested init_priority is reserved for internal use");
     }
 
@@ -2145,55 +1878,80 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
     }
   else
     {
-      error ("`%s' attribute is not supported on this platform",
-            IDENTIFIER_POINTER (name));
+      error ("`%E' attribute is not supported on this platform", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
 }
 
+/* Return a new TINST_LEVEL for DECL at location locus.  */
+tree
+make_tinst_level (tree decl, location_t locus)
+{
+  tree tinst_level = make_node (TINST_LEVEL);
+  TREE_CHAIN (tinst_level) = NULL_TREE;
+  TINST_DECL (tinst_level) = decl;
+  TINST_LOCATION (tinst_level) = locus;
+  return tinst_level;
+}
+
 /* Return a new PTRMEM_CST of the indicated TYPE.  The MEMBER is the
    thing pointed to by the constant.  */
 
 tree
-make_ptrmem_cst (type, member)
-     tree type;
-     tree member;
+make_ptrmem_cst (tree type, tree member)
 {
   tree ptrmem_cst = make_node (PTRMEM_CST);
-  /* If would seem a great convenience if make_node would set
-     TREE_CONSTANT for things of class `c', but it does not.  */
-  TREE_CONSTANT (ptrmem_cst) = 1;
   TREE_TYPE (ptrmem_cst) = type;
   PTRMEM_CST_MEMBER (ptrmem_cst) = member;
   return ptrmem_cst;
 }
 
+/* Build a variant of TYPE that has the indicated ATTRIBUTES.  May
+   return an existing type of an appropriate type already exists.  */
+
+tree
+cp_build_type_attribute_variant (tree type, tree attributes)
+{
+  tree new_type;
+
+  new_type = build_type_attribute_variant (type, attributes);
+  if (TREE_CODE (new_type) == FUNCTION_TYPE
+      && (TYPE_RAISES_EXCEPTIONS (new_type)
+         != TYPE_RAISES_EXCEPTIONS (type)))
+    new_type = build_exception_variant (new_type,
+                                       TYPE_RAISES_EXCEPTIONS (type));
+  return new_type;
+}
+
 /* Apply FUNC to all language-specific sub-trees of TP in a pre-order
-   traversal.  Called from walk_tree().  */
+   traversal.  Called from walk_tree.  */
 
-tree 
-cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
-     tree *tp;
-     int *walk_subtrees_p;
-     walk_tree_fn func;
-     void *data;
-     void *htab;
+tree
+cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
+                 void *data, void *htab)
 {
   enum tree_code code = TREE_CODE (*tp);
+  location_t save_locus;
   tree result;
-  
+
 #define WALK_SUBTREE(NODE)                             \
   do                                                   \
     {                                                  \
       result = walk_tree (&(NODE), func, data, htab);  \
-      if (result)                                      \
-       return result;                                  \
+      if (result) goto out;                            \
     }                                                  \
   while (0)
 
+  /* Set input_location here so we get the right instantiation context
+     if we call instantiate_decl from inlinable_function_p.  */
+  save_locus = input_location;
+  if (EXPR_HAS_LOCATION (*tp))
+    input_location = EXPR_LOCATION (*tp);
+
   /* Not one of the easy cases.  We must explicitly go through the
      children.  */
+  result = NULL_TREE;
   switch (code)
     {
     case DEFAULT_ARG:
@@ -2205,11 +1963,16 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
     case TYPENAME_TYPE:
     case TYPEOF_TYPE:
     case BASELINK:
-      /* None of thse have subtrees other than those already walked
+      /* None of these have subtrees other than those already walked
          above.  */
       *walk_subtrees_p = 0;
       break;
 
+    case TINST_LEVEL:
+      WALK_SUBTREE (TINST_DECL (*tp));
+      *walk_subtrees_p = 0;
+      break;
+
     case PTRMEM_CST:
       WALK_SUBTREE (TREE_TYPE (*tp));
       *walk_subtrees_p = 0;
@@ -2231,11 +1994,14 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
       break;
 
     default:
-      break;
+      input_location = save_locus;
+      return NULL_TREE;
     }
 
   /* We didn't find what we were looking for.  */
-  return NULL_TREE;
+ out:
+  input_location = save_locus;
+  return result;
 
 #undef WALK_SUBTREE
 }
@@ -2244,28 +2010,38 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
    function as a tree.  */
 
 int
-cp_cannot_inline_tree_fn (fnp)
-     tree *fnp;
+cp_cannot_inline_tree_fn (tree* fnp)
 {
   tree fn = *fnp;
 
-  if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
-    return 1;
-
   /* We can inline a template instantiation only if it's fully
      instantiated.  */
   if (DECL_TEMPLATE_INFO (fn)
       && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
     {
-      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
+      /* Don't instantiate functions that are not going to be
+        inlined.  */
+      if (!DECL_INLINE (DECL_TEMPLATE_RESULT
+                       (template_for_substitution (fn))))
+       return 1;
+
+      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
+
       if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
        return 1;
     }
 
+  if (flag_really_no_inline
+      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
+    return 1;
+
   /* Don't auto-inline anything that might not be bound within
-     this unit of translation.  */
-  if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
+     this unit of translation.
+     Exclude comdat functions from this rule.  While they can be bound
+     to the other unit, they all must be the same.  This is especially
+     important so templates can inline.  */
+  if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn)
+      && !DECL_COMDAT (fn))
     {
       DECL_UNINLINABLE (fn) = 1;
       return 1;
@@ -2291,9 +2067,7 @@ cp_cannot_inline_tree_fn (fnp)
    return the latest function added to the array, PREV_FN.  */
 
 tree
-cp_add_pending_fn_decls (fns_p, prev_fn)
-     void *fns_p;
-     tree prev_fn;
+cp_add_pending_fn_decls (void* fns_p, tree prev_fn)
 {
   varray_type *fnsp = (varray_type *)fns_p;
   struct saved_scope *s;
@@ -2313,8 +2087,7 @@ cp_add_pending_fn_decls (fns_p, prev_fn)
    function.  */
 
 int
-cp_is_overload_p (t)
-     tree t;
+cp_is_overload_p (tree t)
 {
   return TREE_CODE (t) == OVERLOAD;
 }
@@ -2323,228 +2096,40 @@ cp_is_overload_p (t)
    function FN.  */
 
 int
-cp_auto_var_in_fn_p (var, fn)
-     tree var, fn;
+cp_auto_var_in_fn_p (tree var, tree fn)
 {
   return (DECL_P (var) && DECL_CONTEXT (var) == fn
          && nonstatic_local_decl_p (var));
 }
 
-/* Tell whether a declaration is needed for the RESULT of a function
-   FN being inlined into CALLER or if the top node of target_exprs is
-   to be used.  */
+/* FN body has been duplicated.  Update language specific fields.  */
 
-tree
-cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
-                              need_decl, return_slot_addr)
-     tree result, fn, caller;
-     void *decl_map_;
-     int *need_decl;
-     tree return_slot_addr;
+void
+cp_update_decl_after_saving (tree fn,
+                             void* decl_map_)
 {
   splay_tree decl_map = (splay_tree)decl_map_;
-  tree var;
-
-  /* If FN returns an aggregate then the caller will always pass the
-     address of the return slot explicitly.  If we were just to
-     create a new VAR_DECL here, then the result of this function
-     would be copied (bitwise) into the variable initialized by the
-     TARGET_EXPR.  That's incorrect, so we must transform any
-     references to the RESULT into references to the target.  */
-
-  /* We should have an explicit return slot iff the return type is
-     TREE_ADDRESSABLE.  See simplify_aggr_init_expr.  */
-  if (TREE_ADDRESSABLE (TREE_TYPE (result))
-      != (return_slot_addr != NULL_TREE))
-    abort ();
-
-  *need_decl = !return_slot_addr;
-  if (return_slot_addr)
-    {
-      var = build_indirect_ref (return_slot_addr, "");
-      if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
-                                                      TREE_TYPE (result)))
-       abort ();
-    }
-  /* Otherwise, make an appropriate copy.  */
-  else
-    var = copy_decl_for_inlining (result, fn, caller);
-
-  if (DECL_SAVED_FUNCTION_DATA (fn))
+  tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
+  if (nrv)
     {
-      tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
-      if (nrv)
-       {
-         /* We have a named return value; copy the name and source
-            position so we can get reasonable debugging information, and
-            register the return variable as its equivalent.  */
-         if (TREE_CODE (var) == VAR_DECL)
-           {
-             DECL_NAME (var) = DECL_NAME (nrv);
-             DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
-             DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
-             /* Don't lose initialization info.  */
-             DECL_INITIAL (var) = DECL_INITIAL (nrv);
-             /* Don't forget that it needs to go in the stack.  */
-             TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
-           }
-
-         splay_tree_insert (decl_map,
-                            (splay_tree_key) nrv,
-                            (splay_tree_value) var);
-       }
+      DECL_SAVED_FUNCTION_DATA (fn)->x_return_value
+       = (tree) splay_tree_lookup (decl_map, (splay_tree_key) nrv)->value;
     }
-
-  return var;
-}
-
-/* Record that we're about to start inlining FN, and return nonzero if
-   that's OK.  Used for lang_hooks.tree_inlining.start_inlining.  */
-
-int
-cp_start_inlining (fn)
-     tree fn;
-{
-  if (DECL_TEMPLATE_INSTANTIATION (fn))
-    return push_tinst_level (fn);
-  else
-    return 1;
-}
-
-/* Record that we're done inlining FN.  Used for
-   lang_hooks.tree_inlining.end_inlining.  */
-
-void
-cp_end_inlining (fn)
-     tree fn ATTRIBUTE_UNUSED;
-{
-  if (DECL_TEMPLATE_INSTANTIATION (fn))
-    pop_tinst_level ();
 }
-
 /* Initialize tree.c.  */
 
 void
-init_tree ()
+init_tree (void)
 {
-  lang_statement_code_p = cp_statement_code_p;
   list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
 }
 
-/* Called via walk_tree.  If *TP points to a DECL_STMT for a local
-   declaration, copies the declaration and enters it in the splay_tree
-   pointed to by DATA (which is really a `splay_tree *').  */
-
-static tree
-mark_local_for_remap_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data;
-{
-  tree t = *tp;
-  splay_tree st = (splay_tree) data;
-  tree decl;
-
-  
-  if (TREE_CODE (t) == DECL_STMT
-      && nonstatic_local_decl_p (DECL_STMT_DECL (t)))
-    decl = DECL_STMT_DECL (t);
-  else if (TREE_CODE (t) == LABEL_STMT)
-    decl = LABEL_STMT_LABEL (t);
-  else if (TREE_CODE (t) == TARGET_EXPR
-          && nonstatic_local_decl_p (TREE_OPERAND (t, 0)))
-    decl = TREE_OPERAND (t, 0);
-  else if (TREE_CODE (t) == CASE_LABEL)
-    decl = CASE_LABEL_DECL (t);
-  else
-    decl = NULL_TREE;
-
-  if (decl)
-    {
-      tree copy;
-
-      /* Make a copy.  */
-      copy = copy_decl_for_inlining (decl, 
-                                    DECL_CONTEXT (decl), 
-                                    DECL_CONTEXT (decl));
-
-      /* Remember the copy.  */
-      splay_tree_insert (st,
-                        (splay_tree_key) decl, 
-                        (splay_tree_value) copy);
-    }
-
-  return NULL_TREE;
-}
-
-/* Called via walk_tree when an expression is unsaved.  Using the
-   splay_tree pointed to by ST (which is really a `splay_tree'),
-   remaps all local declarations to appropriate replacements.  */
-
-static tree
-cp_unsave_r (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees;
-     void *data;
-{
-  splay_tree st = (splay_tree) data;
-  splay_tree_node n;
-
-  /* Only a local declaration (variable or label).  */
-  if (nonstatic_local_decl_p (*tp))
-    {
-      /* Lookup the declaration.  */
-      n = splay_tree_lookup (st, (splay_tree_key) *tp);
-      
-      /* If it's there, remap it.  */
-      if (n)
-       *tp = (tree) n->value;
-    }
-  else if (TREE_CODE (*tp) == SAVE_EXPR)
-    remap_save_expr (tp, st, current_function_decl, walk_subtrees);
-  else
-    {
-      copy_tree_r (tp, walk_subtrees, NULL);
-
-      /* Do whatever unsaving is required.  */
-      unsave_expr_1 (*tp);
-    }
-
-  /* Keep iterating.  */
-  return NULL_TREE;
-}
-
-/* Called whenever an expression needs to be unsaved.  */
-
-tree
-cxx_unsave_expr_now (tp)
-     tree tp;
-{
-  splay_tree st;
-
-  /* Create a splay-tree to map old local variable declarations to new
-     ones.  */
-  st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
-
-  /* Walk the tree once figuring out what needs to be remapped.  */
-  walk_tree (&tp, mark_local_for_remap_r, st, NULL);
-
-  /* Walk the tree again, copying, remapping, and unsaving.  */
-  walk_tree (&tp, cp_unsave_r, st, NULL);
-
-  /* Clean up.  */
-  splay_tree_delete (st);
-
-  return tp;
-}
-
 /* Returns the kind of special function that DECL (a FUNCTION_DECL)
    is.  Note that sfk_none is zero, so this function can be used as a
    predicate to test whether or not DECL is a special function.  */
 
 special_function_kind
-special_function_p (decl)
-     tree decl;
+special_function_p (tree decl)
 {
   /* Rather than doing all this stuff with magic names, we should
      probably have a field of type `special_function_kind' in
@@ -2588,8 +2173,7 @@ name_p (tree node)
 /* Returns nonzero if TYPE is a character type, including wchar_t.  */
 
 int
-char_type_p (type)
-     tree type;
+char_type_p (tree type)
 {
   return (same_type_p (type, char_type_node)
          || same_type_p (type, unsigned_char_type_node)
@@ -2605,8 +2189,7 @@ char_type_p (type)
    as a global symbol when you run `nm' on the resulting object file.  */
 
 linkage_kind
-decl_linkage (decl)
-     tree decl;
+decl_linkage (tree decl)
 {
   /* This function doesn't attempt to calculate the linkage from first
      principles as given in [basic.link].  Instead, it makes use of
@@ -2645,15 +2228,13 @@ decl_linkage (decl)
    expression to use the precalculated result.  */
 
 tree
-stabilize_expr (exp, initp)
-     tree exp;
-     tree *initp;
+stabilize_expr (tree exp, tree* initp)
 {
   tree init_expr;
 
   if (!TREE_SIDE_EFFECTS (exp))
     {
-      init_expr = void_zero_node;
+      init_expr = NULL_TREE;
     }
   else if (!real_lvalue_p (exp)
           || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
@@ -2672,16 +2253,87 @@ stabilize_expr (exp, initp)
   *initp = init_expr;
   return exp;
 }
+
+/* Like stabilize_expr, but for a call whose args we want to
+   pre-evaluate.  */
+
+void
+stabilize_call (tree call, tree *initp)
+{
+  tree inits = NULL_TREE;
+  tree t;
+
+  if (call == error_mark_node)
+    return;
+
+  if (TREE_CODE (call) != CALL_EXPR
+      && TREE_CODE (call) != AGGR_INIT_EXPR)
+    abort ();
+
+  for (t = TREE_OPERAND (call, 1); t; t = TREE_CHAIN (t))
+    if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
+      {
+       tree init;
+       TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
+       if (!init)
+         /* Nothing.  */;
+       else if (inits)
+         inits = build2 (COMPOUND_EXPR, void_type_node, inits, init);
+       else
+         inits = init;
+      }
+
+  *initp = inits;
+}
+
+/* Like stabilize_expr, but for an initialization.  If we are initializing
+   an object of class type, we don't want to introduce an extra temporary,
+   so we look past the TARGET_EXPR and stabilize the arguments of the call
+   instead.  */
+
+bool
+stabilize_init (tree init, tree *initp)
+{
+  tree t = init;
+
+  if (t == error_mark_node)
+    return true;
+
+  if (TREE_CODE (t) == INIT_EXPR
+      && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+    TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+  else
+    {
+      if (TREE_CODE (t) == INIT_EXPR)
+       t = TREE_OPERAND (t, 1);
+      if (TREE_CODE (t) == TARGET_EXPR)
+       t = TARGET_EXPR_INITIAL (t);
+      if (TREE_CODE (t) == CONSTRUCTOR
+         && CONSTRUCTOR_ELTS (t) == NULL_TREE)
+       {
+         /* Default-initialization.  */
+         *initp = NULL_TREE;
+         return true;
+       }
+
+      /* If the initializer is a COND_EXPR, we can't preevaluate
+        anything.  */
+      if (TREE_CODE (t) == COND_EXPR)
+       return false;
+
+      stabilize_call (t, initp);
+    }
+
+  return true;
+}
+
 \f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
    node has been accessed improperly.  */
 
 void
-lang_check_failed (file, line, function)
-     const char *file;
-     int line;
-     const char *function;
+lang_check_failed (const char* file, int line, const char* function)
 {
   internal_error ("lang_* check: failed in %s, at %s:%d",
                  function, trim_filename (file), line);