OSDN Git Service

Merge in gcc2-ss-010999
[pf3gnuchains/gcc-fork.git] / gcc / cp / tree.c
index 9012810..a1928ef 100644 (file)
@@ -36,27 +36,29 @@ static int list_hash PROTO((tree, tree, tree));
 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 int lvalue_p_1 PROTO((tree, int));
-static int equal_functions PROTO((tree, tree));
+static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
 static tree no_linkage_helper PROTO((tree));
 static tree build_srcloc PROTO((char *, int));
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
-/* Returns non-zero if REF is an lvalue.  If
-   TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
-   are considered lvalues.  */
+/* If REF is an lvalue, returns the kind of lvalue that REF is.
+   Otherwise, returns clk_none.  If TREAT_CLASS_RVALUES_AS_LVALUES is
+   non-zero, rvalues of class type are considered lvalues.  */
 
-static int
+static cp_lvalue_kind
 lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
      tree ref;
      int treat_class_rvalues_as_lvalues;
 {
+  cp_lvalue_kind op1_lvalue_kind = clk_none;
+  cp_lvalue_kind op2_lvalue_kind = clk_none;
+
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
-    return 1;
+    return clk_ordinary;
 
   if (ref == current_class_ptr && flag_this_is_variable <= 0)
-    return 0;
+    return clk_none;
 
   switch (TREE_CODE (ref))
     {
@@ -64,30 +66,47 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
         what they refer to are valid lvals.  */
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
-    case COMPONENT_REF:
     case SAVE_EXPR:
     case UNSAVE_EXPR:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
+    case NOP_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 0),
                         treat_class_rvalues_as_lvalues);
 
+    case COMPONENT_REF:
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
+                                   treat_class_rvalues_as_lvalues);
+      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_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.  */
+         op1_lvalue_kind |= clk_bitfield;
+       }
+      return op1_lvalue_kind;
+
     case STRING_CST:
-      return 1;
+      return clk_ordinary;
 
     case VAR_DECL:
       if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
          && DECL_LANG_SPECIFIC (ref)
          && DECL_IN_AGGR_P (ref))
-       return 0;
+       return clk_none;
     case INDIRECT_REF:
     case ARRAY_REF:
     case PARM_DECL:
     case RESULT_DECL:
       if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
-       return 1;
+       return clk_ordinary;
       break;
 
       /* A currently unresolved scope ref.  */
@@ -95,72 +114,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
       my_friendly_abort (103);
     case OFFSET_REF:
       if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
-       return 1;
-      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 1),
-                            treat_class_rvalues_as_lvalues));
+       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);
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+                                   treat_class_rvalues_as_lvalues);
       break;
 
     case COND_EXPR:
-      return (lvalue_p_1 (TREE_OPERAND (ref, 1),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 2),
-                            treat_class_rvalues_as_lvalues));
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+                                   treat_class_rvalues_as_lvalues);
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
+                                   treat_class_rvalues_as_lvalues);
+      break;
 
     case MODIFY_EXPR:
-      return 1;
+      return clk_ordinary;
 
     case COMPOUND_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 1),
-                           treat_class_rvalues_as_lvalues);
-
-    case MAX_EXPR:
-    case MIN_EXPR:
-      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 1),
-                            treat_class_rvalues_as_lvalues));
+                        treat_class_rvalues_as_lvalues);
 
     case TARGET_EXPR:
-      return treat_class_rvalues_as_lvalues;
+      return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
 
     case CALL_EXPR:
-      return (treat_class_rvalues_as_lvalues
-             && IS_AGGR_TYPE (TREE_TYPE (ref)));
+      return ((treat_class_rvalues_as_lvalues
+              && IS_AGGR_TYPE (TREE_TYPE (ref)))
+             ? clk_class : clk_none);
 
     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);
 
     default:
       break;
     }
 
-  return 0;
+  /* If one operand is not an lvalue at all, then this expression is
+     not an lvalue.  */
+  if (!op1_lvalue_kind || !op2_lvalue_kind)
+    return clk_none;
+
+  /* Otherwise, it's an lvalue, and it has all the odd properties
+     contributed by either operand.  */
+  op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
+  /* It's not an ordinary lvalue if it involves either a bit-field or
+     a class rvalue.  */
+  if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
+    op1_lvalue_kind &= ~clk_ordinary;
+  return op1_lvalue_kind;
 }
 
-/* Return nonzero if REF is an lvalue valid for this language.
-   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.  */
+/* 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.  */
 
-int
+cp_lvalue_kind
 real_lvalue_p (ref)
      tree ref;
 {
   return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
 }
 
-/* This differs from real_lvalue_p in that class rvalues are considered
-   lvalues.  */
+/* This differs from real_lvalue_p in that class rvalues are
+   considered lvalues.  */
 
 int
 lvalue_p (ref)
      tree ref;
 {
-  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
+  return 
+    (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
@@ -189,18 +220,36 @@ build_cplus_new (type, init)
      tree type;
      tree init;
 {
+  tree fn;
   tree slot;
   tree rval;
 
+  /* Make sure that we're not trying to create an instance of an
+     abstract class.  */
+  abstract_virtuals_error (NULL_TREE, type);
+
   if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
-    return init;
+    return convert (type, init);
 
   slot = build (VAR_DECL, type);
   DECL_ARTIFICIAL (slot) = 1;
   layout_decl (slot, 0);
-  rval = build (AGGR_INIT_EXPR, type,
-               TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
+
+  /* We split the CALL_EXPR into its function and its arguments here.
+     Then, in expand_expr, we put them back together.  The reason for
+     this is that this expression might be a default argument
+     expression.  In that case, we need a new temporary every time the
+     expression is used.  That's what break_out_target_exprs does; it
+     replaces every AGGR_INIT_EXPR with a copy that uses a fresh
+     temporary slot.  Then, expand_expr builds up a call-expression
+     using the new slot.  */
+  fn = TREE_OPERAND (init, 0);
+  rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
   TREE_SIDE_EFFECTS (rval) = 1;
+  AGGR_INIT_VIA_CTOR_P (rval) 
+    = (TREE_CODE (fn) == ADDR_EXPR
+       && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+       && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
   rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (rval) = 1;
 
@@ -374,21 +423,23 @@ build_cplus_method_type (basetype, rettype, argtypes)
 
   TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
   TREE_TYPE (t) = rettype;
-  if (IS_SIGNATURE (basetype))
-    ptype = build_signature_pointer_type (basetype);
-  else
-    ptype = build_pointer_type (basetype);
+  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.  */
-
+     which is "this".  Put it into the list of argument types.  Make
+     sure that the new argument list is allocated on the same obstack
+     as the type.  */
+  push_obstacks (TYPE_OBSTACK (t), TYPE_OBSTACK (t));
   argtypes = tree_cons (NULL_TREE, ptype, argtypes);
   TYPE_ARG_TYPES (t) = argtypes;
   TREE_SIDE_EFFECTS (argtypes) = 1;  /* Mark first argtype as "artificial".  */
+  pop_obstacks ();
 
   /* 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);
+  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
+    type_hash_list (argtypes);
+
   t = type_hash_canon (hashcode, t);
 
   if (TYPE_SIZE (t) == 0)
@@ -402,18 +453,18 @@ build_cplus_array_type_1 (elt_type, index_type)
      tree elt_type;
      tree index_type;
 {
-  register struct obstack *ambient_obstack = current_obstack;
-  register struct obstack *ambient_saveable_obstack = saveable_obstack;
   tree t;
 
-  /* We need a new one.  If both ELT_TYPE and INDEX_TYPE are permanent,
+  if (elt_type == error_mark_node || index_type == error_mark_node)
+    return error_mark_node;
+
+  push_obstacks_nochange ();
+
+  /* If both ELT_TYPE and INDEX_TYPE are permanent,
      make this permanent too.  */
   if (TREE_PERMANENT (elt_type)
       && (index_type == 0 || TREE_PERMANENT (index_type)))
-    {
-      current_obstack = &permanent_obstack;
-      saveable_obstack = &permanent_obstack;
-    }
+    end_temporary_allocation ();
 
   if (processing_template_decl 
       || uses_template_parms (elt_type) 
@@ -428,10 +479,11 @@ 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 (TYPE_MAIN_VARIANT (elt_type));
-  TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
-  current_obstack = ambient_obstack;
-  saveable_obstack = ambient_saveable_obstack;
+  TYPE_NEEDS_CONSTRUCTING (t) 
+    = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
+  TYPE_NEEDS_DESTRUCTOR (t) 
+    = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
+  pop_obstacks ();
   return t;
 }
 
@@ -453,53 +505,118 @@ build_cplus_array_type (elt_type, index_type)
   return t;
 }
 \f
-/* Make a variant type in the proper way for C/C++, propagating qualifiers
-   down to the element type of an array.  */
+/* 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.  If
+   at attempt is made to qualify a type illegally, and COMPLAIN is
+   non-zero, an error is issued.  If COMPLAIN is zero, error_mark_node
+   is returned.  */
 
 tree
-cp_build_qualified_type (type, type_quals)
+cp_build_qualified_type_real (type, type_quals, complain)
      tree type;
      int type_quals;
+     int complain;
 {
+  tree result;
+
   if (type == error_mark_node)
     return type;
-  
+
+  if (type_quals == TYPE_QUALS (type))
+    return type;
+
   /* A restrict-qualified pointer type must be a pointer (or reference)
      to object or incomplete type.  */
   if ((type_quals & TYPE_QUAL_RESTRICT)
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM
       && (!POINTER_TYPE_P (type)
          || TYPE_PTRMEM_P (type)
          || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
     {
-      cp_error ("`%T' cannot be `restrict'-qualified", type);
+      if (complain)
+       cp_error ("`%T' cannot be `restrict'-qualified", type);
+      else
+       return error_mark_node;
+
       type_quals &= ~TYPE_QUAL_RESTRICT;
     }
 
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  if (type_quals != TYPE_UNQUALIFIED
+      && TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      if (complain)
+       cp_error ("`%T' cannot be `const'-, `volatile'-, or `restrict'-qualified", type);
+      else
+       return error_mark_node;
+      type_quals = TYPE_UNQUALIFIED;
+    }
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      tree real_main_variant = TYPE_MAIN_VARIANT (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), 
+                                       type_quals,
+                                       complain);
 
-      push_obstacks (TYPE_OBSTACK (real_main_variant),
-                    TYPE_OBSTACK (real_main_variant));
-      type = build_cplus_array_type_1 (cp_build_qualified_type 
-                                      (TREE_TYPE (type), type_quals),
-                                      TYPE_DOMAIN (type));
+      if (element_type == error_mark_node)
+       return error_mark_node;
 
-      /* TYPE must be on same obstack as REAL_MAIN_VARIANT.  If not,
-        make a copy.  (TYPE might have come from the hash table and
-        REAL_MAIN_VARIANT might be in some function's obstack.)  */
+      /* 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)
+         break;
 
-      if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant))
+      /* If we didn't already have it, create it now.  */
+      if (!t)
        {
-         type = copy_node (type);
-         TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0;
+         /* Make a new array type, just like the old one, but with the
+            appropriately qualified element type.  */
+         t = build_type_copy (type);
+         TREE_TYPE (t) = element_type;
        }
 
-      TYPE_MAIN_VARIANT (type) = real_main_variant;
-      pop_obstacks ();
-      return type;
+      /* Even if we already had this variant, we update
+        TYPE_NEEDS_CONSTRUCTING and TYPE_NEEDS_DESTRUCTOR in case
+        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 (TYPE_MAIN_VARIANT (element_type));
+      TYPE_NEEDS_DESTRUCTOR (t) 
+       = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (element_type));
+      return t;
+    }
+  else if (TYPE_PTRMEMFUNC_P (type))
+    {
+      /* For a pointer-to-member type, we can't just return a
+        cv-qualified version of the RECORD_TYPE.  If we do, we
+        haven't change the field that contains the actual pointer to
+        a method, and so TYPE_PTRMEMFUNC_FN_TYPE will be wrong.  */
+      tree t;
+
+      t = TYPE_PTRMEMFUNC_FN_TYPE (type);
+      t = cp_build_qualified_type_real (t, type_quals, complain);
+      return build_ptrmemfunc_type (t);
     }
-  return build_qualified_type (type, type_quals);
+
+  /* Retrieve (or create) the appropriately qualified variant.  */
+  result = build_qualified_type (type, type_quals);
+
+  /* If this was a pointer-to-method type, and we just made a copy,
+     then we need to clear the cached associated
+     pointer-to-member-function type; it is not valid for the new
+     type.  */
+  if (result != type 
+      && TREE_CODE (type) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+    TYPE_SET_PTRMEMFUNC_TYPE (result, NULL_TREE);
+
+  return result;
 }
 
 /* Returns the canonical version of TYPE.  In other words, if TYPE is
@@ -788,7 +905,7 @@ build_base_fields (rec)
       if (TREE_VIA_VIRTUAL (base_binfo))
        continue;
 
-      decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, basetype);
+      decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
       DECL_ARTIFICIAL (decl) = 1;
       DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
       DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
@@ -900,8 +1017,8 @@ build_vbase_pointer_fields (rec)
                goto got_it;
            }
          FORMAT_VBASE_NAME (name, basetype);
-         decl = build_lang_field_decl (FIELD_DECL, get_identifier (name),
-                                       build_pointer_type (basetype));
+         decl = build_lang_decl (FIELD_DECL, get_identifier (name),
+                                 build_pointer_type (basetype));
          /* If you change any of the below, take a look at all the
             other VFIELD_BASEs and VTABLE_BASEs in the code, and change
             them too.  */
@@ -911,7 +1028,7 @@ build_vbase_pointer_fields (rec)
          DECL_FIELD_CONTEXT (decl) = rec;
          DECL_CLASS_CONTEXT (decl) = rec;
          DECL_FCONTEXT (decl) = basetype;
-         DECL_SAVED_INSNS (decl) = NULL_RTX;
+         DECL_SAVED_INSNS (decl) = 0;
          DECL_FIELD_SIZE (decl) = 0;
          DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node);
          TREE_CHAIN (decl) = vbase_decls;
@@ -1173,7 +1290,7 @@ debug_binfo (elem)
 
   while (virtuals)
     {
-      tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
+      tree fndecl = TREE_VALUE (virtuals);
       fprintf (stderr, "%s [%ld =? %ld]\n",
               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
               (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
@@ -1315,20 +1432,6 @@ build_overload (decl, chain)
   return ovl_cons (decl, chain);
 }
 
-/* Returns true iff functions are equivalent. Equivalent functions are
-   not identical only if one is a function-local extern function.
-   This assumes that function-locals don't have TREE_PERMANENT.  */
-
-static int
-equal_functions (fn1, fn2)
-     tree fn1;
-     tree fn2;
-{
-  if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
-    return decls_match (fn1, fn2);
-  return fn1 == fn2;
-}
-
 /* True if fn is in ovl. */
 
 int
@@ -1339,9 +1442,9 @@ ovl_member (fn, ovl)
   if (ovl == NULL_TREE)
     return 0;
   if (TREE_CODE (ovl) != OVERLOAD)
-    return equal_functions (ovl, fn);
+    return ovl == fn;
   for (; ovl; ovl = OVL_CHAIN (ovl))
-    if (equal_functions (OVL_FUNCTION (ovl), fn))
+    if (OVL_FUNCTION (ovl) == fn)
       return 1;
   return 0;
 }
@@ -1357,7 +1460,7 @@ is_aggr_type_2 (t1, t2)
 \f
 #define PRINT_RING_SIZE 4
 
-char *
+const char *
 lang_printable_name (decl, v)
      tree decl;
      int v;
@@ -1412,25 +1515,9 @@ build_exception_variant (type, raises)
   int type_quals = TYPE_QUALS (type);
 
   for (; v; v = TYPE_NEXT_VARIANT (v))
-    {
-      tree t;
-      tree u;
-
-      if (TYPE_QUALS (v) != type_quals)
-       continue;
-
-      for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
-          t != NULL_TREE && u != NULL_TREE;
-          t = TREE_CHAIN (t), u = TREE_CHAIN (u))
-       if (((TREE_VALUE (t) != NULL_TREE) 
-            != (TREE_VALUE (u) != NULL_TREE))
-           || !same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
-         break;
-
-      if (!t && !u)
-       /* There's a memory leak here; RAISES is not freed.  */
-       return v;
-    }
+    if (TYPE_QUALS (v) == type_quals
+        && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
+      return v;
 
   /* Need to build a new variant.  */
   v = build_type_copy (type);
@@ -1453,8 +1540,7 @@ copy_template_template_parm (t)
   tree t2;
 
   /* Make sure these end up on the permanent_obstack.  */
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
+  push_permanent_obstack ();
   
   t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
   template = copy_node (template);
@@ -1484,14 +1570,30 @@ search_tree (t, func)
 #define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
 
   tree tmp;
+  enum tree_code code; 
 
   if (t == NULL_TREE)
     return t;
-
-  if (tmp = func (t), tmp != NULL_TREE)
+  
+  tmp = func (t);
+  if (tmp)
     return tmp;
 
-  switch (TREE_CODE (t))
+  /* Handle some common cases up front.  */
+  code = TREE_CODE (t);
+  if (TREE_CODE_CLASS (code) == '1')
+    {
+      TRY (TREE_OPERAND (t, 0));
+      return NULL_TREE;
+    }
+  else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
+    {
+      TRY (TREE_OPERAND (t, 0));
+      TRY (TREE_OPERAND (t, 1));
+      return NULL_TREE;
+    }
+
+  switch (code)
     {
     case ERROR_MARK:
       break;
@@ -1555,35 +1657,11 @@ search_tree (t, func)
       TRY (TREE_OPERAND (t, 2));
       break;
 
-    case MODIFY_EXPR:
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case MULT_EXPR:
-    case TRUNC_DIV_EXPR:
-    case TRUNC_MOD_EXPR:
-    case MIN_EXPR:
-    case MAX_EXPR:
-    case LSHIFT_EXPR:
-    case RSHIFT_EXPR:
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-    case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-    case LT_EXPR:
-    case LE_EXPR:
-    case GT_EXPR:
-    case GE_EXPR:
-    case EQ_EXPR:
-    case NE_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-    case COMPOUND_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -1593,36 +1671,31 @@ search_tree (t, func)
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case CALL_EXPR:
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+    case INIT_EXPR:
       TRY (TREE_OPERAND (t, 0));
       TRY (TREE_OPERAND (t, 1));
       break;
 
     case SAVE_EXPR:
-    case CONVERT_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
-    case NEGATE_EXPR:
-    case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
-    case NOP_EXPR:
-    case NON_LVALUE_EXPR:
     case COMPONENT_REF:
     case CLEANUP_POINT_EXPR:
     case LOOKUP_EXPR:
-    case SIZEOF_EXPR:
-    case ALIGNOF_EXPR:
+    case THROW_EXPR:
+    case EXIT_EXPR:
+    case LOOP_EXPR:
       TRY (TREE_OPERAND (t, 0));
       break;
 
     case MODOP_EXPR:
-    case CAST_EXPR:
-    case REINTERPRET_CAST_EXPR:
-    case CONST_CAST_EXPR:
-    case STATIC_CAST_EXPR:
-    case DYNAMIC_CAST_EXPR:
     case ARROW_EXPR:
     case DOTSTAR_EXPR:
     case TYPEID_EXPR:
+    case PSEUDO_DTOR_EXPR:
       break;
 
     case COMPLEX_CST:
@@ -1640,6 +1713,7 @@ search_tree (t, func)
       break;
 
     case BIND_EXPR:
+    case STMT_EXPR:
       break;
 
     case REAL_TYPE:
@@ -1682,13 +1756,8 @@ search_tree (t, func)
        TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
       break;
       
-      /*  This list is incomplete, but should suffice for now.
-         It is very important that `sorry' not call
-         `report_error_function'.  That could cause an infinite loop.  */
     default:
-      sorry ("initializer contains unrecognized tree code");
-      return error_mark_node;
-
+      my_friendly_abort (19990803);
     }
 
   return NULL_TREE;
@@ -1717,6 +1786,11 @@ tree
 no_linkage_check (t)
      tree t;
 {
+  /* 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 = search_tree (t, no_linkage_helper);
   if (t != error_mark_node)
     return t;
@@ -1724,10 +1798,8 @@ no_linkage_check (t)
 }
 
 
-/* Subroutine of copy_to_permanent
-
-   Assuming T is a node build bottom-up, make it all exist on
-   permanent obstack, if it is not permanent already.  */
+/* Make copies of all the nodes below T.  If FUNC is non-NULL, call it
+   for each node.  */
 
 tree
 mapcar (t, func)
@@ -1735,12 +1807,35 @@ mapcar (t, func)
      tree (*func) PROTO((tree));
 {
   tree tmp;
+  enum tree_code code; 
 
   if (t == NULL_TREE)
     return t;
 
-  if (tmp = func (t), tmp != NULL_TREE)
-    return tmp;
+  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))
     {
@@ -1828,40 +1923,11 @@ mapcar (t, func)
       TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
       return t;
 
-    case SAVE_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      return t;
-
-    case MODIFY_EXPR:
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case MULT_EXPR:
-    case TRUNC_DIV_EXPR:
-    case TRUNC_MOD_EXPR:
-    case MIN_EXPR:
-    case MAX_EXPR:
-    case LSHIFT_EXPR:
-    case RSHIFT_EXPR:
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-    case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-    case LT_EXPR:
-    case LE_EXPR:
-    case GT_EXPR:
-    case GE_EXPR:
-    case EQ_EXPR:
-    case NE_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-    case COMPOUND_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -1870,6 +1936,9 @@ mapcar (t, func)
     case SCOPE_REF:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+    case 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);
@@ -1880,25 +1949,17 @@ mapcar (t, func)
       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.def says that operand two is RTL, but
-        make_call_declarator puts trees in there.  */
-      if (TREE_OPERAND (t, 2)
-         && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
-       TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
-      else
-       TREE_OPERAND (t, 2) = NULL_TREE;
+      TREE_OPERAND (t, 2) = NULL_TREE;
       return t;
 
-    case CONVERT_EXPR:
+    case SAVE_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
-    case NEGATE_EXPR:
-    case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
-    case NOP_EXPR:
     case COMPONENT_REF:
     case CLEANUP_POINT_EXPR:
+    case THROW_EXPR:
+    case STMT_EXPR:
       t = copy_node (t);
       TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
@@ -1961,29 +2022,41 @@ mapcar (t, 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 */
-      
-      /*  This list is incomplete, but should suffice for now.
-         It is very important that `sorry' not call
-         `report_error_function'.  That could cause an infinite loop.  */
-    default:
-      sorry ("initializer contains unrecognized tree code");
-      return error_mark_node;
 
+    default:
+      my_friendly_abort (19990815);
     }
   my_friendly_abort (107);
   /* NOTREACHED */
   return NULL_TREE;
 }
 
+/* Returns T if T is allocated on the permanent obstack, NULL_TREE
+   otherwise.  */
+
+tree
+permanent_p (t)
+     tree t;
+{
+  return TREE_PERMANENT (t) ? t : NULL_TREE;
+}
+
 static tree
 perm_manip (t)
      tree t;
@@ -2016,11 +2089,8 @@ copy_to_permanent (t)
   if (t == NULL_TREE || TREE_PERMANENT (t))
     return t;
 
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
-
+  push_permanent_obstack ();
   t = mapcar (t, perm_manip);
-
   pop_obstacks ();
 
   return t;
@@ -2137,7 +2207,7 @@ break_out_target_exprs (t)
 tree
 build_min_nt VPROTO((enum tree_code code, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum tree_code code;
 #endif
   register struct obstack *ambient_obstack = expression_obstack;
@@ -2148,7 +2218,7 @@ build_min_nt VPROTO((enum tree_code code, ...))
 
   VA_START (p, code);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum tree_code);
 #endif
 
@@ -2175,7 +2245,7 @@ build_min_nt VPROTO((enum tree_code code, ...))
 tree
 build_min VPROTO((enum tree_code code, tree tt, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum tree_code code;
   tree tt;
 #endif
@@ -2187,7 +2257,7 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
 
   VA_START (p, tt);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum tree_code);
   tt = va_arg (p, tree);
 #endif
@@ -2552,6 +2622,17 @@ push_expression_obstack ()
   current_obstack = expression_obstack;
 }
 
+/* Begin allocating on the permanent obstack.  When you're done
+   allocating there, call pop_obstacks to return to the previous set
+   of obstacks.  */
+
+void
+push_permanent_obstack ()
+{
+  push_obstacks_nochange ();
+  end_temporary_allocation ();
+}
+
 /* The type of ARG when used as an lvalue.  */
 
 tree
@@ -2664,30 +2745,24 @@ int
 pod_type_p (t)
      tree t;
 {
-  tree f;
-
   while (TREE_CODE (t) == ARRAY_TYPE)
     t = TREE_TYPE (t);
 
-  if (! IS_AGGR_TYPE (t))
+  if (INTEGRAL_TYPE_P (t))
+    return 1;  /* integral, character or enumeral type */
+  if (FLOAT_TYPE_P (t))
     return 1;
-
-  if (CLASSTYPE_NON_AGGREGATE (t)
-      || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
-      || TYPE_HAS_DESTRUCTOR (t))
+  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 (! CLASS_TYPE_P (t))
+    return 0; /* other non-class type (reference or function) */
+  if (CLASSTYPE_NON_POD_P (t))
     return 0;
-
-  for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f))
-    {
-      if (TREE_CODE (f) != FIELD_DECL)
-       continue;
-
-      if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE
-         || TYPE_PTRMEMFUNC_P (TREE_TYPE (f))
-         || TYPE_PTRMEM_P (TREE_TYPE (f)))
-       return 0;
-    }
-
   return 1;
 }
 
@@ -2777,3 +2852,59 @@ cp_valid_lang_attribute (attr_name, attr_args, decl, type)
 
   return 0;
 }
+
+/* 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;
+{
+  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;
+}
+
+/* Initialize unsave for C++. */
+void
+init_cplus_unsave ()
+{
+  lang_unsave_expr_now = cplus_unsave_expr_now;
+}
+
+/* The C++ version of unsave_expr_now.
+   See gcc/tree.c:unsave_expr_now for comments. */
+
+void
+cplus_unsave_expr_now (expr)
+     tree expr;
+{
+  if (expr == NULL)
+    return;
+
+  else if (TREE_CODE (expr) == AGGR_INIT_EXPR)
+    {
+      unsave_expr_now (TREE_OPERAND (expr,0));
+      if (TREE_OPERAND (expr, 1)
+         && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
+       {
+         tree exp = TREE_OPERAND (expr, 1);
+         while (exp)
+           {
+             unsave_expr_now (TREE_VALUE (exp));
+             exp = TREE_CHAIN (exp);
+           }
+       }
+      unsave_expr_now (TREE_OPERAND (expr,2));
+      return;
+    }
+
+  else
+    return;
+}
+