class.c (instantiate_type): Don't just return a known type if it's wrong.
[gcc.git] / gcc / cp / tree.c
index c391d7af0217dedbbd08b0987f2b8c2b4ed36ffc..16bcb1357351fc98a265e44b59c2ac70fed97d3a 100644 (file)
@@ -32,6 +32,25 @@ Boston, MA 02111-1307, USA.  */
 #include <varargs.h>
 #endif
 
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free       PROTO((void *));
+#endif
+
+extern void compiler_error ();
+
+static tree get_identifier_list PROTO((tree));
+static tree bot_manip PROTO((tree));
+static tree perm_manip PROTO((tree));
+static tree build_cplus_array_type_1 PROTO((tree, tree));
+static void list_hash_add PROTO((int, tree));
+static int list_hash PROTO((tree, tree, tree));
+static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
+                                   tree));
+
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
 /* Return nonzero if REF is an lvalue valid for this language.
@@ -59,6 +78,9 @@ real_lvalue_p (ref)
     case PREDECREMENT_EXPR:
     case COMPONENT_REF:
     case SAVE_EXPR:
+    case UNSAVE_EXPR:
+    case TRY_CATCH_EXPR:
+    case WITH_CLEANUP_EXPR:
       return real_lvalue_p (TREE_OPERAND (ref, 0));
 
     case STRING_CST:
@@ -103,11 +125,16 @@ real_lvalue_p (ref)
     case MIN_EXPR:
       return (real_lvalue_p (TREE_OPERAND (ref, 0))
              && real_lvalue_p (TREE_OPERAND (ref, 1)));
+
+    default:
+      break;
     }
 
   return 0;
 }
 
+/* This differs from real_lvalue_p in that class rvalues are considered
+   lvalues.  */
 int
 lvalue_p (ref)
      tree ref;
@@ -127,8 +154,13 @@ lvalue_p (ref)
         what they refer to are valid lvals.  */
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
     case COMPONENT_REF:
     case SAVE_EXPR:
+    case UNSAVE_EXPR:
+    case TRY_CATCH_EXPR:
+    case WITH_CLEANUP_EXPR:
       return lvalue_p (TREE_OPERAND (ref, 0));
 
     case STRING_CST:
@@ -181,6 +213,9 @@ lvalue_p (ref)
     case MIN_EXPR:
       return (lvalue_p (TREE_OPERAND (ref, 0))
              && lvalue_p (TREE_OPERAND (ref, 1)));
+
+    default:
+      break;
     }
 
   return 0;
@@ -215,18 +250,36 @@ build_cplus_new (type, init)
   tree slot;
   tree rval;
 
-  if (TREE_CODE (init) == TARGET_EXPR || init == error_mark_node)
+  if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
     return init;
 
   slot = build (VAR_DECL, type);
+  DECL_ARTIFICIAL (slot) = 1;
   layout_decl (slot, 0);
-  rval = build (NEW_EXPR, type,
+  rval = build (AGGR_INIT_EXPR, type,
                TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
   TREE_SIDE_EFFECTS (rval) = 1;
-  TREE_ADDRESSABLE (rval) = 1;
   rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
   TREE_SIDE_EFFECTS (rval) = 1;
-  TREE_ADDRESSABLE (rval) = 1;
+
+  return rval;
+}
+
+/* Encapsulate the expression INIT in a TARGET_EXPR.  */
+
+tree
+get_target_expr (init)
+     tree init;
+{
+  tree slot;
+  tree rval;
+
+  slot = build (VAR_DECL, TREE_TYPE (init));
+  DECL_ARTIFICIAL (slot) = 1;
+  layout_decl (slot, 0);
+  rval = build (TARGET_EXPR, TREE_TYPE (init), slot, init,
+               NULL_TREE, NULL_TREE);
+  TREE_SIDE_EFFECTS (rval) = 1;
 
   return rval;
 }
@@ -404,7 +457,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
   return t;
 }
 
-tree
+static tree
 build_cplus_array_type_1 (elt_type, index_type)
      tree elt_type;
      tree index_type;
@@ -817,6 +870,7 @@ layout_basetypes (rec, binfos)
             them too.  */
          DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
          DECL_VIRTUAL_P (decl) = 1;
+         DECL_ARTIFICIAL (decl) = 1;
          DECL_FIELD_CONTEXT (decl) = rec;
          DECL_CLASS_CONTEXT (decl) = rec;
          DECL_FCONTEXT (decl) = basetype;
@@ -827,20 +881,18 @@ layout_basetypes (rec, binfos)
          BINFO_VPTR_FIELD (base_binfo) = decl;
          vbase_decls = decl;
 
-         if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
-             && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1)) == NULL_TREE)
-           {
-             warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1),
-                                "destructor `%s' non-virtual");
-             warning ("in inheritance relationship `%s: virtual %s'",
-                      TYPE_NAME_STRING (rec),
-                      TYPE_NAME_STRING (basetype));
-           }
        got_it:
          /* The space this decl occupies has already been accounted for.  */
          continue;
        }
 
+      /* Effective C++ rule 14.  We only need to check TYPE_VIRTUAL_P
+        here because the case of virtual functions but non-virtual
+        dtor is handled in finish_struct_1.  */
+      if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
+         && TYPE_HAS_DESTRUCTOR (basetype))
+       cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
+
       if (const_size == 0)
        offset = integer_zero_node;
       else
@@ -849,22 +901,6 @@ layout_basetypes (rec, binfos)
          const_size = CEIL (const_size, TYPE_ALIGN (basetype))
            * TYPE_ALIGN (basetype);
          offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
-#if 0
-         /* bpk: Disabled this check until someone is willing to
-            claim it as theirs and explain exactly what circumstances
-            warrant the warning.  */ 
-         if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
-             && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1)) == NULL_TREE)
-           {
-             warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1),
-                                "destructor `%s' non-virtual");
-             warning ("in inheritance relationship `%s:%s %s'",
-                      TYPE_NAME_STRING (rec),
-                      TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "",
-                      TYPE_NAME_STRING (basetype));
-           }
-#endif
        }
       BINFO_OFFSET (base_binfo) = offset;
       if (CLASSTYPE_VSIZE (basetype))
@@ -922,27 +958,27 @@ struct list_hash
    and the hash code is computed differently for each of these.  */
 
 #define TYPE_HASH_SIZE 59
-struct list_hash *list_hash_table[TYPE_HASH_SIZE];
+static struct list_hash *list_hash_table[TYPE_HASH_SIZE];
 
 /* Compute a hash code for a list (chain of TREE_LIST nodes
    with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
    TREE_COMMON slots), by adding the hash codes of the individual entries.  */
 
-int
-list_hash (list)
-     tree list;
+static int
+list_hash (purpose, value, chain)
+     tree purpose, value, chain;
 {
   register int hashcode = 0;
 
-  if (TREE_CHAIN (list))
-    hashcode += TYPE_HASH (TREE_CHAIN (list));
+  if (chain)
+    hashcode += TYPE_HASH (chain);
 
-  if (TREE_VALUE (list))
-    hashcode += TYPE_HASH (TREE_VALUE (list));
+  if (value)
+    hashcode += TYPE_HASH (value);
   else
     hashcode += 1007;
-  if (TREE_PURPOSE (list))
-    hashcode += TYPE_HASH (TREE_PURPOSE (list));
+  if (purpose)
+    hashcode += TYPE_HASH (purpose);
   else
     hashcode += 1009;
   return hashcode;
@@ -951,31 +987,30 @@ list_hash (list)
 /* Look in the type hash table for a type isomorphic to TYPE.
    If one is found, return it.  Otherwise return 0.  */
 
-tree
-list_hash_lookup (hashcode, list)
-     int hashcode;
-     tree list;
+static tree
+list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+                 purpose, value, chain)
+     int hashcode, via_public, via_virtual, via_protected;
+     tree purpose, value, chain;
 {
   register struct list_hash *h;
+
   for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
     if (h->hashcode == hashcode
-       && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
-       && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
-       && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list)
-       && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
-       && TREE_VALUE (h->list) == TREE_VALUE (list)
-       && TREE_CHAIN (h->list) == TREE_CHAIN (list))
-      {
-       my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299);
-       return h->list;
-      }
+       && TREE_VIA_VIRTUAL (h->list) == via_virtual
+       && TREE_VIA_PUBLIC (h->list) == via_public
+       && TREE_VIA_PROTECTED (h->list) == via_protected
+       && TREE_PURPOSE (h->list) == purpose
+       && TREE_VALUE (h->list) == value
+       && TREE_CHAIN (h->list) == chain)
+      return h->list;
   return 0;
 }
 
 /* Add an entry to the list-hash-table
    for a list TYPE whose hash code is HASHCODE.  */
 
-void
+static void
 list_hash_add (hashcode, list)
      int hashcode;
      tree list;
@@ -1004,29 +1039,6 @@ list_hash_add (hashcode, list)
 
 static int debug_no_list_hash = 0;
 
-tree
-list_hash_canon (hashcode, list)
-     int hashcode;
-     tree list;
-{
-  tree t1;
-
-  if (debug_no_list_hash)
-    return list;
-
-  t1 = list_hash_lookup (hashcode, list);
-  if (t1 != 0)
-    {
-      obstack_free (&class_obstack, list);
-      return t1;
-    }
-
-  /* If this is a new list, record it for later reuse.  */
-  list_hash_add (hashcode, list);
-
-  return list;
-}
-
 tree
 hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
      int via_public, via_virtual, via_protected;
@@ -1036,13 +1048,26 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
   tree t;
   int hashcode;
 
+  if (! debug_no_list_hash)
+    {
+      hashcode = list_hash (purpose, value, chain);
+      t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+                           purpose, value, chain);
+      if (t)
+       return t;
+    }
+
   current_obstack = &class_obstack;
+
   t = tree_cons (purpose, value, chain);
   TREE_VIA_PUBLIC (t) = via_public;
   TREE_VIA_PROTECTED (t) = via_protected;
   TREE_VIA_VIRTUAL (t) = via_virtual;
-  hashcode = list_hash (t);
-  t = list_hash_canon (hashcode, t);
+
+  /* If this is a new list, record it for later reuse.  */
+  if (! debug_no_list_hash)
+    list_hash_add (hashcode, t);
+
   current_obstack = ambient_obstack;
   return t;
 }
@@ -1053,16 +1078,7 @@ tree
 hash_tree_chain (value, chain)
      tree value, chain;
 {
-  struct obstack *ambient_obstack = current_obstack;
-  tree t;
-  int hashcode;
-
-  current_obstack = &class_obstack;
-  t = tree_cons (NULL_TREE, value, chain);
-  hashcode = list_hash (t);
-  t = list_hash_canon (hashcode, t);
-  current_obstack = ambient_obstack;
-  return t;
+  return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
 }
 
 /* Similar, but used for concatenating two lists.  */
@@ -1283,12 +1299,14 @@ int
 is_overloaded_fn (x)
      tree x;
 {
-  if (TREE_CODE (x) == FUNCTION_DECL)
+  if (TREE_CODE (x) == FUNCTION_DECL
+      || TREE_CODE (x) == TEMPLATE_ID_EXPR
+      || DECL_FUNCTION_TEMPLATE_P (x))
     return 1;
 
   if (TREE_CODE (x) == TREE_LIST
       && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
-         || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
+         || DECL_FUNCTION_TEMPLATE_P (TREE_VALUE (x))))
     return 1;
 
   return 0;
@@ -1298,19 +1316,17 @@ int
 really_overloaded_fn (x)
      tree x;
 {     
-  if (TREE_CODE (x) == TREE_LIST
-      && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
-         || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
-    return 1;
-
-  return 0;
+  return TREE_CODE (x) != FUNCTION_DECL 
+    && is_overloaded_fn (x);
 }
 
 tree
 get_first_fn (from)
      tree from;
 {
-  if (TREE_CODE (from) == FUNCTION_DECL)
+  if (TREE_CODE (from) == FUNCTION_DECL
+      || TREE_CODE (from) == TEMPLATE_ID_EXPR
+      || DECL_FUNCTION_TEMPLATE_P (from))
     return from;
 
   my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
@@ -1318,41 +1334,6 @@ get_first_fn (from)
   return TREE_VALUE (from);
 }
 
-tree
-fnaddr_from_vtable_entry (entry)
-     tree entry;
-{
-  if (flag_vtable_thunks)
-    {
-      tree func = entry;
-      if (TREE_CODE (func) == ADDR_EXPR)
-       func = TREE_OPERAND (func, 0);
-      if (TREE_CODE (func) == THUNK_DECL)
-       return DECL_INITIAL (func);
-      else
-       return entry;
-    }
-  else
-    return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
-}
-
-tree
-function_arg_chain (t)
-     tree t;
-{
-  return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
-}
-
-int
-promotes_to_aggr_type (t, code)
-     tree t;
-     enum tree_code code;
-{
-  if (TREE_CODE (t) == code)
-    t = TREE_TYPE (t);
-  return IS_AGGR_TYPE (t);
-}
-
 int
 is_aggr_type_2 (t1, t2)
      tree t1, t2;
@@ -1361,31 +1342,13 @@ is_aggr_type_2 (t1, t2)
     return 0;
   return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
 }
-
-/* Give message using types TYPE1 and TYPE2 as arguments.
-   PFN is the function which will print the message;
-   S is the format string for PFN to use.  */
-
-void
-message_2_types (pfn, s, type1, type2)
-     void (*pfn) ();
-     char *s;
-     tree type1, type2;
-{
-  tree name1 = TYPE_NAME (type1);
-  tree name2 = TYPE_NAME (type2);
-  if (TREE_CODE (name1) == TYPE_DECL)
-    name1 = DECL_NAME (name1);
-  if (TREE_CODE (name2) == TYPE_DECL)
-    name2 = DECL_NAME (name2);
-  (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
-}
 \f
 #define PRINT_RING_SIZE 4
 
 char *
-lang_printable_name (decl)
+lang_printable_name (decl, v)
      tree decl;
+     int v;
 {
   static tree decl_ring[PRINT_RING_SIZE];
   static char *print_ring[PRINT_RING_SIZE];
@@ -1393,9 +1356,10 @@ lang_printable_name (decl)
   int i;
 
   /* Only cache functions.  */
-  if (TREE_CODE (decl) != FUNCTION_DECL
+  if (v < 2
+      || TREE_CODE (decl) != FUNCTION_DECL
       || DECL_LANG_SPECIFIC (decl) == 0)
-    return decl_as_string (decl, 1);
+    return lang_decl_name (decl, v);
 
   /* See if this print name is lying around.  */
   for (i = 0; i < PRINT_RING_SIZE; i++)
@@ -1419,16 +1383,8 @@ lang_printable_name (decl)
   if (print_ring[ring_counter])
     free (print_ring[ring_counter]);
 
-  {
-    int print_ret_type_p
-      = (!DECL_CONSTRUCTOR_P (decl)
-        && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
-    char *name = (char *)decl_as_string (decl, print_ret_type_p);
-    print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
-    strcpy (print_ring[ring_counter], name);
-    decl_ring[ring_counter] = decl;
-  }
+  print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
+  decl_ring[ring_counter] = decl;
   return print_ring[ring_counter];
 }
 \f
@@ -1474,6 +1430,27 @@ build_exception_variant (type, raises)
   return v;
 }
 
+/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its 
+   lang_specific field and its corresponding TEMPLATE_DECL node */
+
+tree
+copy_template_template_parm (t)
+     tree t;
+{
+  tree template = TYPE_NAME (t);
+  tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+  template = copy_node (template);
+  copy_lang_decl (template);
+  TREE_TYPE (template) = t2;
+  TYPE_NAME (t2) = template;
+  TYPE_STUB_DECL (t2) = template;
+
+  /* No need to copy these */
+  TYPE_FIELDS (t2) = TYPE_FIELDS (t);
+  CLASSTYPE_TEMPLATE_INFO (t2) = CLASSTYPE_TEMPLATE_INFO (t);
+  return t2;
+}
+
 /* Subroutine of copy_to_permanent
 
    Assuming T is a node build bottom-up, make it all exist on
@@ -1482,7 +1459,7 @@ build_exception_variant (type, raises)
 tree
 mapcar (t, func)
      tree t;
-     tree (*func)();
+     tree (*func) PROTO((tree));
 {
   tree tmp;
 
@@ -1500,7 +1477,11 @@ mapcar (t, func)
     case VAR_DECL:
     case FUNCTION_DECL:
     case CONST_DECL:
-      break;
+      /* Rather than aborting, return error_mark_node.  This allows us
+        to report a sensible error message on code like this:
+
+        void g() { int i; f<i>(7); } */
+      return error_mark_node;
 
     case PARM_DECL:
       {
@@ -1540,7 +1521,7 @@ mapcar (t, func)
 
     case COND_EXPR:
     case TARGET_EXPR:
-    case NEW_EXPR:
+    case AGGR_INIT_EXPR:
       t = copy_node (t);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@@ -1585,23 +1566,29 @@ mapcar (t, func)
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
-    case CALL_EXPR:
     case ARRAY_REF:
     case SCOPE_REF:
+    case TRY_CATCH_EXPR:
+    case WITH_CLEANUP_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);
       return t;
-      break;
 
-    case RTL_EXPR:
+    case CALL_EXPR:
       t = copy_node (t);
-      if (RTL_EXPR_SEQUENCE (t))
-       RTL_EXPR_SEQUENCE (t) = copy_rtx (RTL_EXPR_SEQUENCE (t));
-      if (RTL_EXPR_RTL (t))
-       RTL_EXPR_RTL (t) = copy_rtx (RTL_EXPR_RTL (t));
+      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+
+      /* tree.def says that operand two is RTL, but
+        build_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;
       return t;
-      break;
 
     case CONVERT_EXPR:
     case ADDR_EXPR:
@@ -1611,6 +1598,7 @@ mapcar (t, func)
     case TRUTH_NOT_EXPR:
     case NOP_EXPR:
     case COMPONENT_REF:
+    case CLEANUP_POINT_EXPR:
       t = copy_node (t);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       return t;
@@ -1643,11 +1631,20 @@ mapcar (t, func)
         mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
       return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
 
+    case COMPLEX_CST:
+      t = copy_node (t);
+      TREE_REALPART (t) = mapcar (TREE_REALPART (t), func);
+      TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func);
+      return t;
+
     case CONSTRUCTOR:
       t = copy_node (t);
       CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
       return t;
 
+    case TEMPLATE_TEMPLATE_PARM:
+      return copy_template_template_parm (t);
+
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
        return build_ptrmemfunc_type
@@ -1714,11 +1711,9 @@ extern int depth_reached;
 void
 print_lang_statistics ()
 {
-  extern struct obstack maybepermanent_obstack, decl_obstack;
+  extern struct obstack decl_obstack;
   print_obstack_statistics ("class_obstack", &class_obstack);
   print_obstack_statistics ("decl_obstack", &decl_obstack);
-  print_obstack_statistics ("permanent_obstack", &permanent_obstack);
-  print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
   print_search_statistics ();
   print_class_statistics ();
 #ifdef GATHER_STATISTICS
@@ -1792,7 +1787,7 @@ bot_manip (t)
     return t;
   else if (TREE_CODE (t) == TARGET_EXPR)
     {
-      if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR)
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
        {
          mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
          return build_cplus_new
@@ -1821,8 +1816,6 @@ break_out_target_exprs (t)
 /* Obstack used for allocating nodes in template function and variable
    definitions.  */
 
-extern struct obstack *expression_obstack;
-
 /* Similar to `build_nt', except we build
    on the permanent_obstack, regardless.  */
 
@@ -1922,8 +1915,6 @@ tree
 get_type_decl (t)
      tree t;
 {
-  if (TREE_CODE (t) == IDENTIFIER_NODE)
-    return identifier_typedecl_value (t);
   if (TREE_CODE (t) == TYPE_DECL)
     return t;
   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
@@ -2079,14 +2070,19 @@ cp_tree_equal (t1, t2)
       return 0;
 
     case TEMPLATE_CONST_PARM:
-      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
+      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
+       && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
 
     case SIZEOF_EXPR:
+    case ALIGNOF_EXPR:
       if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
        return 0;
       if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
        return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
       break;
+
+    default:
+      break;
     }
 
   switch (TREE_CODE_CLASS (code1))
@@ -2118,13 +2114,20 @@ make_temp_vec (len)
      int len;
 {
   register tree node;
-  push_obstacks_nochange ();
-  resume_temporary_allocation ();
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = expression_obstack;
   node = make_tree_vec (len);
-  pop_obstacks ();
+  current_obstack = ambient_obstack;
   return node;
 }
 
+void
+push_expression_obstack ()
+{
+  push_obstacks_nochange ();
+  current_obstack = expression_obstack;
+}
+
 /* The type of ARG when used as an lvalue.  */
 
 tree
@@ -2152,3 +2155,16 @@ error_type (arg)
 
   return type;
 }
+
+/* Does FUNCTION use a variable-length argument list?  */
+
+int
+varargs_function_p (function)
+     tree function;
+{
+  tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+  for (; parm; parm = TREE_CHAIN (parm))
+    if (TREE_VALUE (parm) == void_type_node)
+      return 0;
+  return 1;
+}