OSDN Git Service

(struct function): Make frame_offset be HOST_WIDE_INT.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index fcbfd53..6a1e953 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, 93, 94, 95, 1996 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__
@@ -339,6 +341,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 +394,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 +423,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;
@@ -749,7 +754,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 +925,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 +1133,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)
@@ -1161,6 +1164,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 +1227,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;
@@ -1325,8 +1336,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 +1346,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 +1400,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 +1444,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 +1464,7 @@ build_complex (real, imag)
 }
 
 /* Build a newly constructed TREE_VEC node of length LEN.  */
+
 tree
 make_tree_vec (len)
      int len;
@@ -1482,6 +1502,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 +1520,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 +1545,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));
@@ -1572,7 +1595,7 @@ 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;
 
   high = TREE_INT_CST_HIGH (expr);
@@ -1594,6 +1617,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 +1633,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 +1649,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 +1718,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 +1735,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 +1755,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.  */
@@ -2043,7 +2069,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);
 
@@ -2057,8 +2083,13 @@ staticp (arg)
     case BIT_FIELD_REF:
       return staticp (TREE_OPERAND (arg, 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 +2137,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,6 +2163,95 @@ 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;
+
+  if (expr == NULL_TREE)
+    return expr;
+
+  code = TREE_CODE (expr);
+  switch (code)
+    {
+    case SAVE_EXPR:
+      SAVE_EXPR_RTL (expr) = 0;
+      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 ();
+      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);
+           }
+       }
+      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 = tree_code_length[(int) code] - 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.
@@ -2150,6 +2270,8 @@ contains_placeholder_p (exp)
      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))
     {
@@ -2197,6 +2319,8 @@ substitute_in_expr (exp, f, r)
      tree r;
 {
   enum tree_code code = TREE_CODE (exp);
+  tree op0, op1, op2;
+  tree new = 0;
   tree inner;
 
   switch (TREE_CODE_CLASS (code))
@@ -2217,9 +2341,12 @@ substitute_in_expr (exp, f, r)
       switch (tree_code_length[(int) code])
        {
        case 1:
-         return 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:
          /* An RTL_EXPR cannot contain a PLACEHOLDER_EXPR; a CONSTRUCTOR
@@ -2229,10 +2356,13 @@ substitute_in_expr (exp, f, r)
          else if (code == CONSTRUCTOR)
            abort ();
 
-         return 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:
          /* It cannot be that anything inside a SAVE_EXPR contains a
@@ -2243,11 +2373,14 @@ substitute_in_expr (exp, f, r)
          if (code != COND_EXPR)
            abort ();
 
-         return 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;
@@ -2266,169 +2399,48 @@ substitute_in_expr (exp, f, r)
              && TREE_OPERAND (exp, 1) == f)
            return r;
 
-         return fold (build (code, TREE_TYPE (exp),
-                             substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                             TREE_OPERAND (exp, 1)));
-       case BIT_FIELD_REF:
-         return 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)));
-       case INDIRECT_REF:
-       case BUFFER_REF:
-         return fold (build1 (code, TREE_TYPE (exp),
-                              substitute_in_expr (TREE_OPERAND (exp, 0),
-                                                f, r)));
-       case OFFSET_REF:
-         return fold (build (code, TREE_TYPE (exp),
-                             substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
-                             substitute_in_expr (TREE_OPERAND (exp, 1), 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;
 
-  /* If it wasn't one of the cases we handle, give up.  */
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
 
-  abort ();
-}
-\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.  */
+         new = fold (build (code, TREE_TYPE (exp), op0,
+                            TREE_OPERAND (exp, 1)));
+         break;
 
-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 BIT_FIELD_REF:
+         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;
 
-    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);
+         new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
+         break;
 
-         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 INDIRECT_REF:
+       case BUFFER_REF:
+         op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
+         if (op0 == TREE_OPERAND (exp, 0))
+           return exp;
 
-    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 ();
+         new = fold (build1 (code, TREE_TYPE (exp), op0));
+         break;
+       }
+    }
 
-    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;
+  /* If it wasn't one of the cases we handle, give up.  */
+  if (new == 0)
+    abort ();
 
-    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;
-      }
-    }
+  TREE_READONLY (new) = TREE_READONLY (exp);
+  return new;
 }
 \f
 /* Stabilize a reference so that we can use it any number of times
@@ -2489,10 +2501,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),
@@ -2680,13 +2692,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;
@@ -2698,7 +2711,6 @@ build1 (code, type, node)
     kind = e_kind;
 #endif
 
-  obstack = expression_obstack;
   length = sizeof (struct tree_exp);
 
   t = (tree) obstack_alloc (obstack, length);
@@ -2859,7 +2871,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)
@@ -2929,7 +2941,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)
@@ -2990,6 +3002,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;
@@ -3065,6 +3104,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.
@@ -3094,7 +3171,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;
@@ -3219,12 +3296,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;
 }
@@ -3346,7 +3425,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;
@@ -3367,21 +3447,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;
 }
@@ -3438,21 +3511,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);
 }
 
@@ -3551,8 +3625,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))
     {
@@ -3647,7 +3726,7 @@ 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)
@@ -3676,7 +3755,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)
@@ -3700,13 +3779,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;
 }
 
@@ -4166,8 +4248,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)
@@ -4269,7 +4352,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)
@@ -4293,7 +4376,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++)
@@ -4306,7 +4389,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')
@@ -4319,12 +4402,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)
@@ -4350,7 +4433,7 @@ get_set_constructor_bits (init, buffer, bit_size)
          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
@@ -4363,7 +4446,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)
@@ -4377,10 +4460,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)
@@ -4394,7 +4477,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++)