OSDN Git Service

* tree.c (get_unwidened): Check TREE_UNSIGNED on the field's type.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 8cb27aa..7d0258c 100644 (file)
@@ -1,6 +1,6 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -47,32 +47,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 
 /* obstack.[ch] explicitly declined to prototype this.  */
-extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj));
+extern int _obstack_allocated_p (struct obstack *h, void *obj);
 
 #ifdef GATHER_STATISTICS
 /* Statistics-gathering stuff.  */
-typedef enum
-{
-  d_kind,
-  t_kind,
-  b_kind,
-  s_kind,
-  r_kind,
-  e_kind,
-  c_kind,
-  id_kind,
-  perm_list_kind,
-  temp_list_kind,
-  vec_kind,
-  x_kind,
-  lang_decl,
-  lang_type,
-  all_kinds
-} tree_node_kind;
 
 int tree_node_counts[(int) all_kinds];
 int tree_node_sizes[(int) all_kinds];
 
+/* Keep in sync with tree.h:enum tree_node_kind.  */
 static const char * const tree_node_kind_names[] = {
   "decls",
   "types",
@@ -92,9 +75,9 @@ static const char * const tree_node_kind_names[] = {
 #endif /* GATHER_STATISTICS */
 
 /* Unique id for next decl created.  */
-static int next_decl_uid;
+static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
-static int next_type_uid = 1;
+static GTY(()) int next_type_uid = 1;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -118,14 +101,13 @@ struct type_hash GTY(())
 static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
      htab_t type_hash_table;
 
-static void set_type_quals PARAMS ((tree, int));
-static void append_random_chars PARAMS ((char *));
-static int type_hash_eq PARAMS ((const void *, const void *));
-static hashval_t type_hash_hash PARAMS ((const void *));
-static void print_type_hash_statistics PARAMS((void));
-static void finish_vector_type PARAMS((tree));
-static tree make_vector PARAMS ((enum machine_mode, tree, int));
-static int type_hash_marked_p PARAMS ((const void *));
+static void set_type_quals (tree, int);
+static int type_hash_eq (const void *, const void *);
+static hashval_t type_hash_hash (const void *);
+static void print_type_hash_statistics (void);
+static void finish_vector_type (tree);
+static tree make_vector (enum machine_mode, tree, int);
+static int type_hash_marked_p (const void *);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -133,7 +115,7 @@ tree integer_types[itk_none];
 /* Init tree.c.  */
 
 void
-init_ttree ()
+init_ttree (void)
 {
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
@@ -145,8 +127,7 @@ init_ttree ()
    translations made by ASM_OUTPUT_LABELREF).  Often this is the same
    as DECL_NAME.  It is an IDENTIFIER_NODE.  */
 tree
-decl_assembler_name (decl)
-     tree decl;
+decl_assembler_name (tree decl)
 {
   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
     (*lang_hooks.set_decl_assembler_name) (decl);
@@ -156,8 +137,7 @@ decl_assembler_name (decl)
 /* Compute the number of bytes occupied by 'node'.  This routine only
    looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
 size_t
-tree_size (node)
-     tree node;
+tree_size (tree node)
 {
   enum tree_code code = TREE_CODE (node);
 
@@ -182,28 +162,32 @@ tree_size (node)
              + TREE_CODE_LENGTH (code) * sizeof (char *) - sizeof (char *));
 
     case 'c':  /* a constant */
-      /* We can't use TREE_CODE_LENGTH for INTEGER_CST, since the number of
-        words is machine-dependent due to varying length of HOST_WIDE_INT,
-        which might be wider than a pointer (e.g., long long).  Similarly
-        for REAL_CST, since the number of words is machine-dependent due
-        to varying size and alignment of `double'.  */
-      if (code == INTEGER_CST)
-       return sizeof (struct tree_int_cst);
-      else if (code == REAL_CST)
-       return sizeof (struct tree_real_cst);
-      else
-       return (sizeof (struct tree_common)
-               + TREE_CODE_LENGTH (code) * sizeof (char *));
+      switch (code)
+       {
+       case INTEGER_CST:       return sizeof (struct tree_int_cst);
+       case REAL_CST:          return sizeof (struct tree_real_cst);
+       case COMPLEX_CST:       return sizeof (struct tree_complex);
+       case VECTOR_CST:        return sizeof (struct tree_vector);
+       case STRING_CST:        return sizeof (struct tree_string);
+       default:
+         return (*lang_hooks.tree_size) (code);
+       }
 
     case 'x':  /* something random, like an identifier.  */
-      {
-       size_t length;
-       length = (sizeof (struct tree_common)
-                 + TREE_CODE_LENGTH (code) * sizeof (char *));
-       if (code == TREE_VEC)
-         length += TREE_VEC_LENGTH (node) * sizeof (char *) - sizeof (char *);
-       return length;
-      }
+      switch (code)
+       {
+       case IDENTIFIER_NODE:   return lang_hooks.identifier_size;
+       case TREE_LIST:         return sizeof (struct tree_list);
+       case TREE_VEC:          return (sizeof (struct tree_vec)
+                                       + TREE_VEC_LENGTH(node) * sizeof(char *)
+                                       - sizeof (char *));
+
+       case ERROR_MARK:
+       case PLACEHOLDER_EXPR:  return sizeof (struct tree_common);
+
+       default:
+         return (*lang_hooks.tree_size) (code);
+       }
 
     default:
       abort ();
@@ -217,8 +201,7 @@ tree_size (node)
    Achoo!  I got a code in the node.  */
 
 tree
-make_node (code)
-     enum tree_code code;
+make_node (enum tree_code code)
 {
   tree t;
   int type = TREE_CODE_CLASS (code);
@@ -289,7 +272,7 @@ make_node (code)
 
   t = ggc_alloc_tree (length);
 
-  memset ((PTR) t, 0, length);
+  memset (t, 0, length);
 
   TREE_SET_CODE (t, code);
 
@@ -304,9 +287,7 @@ make_node (code)
        DECL_ALIGN (t) = 1;
       DECL_USER_ALIGN (t) = 0;
       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
-      DECL_SOURCE_LINE (t) = lineno;
-      DECL_SOURCE_FILE (t) =
-       (input_filename) ? input_filename : "<built-in>";
+      DECL_SOURCE_LOCATION (t) = input_location;
       DECL_UID (t) = next_decl_uid++;
 
       /* We have not yet computed the alias set for this declaration.  */
@@ -360,8 +341,7 @@ make_node (code)
    TREE_CHAIN is zero and it has a fresh uid.  */
 
 tree
-copy_node (node)
-     tree node;
+copy_node (tree node)
 {
   tree t;
   enum tree_code code = TREE_CODE (node);
@@ -395,8 +375,7 @@ copy_node (node)
    For example, this can copy a list made of TREE_LIST nodes.  */
 
 tree
-copy_list (list)
-     tree list;
+copy_list (tree list)
 {
   tree head;
   tree prev, next;
@@ -423,9 +402,7 @@ copy_list (list)
    This function should be used via the `build_int_2' macro.  */
 
 tree
-build_int_2_wide (low, hi)
-     unsigned HOST_WIDE_INT low;
-     HOST_WIDE_INT hi;
+build_int_2_wide (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 {
   tree t = make_node (INTEGER_CST);
 
@@ -439,8 +416,7 @@ build_int_2_wide (low, hi)
    are in a list pointed by VALS.  */
 
 tree
-build_vector (type, vals)
-     tree type, vals;
+build_vector (tree type, tree vals)
 {
   tree v = make_node (VECTOR_CST);
   int over1 = 0, over2 = 0;
@@ -464,12 +440,32 @@ build_vector (type, vals)
   return v;
 }
 
+/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
+   are in a list pointed to by VALS.  */
+tree
+build_constructor (tree type, tree vals)
+{
+  tree c = make_node (CONSTRUCTOR);
+  TREE_TYPE (c) = type;
+  CONSTRUCTOR_ELTS (c) = vals;
+
+  /* ??? May not be necessary.  Mirrors what build does.  */
+  if (vals)
+    {
+      TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals);
+      TREE_READONLY (c) = TREE_READONLY (vals);
+      TREE_CONSTANT (c) = TREE_CONSTANT (vals);
+    }
+  else
+    TREE_CONSTANT (c) = 0;  /* safe side */
+
+  return c;
+}
+
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
 tree
-build_real (type, d)
-     tree type;
-     REAL_VALUE_TYPE d;
+build_real (tree type, REAL_VALUE_TYPE d)
 {
   tree v;
   REAL_VALUE_TYPE *dp;
@@ -492,21 +488,17 @@ build_real (type, d)
    and whose value is the integer value of the INTEGER_CST node I.  */
 
 REAL_VALUE_TYPE
-real_value_from_int_cst (type, i)
-     tree type ATTRIBUTE_UNUSED, i;
+real_value_from_int_cst (tree type, tree i)
 {
   REAL_VALUE_TYPE d;
 
   /* Clear all bits of the real value type so that we can later do
      bitwise comparisons to see if two values are the same.  */
-  memset ((char *) &d, 0, sizeof d);
+  memset (&d, 0, sizeof d);
 
-  if (! TREE_UNSIGNED (TREE_TYPE (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), TYPE_MODE (type));
+  real_from_integer (&d, type ? TYPE_MODE (type) : VOIDmode,
+                    TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
+                    TREE_UNSIGNED (TREE_TYPE (i)));
   return d;
 }
 
@@ -514,9 +506,7 @@ real_value_from_int_cst (type, i)
    representing the same value as a floating-point constant of type TYPE.  */
 
 tree
-build_real_from_int_cst (type, i)
-     tree type;
-     tree i;
+build_real_from_int_cst (tree type, tree i)
 {
   tree v;
   int overflow = TREE_OVERFLOW (i);
@@ -533,9 +523,7 @@ build_real_from_int_cst (type, i)
    The TREE_TYPE is not initialized.  */
 
 tree
-build_string (len, str)
-     int len;
-     const char *str;
+build_string (int len, const char *str)
 {
   tree s = make_node (STRING_CST);
 
@@ -551,9 +539,7 @@ build_string (len, str)
    will be the type of the COMPLEX_CST; otherwise a new type will be made.  */
 
 tree
-build_complex (type, real, imag)
-     tree type;
-     tree real, imag;
+build_complex (tree type, tree real, tree imag)
 {
   tree t = make_node (COMPLEX_CST);
 
@@ -569,8 +555,7 @@ build_complex (type, real, imag)
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
-make_tree_vec (len)
-     int len;
+make_tree_vec (int len)
 {
   tree t;
   int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
@@ -582,7 +567,7 @@ make_tree_vec (len)
 
   t = ggc_alloc_tree (length);
 
-  memset ((PTR) t, 0, length);
+  memset (t, 0, length);
   TREE_SET_CODE (t, TREE_VEC);
   TREE_VEC_LENGTH (t) = len;
 
@@ -593,8 +578,7 @@ make_tree_vec (len)
    of zero.  */
 
 int
-integer_zerop (expr)
-     tree expr;
+integer_zerop (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -611,8 +595,7 @@ integer_zerop (expr)
    complex constant.  */
 
 int
-integer_onep (expr)
-     tree expr;
+integer_onep (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -629,8 +612,7 @@ integer_onep (expr)
    it contains.  Likewise for the corresponding complex constant.  */
 
 int
-integer_all_onesp (expr)
-     tree expr;
+integer_all_onesp (tree expr)
 {
   int prec;
   int uns;
@@ -682,8 +664,7 @@ integer_all_onesp (expr)
    one bit on).  */
 
 int
-integer_pow2p (expr)
-     tree expr;
+integer_pow2p (tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -728,8 +709,7 @@ integer_pow2p (expr)
    complex constant other than zero.  */
 
 int
-integer_nonzerop (expr)
-     tree expr;
+integer_nonzerop (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -746,8 +726,7 @@ integer_nonzerop (expr)
    power of two.  */
 
 int
-tree_log2 (expr)
-     tree expr;
+tree_log2 (tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -785,8 +764,7 @@ tree_log2 (expr)
    than or equal to EXPR.  */
 
 int
-tree_floor_log2 (expr)
-     tree expr;
+tree_floor_log2 (tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -824,8 +802,7 @@ tree_floor_log2 (expr)
 /* Return 1 if EXPR is the real constant zero.  */
 
 int
-real_zerop (expr)
-     tree expr;
+real_zerop (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -840,8 +817,7 @@ real_zerop (expr)
 /* Return 1 if EXPR is the real constant one in real or complex form.  */
 
 int
-real_onep (expr)
-     tree expr;
+real_onep (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -856,8 +832,7 @@ real_onep (expr)
 /* Return 1 if EXPR is the real constant two.  */
 
 int
-real_twop (expr)
-     tree expr;
+real_twop (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -872,8 +847,7 @@ real_twop (expr)
 /* Return 1 if EXPR is the real constant minus one.  */
 
 int
-real_minus_onep (expr)
-     tree expr;
+real_minus_onep (tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -888,8 +862,7 @@ real_minus_onep (expr)
 /* Nonzero if EXP is a constant or a cast of a constant.  */
 
 int
-really_constant_p (exp)
-     tree exp;
+really_constant_p (tree exp)
 {
   /* This is not quite the same as STRIP_NOPS.  It does more.  */
   while (TREE_CODE (exp) == NOP_EXPR
@@ -903,8 +876,7 @@ really_constant_p (exp)
    Return 0 if ELEM is not in LIST.  */
 
 tree
-value_member (elem, list)
-     tree elem, list;
+value_member (tree elem, tree list)
 {
   while (list)
     {
@@ -919,8 +891,7 @@ value_member (elem, list)
    Return 0 if ELEM is not in LIST.  */
 
 tree
-purpose_member (elem, list)
-     tree elem, list;
+purpose_member (tree elem, tree list)
 {
   while (list)
     {
@@ -935,8 +906,7 @@ purpose_member (elem, list)
    Return 0 if ELEM is not in LIST.  */
 
 tree
-binfo_member (elem, list)
-     tree elem, list;
+binfo_member (tree elem, tree list)
 {
   while (list)
     {
@@ -950,8 +920,7 @@ binfo_member (elem, list)
 /* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
-chain_member (elem, chain)
-     tree elem, chain;
+chain_member (tree elem, tree chain)
 {
   while (chain)
     {
@@ -968,8 +937,7 @@ chain_member (elem, chain)
    This is the Lisp primitive `length'.  */
 
 int
-list_length (t)
-     tree t;
+list_length (tree t)
 {
   tree tail;
   int len = 0;
@@ -983,8 +951,7 @@ list_length (t)
 /* Returns the number of FIELD_DECLs in TYPE.  */
 
 int
-fields_length (type)
-     tree type;
+fields_length (tree type)
 {
   tree t = TYPE_FIELDS (type);
   int count = 0;
@@ -1001,36 +968,35 @@ fields_length (type)
    This is the Lisp primitive `nconc'.  */
 
 tree
-chainon (op1, op2)
-     tree op1, op2;
+chainon (tree op1, tree op2)
 {
+  tree t1;
 
-  if (op1)
-    {
-      tree t1;
-#ifdef ENABLE_TREE_CHECKING
-      tree t2;
-#endif
+  if (!op1)
+    return op2;
+  if (!op2)
+    return op1;
+
+  for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
+    continue;
+  TREE_CHAIN (t1) = op2;
 
-      for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
-       ;
-      TREE_CHAIN (t1) = op2;
 #ifdef ENABLE_TREE_CHECKING
-      for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
-       if (t2 == t1)
-         abort ();  /* Circularity created.  */
+  {
+    tree t2;
+    for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
+      if (t2 == t1)
+       abort ();  /* Circularity created.  */
+  }
 #endif
-      return op1;
-    }
-  else
-    return op2;
+
+  return op1;
 }
 
 /* Return the last node in a chain of nodes (chained through TREE_CHAIN).  */
 
 tree
-tree_last (chain)
-     tree chain;
+tree_last (tree chain)
 {
   tree next;
   if (chain)
@@ -1043,8 +1009,7 @@ tree_last (chain)
    and return the new head of the chain (old last element).  */
 
 tree
-nreverse (t)
-     tree t;
+nreverse (tree t)
 {
   tree prev = 0, decl, next;
   for (decl = t; decl; decl = next)
@@ -1060,8 +1025,7 @@ nreverse (t)
    purpose and value fields are PARM and VALUE.  */
 
 tree
-build_tree_list (parm, value)
-     tree parm, value;
+build_tree_list (tree parm, tree value)
 {
   tree t = make_node (TREE_LIST);
   TREE_PURPOSE (t) = parm;
@@ -1074,8 +1038,7 @@ build_tree_list (parm, value)
    and whose TREE_CHAIN is CHAIN.  */
 
 tree
-tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
+tree_cons (tree purpose, tree value, tree chain)
 {
   tree node;
 
@@ -1095,6 +1058,44 @@ tree_cons (purpose, value, chain)
   return node;
 }
 
+/* Return the first expression in a sequence of COMPOUND_EXPRs.  */
+
+tree
+expr_first (tree expr)
+{
+  if (expr == NULL_TREE)
+    return expr;
+  while (TREE_CODE (expr) == COMPOUND_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+  return expr;
+}
+
+/* Return the last expression in a sequence of COMPOUND_EXPRs.  */
+
+tree
+expr_last (tree expr)
+{
+  if (expr == NULL_TREE)
+    return expr;
+  while (TREE_CODE (expr) == COMPOUND_EXPR)
+    expr = TREE_OPERAND (expr, 1);
+  return expr;
+}
+
+/* Return the number of subexpressions in a sequence of COMPOUND_EXPRs.  */
+
+int
+expr_length (tree expr)
+{
+  int len = 0;
+
+  if (expr == NULL_TREE)
+    return 0;
+  for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1))
+    len += expr_length (TREE_OPERAND (expr, 0));
+  ++len;
+  return len;
+}
 \f
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -1103,8 +1104,7 @@ tree_cons (purpose, value, chain)
    make_unsigned_type).  */
 
 tree
-size_in_bytes (type)
-     tree type;
+size_in_bytes (tree type)
 {
   tree t;
 
@@ -1130,8 +1130,7 @@ size_in_bytes (type)
    or return -1 if the size can vary or is larger than an integer.  */
 
 HOST_WIDE_INT
-int_size_in_bytes (type)
-     tree type;
+int_size_in_bytes (tree type)
 {
   tree t;
 
@@ -1155,10 +1154,8 @@ int_size_in_bytes (type)
    This is a tree of type bitsizetype.  */
 
 tree
-bit_position (field)
-     tree field;
+bit_position (tree field)
 {
-
   return bit_from_pos (DECL_FIELD_OFFSET (field),
                       DECL_FIELD_BIT_OFFSET (field));
 }
@@ -1168,8 +1165,7 @@ bit_position (field)
    of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
-int_bit_position (field)
-     tree field;
+int_bit_position (tree field)
 {
   return tree_low_cst (bit_position (field), 0);
 }
@@ -1178,8 +1174,7 @@ int_bit_position (field)
    This is a tree of type sizetype.  */
 
 tree
-byte_position (field)
-     tree field;
+byte_position (tree field)
 {
   return byte_from_pos (DECL_FIELD_OFFSET (field),
                        DECL_FIELD_BIT_OFFSET (field));
@@ -1190,8 +1185,7 @@ byte_position (field)
    of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
-int_byte_position (field)
-     tree field;
+int_byte_position (tree field)
 {
   return tree_low_cst (byte_position (field), 0);
 }
@@ -1199,8 +1193,7 @@ int_byte_position (field)
 /* Return the strictest alignment, in bits, that T is known to have.  */
 
 unsigned int
-expr_align (t)
-     tree t;
+expr_align (tree t)
 {
   unsigned int align0, align1;
 
@@ -1247,8 +1240,7 @@ expr_align (t)
    ARRAY_TYPE) minus one. This counts only elements of the top array.  */
 
 tree
-array_type_nelts (type)
-     tree type;
+array_type_nelts (tree type)
 {
   tree index_type, min, max;
 
@@ -1270,8 +1262,7 @@ array_type_nelts (type)
    static storage.  This is not the same as the C meaning of `static'.  */
 
 int
-staticp (arg)
-     tree arg;
+staticp (tree arg)
 {
   switch (TREE_CODE (arg))
     {
@@ -1348,51 +1339,24 @@ staticp (arg)
    are used for.  */
 
 tree
-save_expr (expr)
-     tree expr;
+save_expr (tree expr)
 {
   tree t = fold (expr);
   tree inner;
 
-  /* We don't care about whether this can be used as an lvalue in this
-     context.  */
-  while (TREE_CODE (t) == NON_LVALUE_EXPR)
-    t = TREE_OPERAND (t, 0);
-
-  /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
-     a constant, it will be more efficient to not make another SAVE_EXPR since
-     it will allow better simplification and GCSE will be able to merge the
-     computations if they actually occur.  */
-  inner = t;
-  while (1)
-    {
-      if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
-       inner = TREE_OPERAND (inner, 0);
-      else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
-       {
-         if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
-           inner = TREE_OPERAND (inner, 0);
-         else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
-           inner = TREE_OPERAND (inner, 1);
-         else
-           break;
-       }
-      else
-       break;
-    }
-
   /* If the tree evaluates to a constant, then we don't want to hide that
      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.  */
+  inner = skip_simple_arithmetic (t);
   if (TREE_CONSTANT (inner)
       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
       || TREE_CODE (inner) == SAVE_EXPR
       || TREE_CODE (inner) == ERROR_MARK)
     return t;
 
-  /* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
+  /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
      it means that the size or offset of some field of an object depends on
      the value within another field.
 
@@ -1401,7 +1365,7 @@ save_expr (expr)
      evaluated more than once.  Front-ends must assure this case cannot
      happen by surrounding any such subexpressions in their own SAVE_EXPR
      and forcing evaluation at the proper time.  */
-  if (contains_placeholder_p (t))
+  if (contains_placeholder_p (inner))
     return t;
 
   t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
@@ -1414,13 +1378,59 @@ save_expr (expr)
   return t;
 }
 
+/* Look inside EXPR and into any simple arithmetic operations.  Return
+   the innermost non-arithmetic node.  */
+
+tree
+skip_simple_arithmetic (tree expr)
+{
+  tree inner;
+
+  /* We don't care about whether this can be used as an lvalue in this
+     context.  */
+  while (TREE_CODE (expr) == NON_LVALUE_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+
+  /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
+     a constant, it will be more efficient to not make another SAVE_EXPR since
+     it will allow better simplification and GCSE will be able to merge the
+     computations if they actually occur.  */
+  inner = expr;
+  while (1)
+    {
+      if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
+       inner = TREE_OPERAND (inner, 0);
+      else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
+       {
+         if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
+           inner = TREE_OPERAND (inner, 0);
+         else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
+           inner = TREE_OPERAND (inner, 1);
+         else
+           break;
+       }
+      else
+       break;
+    }
+
+  return inner;
+}
+
+/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
+   SAVE_EXPR.  Return FALSE otherwise.  */
+
+bool
+saved_expr_p (tree expr)
+{
+  return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR;
+}
+
 /* 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;
+unsave_expr (tree expr)
 {
   tree t;
 
@@ -1437,8 +1447,7 @@ unsave_expr (expr)
    of operands if all are trees.  */
 
 int
-first_rtl_op (code)
-     enum tree_code code;
+first_rtl_op (enum tree_code code)
 {
   switch (code)
     {
@@ -1449,8 +1458,6 @@ first_rtl_op (code)
       return 0;
     case WITH_CLEANUP_EXPR:
       return 2;
-    case METHOD_CALL_EXPR:
-      return 3;
     default:
       return TREE_CODE_LENGTH (code);
     }
@@ -1459,17 +1466,16 @@ first_rtl_op (code)
 /* Return which tree structure is used by T.  */
 
 enum tree_node_structure_enum
-tree_node_structure (t)
-     tree t;
+tree_node_structure (tree t)
 {
   enum tree_code code = TREE_CODE (t);
-  
+
   switch (TREE_CODE_CLASS (code))
     {
     case 'd':  return TS_DECL;
     case 't':  return TS_TYPE;
     case 'b':  return TS_BLOCK;
-    case 'r': case '<': case '1': case '2': case 'e': case 's': 
+    case 'r': case '<': case '1': case '2': case 'e': case 's':
       return TS_EXP;
     default:  /* 'c' and 'x' */
       break;
@@ -1498,8 +1504,7 @@ tree_node_structure (t)
    not recurse into EXPR's subtrees.  */
 
 void
-unsave_expr_1 (expr)
-     tree expr;
+unsave_expr_1 (tree expr)
 {
   switch (TREE_CODE (expr))
     {
@@ -1534,8 +1539,7 @@ unsave_expr_1 (expr)
 /* Default lang hook for "unsave_expr_now".  */
 
 tree
-lhd_unsave_expr_now (expr)
-     tree expr;
+lhd_unsave_expr_now (tree expr)
 {
   enum tree_code code;
 
@@ -1600,8 +1604,7 @@ lhd_unsave_expr_now (expr)
    never possible to unsave them.  */
 
 int
-unsafe_for_reeval (expr)
-     tree expr;
+unsafe_for_reeval (tree expr)
 {
   int unsafeness = 0;
   enum tree_code code;
@@ -1677,9 +1680,8 @@ unsafe_for_reeval (expr)
 /* 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.  */
 
-int
-contains_placeholder_p (exp)
-     tree exp;
+bool
+contains_placeholder_p (tree exp)
 {
   enum tree_code code;
   int result;
@@ -1702,13 +1704,12 @@ contains_placeholder_p (exp)
         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));
+      return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
 
     case 'x':
       if (code == TREE_LIST)
-       return (contains_placeholder_p (TREE_VALUE (exp))
-               || (TREE_CHAIN (exp) != 0
-                   && contains_placeholder_p (TREE_CHAIN (exp))));
+       return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
+               || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
       break;
 
     case '1':
@@ -1718,16 +1719,16 @@ contains_placeholder_p (exp)
        {
        case COMPOUND_EXPR:
          /* Ignoring the first operand isn't quite right, but works best.  */
-         return contains_placeholder_p (TREE_OPERAND (exp, 1));
+         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)));
+         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:
          /* If we already know this doesn't have a placeholder, don't
@@ -1736,15 +1737,14 @@ contains_placeholder_p (exp)
            return 0;
 
          SAVE_EXPR_NOPLACEHOLDER (exp) = 1;
-         result = contains_placeholder_p (TREE_OPERAND (exp, 0));
+         result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
          if (result)
            SAVE_EXPR_NOPLACEHOLDER (exp) = 0;
 
          return result;
 
        case CALL_EXPR:
-         return (TREE_OPERAND (exp, 1) != 0
-                 && contains_placeholder_p (TREE_OPERAND (exp, 1)));
+         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
 
        default:
          break;
@@ -1753,10 +1753,10 @@ contains_placeholder_p (exp)
       switch (TREE_CODE_LENGTH (code))
        {
        case 1:
-         return contains_placeholder_p (TREE_OPERAND (exp, 0));
+         return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
        case 2:
-         return (contains_placeholder_p (TREE_OPERAND (exp, 0))
-                 || contains_placeholder_p (TREE_OPERAND (exp, 1)));
+         return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
+                 || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)));
        default:
          return 0;
        }
@@ -1767,12 +1767,113 @@ contains_placeholder_p (exp)
   return 0;
 }
 
+/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR.
+   This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field
+   positions.  */
+
+bool
+type_contains_placeholder_p (tree type)
+{
+  /* If the size contains a placeholder or the parent type (component type in
+     the case of arrays) type involves a placeholder, this type does.  */
+  if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
+      || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
+      || (TREE_TYPE (type) != 0
+         && type_contains_placeholder_p (TREE_TYPE (type))))
+    return 1;
+
+  /* Now do type-specific checks.  Note that the last part of the check above
+     greatly limits what we have to do below.  */
+  switch (TREE_CODE (type))
+    {
+    case VOID_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case CHAR_TYPE:
+    case POINTER_TYPE:
+    case OFFSET_TYPE:
+    case REFERENCE_TYPE:
+    case METHOD_TYPE:
+    case FILE_TYPE:
+    case FUNCTION_TYPE:
+      return 0;
+
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+      /* Here we just check the bounds.  */
+      return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
+             || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
+
+    case ARRAY_TYPE:
+    case SET_TYPE:
+      /* We're already checked the component type (TREE_TYPE), so just check
+        the index type.  */
+      return type_contains_placeholder_p (TYPE_DOMAIN (type));
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+       static tree seen_types = 0;
+       tree field;
+       bool ret = 0;
+
+       /* We have to be careful here that we don't end up in infinite
+          recursions due to a field of a type being a pointer to that type
+          or to a mutually-recursive type.  So we store a list of record
+          types that we've seen and see if this type is in them.  To save
+          memory, we don't use a list for just one type.  Here we check
+          whether we've seen this type before and store it if not.  */
+       if (seen_types == 0)
+         seen_types = type;
+       else if (TREE_CODE (seen_types) != TREE_LIST)
+         {
+           if (seen_types == type)
+             return 0;
+
+           seen_types = tree_cons (NULL_TREE, type,
+                                   build_tree_list (NULL_TREE, seen_types));
+         }
+       else
+         {
+           if (value_member (type, seen_types) != 0)
+             return 0;
+
+           seen_types = tree_cons (NULL_TREE, type, seen_types);
+         }
+
+       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+         if (TREE_CODE (field) == FIELD_DECL
+             && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field))
+                 || (TREE_CODE (type) == QUAL_UNION_TYPE
+                     && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field)))
+                 || type_contains_placeholder_p (TREE_TYPE (field))))
+           {
+             ret = true;
+             break;
+           }
+
+       /* Now remove us from seen_types and return the result.  */
+       if (seen_types == type)
+         seen_types = 0;
+       else
+         seen_types = TREE_CHAIN (seen_types);
+
+       return ret;
+      }
+
+    default:
+      abort ();
+    }
+}
+
 /* Return 1 if EXP contains any expressions that produce cleanups for an
    outer scope to deal with.  Used by fold.  */
 
 int
-has_cleanups (exp)
-     tree exp;
+has_cleanups (tree exp)
 {
   int i, nops, cmp;
 
@@ -1833,10 +1934,7 @@ has_cleanups (exp)
    PLACEHOLDER_EXPR occurring only in its arglist.  */
 
 tree
-substitute_in_expr (exp, f, r)
-     tree exp;
-     tree f;
-     tree r;
+substitute_in_expr (tree exp, tree f, tree r)
 {
   enum tree_code code = TREE_CODE (exp);
   tree op0, op1, op2;
@@ -1892,9 +1990,9 @@ substitute_in_expr (exp, f, r)
 
          op0 = TREE_OPERAND (exp, 0);
          op1 = TREE_OPERAND (exp, 1);
-         if (contains_placeholder_p (op0))
+         if (CONTAINS_PLACEHOLDER_P (op0))
            op0 = substitute_in_expr (op0, f, r);
-         if (contains_placeholder_p (op1))
+         if (CONTAINS_PLACEHOLDER_P (op1))
            op1 = substitute_in_expr (op1, f, r);
 
          if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
@@ -1926,11 +2024,11 @@ substitute_in_expr (exp, f, r)
          op1 = TREE_OPERAND (exp, 1);
          op2 = TREE_OPERAND (exp, 2);
 
-         if (contains_placeholder_p (op0))
+         if (CONTAINS_PLACEHOLDER_P (op0))
            op0 = substitute_in_expr (op0, f, r);
-         if (contains_placeholder_p (op1))
+         if (CONTAINS_PLACEHOLDER_P (op1))
            op1 = substitute_in_expr (op1, f, r);
-         if (contains_placeholder_p (op2))
+         if (CONTAINS_PLACEHOLDER_P (op2))
            op2 = substitute_in_expr (op2, f, r);
 
          if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
@@ -2016,8 +2114,7 @@ substitute_in_expr (exp, f, r)
    Any other kind of expression is returned unchanged.  */
 
 tree
-stabilize_reference (ref)
-     tree ref;
+stabilize_reference (tree ref)
 {
   tree result;
   enum tree_code code = TREE_CODE (ref);
@@ -2114,8 +2211,7 @@ stabilize_reference (ref)
    multiple utterances of the same expression should that prove fruitful.  */
 
 tree
-stabilize_reference_1 (e)
-     tree e;
+stabilize_reference_1 (tree e)
 {
   tree result;
   enum tree_code code = TREE_CODE (e);
@@ -2190,17 +2286,16 @@ stabilize_reference_1 (e)
    Constants, decls, types and misc nodes cannot be.  */
 
 tree
-build VPARAMS ((enum tree_code code, tree tt, ...))
+build (enum tree_code code, tree tt, ...)
 {
   tree t;
   int length;
   int i;
   int fro;
   int constant;
+  va_list p;
 
-  VA_OPEN (p, tt);
-  VA_FIXEDARG (p, enum tree_code, code);
-  VA_FIXEDARG (p, tree, tt);
+  va_start (p, tt);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
@@ -2277,9 +2372,20 @@ build VPARAMS ((enum tree_code code, tree tt, ...))
            }
        }
     }
-  VA_CLOSE (p);
+  va_end (p);
 
   TREE_CONSTANT (t) = constant;
+  
+  if (code == CALL_EXPR && !TREE_SIDE_EFFECTS (t))
+    {
+      /* Calls have side-effects, except those to const or
+        pure functions.  */
+      tree fn = get_callee_fndecl (t);
+
+      if (!fn || (!DECL_IS_PURE (fn) && !TREE_READONLY (fn)))
+       TREE_SIDE_EFFECTS (t) = 1;
+    }
+
   return t;
 }
 
@@ -2288,10 +2394,7 @@ build VPARAMS ((enum tree_code code, tree tt, ...))
    of varargs, which is expensive for RISC machines.  */
 
 tree
-build1 (code, type, node)
-     enum tree_code code;
-     tree type;
-     tree node;
+build1 (enum tree_code code, tree type, tree node)
 {
   int length = sizeof (struct tree_exp);
 #ifdef GATHER_STATISTICS
@@ -2326,7 +2429,7 @@ build1 (code, type, node)
 
   t = ggc_alloc_tree (length);
 
-  memset ((PTR) t, 0, sizeof (struct tree_common));
+  memset (t, 0, sizeof (struct tree_common));
 
   TREE_SET_CODE (t, code);
 
@@ -2363,6 +2466,29 @@ build1 (code, type, node)
       TREE_READONLY (t) = 0;
       break;
 
+    case ADDR_EXPR:
+      if (node)
+       {
+         /* The address of a volatile decl or reference does not have
+            side-effects.  But be careful not to ignore side-effects from
+            other sources deeper in the expression--if node is a _REF and
+            one of its operands has side-effects, so do we.  */
+         if (TREE_THIS_VOLATILE (node))
+           {
+             TREE_SIDE_EFFECTS (t) = 0;
+             if (!DECL_P (node))
+               {
+                 int i = first_rtl_op (TREE_CODE (node)) - 1;
+                 for (; i >= 0; --i)
+                   {
+                     if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, i)))
+                       TREE_SIDE_EFFECTS (t) = 1;
+                   }
+               }
+           }
+       }
+      break;
+
     default:
       if (TREE_CODE_CLASS (code) == '1' && node && TREE_CONSTANT (node))
        TREE_CONSTANT (t) = 1;
@@ -2378,14 +2504,14 @@ build1 (code, type, node)
    or even garbage if their values do not matter.  */
 
 tree
-build_nt VPARAMS ((enum tree_code code, ...))
+build_nt (enum tree_code code, ...)
 {
   tree t;
   int length;
   int i;
+  va_list p;
 
-  VA_OPEN (p, code);
-  VA_FIXEDARG (p, enum tree_code, code);
+  va_start (p, code);
 
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
@@ -2393,7 +2519,7 @@ build_nt VPARAMS ((enum tree_code code, ...))
   for (i = 0; i < length; i++)
     TREE_OPERAND (t, i) = va_arg (p, tree);
 
-  VA_CLOSE (p);
+  va_end (p);
   return t;
 }
 \f
@@ -2404,9 +2530,7 @@ build_nt VPARAMS ((enum tree_code code, ...))
    Other slots are initialized to 0 or null pointers.  */
 
 tree
-build_decl (code, name, type)
-     enum tree_code code;
-     tree name, type;
+build_decl (enum tree_code code, tree name, tree type)
 {
   tree t;
 
@@ -2433,8 +2557,8 @@ build_decl (code, name, type)
    compiled.  This information is used for outputting debugging info.  */
 
 tree
-build_block (vars, tags, subblocks, supercontext, chain)
-     tree vars, tags ATTRIBUTE_UNUSED, subblocks, supercontext, chain;
+build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
+            tree supercontext, tree chain)
 {
   tree block = make_node (BLOCK);
 
@@ -2451,10 +2575,7 @@ build_block (vars, tags, subblocks, supercontext, chain)
    recursively more than one file (Java is one of them).  */
 
 tree
-build_expr_wfl (node, file, line, col)
-     tree node;
-     const char *file;
-     int line, col;
+build_expr_wfl (tree node, const char *file, int line, int col)
 {
   static const char *last_file = 0;
   static tree last_filenode = NULL_TREE;
@@ -2482,8 +2603,7 @@ build_expr_wfl (node, file, line, col)
    is ATTRIBUTE.  */
 
 tree
-build_decl_attribute_variant (ddecl, attribute)
-     tree ddecl, attribute;
+build_decl_attribute_variant (tree ddecl, tree attribute)
 {
   DECL_ATTRIBUTES (ddecl) = attribute;
   return ddecl;
@@ -2495,8 +2615,7 @@ build_decl_attribute_variant (ddecl, attribute)
    Record such modified types already made so we don't make duplicates.  */
 
 tree
-build_type_attribute_variant (ttype, attribute)
-     tree ttype, attribute;
+build_type_attribute_variant (tree ttype, tree attribute)
 {
   if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
     {
@@ -2552,9 +2671,7 @@ build_type_attribute_variant (ttype, attribute)
    their canonicalized form.  */
 
 int
-is_attribute_p (attr, ident)
-     const char *attr;
-     tree ident;
+is_attribute_p (const char *attr, tree ident)
 {
   int ident_len, attr_len;
   const char *p;
@@ -2599,9 +2716,7 @@ is_attribute_p (attr, ident)
    be passed back in if further occurrences are wanted.  */
 
 tree
-lookup_attribute (attr_name, list)
-     const char *attr_name;
-     tree list;
+lookup_attribute (const char *attr_name, tree list)
 {
   tree l;
 
@@ -2619,8 +2734,7 @@ lookup_attribute (attr_name, list)
 /* Return an attribute list that is the union of a1 and a2.  */
 
 tree
-merge_attributes (a1, a2)
-     tree a1, a2;
+merge_attributes (tree a1, tree a2)
 {
   tree attributes;
 
@@ -2670,8 +2784,7 @@ merge_attributes (a1, a2)
   the result.  */
 
 tree
-merge_type_attributes (t1, t2)
-     tree t1, t2;
+merge_type_attributes (tree t1, tree t2)
 {
   return merge_attributes (TYPE_ATTRIBUTES (t1),
                           TYPE_ATTRIBUTES (t2));
@@ -2681,8 +2794,7 @@ merge_type_attributes (t1, t2)
    the result.  */
 
 tree
-merge_decl_attributes (olddecl, newdecl)
-     tree olddecl, newdecl;
+merge_decl_attributes (tree olddecl, tree newdecl)
 {
   return merge_attributes (DECL_ATTRIBUTES (olddecl),
                           DECL_ATTRIBUTES (newdecl));
@@ -2700,9 +2812,7 @@ merge_decl_attributes (olddecl, newdecl)
    The second instance of `foo' nullifies the dllimport.  */
 
 tree
-merge_dllimport_decl_attributes (old, new)
-     tree old;
-     tree new;
+merge_dllimport_decl_attributes (tree old, tree new)
 {
   tree a;
   int delete_dllimport_p;
@@ -2749,9 +2859,7 @@ merge_dllimport_decl_attributes (old, new)
    of the various TYPE_QUAL values.  */
 
 static void
-set_type_quals (type, type_quals)
-     tree type;
-     int type_quals;
+set_type_quals (tree type, int type_quals)
 {
   TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
   TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
@@ -2763,9 +2871,7 @@ set_type_quals (type, type_quals)
    return NULL_TREE.  */
 
 tree
-get_qualified_type (type, type_quals)
-     tree type;
-     int type_quals;
+get_qualified_type (tree type, int type_quals)
 {
   tree t;
 
@@ -2774,7 +2880,8 @@ get_qualified_type (type, type_quals)
      preserve the TYPE_NAME, since there is code that depends on this.  */
   for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
     if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)
-        && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+        && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+       && attribute_list_equal (TYPE_ATTRIBUTES (t), TYPE_ATTRIBUTES (type)))
       return t;
 
   return NULL_TREE;
@@ -2784,9 +2891,7 @@ get_qualified_type (type, type_quals)
    exist.  This function never returns NULL_TREE.  */
 
 tree
-build_qualified_type (type, type_quals)
-     tree type;
-     int type_quals;
+build_qualified_type (tree type, int type_quals)
 {
   tree t;
 
@@ -2807,8 +2912,7 @@ build_qualified_type (type, type_quals)
    This is so the caller can modify it.  */
 
 tree
-build_type_copy (type)
-     tree type;
+build_type_copy (tree type)
 {
   tree t, m = TYPE_MAIN_VARIANT (type);
 
@@ -2832,8 +2936,7 @@ build_type_copy (type)
    of the individual types.  */
 
 unsigned int
-type_hash_list (list)
-     tree list;
+type_hash_list (tree list)
 {
   unsigned int hashcode;
   tree tail;
@@ -2849,9 +2952,7 @@ type_hash_list (list)
 /* Returns true if the types are equal.  */
 
 static int
-type_hash_eq (va, vb)
-     const void *va;
-     const void *vb;
+type_hash_eq (const void *va, const void *vb)
 {
   const struct type_hash *a = va, *b = vb;
   if (a->hash == b->hash
@@ -2881,8 +2982,7 @@ type_hash_eq (va, vb)
 /* Return the cached hash value.  */
 
 static hashval_t
-type_hash_hash (item)
-     const void *item;
+type_hash_hash (const void *item)
 {
   return ((const struct type_hash *) item)->hash;
 }
@@ -2891,9 +2991,7 @@ type_hash_hash (item)
    If one is found, return it.  Otherwise return 0.  */
 
 tree
-type_hash_lookup (hashcode, type)
-     unsigned int hashcode;
-     tree type;
+type_hash_lookup (unsigned int hashcode, tree type)
 {
   struct type_hash *h, in;
 
@@ -2914,14 +3012,12 @@ type_hash_lookup (hashcode, type)
    for a type TYPE whose hash code is HASHCODE.  */
 
 void
-type_hash_add (hashcode, type)
-     unsigned int hashcode;
-     tree type;
+type_hash_add (unsigned int hashcode, tree type)
 {
   struct type_hash *h;
   void **loc;
 
-  h = (struct type_hash *) ggc_alloc (sizeof (struct type_hash));
+  h = ggc_alloc (sizeof (struct type_hash));
   h->hash = hashcode;
   h->type = type;
   loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
@@ -2943,9 +3039,7 @@ type_hash_add (hashcode, type)
 int debug_no_type_hash = 0;
 
 tree
-type_hash_canon (hashcode, type)
-     unsigned int hashcode;
-     tree type;
+type_hash_canon (unsigned int hashcode, tree type)
 {
   tree t1;
 
@@ -2977,8 +3071,7 @@ type_hash_canon (hashcode, type)
    the number of garbage collections.  */
 
 static int
-type_hash_marked_p (p)
-     const void *p;
+type_hash_marked_p (const void *p)
 {
   tree type = ((struct type_hash *) p)->type;
 
@@ -2986,7 +3079,7 @@ type_hash_marked_p (p)
 }
 
 static void
-print_type_hash_statistics ()
+print_type_hash_statistics (void)
 {
   fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
           (long) htab_size (type_hash_table),
@@ -2999,8 +3092,7 @@ print_type_hash_statistics ()
    by adding the hash codes of the individual attributes.  */
 
 unsigned int
-attribute_hash_list (list)
-     tree list;
+attribute_hash_list (tree list)
 {
   unsigned int hashcode;
   tree tail;
@@ -3015,8 +3107,7 @@ attribute_hash_list (list)
    equivalent to l1.  */
 
 int
-attribute_list_equal (l1, l2)
-     tree l1, l2;
+attribute_list_equal (tree l1, tree l2)
 {
   return attribute_list_contained (l1, l2)
         && attribute_list_contained (l2, l1);
@@ -3031,8 +3122,7 @@ attribute_list_equal (l1, l2)
    correctly.  */
 
 int
-attribute_list_contained (l1, l2)
-     tree l1, l2;
+attribute_list_contained (tree l1, tree l2)
 {
   tree t1, t2;
 
@@ -3079,8 +3169,7 @@ attribute_list_contained (l1, l2)
    Also, the TREE_PURPOSEs must match.  */
 
 int
-type_list_equal (l1, l2)
-     tree l1, l2;
+type_list_equal (tree l1, tree l2)
 {
   tree t1, t2;
 
@@ -3100,8 +3189,7 @@ type_list_equal (l1, l2)
    then this function counts only the ordinary arguments.  */
 
 int
-type_num_arguments (type)
-     tree type;
+type_num_arguments (tree type)
 {
   int i = 0;
   tree t;
@@ -3121,8 +3209,7 @@ type_num_arguments (type)
    represent the same constant value.  */
 
 int
-tree_int_cst_equal (t1, t2)
-     tree t1, t2;
+tree_int_cst_equal (tree t1, tree t2)
 {
   if (t1 == t2)
     return 1;
@@ -3143,8 +3230,7 @@ tree_int_cst_equal (t1, t2)
    The precise way of comparison depends on their data type.  */
 
 int
-tree_int_cst_lt (t1, t2)
-     tree t1, t2;
+tree_int_cst_lt (tree t1, tree t2)
 {
   if (t1 == t2)
     return 0;
@@ -3171,9 +3257,7 @@ tree_int_cst_lt (t1, t2)
 /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2.  */
 
 int
-tree_int_cst_compare (t1, t2)
-     tree t1;
-     tree t2;
+tree_int_cst_compare (tree t1, tree t2)
 {
   if (tree_int_cst_lt (t1, t2))
     return -1;
@@ -3189,9 +3273,7 @@ tree_int_cst_compare (t1, t2)
    be represented in a single unsigned HOST_WIDE_INT.  */
 
 int
-host_integerp (t, pos)
-     tree t;
-     int pos;
+host_integerp (tree t, int pos)
 {
   return (TREE_CODE (t) == INTEGER_CST
          && ! TREE_OVERFLOW (t)
@@ -3208,9 +3290,7 @@ host_integerp (t, pos)
    be positive.  Abort if we cannot satisfy the above conditions.  */
 
 HOST_WIDE_INT
-tree_low_cst (t, pos)
-     tree t;
-     int pos;
+tree_low_cst (tree t, int pos)
 {
   if (host_integerp (t, pos))
     return TREE_INT_CST_LOW (t);
@@ -3218,13 +3298,29 @@ tree_low_cst (t, pos)
     abort ();
 }
 
+/* Return the most significant bit of the integer constant T.  */
+
+int
+tree_int_cst_msb (tree t)
+{
+  int prec;
+  HOST_WIDE_INT h;
+  unsigned HOST_WIDE_INT l;
+
+  /* Note that using TYPE_PRECISION here is wrong.  We care about the
+     actual bits, not the (arbitrary) range of the type.  */
+  prec = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (t))) - 1;
+  rshift_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t), prec,
+                2 * HOST_BITS_PER_WIDE_INT, &l, &h, 0);
+  return (l & 1) == 1;
+}
+
 /* Return an indication of the sign of the integer constant T.
    The return value is -1 if T < 0, 0 if T == 0, and 1 if T > 0.
    Note that -1 will never be returned it T's type is unsigned.  */
 
 int
-tree_int_cst_sgn (t)
-     tree t;
+tree_int_cst_sgn (tree t)
 {
   if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0)
     return 0;
@@ -3240,8 +3336,7 @@ tree_int_cst_sgn (t)
    are known to be equal; otherwise return 0.  */
 
 int
-simple_cst_list_equal (l1, l2)
-     tree l1, l2;
+simple_cst_list_equal (tree l1, tree l2)
 {
   while (l1 != NULL_TREE && l2 != NULL_TREE)
     {
@@ -3262,8 +3357,7 @@ simple_cst_list_equal (l1, l2)
    this function.  */
 
 int
-simple_cst_equal (t1, t2)
-     tree t1, t2;
+simple_cst_equal (tree t1, tree t2)
 {
   enum tree_code code1, code2;
   int cmp;
@@ -3401,9 +3495,7 @@ simple_cst_equal (t1, t2)
    than U, respectively.  */
 
 int
-compare_tree_int (t, u)
-     tree t;
-     unsigned HOST_WIDE_INT u;
+compare_tree_int (tree t, unsigned HOST_WIDE_INT u)
 {
   if (tree_int_cst_sgn (t) < 0)
     return -1;
@@ -3416,6 +3508,98 @@ compare_tree_int (t, u)
   else
     return 1;
 }
+
+/* Generate a hash value for an expression.  This can be used iteratively
+   by passing a previous result as the "val" argument.
+
+   This function is intended to produce the same hash for expressions which
+   would compare equal using operand_equal_p.  */
+
+hashval_t
+iterative_hash_expr (tree t, hashval_t val)
+{
+  int i;
+  enum tree_code code;
+  char class;
+
+  if (t == NULL_TREE)
+    return iterative_hash_object (t, val);
+
+  code = TREE_CODE (t);
+  class = TREE_CODE_CLASS (code);
+
+  if (class == 'd')
+    {
+      /* Decls we can just compare by pointer.  */
+      val = iterative_hash_object (t, val);
+    }
+  else if (class == 'c')
+    {
+      /* Alas, constants aren't shared, so we can't rely on pointer
+        identity.  */
+      if (code == INTEGER_CST)
+       {
+         val = iterative_hash_object (TREE_INT_CST_LOW (t), val);
+         val = iterative_hash_object (TREE_INT_CST_HIGH (t), val);
+       }
+      else if (code == REAL_CST)
+       val = iterative_hash (TREE_REAL_CST_PTR (t),
+                             sizeof (REAL_VALUE_TYPE), val);
+      else if (code == STRING_CST)
+       val = iterative_hash (TREE_STRING_POINTER (t),
+                             TREE_STRING_LENGTH (t), val);
+      else if (code == COMPLEX_CST)
+       {
+         val = iterative_hash_expr (TREE_REALPART (t), val);
+         val = iterative_hash_expr (TREE_IMAGPART (t), val);
+       }
+      else if (code == VECTOR_CST)
+       val = iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
+      else
+       abort ();
+    }
+  else if (IS_EXPR_CODE_CLASS (class))
+    {
+      val = iterative_hash_object (code, val);
+
+      if (code == NOP_EXPR || code == CONVERT_EXPR
+         || code == NON_LVALUE_EXPR)
+       val = iterative_hash_object (TREE_TYPE (t), val);
+
+      if (code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
+         || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
+         || code == BIT_AND_EXPR || code == NE_EXPR || code == EQ_EXPR)
+       {
+         /* It's a commutative expression.  We want to hash it the same
+            however it appears.  We do this by first hashing both operands
+            and then rehashing based on the order of their independent
+            hashes.  */
+         hashval_t one = iterative_hash_expr (TREE_OPERAND (t, 0), 0);
+         hashval_t two = iterative_hash_expr (TREE_OPERAND (t, 1), 0);
+         hashval_t t;
+
+         if (one > two)
+           t = one, one = two, two = t;
+
+         val = iterative_hash_object (one, val);
+         val = iterative_hash_object (two, val);
+       }
+      else
+       for (i = first_rtl_op (code) - 1; i >= 0; --i)
+         val = iterative_hash_expr (TREE_OPERAND (t, i), val);
+    }
+  else if (code == TREE_LIST)
+    {
+      /* A list of expressions, for a CALL_EXPR or as the elements of a
+        VECTOR_CST.  */
+      for (; t; t = TREE_CHAIN (t))
+       val = iterative_hash_expr (TREE_VALUE (t), val);
+    }
+  else
+    abort ();
+
+  return val;
+}
 \f
 /* Constructors for pointer, array and function types.
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
@@ -3426,9 +3610,7 @@ compare_tree_int (t, u)
    reuse it.  */
 
 tree
-build_pointer_type_for_mode (to_type, mode)
-     tree to_type;
-     enum machine_mode mode;
+build_pointer_type_for_mode (tree to_type, enum machine_mode mode)
 {
   tree t = TYPE_POINTER_TO (to_type);
 
@@ -3456,8 +3638,7 @@ build_pointer_type_for_mode (to_type, mode)
 /* By default build pointers in ptr_mode.  */
 
 tree
-build_pointer_type (to_type)
-     tree to_type;
+build_pointer_type (tree to_type)
 {
   return build_pointer_type_for_mode (to_type, ptr_mode);
 }
@@ -3467,9 +3648,7 @@ build_pointer_type (to_type)
    reuse it.  */
 
 tree
-build_reference_type_for_mode (to_type, mode)
-     tree to_type;
-     enum machine_mode mode;
+build_reference_type_for_mode (tree to_type, enum machine_mode mode)
 {
   tree t = TYPE_REFERENCE_TO (to_type);
 
@@ -3496,8 +3675,7 @@ build_reference_type_for_mode (to_type, mode)
    in ptr_mode.  */
 
 tree
-build_reference_type (to_type)
-     tree to_type;
+build_reference_type (tree to_type)
 {
   return build_reference_type_for_mode (to_type, ptr_mode);
 }
@@ -3508,8 +3686,7 @@ build_reference_type (to_type)
    const char *const *const *  ->  char ***.  */
 
 tree
-build_type_no_quals (t)
-     tree t;
+build_type_no_quals (tree t)
 {
   switch (TREE_CODE (t))
     {
@@ -3532,8 +3709,7 @@ build_type_no_quals (t)
    sizes that use more than one HOST_WIDE_INT.  */
 
 tree
-build_index_type (maxval)
-     tree maxval;
+build_index_type (tree maxval)
 {
   tree itype = make_node (INTEGER_TYPE);
 
@@ -3559,8 +3735,7 @@ build_index_type (maxval)
    if TYPE==NULL_TREE, sizetype is used.  */
 
 tree
-build_range_type (type, lowval, highval)
-     tree type, lowval, highval;
+build_range_type (tree type, tree lowval, tree highval)
 {
   tree itype = make_node (INTEGER_TYPE);
 
@@ -3590,8 +3765,7 @@ build_range_type (type, lowval, highval)
    of just highval (maxval).  */
 
 tree
-build_index_2_type (lowval, highval)
-     tree lowval, highval;
+build_index_2_type (tree lowval, tree highval)
 {
   return build_range_type (sizetype, lowval, highval);
 }
@@ -3601,8 +3775,7 @@ build_index_2_type (lowval, highval)
    If such a type has already been constructed, reuse it.  */
 
 tree
-build_array_type (elt_type, index_type)
-     tree elt_type, index_type;
+build_array_type (tree elt_type, tree index_type)
 {
   tree t;
   unsigned int hashcode;
@@ -3639,8 +3812,7 @@ build_array_type (elt_type, index_type)
    the innermost dimension of ARRAY.  */
 
 tree
-get_inner_array_type (array)
-     tree array;
+get_inner_array_type (tree array)
 {
   tree type = TREE_TYPE (array);
 
@@ -3658,8 +3830,7 @@ get_inner_array_type (array)
    If such a type has already been constructed, reuse it.  */
 
 tree
-build_function_type (value_type, arg_types)
-     tree value_type, arg_types;
+build_function_type (tree value_type, tree arg_types)
 {
   tree t;
   unsigned int hashcode;
@@ -3684,18 +3855,18 @@ build_function_type (value_type, arg_types)
   return t;
 }
 
-/* Build a function type.  The RETURN_TYPE is the type retured by the
+/* Build a function type.  The RETURN_TYPE is the type returned by the
    function.  If additional arguments are provided, they are
    additional argument types.  The list of argument types must always
    be terminated by NULL_TREE.  */
 
 tree
-build_function_type_list VPARAMS ((tree return_type, ...))
+build_function_type_list (tree return_type, ...)
 {
   tree t, args, last;
+  va_list p;
 
-  VA_OPEN (p, return_type);
-  VA_FIXEDARG (p, tree, return_type);
+  va_start (p, return_type);
 
   t = va_arg (p, tree);
   for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
@@ -3706,40 +3877,41 @@ build_function_type_list VPARAMS ((tree return_type, ...))
   TREE_CHAIN (last) = void_list_node;
   args = build_function_type (return_type, args);
 
-  VA_CLOSE (p);
+  va_end (p);
   return args;
 }
 
-/* Construct, lay out and return the type of methods belonging to class
-   BASETYPE and whose arguments and values are described by TYPE.
-   If that type exists already, reuse it.
-   TYPE must be a FUNCTION_TYPE node.  */
+/* Build a METHOD_TYPE for a member of BASETYPE.  The RETTYPE (a TYPE)
+   and ARGTYPES (a TREE_LIST) are the return type and arguments types
+   for the method.  An implicit additional parameter (of type
+   pointer-to-BASETYPE) is added to the ARGTYPES.  */
 
 tree
-build_method_type (basetype, type)
-     tree basetype, type;
+build_method_type_directly (tree basetype,
+                           tree rettype,
+                           tree argtypes)
 {
   tree t;
-  unsigned int hashcode;
+  tree ptype;
+  int hashcode;
 
   /* Make a node of the sort we want.  */
   t = make_node (METHOD_TYPE);
 
-  if (TREE_CODE (type) != FUNCTION_TYPE)
-    abort ();
-
   TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
-  TREE_TYPE (t) = TREE_TYPE (type);
+  TREE_TYPE (t) = rettype;
+  ptype = build_pointer_type (basetype);
 
   /* The actual arglist for this function includes a "hidden" argument
      which is "this".  Put it into the list of argument types.  */
+  argtypes = tree_cons (NULL_TREE, ptype, argtypes);
+  TYPE_ARG_TYPES (t) = argtypes;
 
-  TYPE_ARG_TYPES (t)
-    = tree_cons (NULL_TREE,
-                build_pointer_type (basetype), TYPE_ARG_TYPES (type));
+  /* If we already have such a type, use the old one and free this one.
+     Note that it also frees up the above cons cell if found.  */
+  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
+    type_hash_list (argtypes);
 
-  /* If we already have such a type, use the old one and free this one.  */
-  hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);
   t = type_hash_canon (hashcode, t);
 
   if (!COMPLETE_TYPE_P (t))
@@ -3748,13 +3920,28 @@ build_method_type (basetype, type)
   return t;
 }
 
+/* Construct, lay out and return the type of methods belonging to class
+   BASETYPE and whose arguments and values are described by TYPE.
+   If that type exists already, reuse it.
+   TYPE must be a FUNCTION_TYPE node.  */
+
+tree
+build_method_type (tree basetype, tree type)
+{
+  if (TREE_CODE (type) != FUNCTION_TYPE)
+    abort ();
+
+  return build_method_type_directly (basetype, 
+                                    TREE_TYPE (type),
+                                    TYPE_ARG_TYPES (type));
+}
+
 /* Construct, lay out and return the type of offsets to a value
    of type TYPE, within an object of type BASETYPE.
    If a suitable offset type exists already, reuse it.  */
 
 tree
-build_offset_type (basetype, type)
-     tree basetype, type;
+build_offset_type (tree basetype, tree type)
 {
   tree t;
   unsigned int hashcode;
@@ -3778,8 +3965,7 @@ build_offset_type (basetype, type)
 /* Create a complex type whose components are COMPONENT_TYPE.  */
 
 tree
-build_complex_type (component_type)
-     tree component_type;
+build_complex_type (tree component_type)
 {
   tree t;
   unsigned int hashcode;
@@ -3859,9 +4045,7 @@ build_complex_type (component_type)
    is different from (int) OP.  */
 
 tree
-get_unwidened (op, for_type)
-     tree op;
-     tree for_type;
+get_unwidened (tree op, tree for_type)
 {
   /* Set UNS initially if converting OP to FOR_TYPE is a zero-extension.  */
   tree type = TREE_TYPE (op);
@@ -3921,7 +4105,8 @@ get_unwidened (op, for_type)
     {
       unsigned int innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-      int unsignedp = TREE_UNSIGNED (TREE_OPERAND (op, 1));
+      int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1))
+                      || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
       type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp);
 
       /* We can get this structure field in the narrowest type it fits in.
@@ -3951,9 +4136,7 @@ get_unwidened (op, for_type)
    or 0 if the value should be sign-extended.  */
 
 tree
-get_narrower (op, unsignedp_ptr)
-     tree op;
-     int *unsignedp_ptr;
+get_narrower (tree op, int *unsignedp_ptr)
 {
   int uns = 0;
   int first = 1;
@@ -4007,8 +4190,9 @@ get_narrower (op, unsignedp_ptr)
     {
       unsigned HOST_WIDE_INT innerprec
        = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-      tree type = (*lang_hooks.types.type_for_size) (innerprec,
-                                                    TREE_UNSIGNED (op));
+      int unsignedp = (TREE_UNSIGNED (TREE_OPERAND (op, 1))
+                      || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
+      tree type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp);
 
       /* We can get this structure field in a narrower type that fits it,
         but the resulting extension to its nominal type (a fullword type)
@@ -4039,32 +4223,60 @@ get_narrower (op, unsignedp_ptr)
    for type TYPE (an INTEGER_TYPE).  */
 
 int
-int_fits_type_p (c, type)
-     tree c, type;
-{
-  /* If the bounds of the type are integers, we can check ourselves.
-     If not, but this type is a subtype, try checking against that.
-     Otherwise, use force_fit_type, which checks against the precision.  */
-  if (TYPE_MAX_VALUE (type) != NULL_TREE
-      && TYPE_MIN_VALUE (type) != NULL_TREE
-      && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-      && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
+int_fits_type_p (tree c, tree type)
+{
+  tree type_low_bound = TYPE_MIN_VALUE (type);
+  tree type_high_bound = TYPE_MAX_VALUE (type);
+  int ok_for_low_bound, ok_for_high_bound;
+
+  /* Perform some generic filtering first, which may allow making a decision
+     even if the bounds are not constant.  First, negative integers never fit
+     in unsigned types, */
+  if ((TREE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+      /* Also, unsigned integers with top bit set never fit signed types.  */
+      || (! TREE_UNSIGNED (type)
+         && TREE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
+    return 0;
+
+  /* If at least one bound of the type is a constant integer, we can check
+     ourselves and maybe make a decision. If no such decision is possible, but
+     this type is a subtype, try checking against that.  Otherwise, use
+     force_fit_type, which checks against the precision.
+
+     Compute the status for each possibly constant bound, and return if we see
+     one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
+     for "unknown if constant fits", 0 for "constant known *not* to fit" and 1
+     for "constant known to fit".  */
+
+  ok_for_low_bound = -1;
+  ok_for_high_bound = -1;
+
+  /* Check if C >= type_low_bound.  */
+  if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
     {
-      if (TREE_UNSIGNED (type))
-       return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c)
-               && ! 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 (! INT_CST_LT (TYPE_MAX_VALUE (type), c)
-               && ! 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))));
+      ok_for_low_bound = ! tree_int_cst_lt (c, type_low_bound);
+      if (! ok_for_low_bound)
+       return 0;
+    }
+
+  /* Check if c <= type_high_bound.  */
+  if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
+    {
+      ok_for_high_bound = ! tree_int_cst_lt (type_high_bound, c);
+      if (! ok_for_high_bound)
+       return 0;
     }
+
+  /* If the constant fits both bounds, the result is known.  */
+  if (ok_for_low_bound == 1 && ok_for_high_bound == 1)
+    return 1;
+
+  /* If we haven't been able to decide at this point, there nothing more we
+     can check ourselves here. Look at the base type if we have one.  */
   else if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != 0)
     return int_fits_type_p (c, TREE_TYPE (type));
+
+  /* Or to force_fit_type, if nothing else.  */
   else
     {
       c = copy_node (c);
@@ -4078,56 +4290,68 @@ int_fits_type_p (c, type)
    modified types': in C99, a struct type is never variably modified
    because a VLA may not appear as a structure member.  However, in
    GNU C code like:
-    
+
      struct S { int i[f()]; };
 
    is valid, and other languages may define similar constructs.  */
 
 bool
-variably_modified_type_p (type)
-     tree type;
+variably_modified_type_p (tree type)
 {
+  tree t;
+
   if (type == error_mark_node)
     return false;
 
-  /* If TYPE itself has variable size, it is variably modified.  
+  /* If TYPE itself has variable size, it is variably modified.
 
      We do not yet have a representation of the C99 '[*]' syntax.
      When a representation is chosen, this function should be modified
      to test for that case as well.  */
-  if (TYPE_SIZE (type) 
-      && TYPE_SIZE (type) != error_mark_node
-      && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
-    return true;
-
-  /* If TYPE is a pointer or reference, it is variably modified if 
-     the type pointed to is variably modified.  */
-  if ((TREE_CODE (type) == POINTER_TYPE
-       || TREE_CODE (type) == REFERENCE_TYPE)
-      && variably_modified_type_p (TREE_TYPE (type)))
-    return true;
-  
-  /* If TYPE is an array, it is variably modified if the array
-     elements are.  (Note that the VLA case has already been checked
-     above.)  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && variably_modified_type_p (TREE_TYPE (type)))
+  t = TYPE_SIZE (type);
+  if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
     return true;
 
-  /* If TYPE is a function type, it is variably modified if any of the
-     parameters or the return type are variably modified.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE
-      || TREE_CODE (type) == METHOD_TYPE)
+  switch (TREE_CODE (type))
     {
-      tree parm;
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case ARRAY_TYPE:
+      /* If TYPE is a pointer or reference, it is variably modified if
+        the type pointed to is variably modified.  Similarly for arrays;
+        note that VLAs are handled by the TYPE_SIZE check above.  */
+      return variably_modified_type_p (TREE_TYPE (type));
+
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+      /* If TYPE is a function type, it is variably modified if any of the
+         parameters or the return type are variably modified.  */
+      {
+       tree parm;
 
-      if (variably_modified_type_p (TREE_TYPE (type)))
-       return true;
-      for (parm = TYPE_ARG_TYPES (type); 
-          parm && parm != void_list_node; 
-          parm = TREE_CHAIN (parm))
-       if (variably_modified_type_p (TREE_VALUE (parm)))
+       if (variably_modified_type_p (TREE_TYPE (type)))
          return true;
+       for (parm = TYPE_ARG_TYPES (type);
+            parm && parm != void_list_node;
+            parm = TREE_CHAIN (parm))
+         if (variably_modified_type_p (TREE_VALUE (parm)))
+           return true;
+      }
+      break;
+
+    case INTEGER_TYPE:
+      /* Scalar types are variably modified if their end points
+        aren't constant.  */
+      t = TYPE_MIN_VALUE (type);
+      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
+       return true;
+      t = TYPE_MAX_VALUE (type);
+      if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
+       return true;
+      return false;
+
+    default:
+      break;
     }
 
   /* The current language may have other cases to check, but in general,
@@ -4139,8 +4363,7 @@ variably_modified_type_p (type)
    NULL_TREE if there is no containing scope.  */
 
 tree
-get_containing_scope (t)
-     tree t;
+get_containing_scope (tree t)
 {
   return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t));
 }
@@ -4149,8 +4372,7 @@ get_containing_scope (t)
    a FUNCTION_DECL, or zero if none.  */
 
 tree
-decl_function_context (decl)
-     tree decl;
+decl_function_context (tree decl)
 {
   tree context;
 
@@ -4189,32 +4411,35 @@ decl_function_context (decl)
    TYPE_DECLs and FUNCTION_DECLs are transparent to this function.  */
 
 tree
-decl_type_context (decl)
-     tree decl;
+decl_type_context (tree decl)
 {
   tree context = DECL_CONTEXT (decl);
 
   while (context)
-    {
-      if (TREE_CODE (context) == NAMESPACE_DECL)
+    switch (TREE_CODE (context))
+      {
+      case NAMESPACE_DECL:
+      case TRANSLATION_UNIT_DECL:
        return NULL_TREE;
 
-      if (TREE_CODE (context) == RECORD_TYPE
-         || TREE_CODE (context) == UNION_TYPE
-         || TREE_CODE (context) == QUAL_UNION_TYPE)
+      case RECORD_TYPE:
+      case UNION_TYPE:
+      case QUAL_UNION_TYPE:
        return context;
-
-      if (TREE_CODE (context) == TYPE_DECL
-         || TREE_CODE (context) == FUNCTION_DECL)
+       
+      case TYPE_DECL:
+      case FUNCTION_DECL:
        context = DECL_CONTEXT (context);
-
-      else if (TREE_CODE (context) == BLOCK)
+       break;
+       
+      case BLOCK:
        context = BLOCK_SUPERCONTEXT (context);
-
-      else
-       /* Unhandled CONTEXT!?  */
+       break;
+       
+      default:
        abort ();
-    }
+      }
+
   return NULL_TREE;
 }
 
@@ -4223,8 +4448,7 @@ decl_type_context (decl)
    determined.  */
 
 tree
-get_callee_fndecl (call)
-     tree call;
+get_callee_fndecl (tree call)
 {
   tree addr;
 
@@ -4250,39 +4474,17 @@ get_callee_fndecl (call)
   if (TREE_CODE (addr) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
     return TREE_OPERAND (addr, 0);
-
-  /* We couldn't figure out what was being called.  */
-  return NULL_TREE;
-}
-
-/* Print debugging information about the obstack O, named STR.  */
-
-void
-print_obstack_statistics (str, o)
-     const char *str;
-     struct obstack *o;
-{
-  struct _obstack_chunk *chunk = o->chunk;
-  int n_chunks = 1;
-  int n_alloc = 0;
-
-  n_alloc += o->next_free - chunk->contents;
-  chunk = chunk->prev;
-  while (chunk)
-    {
-      n_chunks += 1;
-      n_alloc += chunk->limit - &chunk->contents[0];
-      chunk = chunk->prev;
-    }
-  fprintf (stderr, "obstack %s: %u bytes, %d chunks\n",
-          str, n_alloc, n_chunks);
+  
+  /* We couldn't figure out what was being called.  Maybe the front
+     end has some idea.  */
+  return (*lang_hooks.lang_get_callee_fndecl) (call);
 }
 
 /* Print debugging information about tree nodes generated during the compile,
    and any language-specific information.  */
 
 void
-dump_tree_statistics ()
+dump_tree_statistics (void)
 {
 #ifdef GATHER_STATISTICS
   int i;
@@ -4291,19 +4493,19 @@ dump_tree_statistics ()
 
   fprintf (stderr, "\n??? tree nodes created\n\n");
 #ifdef GATHER_STATISTICS
-  fprintf (stderr, "Kind                  Nodes     Bytes\n");
-  fprintf (stderr, "-------------------------------------\n");
+  fprintf (stderr, "Kind                   Nodes      Bytes\n");
+  fprintf (stderr, "---------------------------------------\n");
   total_nodes = total_bytes = 0;
   for (i = 0; i < (int) all_kinds; i++)
     {
-      fprintf (stderr, "%-20s %6d %9d\n", tree_node_kind_names[i],
+      fprintf (stderr, "%-20s %7d %10d\n", tree_node_kind_names[i],
               tree_node_counts[i], tree_node_sizes[i]);
       total_nodes += tree_node_counts[i];
       total_bytes += tree_node_sizes[i];
     }
-  fprintf (stderr, "-------------------------------------\n");
-  fprintf (stderr, "%-20s %6d %9d\n", "Total", total_nodes, total_bytes);
-  fprintf (stderr, "-------------------------------------\n");
+  fprintf (stderr, "---------------------------------------\n");
+  fprintf (stderr, "%-20s %7d %10d\n", "Total", total_nodes, total_bytes);
+  fprintf (stderr, "---------------------------------------\n");
 #else
   fprintf (stderr, "(No per-node statistics)\n");
 #endif
@@ -4313,73 +4515,34 @@ dump_tree_statistics ()
 \f
 #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
 
-/* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
-   clashes in cases where we can't reliably choose a unique name.
-
-   Derived from mkstemp.c in libiberty.  */
+/* Generate a crc32 of a string.  */
 
-static void
-append_random_chars (template)
-     char *template;
+unsigned
+crc32_string (unsigned chksum, const char *string)
 {
-  static const char letters[]
-    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-  static unsigned HOST_WIDE_INT value;
-  unsigned HOST_WIDE_INT v;
-
-  if (! value)
+  do
     {
-      struct stat st;
-
-      /* VALUE should be unique for each file and must not change between
-        compiles since this can cause bootstrap comparison errors.  */
-
-      if (stat (main_input_filename, &st) < 0)
-       {
-         /* This can happen when preprocessed text is shipped between
-            machines, e.g. with bug reports.  Assume that uniqueness
-            isn't actually an issue.  */
-         value = 1;
-       }
-      else
-       {
-         /* In VMS, ino is an array, so we have to use both values.  We
-            conditionalize that.  */
-#ifdef VMS
-#define INO_TO_INT(INO) ((int) (INO)[1] << 16 ^ (int) (INO)[2])
-#else
-#define INO_TO_INT(INO) INO
-#endif
-         value = st.st_dev ^ INO_TO_INT (st.st_ino) ^ st.st_mtime;
-       }
+      unsigned value = *string << 24;
+      unsigned ix;
+      
+      for (ix = 8; ix--; value <<= 1)
+       {
+         unsigned feedback;
+         
+         feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
+         chksum <<= 1;
+         chksum ^= feedback;
+       }
     }
-
-  template += strlen (template);
-
-  v = value;
-
-  /* Fill in the random bits.  */
-  template[0] = letters[v % 62];
-  v /= 62;
-  template[1] = letters[v % 62];
-  v /= 62;
-  template[2] = letters[v % 62];
-  v /= 62;
-  template[3] = letters[v % 62];
-  v /= 62;
-  template[4] = letters[v % 62];
-  v /= 62;
-  template[5] = letters[v % 62];
-
-  template[6] = '\0';
+  while (*string++);
+  return chksum;
 }
 
 /* P is a string that will be used in a symbol.  Mask out any characters
    that are not valid in that context.  */
 
 void
-clean_symbol_name (p)
-     char *p;
+clean_symbol_name (char *p)
 {
   for (; *p; p++)
     if (! (ISALNUM (*p)
@@ -4398,8 +4561,7 @@ clean_symbol_name (p)
    linker or collect2.  */
 
 tree
-get_file_function_name_long (type)
-     const char *type;
+get_file_function_name_long (const char *type)
 {
   char *buf;
   const char *p;
@@ -4411,7 +4573,7 @@ get_file_function_name_long (type)
     {
       /* We don't have anything that we know to be unique to this translation
         unit, so use what we do have and throw in some randomness.  */
-
+      unsigned len;
       const char *name = weak_global_object_name;
       const char *file = main_input_filename;
 
@@ -4420,15 +4582,18 @@ get_file_function_name_long (type)
       if (! file)
        file = input_filename;
 
-      q = (char *) alloca (7 + strlen (name) + strlen (file));
+      len = strlen (file);
+      q = alloca (9 * 2 + len + 1);
+      memcpy (q, file, len + 1);
+      clean_symbol_name (q);
+
+      sprintf (q + len, "_%08X_%08X", crc32_string (0, name),
+              crc32_string (0, flag_random_seed));
 
-      sprintf (q, "%s%s", name, file);
-      append_random_chars (q);
       p = q;
     }
 
-  buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
-                        + strlen (type));
+  buf = alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p) + strlen (type));
 
   /* Set up the name of the file-level functions we may need.
      Use a global object (which is already required to be unique over
@@ -4436,10 +4601,6 @@ get_file_function_name_long (type)
      constraints).  */
   sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
 
-  /* Don't need to pull weird characters out of global names.  */
-  if (p != first_global_object_name)
-    clean_symbol_name (buf + 11);
-
   return get_identifier (buf);
 }
 
@@ -4447,8 +4608,7 @@ get_file_function_name_long (type)
    If KIND=='D', return a suitable global clean-up (destructor) name.  */
 
 tree
-get_file_function_name (kind)
-     int kind;
+get_file_function_name (int kind)
 {
   char p[2];
 
@@ -4466,10 +4626,7 @@ get_file_function_name (kind)
    Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
 
 tree
-get_set_constructor_bits (init, buffer, bit_size)
-     tree init;
-     char *buffer;
-     int bit_size;
+get_set_constructor_bits (tree init, char *buffer, int bit_size)
 {
   int i;
   tree vals;
@@ -4524,17 +4681,14 @@ get_set_constructor_bits (init, buffer, bit_size)
    Otherwise, a TREE_LIST of the non-constant elements is emitted.  */
 
 tree
-get_set_constructor_bytes (init, buffer, wd_size)
-     tree init;
-     unsigned char *buffer;
-     int wd_size;
+get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
 {
   int i;
   int set_word_size = BITS_PER_UNIT;
   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 = alloca (bit_size);
   tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size);
 
   for (i = 0; i < wd_size; i++)
@@ -4561,12 +4715,8 @@ get_set_constructor_bytes (init, buffer, wd_size)
    FILE, LINE, and FUNCTION are of the caller.  */
 
 void
-tree_check_failed (node, code, file, line, function)
-     const tree node;
-     enum tree_code code;
-     const char *file;
-     int line;
-     const char *function;
+tree_check_failed (const tree node, enum tree_code code, const char *file,
+                  int line, const char *function)
 {
   internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
                  tree_code_name[code], tree_code_name[TREE_CODE (node)],
@@ -4577,12 +4727,8 @@ tree_check_failed (node, code, file, line, function)
    code, given in CL.  */
 
 void
-tree_class_check_failed (node, cl, file, line, function)
-     const tree node;
-     int cl;
-     const char *file;
-     int line;
-     const char *function;
+tree_class_check_failed (const tree node, int cl, const char *file,
+                        int line, const char *function)
 {
   internal_error
     ("tree check: expected class '%c', have '%c' (%s) in %s, at %s:%d",
@@ -4594,26 +4740,33 @@ tree_class_check_failed (node, cl, file, line, function)
    (dynamically sized) vector.  */
 
 void
-tree_vec_elt_check_failed (idx, len, file, line, function)
-     int idx;
-     int len;
-     const char *file;
-     int line;
-     const char *function;
+tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
+                          const char *function)
 {
   internal_error
     ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
      idx + 1, len, function, trim_filename (file), line);
 }
 
+/* Similar to above, except that the check is for the bounds of the operand
+   vector of an expression node.  */
+
+void
+tree_operand_check_failed (int idx, enum tree_code code, const char *file,
+                          int line, const char *function)
+{
+  internal_error
+    ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
+     idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code),
+     function, trim_filename (file), line);
+}
 #endif /* ENABLE_TREE_CHECKING */
 \f
 /* For a new vector type node T, build the information necessary for
    debugging output.  */
 
 static void
-finish_vector_type (t)
-     tree t;
+finish_vector_type (tree t)
 {
   layout_type (t);
 
@@ -4640,8 +4793,7 @@ finish_vector_type (t)
    this function to select one of the types as sizetype.  */
 
 void
-build_common_tree_nodes (signed_char)
-     int signed_char;
+build_common_tree_nodes (int signed_char)
 {
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
@@ -4668,6 +4820,16 @@ build_common_tree_nodes (signed_char)
   long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
   long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
 
+  /* Define a boolean type.  This type only represents boolean values but
+     may be larger than char depending on the value of BOOL_TYPE_SIZE.
+     Front ends which want to override this size (i.e. Java) can redefine
+     boolean_type_node before calling build_common_tree_nodes_2.  */
+  boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
+  TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
+  TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
+  TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
+  TYPE_PRECISION (boolean_type_node) = 1;
+
   intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
   intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
   intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
@@ -4685,8 +4847,7 @@ build_common_tree_nodes (signed_char)
    It will create several other common tree nodes.  */
 
 void
-build_common_tree_nodes_2 (short_double)
-     int short_double;
+build_common_tree_nodes_2 (int short_double)
 {
   /* Define these next since types below may used them.  */
   integer_zero_node = build_int_2 (0, 0);
@@ -4699,6 +4860,9 @@ build_common_tree_nodes_2 (short_double)
   bitsize_one_node = bitsize_int (1);
   bitsize_unit_node = bitsize_int (BITS_PER_UNIT);
 
+  boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
+  boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
+
   void_type_node = make_node (VOID_TYPE);
   layout_type (void_type_node);
 
@@ -4730,6 +4894,11 @@ build_common_tree_nodes_2 (short_double)
   TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
   layout_type (long_double_type_node);
 
+  float_ptr_type_node = build_pointer_type (float_type_node);
+  double_ptr_type_node = build_pointer_type (double_type_node);
+  long_double_ptr_type_node = build_pointer_type (long_double_type_node);
+  integer_ptr_type_node = build_pointer_type (integer_type_node);
+
   complex_integer_type_node = make_node (COMPLEX_TYPE);
   TREE_TYPE (complex_integer_type_node) = integer_type_node;
   layout_type (complex_integer_type_node);
@@ -4750,7 +4919,7 @@ build_common_tree_nodes_2 (short_double)
     tree t;
     BUILD_VA_LIST_TYPE (t);
 
-    /* Many back-ends define record types without seting TYPE_NAME.
+    /* Many back-ends define record types without setting TYPE_NAME.
        If we copied the record type here, we'd keep the original
        record type without a name.  This breaks name mangling.  So,
        don't copy record types and let c_common_nodes_and_builtins()
@@ -4793,16 +4962,14 @@ build_common_tree_nodes_2 (short_double)
   V2DF_type_node = make_vector (V2DFmode, double_type_node, 0);
   V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0);
   V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0);
+  V4DF_type_node = make_vector (V4DFmode, double_type_node, 0);
 }
 
 /* Returns a vector tree node given a vector mode, the inner type, and
    the signness.  */
 
 static tree
-make_vector (mode, innertype, unsignedp)
-     enum machine_mode mode;
-     tree innertype;
-     int unsignedp;
+make_vector (enum machine_mode mode, tree innertype, int unsignedp)
 {
   tree t;
 
@@ -4819,8 +4986,7 @@ make_vector (mode, innertype, unsignedp)
    aggregate of zeros.  Otherwise return FALSE.  */
 
 bool
-initializer_zerop (init)
-     tree init;
+initializer_zerop (tree init)
 {
   STRIP_NOPS (init);
 
@@ -4840,7 +5006,7 @@ initializer_zerop (init)
       {
        if (AGGREGATE_TYPE_P (TREE_TYPE (init)))
          {
-           tree aggr_init = TREE_OPERAND (init, 1);
+           tree aggr_init = CONSTRUCTOR_ELTS (init);
 
            while (aggr_init)
              {