OSDN Git Service

* Make-lang.in (stmp-f2c.h): Don't configure the runtime
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index e8038d7..6812aa4 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file contains the low level primitives for operating on tree nodes,
@@ -36,6 +37,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "config.h"
 #include "flags.h"
 #include "tree.h"
+#include "except.h"
 #include "function.h"
 #include "obstack.h"
 #ifdef __STDC__
@@ -45,6 +47,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif
 #include <stdio.h>
 
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free PROTO((void *));
+#endif
+
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
@@ -339,6 +349,7 @@ save_tree_status (p, context)
   p->all_types_permanent = all_types_permanent;
   p->momentary_stack = momentary_stack;
   p->maybepermanent_firstobj = maybepermanent_firstobj;
+  p->temporary_firstobj = temporary_firstobj;
   p->momentary_firstobj = momentary_firstobj;
   p->momentary_function_firstobj = momentary_function_firstobj;
   p->function_obstack = function_obstack;
@@ -391,6 +402,7 @@ save_tree_status (p, context)
   expression_obstack = &permanent_obstack;
   rtl_obstack = saveable_obstack = &permanent_obstack;
 
+  temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
   momentary_firstobj = (char *) obstack_finish (&momentary_obstack);
   momentary_function_firstobj = momentary_firstobj;
 }
@@ -419,6 +431,7 @@ restore_tree_status (p)
   obstack_free (function_obstack, 0);
   free (function_obstack);
 
+  temporary_firstobj = p->temporary_firstobj;
   momentary_firstobj = p->momentary_firstobj;
   momentary_function_firstobj = p->momentary_function_firstobj;
   maybepermanent_firstobj = p->maybepermanent_firstobj;
@@ -691,6 +704,16 @@ savealloc (size)
 {
   return (char *) obstack_alloc (saveable_obstack, size);
 }
+
+/* Allocate SIZE bytes in the expression obstack
+   and return a pointer to them.  */
+
+char *
+expralloc (size)
+     int size;
+{
+  return (char *) obstack_alloc (expression_obstack, size);
+}
 \f
 /* Print out which obstack an object is in.  */
 
@@ -749,7 +772,7 @@ print_obstack_name (object, file, prefix)
       obstack_name = "temp_decl_obstack";
     }
 
-  /* Check to see if the object is in the free area of the obstack. */
+  /* Check to see if the object is in the free area of the obstack.  */
   if (obstack != NULL)
     {
       if (object >= obstack->next_free
@@ -920,11 +943,11 @@ make_node (code)
       /* PARM_DECLs go on the context of the parent. If this is a nested
         function, then we must allocate the PARM_DECL on the parent's
         obstack, so that they will live to the end of the parent's
-        closing brace.  This is neccesary in case we try to inline the
+        closing brace.  This is necessary in case we try to inline the
         function into its parent.
 
         PARM_DECLs of top-level functions do not have this problem.  However,
-        we allocate them where we put the FUNCTION_DECL for languauges such as
+        we allocate them where we put the FUNCTION_DECL for languages such as
         Ada that need to consult some flags in the PARM_DECLs of the function
         when calling it. 
 
@@ -1128,15 +1151,13 @@ copy_node (node)
         for REAL_CST, since the number of words is machine-dependent due
         to varying size and alignment of `double'.  */
       if (code == INTEGER_CST)
-        {
-          length = sizeof (struct tree_int_cst);
-          break;
-        }
+       length = sizeof (struct tree_int_cst);
       else if (code == REAL_CST)
-       {
-         length = sizeof (struct tree_real_cst);
-         break;
-       }
+       length = sizeof (struct tree_real_cst);
+      else
+       length = (sizeof (struct tree_common)
+                 + tree_code_length[(int) code] * sizeof (char *));
+      break;
 
     case 'x':  /* something random, like an identifier.  */
       length = sizeof (struct tree_common)
@@ -1154,6 +1175,7 @@ copy_node (node)
     ((char *) t)[i] = ((char *) node)[i];
 
   TREE_CHAIN (t) = 0;
+  TREE_ASM_WRITTEN (t) = 0;
 
   if (TREE_CODE_CLASS (code) == 'd')
     DECL_UID (t) = next_decl_uid++;
@@ -1161,6 +1183,14 @@ copy_node (node)
     {
       TYPE_UID (t) = next_type_uid++;
       TYPE_OBSTACK (t) = current_obstack;
+
+      /* The following is so that the debug code for
+        the copy is different from the original type.
+        The two statements usually duplicate each other
+        (because they clear fields of the same union),
+        but the optimizer should catch that.  */
+      TYPE_SYMTAB_POINTER (t) = 0;
+      TYPE_SYMTAB_ADDRESS (t) = 0;
     }
 
   TREE_PERMANENT (t) = (current_obstack == &permanent_obstack);
@@ -1216,9 +1246,9 @@ get_identifier (text)
     hash_len = id_clash_len;
 
   /* Compute hash code */
-  hi = hash_len * 613 + (unsigned)text[0];
+  hi = hash_len * 613 + (unsigned) text[0];
   for (i = 1; i < hash_len; i += 2)
-    hi = ((hi * 613) + (unsigned)(text[i]));
+    hi = ((hi * 613) + (unsigned) (text[i]));
 
   hi &= (1 << HASHBITS) - 1;
   hi %= MAX_HASH_TABLE;
@@ -1257,6 +1287,45 @@ get_identifier (text)
   return idp;                  /* <-- return if created */
 }
 
+/* If an identifier with the name TEXT (a null-terminated string) has
+   previously been referred to, return that node; otherwise return
+   NULL_TREE.  */
+
+tree
+maybe_get_identifier (text)
+     register char *text;
+{
+  register int hi;
+  register int i;
+  register tree idp;
+  register int len, hash_len;
+
+  /* Compute length of text in len.  */
+  for (len = 0; text[len]; len++);
+
+  /* Decide how much of that length to hash on */
+  hash_len = len;
+  if (warn_id_clash && len > id_clash_len)
+    hash_len = id_clash_len;
+
+  /* Compute hash code */
+  hi = hash_len * 613 + (unsigned) text[0];
+  for (i = 1; i < hash_len; i += 2)
+    hi = ((hi * 613) + (unsigned) (text[i]));
+
+  hi &= (1 << HASHBITS) - 1;
+  hi %= MAX_HASH_TABLE;
+  
+  /* Search table for identifier */
+  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
+    if (IDENTIFIER_LENGTH (idp) == len
+       && IDENTIFIER_POINTER (idp)[0] == text[0]
+       && !bcmp (IDENTIFIER_POINTER (idp), text, len))
+      return idp;              /* <-- return if found */
+
+  return NULL_TREE;
+}
+
 /* Enable warnings on similar identifiers (if requested).
    Done after the built-in identifiers are created.  */
 
@@ -1325,8 +1394,8 @@ build_real (type, d)
 #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
 
 REAL_VALUE_TYPE
-real_value_from_int_cst (i)
-     tree i;
+real_value_from_int_cst (type, i)
+     tree type, i;
 {
   REAL_VALUE_TYPE d;
   REAL_VALUE_TYPE e;
@@ -1335,9 +1404,11 @@ real_value_from_int_cst (i)
 
 #ifdef REAL_ARITHMETIC
   if (! TREE_UNSIGNED (TREE_TYPE (i)))
-    REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i));
+    REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
+                        TYPE_MODE (type));
   else
-    REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i));
+    REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i),
+                                 TREE_INT_CST_HIGH (i), TYPE_MODE (type));
 #else /* not REAL_ARITHMETIC */
   if (TREE_INT_CST_HIGH (i) < 0 && ! TREE_UNSIGNED (TREE_TYPE (i)))
     {
@@ -1387,7 +1458,12 @@ build_real_from_int_cst (type, i)
 
   set_float_handler (float_error);
 
-  d = REAL_VALUE_TRUNCATE (TYPE_MODE (type), real_value_from_int_cst (i));
+#ifdef REAL_ARITHMETIC
+  d = real_value_from_int_cst (type, i);
+#else
+  d = REAL_VALUE_TRUNCATE (TYPE_MODE (type),
+                          real_value_from_int_cst (type, i));
+#endif
 
   /* Check for valid float value for this type on this target machine.  */
 
@@ -1426,18 +1502,19 @@ build_string (len, str)
 
 /* Return a newly constructed COMPLEX_CST node whose value is
    specified by the real and imaginary parts REAL and IMAG.
-   Both REAL and IMAG should be constant nodes.
-   The TREE_TYPE is not initialized.  */
+   Both REAL and IMAG should be constant nodes.  TYPE, if specified,
+   will be the type of the COMPLEX_CST; otherwise a new type will be made.  */
 
 tree
-build_complex (real, imag)
+build_complex (type, real, imag)
+     tree type;
      tree real, imag;
 {
   register tree t = make_node (COMPLEX_CST);
 
   TREE_REALPART (t) = real;
   TREE_IMAGPART (t) = imag;
-  TREE_TYPE (t) = build_complex_type (TREE_TYPE (real));
+  TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real));
   TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag);
   TREE_CONSTANT_OVERFLOW (t)
     = TREE_CONSTANT_OVERFLOW (real) | TREE_CONSTANT_OVERFLOW (imag);
@@ -1445,6 +1522,7 @@ build_complex (real, imag)
 }
 
 /* Build a newly constructed TREE_VEC node of length LEN.  */
+
 tree
 make_tree_vec (len)
      int len;
@@ -1482,6 +1560,7 @@ integer_zerop (expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == INTEGER_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
           && TREE_INT_CST_LOW (expr) == 0
           && TREE_INT_CST_HIGH (expr) == 0)
          || (TREE_CODE (expr) == COMPLEX_CST
@@ -1499,6 +1578,7 @@ integer_onep (expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == INTEGER_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
           && TREE_INT_CST_LOW (expr) == 1
           && TREE_INT_CST_HIGH (expr) == 0)
          || (TREE_CODE (expr) == COMPLEX_CST
@@ -1523,7 +1603,8 @@ integer_all_onesp (expr)
       && integer_zerop (TREE_IMAGPART (expr)))
     return 1;
 
-  else if (TREE_CODE (expr) != INTEGER_CST)
+  else if (TREE_CODE (expr) != INTEGER_CST
+          || TREE_CONSTANT_OVERFLOW (expr))
     return 0;
 
   uns = TREE_UNSIGNED (TREE_TYPE (expr));
@@ -1563,6 +1644,7 @@ int
 integer_pow2p (expr)
      tree expr;
 {
+  int prec;
   HOST_WIDE_INT high, low;
 
   STRIP_NOPS (expr);
@@ -1572,12 +1654,28 @@ integer_pow2p (expr)
       && integer_zerop (TREE_IMAGPART (expr)))
     return 1;
 
-  if (TREE_CODE (expr) != INTEGER_CST)
+  if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr))
     return 0;
 
+  prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
+  /* First clear all bits that are beyond the type's precision in case
+     we've been sign extended.  */
+
+  if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+    ;
+  else if (prec > HOST_BITS_PER_WIDE_INT)
+    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+  else
+    {
+      high = 0;
+      if (prec < HOST_BITS_PER_WIDE_INT)
+       low &= ~((HOST_WIDE_INT) (-1) << prec);
+    }
+
   if (high == 0 && low == 0)
     return 0;
 
@@ -1585,6 +1683,45 @@ integer_pow2p (expr)
          || (low == 0 && (high & (high - 1)) == 0));
 }
 
+/* Return the power of two represented by a tree node known to be a
+   power of two.  */
+
+int
+tree_log2 (expr)
+     tree expr;
+{
+  int prec;
+  HOST_WIDE_INT high, low;
+
+  STRIP_NOPS (expr);
+
+  if (TREE_CODE (expr) == COMPLEX_CST)
+    return tree_log2 (TREE_REALPART (expr));
+
+  prec = (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+         ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+
+  high = TREE_INT_CST_HIGH (expr);
+  low = TREE_INT_CST_LOW (expr);
+
+  /* First clear all bits that are beyond the type's precision in case
+     we've been sign extended.  */
+
+  if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+    ;
+  else if (prec > HOST_BITS_PER_WIDE_INT)
+    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+  else
+    {
+      high = 0;
+      if (prec < HOST_BITS_PER_WIDE_INT)
+       low &= ~((HOST_WIDE_INT) (-1) << prec);
+    }
+
+  return (high != 0 ? HOST_BITS_PER_WIDE_INT + exact_log2 (high)
+         :  exact_log2 (low));
+}
+
 /* Return 1 if EXPR is the real constant zero.  */
 
 int
@@ -1594,6 +1731,7 @@ real_zerop (expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
           && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_zerop (TREE_REALPART (expr))
@@ -1609,6 +1747,7 @@ real_onep (expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
           && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_onep (TREE_REALPART (expr))
@@ -1624,6 +1763,7 @@ real_twop (expr)
   STRIP_NOPS (expr);
 
   return ((TREE_CODE (expr) == REAL_CST
+          && ! TREE_CONSTANT_OVERFLOW (expr)
           && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
          || (TREE_CODE (expr) == COMPLEX_CST
              && real_twop (TREE_REALPART (expr))
@@ -1692,7 +1832,7 @@ binfo_member (elem, list)
   return NULL_TREE;
 }
 
-/* Return nonzero if ELEM is part of the chain CHAIN. */
+/* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
 chain_member (elem, chain)
@@ -1709,7 +1849,7 @@ chain_member (elem, chain)
 }
 
 /* Return nonzero if ELEM is equal to TREE_VALUE (CHAIN) for any piece of
-   chain CHAIN. */
+   chain CHAIN.  */
 /* ??? This function was added for machine specific attributes but is no
    longer used.  It could be deleted if we could confirm all front ends
    don't use it.  */
@@ -1729,7 +1869,7 @@ chain_member_value (elem, chain)
 }
 
 /* Return nonzero if ELEM is equal to TREE_PURPOSE (CHAIN)
-   for any piece of chain CHAIN. */
+   for any piece of chain CHAIN.  */
 /* ??? This function was added for machine specific attributes but is no
    longer used.  It could be deleted if we could confirm all front ends
    don't use it.  */
@@ -1872,6 +2012,20 @@ build_decl_list (parm, value)
   return node;
 }
 
+/* Similar, but build on the expression_obstack.  */
+
+tree
+build_expr_list (parm, value)
+     tree parm, value;
+{
+  register tree node;
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = expression_obstack;
+  node = build_tree_list (parm, value);
+  current_obstack = ambient_obstack;
+  return node;
+}
+
 /* Return a newly created TREE_LIST node whose
    purpose and value fields are PARM and VALUE
    and whose TREE_CHAIN is CHAIN.  */
@@ -1918,6 +2072,20 @@ decl_tree_cons (purpose, value, chain)
   return node;
 }
 
+/* Similar, but build on the expression_obstack.  */
+
+tree
+expr_tree_cons (purpose, value, chain)
+     tree purpose, value, chain;
+{
+  register tree node;
+  register struct obstack *ambient_obstack = current_obstack;
+  current_obstack = expression_obstack;
+  node = tree_cons (purpose, value, chain);
+  current_obstack = ambient_obstack;
+  return node;
+}
+
 /* Same as `tree_cons' but make a permanent object.  */
 
 tree
@@ -2016,19 +2184,49 @@ int_size_in_bytes (type)
 }
 \f
 /* Return, as a tree node, the number of elements for TYPE (which is an
-   ARRAY_TYPE) minus one. This counts only elements of the top array.  */
+   ARRAY_TYPE) minus one. This counts only elements of the top array.
+
+   Don't let any SAVE_EXPRs escape; if we are called as part of a cleanup
+   action, they would get unsaved.  */
 
 tree
 array_type_nelts (type)
      tree type;
 {
-  tree index_type = TYPE_DOMAIN (type);
+  tree index_type, min, max;
 
-  return (integer_zerop (TYPE_MIN_VALUE (index_type))
-         ? TYPE_MAX_VALUE (index_type)
-         : fold (build (MINUS_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)),
-                        TYPE_MAX_VALUE (index_type),
-                        TYPE_MIN_VALUE (index_type))));
+  /* If they did it with unspecified bounds, then we should have already
+     given an error about it before we got here.  */
+  if (! TYPE_DOMAIN (type))
+    return error_mark_node;
+
+  index_type = TYPE_DOMAIN (type);
+  min = TYPE_MIN_VALUE (index_type);
+  max = TYPE_MAX_VALUE (index_type);
+
+  if (! TREE_CONSTANT (min))
+    {
+      STRIP_NOPS (min);
+      if (TREE_CODE (min) == SAVE_EXPR)
+       min = build (RTL_EXPR, TREE_TYPE (TYPE_MIN_VALUE (index_type)), 0,
+                    SAVE_EXPR_RTL (min));
+      else
+       min = TYPE_MIN_VALUE (index_type);
+    }
+
+  if (! TREE_CONSTANT (max))
+    {
+      STRIP_NOPS (max);
+      if (TREE_CODE (max) == SAVE_EXPR)
+       max = build (RTL_EXPR, TREE_TYPE (TYPE_MAX_VALUE (index_type)), 0,
+                    SAVE_EXPR_RTL (max));
+      else
+       max = TYPE_MAX_VALUE (index_type);
+    }
+
+  return (integer_zerop (min)
+         ? max
+         : fold (build (MINUS_EXPR, TREE_TYPE (max), max, min)));
 }
 \f
 /* Return nonzero if arg is static -- a reference to an object in
@@ -2043,7 +2241,7 @@ staticp (arg)
     case FUNCTION_DECL:
       /* Nested functions aren't static, since taking their address
         involves a trampoline.  */
-       return decl_function_context (arg) == 0;
+       return decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg);
     case VAR_DECL:
       return TREE_STATIC (arg) || DECL_EXTERNAL (arg);
 
@@ -2053,12 +2251,22 @@ staticp (arg)
     case STRING_CST:
       return 1;
 
+      /* If we are referencing a bitfield, we can't evaluate an
+        ADDR_EXPR at compile time and so it isn't a constant.  */
     case COMPONENT_REF:
+      return (! DECL_BIT_FIELD (TREE_OPERAND (arg, 1))
+             && staticp (TREE_OPERAND (arg, 0)));
+
     case BIT_FIELD_REF:
-      return staticp (TREE_OPERAND (arg, 0));
+      return 0;
 
+#if 0
+       /* This case is technically correct, but results in setting
+         TREE_CONSTANT on ADDR_EXPRs that cannot be evaluated at
+         compile time.  */
     case INDIRECT_REF:
       return TREE_CONSTANT (TREE_OPERAND (arg, 0));
+#endif
 
     case ARRAY_REF:
       if (TREE_CODE (TYPE_SIZE (TREE_TYPE (arg))) == INTEGER_CST
@@ -2106,10 +2314,10 @@ save_expr (expr)
      fact (i.e. this allows further folding, and direct checks for constants).
      However, a read-only object that has side effects cannot be bypassed.
      Since it is no problem to reevaluate literals, we just return the 
-     literal node. */
+     literal node.  */
 
   if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))
-      || TREE_CODE (t) == SAVE_EXPR)
+      || TREE_CODE (t) == SAVE_EXPR || TREE_CODE (t) == ERROR_MARK)
     return t;
 
   /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
@@ -2132,53 +2340,165 @@ save_expr (expr)
   TREE_SIDE_EFFECTS (t) = 1;
   return t;
 }
+
+/* Arrange for an expression to be expanded multiple independent
+   times.  This is useful for cleanup actions, as the backend can
+   expand them multiple times in different places.  */
+
+tree
+unsave_expr (expr)
+     tree expr;
+{
+  tree t;
+
+  /* If this is already protected, no sense in protecting it again.  */
+  if (TREE_CODE (expr) == UNSAVE_EXPR)
+    return expr;
+
+  t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
+  TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
+  return t;
+}
+
+/* Modify a tree in place so that all the evaluate only once things
+   are cleared out.  Return the EXPR given.  */
+
+tree
+unsave_expr_now (expr)
+     tree expr;
+{
+  enum tree_code code;
+  register int i;
+  int first_rtl;
+
+  if (expr == NULL_TREE)
+    return expr;
+
+  code = TREE_CODE (expr);
+  first_rtl = tree_code_length [(int) code];
+  switch (code)
+    {
+    case SAVE_EXPR:
+      SAVE_EXPR_RTL (expr) = 0;
+      first_rtl = 2;
+      break;
+
+    case TARGET_EXPR:
+      TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
+      TREE_OPERAND (expr, 3) = NULL_TREE;
+      break;
+      
+    case RTL_EXPR:
+      /* I don't yet know how to emit a sequence multiple times.  */
+      if (RTL_EXPR_SEQUENCE (expr) != 0)
+       abort ();
+      first_rtl = 0;
+      break;
+
+    case CALL_EXPR:
+      CALL_EXPR_RTL (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);
+           }
+       }
+      first_rtl = 2;
+      break;
+
+    case WITH_CLEANUP_EXPR:
+      /* Should be defined to be 2.  */
+      first_rtl = 1;
+      break;
+
+    case METHOD_CALL_EXPR:
+      first_rtl = 3;
+      break;
+    }
+
+  switch (TREE_CODE_CLASS (code))
+    {
+    case 'c':  /* a constant */
+    case 't':  /* a type node */
+    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
+    case 'd':  /* A decl node */
+    case 'b':  /* A block node */
+      return expr;
+
+    case 'e':  /* an expression */
+    case 'r':  /* a reference */
+    case 's':  /* an expression with side effects */
+    case '<':  /* a comparison expression */
+    case '2':  /* a binary arithmetic expression */
+    case '1':  /* a unary arithmetic expression */
+      for (i = first_rtl - 1; i >= 0; i--)
+       unsave_expr_now (TREE_OPERAND (expr, i));
+      return expr;
+
+    default:
+      abort ();
+    }
+}
 \f
 /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
-   or offset that depends on a field within a record.
-
-   Note that we only allow such expressions within simple arithmetic
-   or a COND_EXPR.  */
+   or offset that depends on a field within a record.  */
 
 int
 contains_placeholder_p (exp)
      tree exp;
 {
   register enum tree_code code = TREE_CODE (exp);
-  tree inner;
 
   /* If we have a WITH_RECORD_EXPR, it "cancels" any PLACEHOLDER_EXPR
      in it since it is supplying a value for it.  */
   if (code == WITH_RECORD_EXPR)
     return 0;
+  else if (code == PLACEHOLDER_EXPR)
+    return 1;
 
   switch (TREE_CODE_CLASS (code))
     {
     case 'r':
-      for (inner = TREE_OPERAND (exp, 0);
-          TREE_CODE_CLASS (TREE_CODE (inner)) == 'r';
-          inner = TREE_OPERAND (inner, 0))
-       ;
-      return TREE_CODE (inner) == PLACEHOLDER_EXPR;
+      /* Don't look at any PLACEHOLDER_EXPRs that might be in index or bit
+        position computations since they will be converted into a
+        WITH_RECORD_EXPR involving the reference, which will assume
+        here will be valid.  */
+      return contains_placeholder_p (TREE_OPERAND (exp, 0));
 
     case '1':
     case '2':  case '<':
     case 'e':
+      switch (code)
+       {
+       case COMPOUND_EXPR:
+         /* Ignoring the first operand isn't quite right, but works best. */
+         return contains_placeholder_p (TREE_OPERAND (exp, 1));
+
+       case RTL_EXPR:
+       case CONSTRUCTOR:
+         return 0;
+
+       case COND_EXPR:
+         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 1))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 2)));
+
+       case SAVE_EXPR:
+          return (SAVE_EXPR_RTL (exp) == 0
+                  && contains_placeholder_p (TREE_OPERAND (exp, 0)));
+       }
+
       switch (tree_code_length[(int) code])
        {
        case 1:
          return contains_placeholder_p (TREE_OPERAND (exp, 0));
        case 2:
-         return (code != RTL_EXPR
-                 && code != CONSTRUCTOR
-                 && ! (code == SAVE_EXPR && SAVE_EXPR_RTL (exp) != 0)
-                 && code != WITH_RECORD_EXPR
-                 && (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 1))));
-       case 3:
-         return (code == COND_EXPR
-                 && (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 1))
-                     || contains_placeholder_p (TREE_OPERAND (exp, 2))));
+         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
+                 || contains_placeholder_p (TREE_OPERAND (exp, 1)));
        }
     }
 
@@ -2197,6 +2517,7 @@ substitute_in_expr (exp, f, r)
      tree r;
 {
   enum tree_code code = TREE_CODE (exp);
+  tree op0, op1, op2;
   tree new = 0;
   tree inner;
 
@@ -2218,9 +2539,11 @@ substitute_in_expr (exp, f, r)
       switch (tree_code_length[(int) code])
        {
        case 1:
-         new = fold (build1 (code, TREE_TYPE (exp),
-                             substitute_in_expr (TREE_OPERAND (exp, 0),
-                                                 f, r)));
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
+         
+         new = fold (build1 (code, TREE_TYPE (exp), op0));
          break;
 
        case 2:
@@ -2231,10 +2554,12 @@ substitute_in_expr (exp, f, r)
          else if (code == CONSTRUCTOR)
            abort ();
 
-         new = fold (build (code, TREE_TYPE (exp),
-                            substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 1),
-                                                f, r)));
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
+         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
+           return exp;
+
+         new = fold (build (code, TREE_TYPE (exp), op0, op1));
          break;
 
        case 3:
@@ -2246,11 +2571,14 @@ substitute_in_expr (exp, f, r)
          if (code != COND_EXPR)
            abort ();
 
-         new = fold (build (code, TREE_TYPE (exp),
-                            substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 1), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 2),
-                                                f, r)));
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
+         op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
+         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+             && op2 == TREE_OPERAND (exp, 2))
+           return exp;
+
+         new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
        }
 
       break;
@@ -2269,29 +2597,38 @@ substitute_in_expr (exp, f, r)
              && TREE_OPERAND (exp, 1) == f)
            return r;
 
-         new = fold (build (code, TREE_TYPE (exp),
-                            substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
+         /* If this expression hasn't been completed let, leave it 
+            alone.  */
+         if (TREE_CODE (inner) == PLACEHOLDER_EXPR
+             && TREE_TYPE (inner) == 0)
+           return exp;
+
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
+
+         new = fold (build (code, TREE_TYPE (exp), op0,
                             TREE_OPERAND (exp, 1)));
          break;
 
        case BIT_FIELD_REF:
-         new = fold (build (code, TREE_TYPE (exp),
-                            substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 1), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 2), f, r)));
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
+         op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
+         if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
+             && op2 == TREE_OPERAND (exp, 2))
+           return exp;
+
+         new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
          break;
 
        case INDIRECT_REF:
        case BUFFER_REF:
-         new = fold (build1 (code, TREE_TYPE (exp),
-                             substitute_in_expr (TREE_OPERAND (exp, 0),
-                                                 f, r)));
-         break;
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
 
-       case OFFSET_REF:
-         new = fold (build (code, TREE_TYPE (exp),
-                            substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                            substitute_in_expr (TREE_OPERAND (exp, 1), f, r)));
+         new = fold (build1 (code, TREE_TYPE (exp), op0));
          break;
        }
     }
@@ -2304,146 +2641,6 @@ substitute_in_expr (exp, f, r)
   return new;
 }
 \f
-/* Given a type T, a FIELD_DECL F, and a replacement value R,
-   return a new type with all size expressions that contain F
-   updated by replacing F with R.  */
-
-tree
-substitute_in_type (t, f, r)
-     tree t, f, r;
-{
-  switch (TREE_CODE (t))
-    {
-    case POINTER_TYPE:
-    case VOID_TYPE:
-      return t;
-    case INTEGER_TYPE:
-    case ENUMERAL_TYPE:
-    case BOOLEAN_TYPE:
-    case CHAR_TYPE:
-      if ((TREE_CODE (TYPE_MIN_VALUE (t)) != INTEGER_CST
-          && contains_placeholder_p (TYPE_MIN_VALUE (t)))
-         || (TREE_CODE (TYPE_MAX_VALUE (t)) != INTEGER_CST
-             && contains_placeholder_p (TYPE_MAX_VALUE (t))))
-       return build_range_type (t,
-                                substitute_in_expr (TYPE_MIN_VALUE (t), f, r),
-                                substitute_in_expr (TYPE_MAX_VALUE (t), f, r));
-      return t;
-
-    case REAL_TYPE:
-      if ((TYPE_MIN_VALUE (t) != 0
-          && TREE_CODE (TYPE_MIN_VALUE (t)) != REAL_CST
-          && contains_placeholder_p (TYPE_MIN_VALUE (t)))
-         || (TYPE_MAX_VALUE (t) != 0
-             && TREE_CODE (TYPE_MAX_VALUE (t)) != REAL_CST
-             && contains_placeholder_p (TYPE_MAX_VALUE (t))))
-       {
-         t = build_type_copy (t);
-
-         if (TYPE_MIN_VALUE (t))
-           TYPE_MIN_VALUE (t) = substitute_in_expr (TYPE_MIN_VALUE (t), f, r);
-         if (TYPE_MAX_VALUE (t))
-           TYPE_MAX_VALUE (t) = substitute_in_expr (TYPE_MAX_VALUE (t), f, r);
-       }
-      return t;
-
-    case COMPLEX_TYPE:
-      return build_complex_type (substitute_in_type (TREE_TYPE (t), f, r));
-
-    case OFFSET_TYPE:
-    case METHOD_TYPE:
-    case REFERENCE_TYPE:
-    case FILE_TYPE:
-    case SET_TYPE:
-    case FUNCTION_TYPE:
-    case LANG_TYPE:
-      /* Don't know how to do these yet.  */
-      abort ();
-
-    case ARRAY_TYPE:
-      t = build_array_type (substitute_in_type (TREE_TYPE (t), f, r),
-                           substitute_in_type (TYPE_DOMAIN (t), f, r));
-      TYPE_SIZE (t) = 0;
-      layout_type (t);
-      return t;
-
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      {
-       tree new = copy_node (t);
-       tree field;
-       tree last_field = 0;
-
-       /* Start out with no fields, make new fields, and chain them
-          in.  */
-
-       TYPE_FIELDS (new) = 0;
-       TYPE_SIZE (new) = 0;
-
-       for (field = TYPE_FIELDS (t); field;
-            field = TREE_CHAIN (field))
-         {
-           tree new_field = copy_node (field);
-
-           TREE_TYPE (new_field)
-             = substitute_in_type (TREE_TYPE (new_field), f, r);
-
-           /* If this is an anonymous field and the type of this field is
-              a UNION_TYPE or RECORD_TYPE with no elements, ignore it.  If
-              the type just has one element, treat that as the field. 
-              But don't do this if we are processing a QUAL_UNION_TYPE.  */
-           if (TREE_CODE (t) != QUAL_UNION_TYPE && DECL_NAME (new_field) == 0
-               && (TREE_CODE (TREE_TYPE (new_field)) == UNION_TYPE
-                   || TREE_CODE (TREE_TYPE (new_field)) == RECORD_TYPE))
-             {
-               if (TYPE_FIELDS (TREE_TYPE (new_field)) == 0)
-                 continue;
-
-               if (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (new_field))) == 0)
-                 new_field = TYPE_FIELDS (TREE_TYPE (new_field));
-             }
-
-           DECL_CONTEXT (new_field) = new;
-           DECL_SIZE (new_field) = 0;
-
-           if (TREE_CODE (t) == QUAL_UNION_TYPE)
-             {
-               /* Do the substitution inside the qualifier and if we find
-                  that this field will not be present, omit it.  */
-               DECL_QUALIFIER (new_field)
-                 = substitute_in_expr (DECL_QUALIFIER (field), f, r);
-               if (integer_zerop (DECL_QUALIFIER (new_field)))
-                 continue;
-             }
-
-           if (last_field == 0)
-             TYPE_FIELDS (new) = new_field;
-           else
-             TREE_CHAIN (last_field) = new_field;
-
-           last_field = new_field;
-
-           /* If this is a qualified type and this field will always be
-              present, we are done.  */
-           if (TREE_CODE (t) == QUAL_UNION_TYPE
-               && integer_onep (DECL_QUALIFIER (new_field)))
-             break;
-         }
-
-       /* If this used to be a qualified union type, but we now know what
-          field will be present, make this a normal union.  */
-       if (TREE_CODE (new) == QUAL_UNION_TYPE
-           && (TYPE_FIELDS (new) == 0
-               || integer_onep (DECL_QUALIFIER (TYPE_FIELDS (new)))))
-         TREE_SET_CODE (new, UNION_TYPE);
-
-       layout_type (new);
-       return new;
-      }
-    }
-}
-\f
 /* Stabilize a reference so that we can use it any number of times
    without causing its operands to be evaluated more than once.
    Returns the stabilized reference.  This works by means of save_expr,
@@ -2502,10 +2699,10 @@ stabilize_reference (ref)
       break;
 
     case COMPOUND_EXPR:
-      result = build_nt (COMPOUND_EXPR,
-                        stabilize_reference_1 (TREE_OPERAND (ref, 0)),
-                        stabilize_reference (TREE_OPERAND (ref, 1)));
-      break;
+      /* We cannot wrap the first expression in a SAVE_EXPR, as then
+        it wouldn't be ignored.  This matters when dealing with
+        volatiles.  */
+      return stabilize_reference_1 (ref);
 
     case RTL_EXPR:
       result = build1 (INDIRECT_REF, TREE_TYPE (ref),
@@ -2693,13 +2890,14 @@ build VPROTO((enum tree_code code, tree tt, ...))
 /* Same as above, but only builds for unary operators.
    Saves lions share of calls to `build'; cuts down use
    of varargs, which is expensive for RISC machines.  */
+
 tree
 build1 (code, type, node)
      enum tree_code code;
      tree type;
      tree node;
 {
-  register struct obstack *obstack = current_obstack;
+  register struct obstack *obstack = expression_obstack;
   register int i, length;
   register tree_node_kind kind;
   register tree t;
@@ -2711,7 +2909,6 @@ build1 (code, type, node)
     kind = e_kind;
 #endif
 
-  obstack = expression_obstack;
   length = sizeof (struct tree_exp);
 
   t = (tree) obstack_alloc (obstack, length);
@@ -2872,7 +3069,7 @@ build_block (vars, tags, subblocks, supercontext, chain)
 }
 \f
 /* Return a declaration like DDECL except that its DECL_MACHINE_ATTRIBUTE
-   is ATTRIBUTE. */
+   is ATTRIBUTE.  */
 
 tree
 build_decl_attribute_variant (ddecl, attribute)
@@ -2942,7 +3139,7 @@ build_type_attribute_variant (ttype, attribute)
 
 /* Return a 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration DECL
    or type TYPE and 0 otherwise.  Validity is determined the configuration
-   macros VALID_MACHINE_DECL_ATTRIBUTE and VALID_MACHINE_TYPE_ATTRIBUTE. */
+   macros VALID_MACHINE_DECL_ATTRIBUTE and VALID_MACHINE_TYPE_ATTRIBUTE.  */
 
 int
 valid_machine_attribute (attr_name, attr_args, decl, type)
@@ -3003,6 +3200,33 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
        TREE_TYPE (decl) = type;
       valid = 1;
     }
+
+  /* Handle putting a type attribute on pointer-to-function-type by putting
+     the attribute on the function type.  */
+  else if (TREE_CODE (type) == POINTER_TYPE
+          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+          && VALID_MACHINE_TYPE_ATTRIBUTE (TREE_TYPE (type), type_attr_list,
+                                           attr_name, attr_args))
+    {
+      tree inner_type = TREE_TYPE (type);
+      tree inner_attr_list = TYPE_ATTRIBUTES (inner_type);
+      tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
+                                   type_attr_list);
+
+      if (attr != NULL_TREE)
+       TREE_VALUE (attr) = attr_args;
+      else
+       {
+         inner_attr_list = tree_cons (attr_name, attr_args, inner_attr_list);
+         inner_type = build_type_attribute_variant (inner_type,
+                                                    inner_attr_list);
+       }
+
+      if (decl != 0)
+       TREE_TYPE (decl) = build_pointer_type (inner_type);
+
+      valid = 1;
+    }
 #endif
 
   return valid;
@@ -3078,6 +3302,44 @@ lookup_attribute (attr_name, list)
 
   return NULL_TREE;
 }
+
+/* Return an attribute list that is the union of a1 and a2.  */
+
+tree
+merge_attributes (a1, a2)
+     register tree a1, a2;
+{
+  tree attributes;
+
+  /* Either one unset?  Take the set one.  */
+
+  if (! (attributes = a1))
+    attributes = a2;
+
+  /* One that completely contains the other?  Take it.  */
+
+  else if (a2 && ! attribute_list_contained (a1, a2))
+    if (attribute_list_contained (a2, a1))
+      attributes = a2;
+    else
+      {
+       /* Pick the longest list, and hang on the other list.  */
+       /* ??? For the moment we punt on the issue of attrs with args.  */
+
+       if (list_length (a1) < list_length (a2))
+         attributes = a2, a2 = a1;
+
+       for (; a2; a2 = TREE_CHAIN (a2))
+         if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
+                               attributes) == NULL_TREE)
+           {
+             a1 = copy_node (a2);
+             TREE_CHAIN (a1) = attributes;
+             attributes = a1;
+           }
+      }
+  return attributes;
+}
 \f
 /* Return a type like TYPE except that its TYPE_READONLY is CONSTP
    and its TYPE_VOLATILE is VOLATILEP.
@@ -3107,7 +3369,7 @@ build_type_variant (type, constp, volatilep)
      like the one we need to have.  If so, use that existing one.  We must
      preserve the TYPE_NAME, since there is code that depends on this.  */
 
-  for (t = TYPE_MAIN_VARIANT(type); t; t = TYPE_NEXT_VARIANT (t))
+  for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
     if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
        && TYPE_NAME (t) == TYPE_NAME (type))
       return t;
@@ -3121,34 +3383,6 @@ build_type_variant (type, constp, volatilep)
   return t;
 }
 
-/* Give TYPE a new main variant: NEW_MAIN.
-   This is the right thing to do only when something else
-   about TYPE is modified in place.  */
-
-void
-change_main_variant (type, new_main)
-     tree type, new_main;
-{
-  tree t;
-  tree omain = TYPE_MAIN_VARIANT (type);
-
-  /* Remove TYPE from the TYPE_NEXT_VARIANT chain of its main variant.  */
-  if (TYPE_NEXT_VARIANT (omain) == type)
-    TYPE_NEXT_VARIANT (omain) = TYPE_NEXT_VARIANT (type);
-  else
-    for (t = TYPE_NEXT_VARIANT (omain); t && TYPE_NEXT_VARIANT (t);
-        t = TYPE_NEXT_VARIANT (t))
-      if (TYPE_NEXT_VARIANT (t) == type)
-       {
-         TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (type);
-         break;
-       }
-
-  TYPE_MAIN_VARIANT (type) = new_main;
-  TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (new_main);
-  TYPE_NEXT_VARIANT (new_main) = type;
-}
-
 /* Create a new variant of TYPE, equivalent but distinct.
    This is so the caller can modify it.  */
 
@@ -3232,12 +3466,14 @@ type_hash_lookup (hashcode, type)
        && (TYPE_MIN_VALUE (h->type) == TYPE_MIN_VALUE (type)
            || tree_int_cst_equal (TYPE_MIN_VALUE (h->type),
                                   TYPE_MIN_VALUE (type)))
+       /* Note that TYPE_DOMAIN is TYPE_ARG_TYPES for FUNCTION_TYPE.  */
        && (TYPE_DOMAIN (h->type) == TYPE_DOMAIN (type)
            || (TYPE_DOMAIN (h->type)
                && TREE_CODE (TYPE_DOMAIN (h->type)) == TREE_LIST
                && TYPE_DOMAIN (type)
                && TREE_CODE (TYPE_DOMAIN (type)) == TREE_LIST
-               && type_list_equal (TYPE_DOMAIN (h->type), TYPE_DOMAIN (type)))))
+               && type_list_equal (TYPE_DOMAIN (h->type),
+                                   TYPE_DOMAIN (type)))))
       return h->type;
   return 0;
 }
@@ -3359,7 +3595,8 @@ attribute_list_contained (l1, l2)
 
   for (; t2; t2 = TREE_CHAIN (t2))
     {
-      tree attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
+      tree attr
+       = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
 
       if (attr == NULL_TREE)
        return 0;
@@ -3380,21 +3617,14 @@ type_list_equal (l1, l2)
      tree l1, l2;
 {
   register tree t1, t2;
+
   for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
-    {
-      if (TREE_VALUE (t1) != TREE_VALUE (t2))
-       return 0;
-      if (TREE_PURPOSE (t1) != TREE_PURPOSE (t2))
-       {
-         int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
-         if (cmp < 0)
-           abort ();
-         if (cmp == 0
-             || TREE_TYPE (TREE_PURPOSE (t1))
-                != TREE_TYPE (TREE_PURPOSE (t2)))
-           return 0;
-       }
-    }
+    if (TREE_VALUE (t1) != TREE_VALUE (t2)
+       || (TREE_PURPOSE (t1) != TREE_PURPOSE (t2)
+           && ! (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))
+                 && (TREE_TYPE (TREE_PURPOSE (t1))
+                     == TREE_TYPE (TREE_PURPOSE (t2))))))
+      return 0;
 
   return t1 == t2;
 }
@@ -3451,21 +3681,22 @@ tree_int_cst_sgn (t)
     return 1;
 }
 
-/* Compare two constructor-element-type constants.  */
+/* Compare two constructor-element-type constants.  Return 1 if the lists
+   are known to be equal; otherwise return 0.  */
+
 int
 simple_cst_list_equal (l1, l2)
      tree l1, l2;
 {
   while (l1 != NULL_TREE && l2 != NULL_TREE)
     {
-      int cmp = simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2));
-      if (cmp < 0)
-       abort ();
-      if (cmp == 0)
+      if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
        return 0;
+
       l1 = TREE_CHAIN (l1);
       l2 = TREE_CHAIN (l2);
     }
+
   return (l1 == l2);
 }
 
@@ -3564,8 +3795,13 @@ simple_cst_equal (t1, t2)
       return 0;
     }
 
-  /* This general rule works for most tree codes.
-     All exceptions should be handled above.  */
+  /* This general rule works for most tree codes.  All exceptions should be
+     handled above.  If this is a language-specific tree code, we can't
+     trust what might be in the operand, so say we don't know
+     the situation.  */
+  if ((int) code1
+      >= sizeof standard_tree_code_type / sizeof standard_tree_code_type[0])
+    return -1;
 
   switch (TREE_CODE_CLASS (code1))
     {
@@ -3634,10 +3870,14 @@ build_index_type (maxval)
      tree maxval;
 {
   register tree itype = make_node (INTEGER_TYPE);
+
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
-  TYPE_MIN_VALUE (itype) = build_int_2 (0, 0);
-  TREE_TYPE (TYPE_MIN_VALUE (itype)) = sizetype;
+  TYPE_MIN_VALUE (itype) = size_zero_node;
+
+  push_obstacks (TYPE_OBSTACK (itype), TYPE_OBSTACK (itype));
   TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
+  pop_obstacks ();
+
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);
@@ -3660,19 +3900,24 @@ build_index_type (maxval)
 /* Create a range of some discrete type TYPE (an INTEGER_TYPE,
    ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
    low bound LOWVAL and high bound HIGHVAL.
-   if TYPE==NULL_TREE, sizetype is used. */
+   if TYPE==NULL_TREE, sizetype is used.  */
 
 tree
 build_range_type (type, lowval, highval)
      tree type, lowval, highval;
 {
   register tree itype = make_node (INTEGER_TYPE);
+
   TREE_TYPE (itype) = type;
   if (type == NULL_TREE)
     type = sizetype;
-  TYPE_PRECISION (itype) = TYPE_PRECISION (type);
+
+  push_obstacks (TYPE_OBSTACK (itype), TYPE_OBSTACK (itype));
   TYPE_MIN_VALUE (itype) = convert (type, lowval);
   TYPE_MAX_VALUE (itype) = convert (type, highval);
+  pop_obstacks ();
+
+  TYPE_PRECISION (itype) = TYPE_PRECISION (type);
   TYPE_MODE (itype) = TYPE_MODE (type);
   TYPE_SIZE (itype) = TYPE_SIZE (type);
   TYPE_ALIGN (itype) = TYPE_ALIGN (type);
@@ -3689,7 +3934,7 @@ build_range_type (type, lowval, highval)
 }
 
 /* Just like build_index_type, but takes lowval and highval instead
-   of just highval (maxval). */
+   of just highval (maxval).  */
 
 tree
 build_index_2_type (lowval,highval)
@@ -3713,13 +3958,16 @@ index_type_equal (itype1, itype2)
     {
       if (TYPE_PRECISION (itype1) != TYPE_PRECISION (itype2)
          || TYPE_MODE (itype1) != TYPE_MODE (itype2)
-         || ! simple_cst_equal (TYPE_SIZE (itype1), TYPE_SIZE (itype2))
+         || simple_cst_equal (TYPE_SIZE (itype1), TYPE_SIZE (itype2)) != 1
          || TYPE_ALIGN (itype1) != TYPE_ALIGN (itype2))
        return 0;
-      if (simple_cst_equal (TYPE_MIN_VALUE (itype1), TYPE_MIN_VALUE (itype2))
-         && simple_cst_equal (TYPE_MAX_VALUE (itype1), TYPE_MAX_VALUE (itype2)))
+      if (1 == simple_cst_equal (TYPE_MIN_VALUE (itype1),
+                                TYPE_MIN_VALUE (itype2))
+         && 1 == simple_cst_equal (TYPE_MAX_VALUE (itype1),
+                                   TYPE_MAX_VALUE (itype2)))
        return 1;
     }
+
   return 0;
 }
 
@@ -3757,15 +4005,6 @@ build_array_type (elt_type, index_type)
   hashcode = TYPE_HASH (elt_type) + TYPE_HASH (index_type);
   t = type_hash_canon (hashcode, t);
 
-#if 0 /* This led to crashes, because it could put a temporary node
-        on the TYPE_NEXT_VARIANT chain of a permanent one.  */
-  /* The main variant of an array type should always
-     be an array whose element type is the main variant.  */
-  if (elt_type != TYPE_MAIN_VARIANT (elt_type))
-    change_main_variant (t, build_array_type (TYPE_MAIN_VARIANT (elt_type),
-                                             index_type));
-#endif
-
   if (TYPE_SIZE (t) == 0)
     layout_type (t);
   return t;
@@ -4012,7 +4251,9 @@ get_unwidened (op, for_type)
 
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
-      && TREE_CODE (type) != REAL_TYPE)
+      && TREE_CODE (type) != REAL_TYPE
+      /* Don't crash if field not layed out yet.  */
+      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
     {
       unsigned innerprec = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
       type = type_for_size (innerprec, TREE_UNSIGNED (TREE_OPERAND (op, 1)));
@@ -4151,12 +4392,18 @@ int_fits_type_p (c, type)
     return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
               && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c))
            && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))));
+                 && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)))
+           /* Negative ints never fit unsigned types.  */
+           && ! (TREE_INT_CST_HIGH (c) < 0
+                 && ! TREE_UNSIGNED (TREE_TYPE (c))));
   else
     return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
               && INT_CST_LT (TYPE_MAX_VALUE (type), c))
            && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT (c, TYPE_MIN_VALUE (type))));
+                 && INT_CST_LT (c, TYPE_MIN_VALUE (type)))
+           /* Unsigned ints with top bit set never fit signed types.  */
+           && ! (TREE_INT_CST_HIGH (c) < 0
+                 && TREE_UNSIGNED (TREE_TYPE (c))));
 }
 
 /* Return the innermost context enclosing DECL that is
@@ -4179,8 +4426,9 @@ decl_function_context (decl)
   while (context && TREE_CODE (context) != FUNCTION_DECL)
     {
       if (TREE_CODE (context) == RECORD_TYPE
-         || TREE_CODE (context) == UNION_TYPE)
-       context = NULL_TREE;
+         || TREE_CODE (context) == UNION_TYPE
+         || TREE_CODE (context) == QUAL_UNION_TYPE)
+       context = TYPE_CONTEXT (context);
       else if (TREE_CODE (context) == TYPE_DECL)
        context = DECL_CONTEXT (context);
       else if (TREE_CODE (context) == BLOCK)
@@ -4282,7 +4530,7 @@ dump_tree_statistics ()
 extern char * first_global_object_name;
 
 /* If KIND=='I', return a suitable global initializer (constructor) name.
-   If KIND=='D', return a suitable global clean-up (destructor) name. */
+   If KIND=='D', return a suitable global clean-up (destructor) name.  */
 
 tree
 get_file_function_name (kind)
@@ -4306,7 +4554,7 @@ get_file_function_name (kind)
      constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
   sprintf (buf, FILE_FUNCTION_FORMAT, p);
 
-  /* Don't need to pull wierd characters out of global names.  */
+  /* Don't need to pull weird characters out of global names.  */
   if (p != first_global_object_name)
     {
       for (p = buf+11; *p; p++)
@@ -4319,7 +4567,7 @@ get_file_function_name (kind)
 #ifndef NO_DOLLAR_IN_LABEL     /* this for `$'; unlikely, but... -- kr */
               || *p == '$'
 #endif
-#ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but... */
+#ifndef NO_DOT_IN_LABEL                /* this for `.'; unlikely, but...  */
               || *p == '.'
 #endif
               || (*p >= 'A' && *p <= 'Z')
@@ -4332,12 +4580,12 @@ get_file_function_name (kind)
   return get_identifier (buf);
 }
 \f
-/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
+/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
    The result is placed in BUFFER (which has length BIT_SIZE),
    with one bit in each char ('\000' or '\001').
 
    If the constructor is constant, NULL_TREE is returned.
-   Otherwise, a TREE_LIST of the non-constant elements is emitted. */
+   Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
 
 tree
 get_set_constructor_bits (init, buffer, bit_size)
@@ -4359,11 +4607,11 @@ get_set_constructor_bits (init, buffer, bit_size)
       if (TREE_CODE (TREE_VALUE (vals)) != INTEGER_CST
          || (TREE_PURPOSE (vals) != NULL_TREE
              && TREE_CODE (TREE_PURPOSE (vals)) != INTEGER_CST))
-       non_const_bits =
-         tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
+       non_const_bits
+         tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
       else if (TREE_PURPOSE (vals) != NULL_TREE)
        {
-         /* Set a range of bits to ones. */
+         /* Set a range of bits to ones.  */
          HOST_WIDE_INT lo_index
            = TREE_INT_CST_LOW (TREE_PURPOSE (vals)) - domain_min;
          HOST_WIDE_INT hi_index
@@ -4376,7 +4624,7 @@ get_set_constructor_bits (init, buffer, bit_size)
        }
       else
        {
-         /* Set a single bit to one. */
+         /* Set a single bit to one.  */
          HOST_WIDE_INT index
            = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
          if (index < 0 || index >= bit_size)
@@ -4390,10 +4638,10 @@ get_set_constructor_bits (init, buffer, bit_size)
   return non_const_bits;
 }
 
-/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
+/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
    The result is placed in BUFFER (which is an array of bytes).
    If the constructor is constant, NULL_TREE is returned.
-   Otherwise, a TREE_LIST of the non-constant elements is emitted. */
+   Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
 
 tree
 get_set_constructor_bytes (init, buffer, wd_size)
@@ -4407,7 +4655,7 @@ get_set_constructor_bytes (init, buffer, wd_size)
   int bit_size = wd_size * set_word_size;
   int bit_pos = 0;
   unsigned char *bytep = buffer;
-  char *bit_buffer = (char*)alloca(bit_size);
+  char *bit_buffer = (char *) alloca(bit_size);
   tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size);
 
   for (i = 0; i < wd_size; i++)