OSDN Git Service

* reorg.c (fill_slots_from_thread): Check side_effects_p when
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index d8e4ff1..62a3b25 100644 (file)
@@ -1,5 +1,6 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -29,48 +30,52 @@ Boston, MA 02111-1307, USA.  */
    like a strange sort of assignment).  */
 
 #include "config.h"
-#include <stdio.h>
+#include "system.h"
 #include "tree.h"
 #include "c-tree.h"
+#include "tm_p.h"
 #include "flags.h"
 #include "output.h"
+#include "rtl.h"
+#include "expr.h"
+#include "toplev.h"
+#include "intl.h"
+#include "defaults.h"
+#include "ggc.h"
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 static int missing_braces_mentioned;
 
-extern char *index ();
-extern char *rindex ();
-
-static tree quality_type               PROTO((tree, tree));
-static int comp_target_types           PROTO((tree, tree));
-static int function_types_compatible_p PROTO((tree, tree));
-static int type_lists_compatible_p     PROTO((tree, tree));
-static int self_promoting_type_p       PROTO((tree));
-static tree decl_constant_value                PROTO((tree));
-static tree lookup_field               PROTO((tree, tree, tree *));
-static tree convert_arguments          PROTO((tree, tree, tree, tree));
-static tree pointer_int_sum            PROTO((enum tree_code, tree, tree));
-static tree pointer_diff               PROTO((tree, tree));
-static tree unary_complex_lvalue       PROTO((enum tree_code, tree));
-static void pedantic_lvalue_warning    PROTO((enum tree_code));
-static tree internal_build_compound_expr PROTO((tree, int));
-static tree convert_for_assignment     PROTO((tree, tree, char *, tree,
-                                              tree, int));
-static void warn_for_assignment                PROTO((char *, char *, tree, int));
-static tree valid_compound_expr_initializer PROTO((tree, tree));
-static void push_string                        PROTO((char *));
-static void push_member_name           PROTO((tree));
-static void push_array_bounds          PROTO((int));
-static int spelling_length             PROTO((void));
-static char *print_spelling            PROTO((char *));
-static char *get_spelling              PROTO((char *));
-static void warning_init               PROTO((char *, char *,
-                                              char *));
-static tree digest_init                        PROTO((tree, tree, int, int));
-static void check_init_type_bitfields  PROTO((tree));
-static void output_init_element                PROTO((tree, tree, tree, int));
-static void output_pending_init_elements PROTO((int));
+static tree qualify_type               PARAMS ((tree, tree));
+static int comp_target_types           PARAMS ((tree, tree));
+static int function_types_compatible_p PARAMS ((tree, tree));
+static int type_lists_compatible_p     PARAMS ((tree, tree));
+static tree decl_constant_value                PARAMS ((tree));
+static tree lookup_field               PARAMS ((tree, tree, tree *));
+static tree convert_arguments          PARAMS ((tree, tree, tree, tree));
+static tree pointer_int_sum            PARAMS ((enum tree_code, tree, tree));
+static tree pointer_diff               PARAMS ((tree, tree));
+static tree unary_complex_lvalue       PARAMS ((enum tree_code, tree));
+static void pedantic_lvalue_warning    PARAMS ((enum tree_code));
+static tree internal_build_compound_expr PARAMS ((tree, int));
+static tree convert_for_assignment     PARAMS ((tree, tree, const char *,
+                                                tree, tree, int));
+static void warn_for_assignment                PARAMS ((const char *, const char *,
+                                                tree, int));
+static tree valid_compound_expr_initializer PARAMS ((tree, tree));
+static void push_string                        PARAMS ((const char *));
+static void push_member_name           PARAMS ((tree));
+static void push_array_bounds          PARAMS ((int));
+static int spelling_length             PARAMS ((void));
+static char *print_spelling            PARAMS ((char *));
+static void warning_init               PARAMS ((const char *));
+static tree digest_init                        PARAMS ((tree, tree, int, int));
+static void check_init_type_bitfields  PARAMS ((tree));
+static void output_init_element                PARAMS ((tree, tree, tree, int));
+static void output_pending_init_elements PARAMS ((int));
+static void add_pending_init           PARAMS ((tree, tree));
+static int pending_init_member         PARAMS ((tree));
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -81,9 +86,11 @@ require_complete_type (value)
 {
   tree type = TREE_TYPE (value);
 
+  if (TREE_CODE (value) == ERROR_MARK)
+    return error_mark_node;
+
   /* First, detect a valid value with a complete type.  */
-  if (TYPE_SIZE (type) != 0
-      && type != void_type_node)
+  if (COMPLETE_TYPE_P (type))
     return value;
 
   incomplete_type_error (value, type);
@@ -99,7 +106,7 @@ incomplete_type_error (value, type)
      tree value;
      tree type;
 {
-  char *errmsg;
+  const char *type_code_string;
 
   /* Avoid duplicate error message.  */
   if (TREE_CODE (type) == ERROR_MARK)
@@ -117,15 +124,15 @@ incomplete_type_error (value, type)
       switch (TREE_CODE (type))
        {
        case RECORD_TYPE:
-         errmsg = "invalid use of undefined type `struct %s'";
+         type_code_string = "struct";
          break;
 
        case UNION_TYPE:
-         errmsg = "invalid use of undefined type `union %s'";
+         type_code_string = "union";
          break;
 
        case ENUMERAL_TYPE:
-         errmsg = "invalid use of undefined type `enum %s'";
+         type_code_string = "enum";
          break;
 
        case VOID_TYPE:
@@ -146,7 +153,8 @@ incomplete_type_error (value, type)
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-       error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
+       error ("invalid use of undefined type `%s %s'",
+              type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type)));
       else
        /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
        error ("invalid use of incomplete typedef `%s'",
@@ -161,48 +169,10 @@ static tree
 qualify_type (type, like)
      tree type, like;
 {
-  int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
-  int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
-  return c_build_type_variant (type, constflag, volflag);
+  return c_build_qualified_type (type, 
+                                TYPE_QUALS (type) | TYPE_QUALS (like));
 }
 \f
-/* 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;
-}
-
 /* Return the common type of two types.
    We assume that comptypes has already been done and returned 1;
    if that isn't so, this may crash.  In particular, we assume that qualifiers
@@ -229,8 +199,8 @@ common_type (t1, t2)
   if (t2 == error_mark_node)
     return t1;
 
-  /* Merge the attributes */
-  attributes = merge_attributes (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
+  /* Merge the attributes */
+  attributes = merge_machine_type_attributes (t1, t2);
 
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
@@ -298,6 +268,12 @@ common_type (t1, t2)
          return build_type_attribute_variant (t1, attributes);
        }
 
+      /* Likewise, prefer long double to double even if same size.  */
+      if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
+         || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+       return build_type_attribute_variant (long_double_type_node,
+                                            attributes);
+
       /* Otherwise prefer the unsigned one.  */
 
       if (TREE_UNSIGNED (t1))
@@ -312,14 +288,14 @@ common_type (t1, t2)
         But ANSI C specifies doing this with the qualifiers.
         So I turned it on again.  */
       {
-       tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
-                                  TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
-       int constp
-         = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
-       int volatilep
-         = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
-       t1 = build_pointer_type (c_build_type_variant (target, constp,
-                                volatilep));
+       tree pointed_to_1 = TREE_TYPE (t1);
+       tree pointed_to_2 = TREE_TYPE (t2);
+       tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
+                                  TYPE_MAIN_VARIANT (pointed_to_2));
+       t1 = build_pointer_type (c_build_qualified_type 
+                                (target, 
+                                 TYPE_QUALS (pointed_to_1) | 
+                                 TYPE_QUALS (pointed_to_2)));
        return build_type_attribute_variant (t1, attributes);
       }
 #if 0
@@ -432,7 +408,7 @@ common_type (t1, t2)
          }
 
        t1 = build_function_type (valtype, newargs);
-       /* ... falls through ... */
+       /* ... falls through ...  */
       }
 
     default:
@@ -455,9 +431,20 @@ comptypes (type1, type2)
 
   /* Suppress errors caused by previously reported errors.  */
 
-  if (t1 == t2 || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
+  if (t1 == t2 || !t1 || !t2
+      || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
     return 1;
 
+  /* If either type is the internal version of sizetype, return the
+     language version.  */
+  if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
+      && TYPE_DOMAIN (t1) != 0)
+    t1 = TYPE_DOMAIN (t1);
+
+  if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
+      && TYPE_DOMAIN (t2) != 0)
+    t2 = TYPE_DOMAIN (t2);
+
   /* Treat an enum type as the integer type of the same width and 
      signedness.  */
 
@@ -475,14 +462,12 @@ comptypes (type1, type2)
 
   /* Qualifiers must match.  */
 
-  if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
-    return 0;
-  if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
     return 0;
 
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
-     type qualifiers (just above).  */
+     qualifiers (just above).  */
 
   if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return 1;
@@ -528,15 +513,10 @@ comptypes (type1, type2)
            || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
          break;
 
-       if (! ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
-                 == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
-                && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
-                    == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
-                && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
-                    == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
-                && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
-                    == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))))
-          val = 0;
+       if (! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
+           || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
+         val = 0;
+
         break;
       }
 
@@ -544,6 +524,9 @@ comptypes (type1, type2)
       if (maybe_objc_comptypes (t1, t2, 0) == 1)
        val = 1;
       break;
+
+    default:
+      break;
     }
   return attrval == 2 && val == 1 ? 2 : val;
 }
@@ -558,7 +541,7 @@ comp_target_types (ttl, ttr)
   int val;
 
   /* Give maybe_objc_comptypes a crack at letting these types through.  */
-  if (val = maybe_objc_comptypes (ttl, ttr, 1) >= 0)
+  if ((val = maybe_objc_comptypes (ttl, ttr, 1)) >= 0)
     return val;
 
   val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
@@ -650,12 +633,12 @@ type_lists_compatible_p (args1, args2)
         So match anything that self-promotes.  */
       if (TREE_VALUE (args1) == 0)
        {
-         if (! self_promoting_type_p (TREE_VALUE (args2)))
+         if (simple_type_promotes_to (TREE_VALUE (args2)) != NULL_TREE)
            return 0;
        }
       else if (TREE_VALUE (args2) == 0)
        {
-         if (! self_promoting_type_p (TREE_VALUE (args1)))
+         if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
            return 0;
        }
       else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2))))
@@ -704,129 +687,7 @@ type_lists_compatible_p (args1, args2)
       args2 = TREE_CHAIN (args2);
     }
 }
-
-/* Return 1 if PARMS specifies a fixed number of parameters
-   and none of their types is affected by default promotions.  */
-
-int
-self_promoting_args_p (parms)
-     tree parms;
-{
-  register tree t;
-  for (t = parms; t; t = TREE_CHAIN (t))
-    {
-      register tree type = TREE_VALUE (t);
-
-      if (TREE_CHAIN (t) == 0 && type != void_type_node)
-       return 0;
-
-      if (type == 0)
-       return 0;
-
-      if (TYPE_MAIN_VARIANT (type) == float_type_node)
-       return 0;
-
-      if (C_PROMOTING_INTEGER_TYPE_P (type))
-       return 0;
-    }
-  return 1;
-}
-
-/* Return 1 if TYPE is not affected by default promotions.  */
-
-static int
-self_promoting_type_p (type)
-     tree type;
-{
-  if (TYPE_MAIN_VARIANT (type) == float_type_node)
-    return 0;
-
-  if (C_PROMOTING_INTEGER_TYPE_P (type))
-    return 0;
-
-  return 1;
-}
 \f
-/* Return an unsigned type the same as TYPE in other respects.  */
-
-tree
-unsigned_type (type)
-     tree type;
-{
-  tree type1 = TYPE_MAIN_VARIANT (type);
-  if (type1 == signed_char_type_node || type1 == char_type_node)
-    return unsigned_char_type_node;
-  if (type1 == integer_type_node)
-    return unsigned_type_node;
-  if (type1 == short_integer_type_node)
-    return short_unsigned_type_node;
-  if (type1 == long_integer_type_node)
-    return long_unsigned_type_node;
-  if (type1 == long_long_integer_type_node)
-    return long_long_unsigned_type_node;
-  if (type1 == intDI_type_node)
-    return unsigned_intDI_type_node;
-  if (type1 == intSI_type_node)
-    return unsigned_intSI_type_node;
-  if (type1 == intHI_type_node)
-    return unsigned_intHI_type_node;
-  if (type1 == intQI_type_node)
-    return unsigned_intQI_type_node;
-  return type;
-}
-
-/* Return a signed type the same as TYPE in other respects.  */
-
-tree
-signed_type (type)
-     tree type;
-{
-  tree type1 = TYPE_MAIN_VARIANT (type);
-  if (type1 == unsigned_char_type_node || type1 == char_type_node)
-    return signed_char_type_node;
-  if (type1 == unsigned_type_node)
-    return integer_type_node;
-  if (type1 == short_unsigned_type_node)
-    return short_integer_type_node;
-  if (type1 == long_unsigned_type_node)
-    return long_integer_type_node;
-  if (type1 == long_long_unsigned_type_node)
-    return long_long_integer_type_node;
-  if (type1 == unsigned_intDI_type_node)
-    return intDI_type_node;
-  if (type1 == unsigned_intSI_type_node)
-    return intSI_type_node;
-  if (type1 == unsigned_intHI_type_node)
-    return intHI_type_node;
-  if (type1 == unsigned_intQI_type_node)
-    return intQI_type_node;
-  return type;
-}
-
-/* Return a type the same as TYPE except unsigned or
-   signed according to UNSIGNEDP.  */
-
-tree
-signed_or_unsigned_type (unsignedp, type)
-     int unsignedp;
-     tree type;
-{
-  if (! INTEGRAL_TYPE_P (type))
-    return type;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
-    return unsignedp ? unsigned_char_type_node : signed_char_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) 
-    return unsignedp ? unsigned_type_node : integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node)) 
-    return unsignedp ? short_unsigned_type_node : short_integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node)) 
-    return unsignedp ? long_unsigned_type_node : long_integer_type_node;
-  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node)) 
-    return (unsignedp ? long_long_unsigned_type_node
-           : long_long_integer_type_node);
-  return type;
-}
-
 /* Compute the value of the `sizeof' operator.  */
 
 tree
@@ -834,35 +695,33 @@ c_sizeof (type)
      tree type;
 {
   enum tree_code code = TREE_CODE (type);
-  tree t;
 
   if (code == FUNCTION_TYPE)
     {
       if (pedantic || warn_pointer_arith)
        pedwarn ("sizeof applied to a function type");
-      return size_int (1);
+      return size_one_node;
     }
   if (code == VOID_TYPE)
     {
       if (pedantic || warn_pointer_arith)
        pedwarn ("sizeof applied to a void type");
-      return size_int (1);
+      return size_one_node;
     }
+
   if (code == ERROR_MARK)
-    return size_int (1);
-  if (TYPE_SIZE (type) == 0)
+    return size_one_node;
+
+  if (!COMPLETE_TYPE_P (type))
     {
       error ("sizeof applied to an incomplete type");
-      return size_int (0);
+      return size_zero_node;
     }
 
   /* Convert in case a char is more than one unit.  */
-  t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), 
-                 size_int (TYPE_PRECISION (char_type_node)));
-  /* size_binop does not put the constant in range, so do it now.  */
-  if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0))
-    TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1;
-  return t;
+  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                    size_int (TYPE_PRECISION (char_type_node)
+                              / BITS_PER_UNIT));
 }
 
 tree
@@ -870,20 +729,17 @@ c_sizeof_nowarn (type)
      tree type;
 {
   enum tree_code code = TREE_CODE (type);
-  tree t;
 
-  if (code == FUNCTION_TYPE
-      || code == VOID_TYPE
-      || code == ERROR_MARK)
-    return size_int (1);
-  if (TYPE_SIZE (type) == 0)
-    return size_int (0);
+  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+    return size_one_node;
+
+  if (!COMPLETE_TYPE_P (type))
+    return size_zero_node;
 
   /* Convert in case a char is more than one unit.  */
-  t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), 
-                 size_int (TYPE_PRECISION (char_type_node)));
-  force_fit_type (t, 0);
-  return t;
+  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                    size_int (TYPE_PRECISION (char_type_node)
+                              / BITS_PER_UNIT));
 }
 
 /* Compute the size to increment a pointer by.  */
@@ -893,25 +749,20 @@ c_size_in_bytes (type)
      tree type;
 {
   enum tree_code code = TREE_CODE (type);
-  tree t;
 
-  if (code == FUNCTION_TYPE)
-    return size_int (1);
-  if (code == VOID_TYPE)
-    return size_int (1);
-  if (code == ERROR_MARK)
-    return size_int (1);
-  if (TYPE_SIZE (type) == 0)
+  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+    return size_one_node;
+
+  if (!COMPLETE_OR_VOID_TYPE_P (type))
     {
       error ("arithmetic on pointer to an incomplete type");
-      return size_int (1);
+      return size_one_node;
     }
 
   /* Convert in case a char is more than one unit.  */
-  t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), 
-                    size_int (BITS_PER_UNIT));
-  force_fit_type (t, 0);
-  return t;
+  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                    size_int (TYPE_PRECISION (char_type_node)
+                              / BITS_PER_UNIT));
 }
 
 /* Implement the __alignof keyword: Return the minimum required
@@ -927,7 +778,13 @@ c_alignof (type)
     return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
 
   if (code == VOID_TYPE || code == ERROR_MARK)
-    return size_int (1);
+    return size_one_node;
+
+  if (!COMPLETE_TYPE_P (type))
+    {
+      error ("__alignof__ applied to an incomplete type");
+      return size_zero_node;
+    }
 
   return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
 }
@@ -945,10 +802,10 @@ c_alignof_expr (expr)
     return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
  
   if (TREE_CODE (expr) == COMPONENT_REF
-      && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+      && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
     {
       error ("`__alignof' applied to a bit-field");
-      return size_int (1);
+      return size_one_node;
     }
   else if (TREE_CODE (expr) == COMPONENT_REF
       && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
@@ -975,16 +832,16 @@ c_alignof_expr (expr)
   else
     return c_alignof (TREE_TYPE (expr));
 }
+
 /* Return either DECL or its known constant value (if it has one).  */
 
 static tree
 decl_constant_value (decl)
      tree decl;
 {
-  if (! TREE_PUBLIC (decl)
-      /* Don't change a variable array bound or initial value to a constant
+  if (/* Don't change a variable array bound or initial value to a constant
         in a place where a variable is invalid.  */
-      && current_function_decl != 0
+      current_function_decl != 0
       && ! pedantic
       && ! TREE_THIS_VOLATILE (decl)
       && TREE_READONLY (decl) && ! ITERATOR_P (decl)
@@ -1027,8 +884,9 @@ default_conversion (exp)
     }
 
   /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
-     an lvalue.  */
-  /* Do not use STRIP_NOPS here!  It will remove conversions from pointer
+     an lvalue. 
+
+     Do not use STRIP_NOPS here!  It will remove conversions from pointer
      to integer and cause infinite recursion.  */
   while (TREE_CODE (exp) == NON_LVALUE_EXPR
         || (TREE_CODE (exp) == NOP_EXPR
@@ -1042,11 +900,23 @@ default_conversion (exp)
       type = type_for_size (MAX (TYPE_PRECISION (type),
                                 TYPE_PRECISION (integer_type_node)),
                            ((flag_traditional
-                             || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
+                             || (TYPE_PRECISION (type)
+                                 >= TYPE_PRECISION (integer_type_node)))
                             && TREE_UNSIGNED (type)));
+
       return convert (type, exp);
     }
 
+  if (TREE_CODE (exp) == COMPONENT_REF
+      && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+      /* If it's thinner than an int, promote it like a
+        C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone.  */
+      && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
+                              TYPE_PRECISION (integer_type_node)))
+    return convert (flag_traditional && TREE_UNSIGNED (type)
+                   ? unsigned_type_node : integer_type_node,
+                   exp);
+
   if (C_PROMOTING_INTEGER_TYPE_P (type))
     {
       /* Traditionally, unsignedness is preserved in default promotions.
@@ -1055,11 +925,14 @@ default_conversion (exp)
          && (flag_traditional
              || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
        return convert (unsigned_type_node, exp);
+
       return convert (integer_type_node, exp);
     }
+
   if (flag_traditional && !flag_allow_single_precision
       && TYPE_MAIN_VARIANT (type) == float_type_node)
     return convert (double_type_node, exp);
+
   if (code == VOID_TYPE)
     {
       error ("void value not ignored as it ought to be");
@@ -1077,18 +950,18 @@ default_conversion (exp)
       int constp = 0;
       int volatilep = 0;
 
-      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
-         || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
+      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
        {
          constp = TREE_READONLY (exp);
          volatilep = TREE_THIS_VOLATILE (exp);
        }
 
-      if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
-         || constp || volatilep)
-       restype = c_build_type_variant (restype,
-                                       TYPE_READONLY (type) || constp,
-                                       TYPE_VOLATILE (type) || volatilep);
+      if (TYPE_QUALS (type) || constp || volatilep)
+       restype 
+         = c_build_qualified_type (restype,
+                                   TYPE_QUALS (type) 
+                                   | (constp * TYPE_QUAL_CONST)
+                                   | (volatilep * TYPE_QUAL_VOLATILE));
 
       if (TREE_CODE (exp) == INDIRECT_REF)
        return convert (TYPE_POINTER_TO (restype),
@@ -1101,7 +974,7 @@ default_conversion (exp)
                        TREE_OPERAND (exp, 0), op1);
        }
 
-      if (!lvalue_p (exp)
+      if (! lvalue_p (exp)
          && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
        {
          error ("invalid use of non-lvalue array");
@@ -1167,10 +1040,13 @@ lookup_field (type, component, indirect)
              /* Step through all anon unions in linear fashion.  */
              while (DECL_NAME (field_array[bot]) == NULL_TREE)
                {
-                 tree anon, junk;
+                 tree anon = 0, junk;
 
                  field = field_array[bot++];
-                 anon = lookup_field (TREE_TYPE (field), component, &junk);
+                 if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                     || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+                   anon = lookup_field (TREE_TYPE (field), component, &junk);
+
                  if (anon != NULL_TREE)
                    {
                      *indirect = field;
@@ -1206,7 +1082,12 @@ lookup_field (type, component, indirect)
          if (DECL_NAME (field) == NULL_TREE)
            {
              tree junk;
-             tree anon = lookup_field (TREE_TYPE (field), component, &junk);
+             tree anon = 0;
+
+             if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+               anon = lookup_field (TREE_TYPE (field), component, &junk);
+
              if (anon != NULL_TREE)
                {
                  *indirect = field;
@@ -1250,6 +1131,9 @@ build_component_ref (datum, component)
        (TREE_OPERAND (datum, 0),
         build_component_ref (TREE_OPERAND (datum, 1), component),
         build_component_ref (TREE_OPERAND (datum, 2), component));
+
+    default:
+      break;
     }
 
   /* See if there is a field or component with name COMPONENT.  */
@@ -1258,7 +1142,7 @@ build_component_ref (datum, component)
     {
       tree indirect = 0;
 
-      if (TYPE_SIZE (type) == 0)
+      if (!COMPLETE_TYPE_P (type))
        {
          incomplete_type_error (NULL_TREE, type);
          return error_mark_node;
@@ -1268,9 +1152,8 @@ build_component_ref (datum, component)
 
       if (!field)
        {
-         error (code == RECORD_TYPE
-                ? "structure has no member named `%s'"
-                : "union has no member named `%s'",
+         error ("%s has no member named `%s'",
+                code == RECORD_TYPE ? "structure" : "union",
                 IDENTIFIER_POINTER (component));
          return error_mark_node;
        }
@@ -1313,7 +1196,7 @@ build_component_ref (datum, component)
 tree
 build_indirect_ref (ptr, errorstring)
      tree ptr;
-     char *errorstring;
+     const char *errorstring;
 {
   register tree pointer = default_conversion (ptr);
   register tree type = TREE_TYPE (pointer);
@@ -1331,12 +1214,12 @@ build_indirect_ref (ptr, errorstring)
          register tree ref = build1 (INDIRECT_REF,
                                      TYPE_MAIN_VARIANT (t), pointer);
 
-         if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
+         if (!COMPLETE_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
              error ("dereferencing pointer to incomplete type");
              return error_mark_node;
            }
-         if (TREE_CODE (t) == VOID_TYPE)
+         if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
            warning ("dereferencing `void *' pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -1411,7 +1294,7 @@ build_array_ref (array, index)
         address arithmetic on its address.
         Likewise an array of elements of variable size.  */
       if (TREE_CODE (index) != INTEGER_CST
-         || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
+         || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
              && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
        {
          if (mark_addressable (array) == 0)
@@ -1470,6 +1353,14 @@ build_array_ref (array, index)
     tree ar = default_conversion (array);
     tree ind = default_conversion (index);
 
+    /* Do the same warning check as above, but only on the part that's
+       syntactically the index and only if it is also semantically
+       the index.  */
+    if (warn_char_subscripts
+       && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
+       && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+      warning ("subscript has type `char'");
+
     /* Put the integer in IND to simplify error checking.  */
     if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
       {
@@ -1481,7 +1372,8 @@ build_array_ref (array, index)
     if (ar == error_mark_node)
       return ar;
 
-    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
+    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE
+       || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE)
       {
        error ("subscripted value is neither array nor pointer");
        return error_mark_node;
@@ -1508,7 +1400,7 @@ build_function_call (function, params)
 {
   register tree fntype, fundecl = 0;
   register tree coerced_params;
-  tree name = NULL_TREE, assembler_name = NULL_TREE;
+  tree name = NULL_TREE, assembler_name = NULL_TREE, result;
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -1564,26 +1456,20 @@ build_function_call (function, params)
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
       && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
-    switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
-      {
-      case BUILT_IN_ABS:
-      case BUILT_IN_LABS:
-      case BUILT_IN_FABS:
-       if (coerced_params == 0)
-         return integer_zero_node;
-       return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
-      }
+    {
+      result = expand_tree_builtin (TREE_OPERAND (function, 0),
+                                   params, coerced_params);
+      if (result)
+       return result;
+    }
 
-  {
-    register tree result
-      = build (CALL_EXPR, TREE_TYPE (fntype),
-              function, coerced_params, NULL_TREE);
-
-    TREE_SIDE_EFFECTS (result) = 1;
-    if (TREE_TYPE (result) == void_type_node)
-      return result;
-    return require_complete_type (result);
-  }
+  result = build (CALL_EXPR, TREE_TYPE (fntype),
+                 function, coerced_params, NULL_TREE);
+
+  TREE_SIDE_EFFECTS (result) = 1;
+  if (TREE_TYPE (result) == void_type_node)
+    return result;
+  return require_complete_type (result);
 }
 \f
 /* Convert the argument expressions in the list VALUES
@@ -1649,7 +1535,7 @@ convert_arguments (typelist, values, name, fundecl)
          /* Formal parm type is specified by a function prototype.  */
          tree parmval;
 
-         if (TYPE_SIZE (type) == 0)
+         if (!COMPLETE_TYPE_P (type))
            {
              error ("type of formal parameter %d is incomplete", parmnum + 1);
              parmval = val;
@@ -1739,15 +1625,14 @@ convert_arguments (typelist, values, name, fundecl)
                }
 
              parmval = convert_for_assignment (type, val, 
-                                               (char *)0, /* arg passing  */
+                                               (char *) 0, /* arg passing  */
                                                fundecl, name, parmnum + 1);
              
-#ifdef PROMOTE_PROTOTYPES
-             if ((TREE_CODE (type) == INTEGER_TYPE
-                  || TREE_CODE (type) == ENUMERAL_TYPE)
+             if (PROMOTE_PROTOTYPES
+                 && (TREE_CODE (type) == INTEGER_TYPE
+                     || TREE_CODE (type) == ENUMERAL_TYPE)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
-#endif
            }
          result = tree_cons (NULL_TREE, parmval, result);
        }
@@ -2025,17 +1910,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
-           {
-             /* Although it would be tempting to shorten always here, that
-                loses on some targets, since the modulo instruction is
-                undefined if the quotient can't be represented in the
-                computation mode.  We shorten only if unsigned or if
-                dividing by something we know != -1.  */
-             shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
-                        || (TREE_CODE (op1) == INTEGER_CST
-                            && (TREE_INT_CST_LOW (op1) != -1
-                                || TREE_INT_CST_HIGH (op1) != -1)));
-           }
+           /* Although it would be tempting to shorten always here, that
+              loses on some targets, since the modulo instruction is
+              undefined if the quotient can't be represented in the
+              computation mode.  We shorten only if unsigned or if
+              dividing by something we know != -1.  */
+           shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
+                      || (TREE_CODE (op1) == INTEGER_CST
+                          && ! integer_all_onesp (op1)));
          common = 1;
        }
       break;
@@ -2081,8 +1963,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
             only if unsigned or if dividing by something we know != -1.  */
          shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
                     || (TREE_CODE (op1) == INTEGER_CST
-                        && (TREE_INT_CST_LOW (op1) != -1
-                            || TREE_INT_CST_HIGH (op1) != -1)));
+                        && ! integer_all_onesp (op1)));
          common = 1;
        }
       break;
@@ -2114,20 +1995,20 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case RSHIFT_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
-         if (TREE_CODE (op1) == INTEGER_CST)
+         if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
              if (tree_int_cst_sgn (op1) < 0)
                warning ("right shift count is negative");
              else
                {
-                 if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1))
+                 if (! integer_zerop (op1))
                    short_shift = 1;
-                 if (TREE_INT_CST_HIGH (op1) != 0
-                     || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
-                         >= TYPE_PRECISION (type0)))
+
+                 if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                    warning ("right shift count >= width of type");
                }
            }
+
          /* Use the type of the value to be shifted.
             This is what most traditional C compilers do.  */
          result_type = type0;
@@ -2146,15 +2027,15 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case LSHIFT_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
-         if (TREE_CODE (op1) == INTEGER_CST)
+         if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
              if (tree_int_cst_sgn (op1) < 0)
                warning ("left shift count is negative");
-             else if (TREE_INT_CST_HIGH (op1) != 0
-                      || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
-                          >= TYPE_PRECISION (type0)))
+
+             else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                warning ("left shift count >= width of type");
            }
+
          /* Use the type of the value to be shifted.
             This is what most traditional C compilers do.  */
          result_type = type0;
@@ -2174,15 +2055,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case LROTATE_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
-         if (TREE_CODE (op1) == INTEGER_CST)
+         if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
              if (tree_int_cst_sgn (op1) < 0)
                warning ("shift count is negative");
-             else if (TREE_INT_CST_HIGH (op1) != 0
-                      || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
-                          >= TYPE_PRECISION (type0)))
+             else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                warning ("shift count >= width of type");
            }
+
          /* Use the type of the value to be shifted.
             This is what most traditional C compilers do.  */
          result_type = type0;
@@ -2200,6 +2080,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
 
     case EQ_EXPR:
     case NE_EXPR:
+      if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
+       warning ("comparing floating point with == or != is unsafe");
       /* Result of comparison is always int,
         but don't convert the args to int!  */
       build_type = integer_type_node;
@@ -2292,8 +2174,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          if (comp_target_types (type0, type1))
            {
              result_type = common_type (type0, type1);
-             if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
-                 != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
+             if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
+                 != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
                pedwarn ("comparison of complete and incomplete pointers");
              else if (pedantic 
                       && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
@@ -2332,6 +2214,25 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            pedwarn ("comparison between pointer and integer");
        }
       break;
+
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+      build_type = integer_type_node;
+      if (code0 != REAL_TYPE || code1 != REAL_TYPE)
+       {
+         error ("unordered comparison on non-floating point argument");
+         return error_mark_node;
+       }
+      common = 1;
+      break;
+
+    default:
+      break;
     }
 
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
@@ -2433,8 +2334,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
-             && TREE_INT_CST_HIGH (op1) == 0
-             && TYPE_PRECISION (TREE_TYPE (arg0)) > TREE_INT_CST_LOW (op1)
+             && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
              /* If arg is sign-extended and then unsigned-shifted,
                 we can simulate this with a signed shift in arg's type
                 only if the extended result is at least twice as wide
@@ -2444,7 +2344,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
                 it never happens because available widths are 2**N.  */
              && (!TREE_UNSIGNED (final_type)
                  || unsigned_arg
-                 || 2 * TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (result_type)))
+                 || (2 * TYPE_PRECISION (TREE_TYPE (arg0))
+                     <= TYPE_PRECISION (result_type))))
            {
              /* Do an unsigned shift if the operand was zero-extended.  */
              result_type
@@ -2470,60 +2371,76 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          enum tree_code xresultcode = resultcode;
          tree val 
            = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
+
          if (val != 0)
            return val;
+
          op0 = xop0, op1 = xop1;
          converted = 1;
          resultcode = xresultcode;
 
-         if (extra_warnings)
+         if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare != 0)
+             && skip_evaluation == 0)
            {
              int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
              int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
-
              int unsignedp0, unsignedp1;
              tree primop0 = get_narrower (op0, &unsignedp0);
              tree primop1 = get_narrower (op1, &unsignedp1);
 
-             /* Avoid spurious warnings for comparison with enumerators.  */
              xop0 = orig_op0;
              xop1 = orig_op1;
              STRIP_TYPE_NOPS (xop0);
              STRIP_TYPE_NOPS (xop1);
 
              /* Give warnings for comparisons between signed and unsigned
-                quantities that may fail.  */
-             /* Do the checking based on the original operand trees, so that
-                casts will be considered, but default promotions won't be.  */
+                quantities that may fail. 
 
-             /* Do not warn if the comparison is being done in a signed type,
+                Do the checking based on the original operand trees, so that
+                casts will be considered, but default promotions won't be.
+
+                Do not warn if the comparison is being done in a signed type,
                 since the signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
              if (! TREE_UNSIGNED (result_type))
                /* OK */;
-              /* Do not warn if both operands are unsigned.  */
+              /* Do not warn if both operands are the same signedness.  */
               else if (op0_signed == op1_signed)
                 /* OK */;
-             /* Do not warn if the signed quantity is an unsuffixed
-                integer literal (or some static constant expression
-                involving such literals) and it is non-negative.  */
-             else if ((op0_signed && TREE_CODE (xop0) == INTEGER_CST
-                       && tree_int_cst_sgn (xop0) >= 0)
-                      || (op1_signed && TREE_CODE (xop1) == INTEGER_CST
-                          && tree_int_cst_sgn (xop1) >= 0))
-               /* OK */;
-             /* Do not warn if the comparison is an equality operation,
-                 the unsigned quantity is an integral constant and it does
-                 not use the most significant bit of result_type.  */
-             else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
-                      && ((op0_signed && TREE_CODE (xop1) == INTEGER_CST
-                           && int_fits_type_p (xop1, signed_type (result_type))
-                          || (op1_signed && TREE_CODE (xop0) == INTEGER_CST
-                              && int_fits_type_p (xop0, signed_type (result_type))))))
-               /* OK */;
              else
-               warning ("comparison between signed and unsigned");
+               {
+                 tree sop, uop;
+
+                 if (op0_signed)
+                   sop = xop0, uop = xop1;
+                 else
+                   sop = xop1, uop = xop0;
+
+                 /* Do not warn if the signed quantity is an
+                    unsuffixed integer literal (or some static
+                    constant expression involving such literals or a
+                    conditional expression involving such literals)
+                    and it is non-negative.  */
+                 if (tree_expr_nonnegative_p (sop))
+                   /* OK */;
+                 /* Do not warn if the comparison is an equality operation,
+                    the unsigned quantity is an integral constant, and it
+                    would fit in the result if the result were signed.  */
+                 else if (TREE_CODE (uop) == INTEGER_CST
+                          && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
+                          && int_fits_type_p (uop, signed_type (result_type)))
+                   /* OK */;
+                 /* Do not warn if the unsigned quantity is an enumeration
+                    constant and its maximum value would fit in the result
+                    if the result were signed.  */
+                 else if (TREE_CODE (uop) == INTEGER_CST
+                          && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
+                          && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE(uop)),
+                                              signed_type (result_type)))
+                   /* OK */;
+                 else
+                   warning ("comparison between signed and unsigned");
+               }
 
              /* Warn if two unsigned values are being compared in a size
                 larger than their original size, and one (and only one) is the
@@ -2543,31 +2460,30 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
                    primop1 = get_narrower (TREE_OPERAND (primop1, 0),
                                            &unsignedp1);
              
-                 if (TREE_CODE (primop0) == INTEGER_CST
-                     || TREE_CODE (primop1) == INTEGER_CST)
+                 if (host_integerp (primop0, 0) || host_integerp (primop1, 0))
                    {
                      tree primop;
-                     long constant, mask;
+                     HOST_WIDE_INT constant, mask;
                      int unsignedp, bits;
 
-                     if (TREE_CODE (primop0) == INTEGER_CST)
+                     if (host_integerp (primop0, 0))
                        {
                          primop = primop1;
                          unsignedp = unsignedp1;
-                         constant = TREE_INT_CST_LOW (primop0);
+                         constant = tree_low_cst (primop0, 0);
                        }
                      else
                        {
                          primop = primop0;
                          unsignedp = unsignedp0;
-                         constant = TREE_INT_CST_LOW (primop1);
+                         constant = tree_low_cst (primop1, 0);
                        }
 
                      bits = TYPE_PRECISION (TREE_TYPE (primop));
                      if (bits < TYPE_PRECISION (result_type)
-                         && bits < HOST_BITS_PER_LONG && unsignedp)
+                         && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
                        {
-                         mask = (~0L) << bits;
+                         mask = (~ (HOST_WIDE_INT) 0) << bits;
                          if ((mask & constant) != mask)
                            warning ("comparison of promoted ~unsigned with constant");
                        }
@@ -2682,11 +2598,13 @@ pointer_int_sum (resultcode, ptrop, intop)
       intop = convert (int_type, TREE_OPERAND (intop, 0));
     }
 
-  /* Convert the integer argument to a type the same size as a pointer
+  /* Convert the integer argument to a type the same size as sizetype
      so the multiply won't overflow spuriously.  */
 
-  if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
-    intop = convert (type_for_size (POINTER_SIZE, 0), intop);
+  if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
+      || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+    intop = convert (type_for_size (TYPE_PRECISION (sizetype), 
+                                   TREE_UNSIGNED (sizetype)), intop);
 
   /* Replace the integer argument with a suitable product by the object size.
      Do this multiplication as signed, then convert to the appropriate
@@ -2727,12 +2645,14 @@ pointer_diff (op0, op1)
     }
 
   /* First do the subtraction as integers;
-     then drop through to build the divide operator.  */
+     then drop through to build the divide operator.
+     Do not do default conversions on the minus operator
+     in case restype is a short type.  */
 
   op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
-                        convert (restype, op1), 1);
+                        convert (restype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
-  if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op1))))
     error ("arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
@@ -2763,7 +2683,6 @@ build_unary_op (code, xarg, noconvert)
   register tree arg = xarg;
   register tree argtype = 0;
   register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
-  char *errstring = NULL;
   tree val;
 
   if (typecode == ERROR_MARK)
@@ -2779,7 +2698,10 @@ build_unary_op (code, xarg, noconvert)
         associativity, but won't generate any code.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
            || typecode == COMPLEX_TYPE))
-        errstring = "wrong type argument to unary plus";
+       {
+         error ("wrong type argument to unary plus");
+         return error_mark_node;
+       }
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -2787,7 +2709,10 @@ build_unary_op (code, xarg, noconvert)
     case NEGATE_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
            || typecode == COMPLEX_TYPE))
-        errstring = "wrong type argument to unary minus";
+       {
+         error ("wrong type argument to unary minus");
+         return error_mark_node;
+       }
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -2800,7 +2725,10 @@ build_unary_op (code, xarg, noconvert)
            arg = default_conversion (arg);
        }
       else if (typecode != INTEGER_TYPE)
-        errstring = "wrong type argument to bit-complement";
+       {
+         error ("wrong type argument to bit-complement");
+         return error_mark_node;
+       }
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -2808,7 +2736,10 @@ build_unary_op (code, xarg, noconvert)
     case ABS_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
            || typecode == COMPLEX_TYPE))
-        errstring = "wrong type argument to abs";
+       {
+         error ("wrong type argument to abs");
+         return error_mark_node;
+       }
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -2817,7 +2748,10 @@ build_unary_op (code, xarg, noconvert)
       /* Conjugating a real value is a no-op, but allow it anyway.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
            || typecode == COMPLEX_TYPE))
-       errstring = "wrong type argument to conjugation";
+       {
+         error ("wrong type argument to conjugation");
+         return error_mark_node;
+       }
       else if (!noconvert)
        arg = default_conversion (arg);
       break;
@@ -2829,8 +2763,8 @@ build_unary_op (code, xarg, noconvert)
          /* These will convert to a pointer.  */
          && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
        {
-         errstring = "wrong type argument to unary exclamation mark";
-         break;
+         error ("wrong type argument to unary exclamation mark");
+         return error_mark_node;
        }
       arg = truthvalue_conversion (arg);
       return invert_truthvalue (arg);
@@ -2883,11 +2817,10 @@ build_unary_op (code, xarg, noconvert)
       if (typecode != POINTER_TYPE
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
-         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-           errstring ="wrong type argument to increment";
-         else
-           errstring ="wrong type argument to decrement";
-         break;
+         error ("wrong type argument to %s",
+                code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+                ? "increment" : "decrement");
+         return error_mark_node;
        }
 
       {
@@ -2903,18 +2836,16 @@ build_unary_op (code, xarg, noconvert)
          {
            /* If pointer target is an undefined struct,
               we just cannot know how to do the arithmetic.  */
-           if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
+           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
              error ("%s of pointer to unknown structure",
-                      ((code == PREINCREMENT_EXPR
-                        || code == POSTINCREMENT_EXPR)
-                       ? "increment" : "decrement"));
+                    code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+                    ? "increment" : "decrement");
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
              pedwarn ("wrong type argument to %s",
-                      ((code == PREINCREMENT_EXPR
-                        || code == POSTINCREMENT_EXPR)
-                       ? "increment" : "decrement"));
+                      code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+                      ? "increment" : "decrement");
            inc = c_size_in_bytes (TREE_TYPE (result_type));
          }
        else
@@ -2971,7 +2902,8 @@ build_unary_op (code, xarg, noconvert)
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
-                                  ? "increment" : "decrement")))
+                                  ? "invalid lvalue in increment"
+                                  : "invalid lvalue in decrement")))
          return error_mark_node;
 
        /* Report a read-only lvalue.  */
@@ -3045,21 +2977,22 @@ build_unary_op (code, xarg, noconvert)
        ;
       /* Anything not already handled and not a true memory reference
         is an error.  */
-      else if (typecode != FUNCTION_TYPE && !lvalue_or_else (arg, "unary `&'"))
+      else if (typecode != FUNCTION_TYPE
+              && !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
        return error_mark_node;
 
       /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
       argtype = TREE_TYPE (arg);
-      /* If the lvalue is const or volatile,
-        merge that into the type that the address will point to.  */
-      if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
-         || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
-       {
-         if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
-           argtype = c_build_type_variant (argtype,
-                                           TREE_READONLY (arg),
-                                           TREE_THIS_VOLATILE (arg));
-       }
+
+      /* If the lvalue is const or volatile, merge that into the type
+         to which the address will point.  Note that you can't get a
+        restricted pointer by taking the address of something, so we
+        only have to deal with `const' and `volatile' here.  */
+      if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
+         argtype = c_build_type_variant (argtype,
+                                         TREE_READONLY (arg),
+                                         TREE_THIS_VOLATILE (arg));
 
       argtype = build_pointer_type (argtype);
 
@@ -3075,25 +3008,16 @@ build_unary_op (code, xarg, noconvert)
 
            addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
 
-           if (DECL_BIT_FIELD (field))
+           if (DECL_C_BIT_FIELD (field))
              {
                error ("attempt to take address of bit-field structure member `%s'",
                       IDENTIFIER_POINTER (DECL_NAME (field)));
                return error_mark_node;
              }
 
-           addr = convert (argtype, addr);
-
-           if (! integer_zerop (DECL_FIELD_BITPOS (field)))
-             {
-               tree offset
-                 = size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (field),
-                               size_int (BITS_PER_UNIT));
-               int flag = TREE_CONSTANT (addr);
-               addr = fold (build (PLUS_EXPR, argtype,
-                                   addr, convert (argtype, offset)));
-               TREE_CONSTANT (addr) = flag;
-             }
+           addr = fold (build (PLUS_EXPR, argtype,
+                               convert (argtype, addr),
+                               convert (argtype, byte_position (field))));
          }
        else
          addr = build1 (code, argtype, arg);
@@ -3106,17 +3030,14 @@ build_unary_op (code, xarg, noconvert)
          TREE_CONSTANT (addr) = 1;
        return addr;
       }
-    }
 
-  if (!errstring)
-    {
-      if (argtype == 0)
-       argtype = TREE_TYPE (arg);
-      return fold (build1 (code, argtype, arg));
+    default:
+      break;
     }
 
-  error (errstring);
-  return error_mark_node;
+  if (argtype == 0)
+    argtype = TREE_TYPE (arg);
+  return fold (build1 (code, argtype, arg));
 }
 
 #if 0
@@ -3174,25 +3095,31 @@ lvalue_p (ref)
     case PARM_DECL:
     case RESULT_DECL:
     case ERROR_MARK:
-      if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
-         && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
-       return 1;
-      break;
+      return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+             && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
+
+    case BIND_EXPR:
+    case RTL_EXPR:
+      return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
+
+    default:
+      return 0;
     }
-  return 0;
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  */
 
 int
-lvalue_or_else (ref, string)
+lvalue_or_else (ref, msgid)
      tree ref;
-     char *string;
+     const char *msgid;
 {
   int win = lvalue_p (ref);
+
   if (! win)
-    error ("invalid lvalue in %s", string);
+    error ("%s", msgid);
+
   return win;
 }
 
@@ -3211,7 +3138,12 @@ unary_complex_lvalue (code, arg)
   if (TREE_CODE (arg) == COMPOUND_EXPR)
     {
       tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
-      pedantic_lvalue_warning (COMPOUND_EXPR);
+
+      /* If this returns a function type, it isn't really being used as
+        an lvalue, so don't issue a warning about it.  */
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
+       pedantic_lvalue_warning (COMPOUND_EXPR);
+
       return build (COMPOUND_EXPR, TREE_TYPE (real_result),
                    TREE_OPERAND (arg, 0), real_result);
     }
@@ -3220,6 +3152,9 @@ unary_complex_lvalue (code, arg)
   if (TREE_CODE (arg) == COND_EXPR)
     {
       pedantic_lvalue_warning (COND_EXPR);
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
+       pedantic_lvalue_warning (COMPOUND_EXPR);
+
       return (build_conditional_expr
              (TREE_OPERAND (arg, 0),
               build_unary_op (code, TREE_OPERAND (arg, 1), 0),
@@ -3237,47 +3172,45 @@ pedantic_lvalue_warning (code)
      enum tree_code code;
 {
   if (pedantic)
-    pedwarn ("ANSI C forbids use of %s expressions as lvalues",
-            code == COND_EXPR ? "conditional"
-            : code == COMPOUND_EXPR ? "compound" : "cast");
+    switch (code)
+      {
+      case COND_EXPR:
+       pedwarn ("ANSI C forbids use of conditional expressions as lvalues");
+       break;
+      case COMPOUND_EXPR:
+       pedwarn ("ANSI C forbids use of compound expressions as lvalues");
+       break;
+      default:
+       pedwarn ("ANSI C forbids use of cast expressions as lvalues");
+       break;
+      }
 }
 \f
 /* Warn about storing in something that is `const'.  */
 
 void
-readonly_warning (arg, string)
+readonly_warning (arg, msgid)
      tree arg;
-     char *string;
+     const char *msgid;
 {
-  char buf[80];
-  strcpy (buf, string);
-
   /* Forbid assignments to iterators.  */
   if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
-    {
-      strcat (buf, " of iterator `%s'");
-      pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (arg)));
-    }
+    pedwarn ("%s of iterator `%s'",  _(msgid), 
+            IDENTIFIER_POINTER (DECL_NAME (arg)));
 
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_warning (TREE_OPERAND (arg, 0), string);
+       readonly_warning (TREE_OPERAND (arg, 0), msgid);
       else
-       {
-         strcat (buf, " of read-only member `%s'");
-         pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
-       }
+       pedwarn ("%s of read-only member `%s'", _(msgid),
+                IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    {
-      strcat (buf, " of read-only variable `%s'");
-      pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (arg)));
-    }
+    pedwarn ("%s of read-only variable `%s'", _(msgid),
+            IDENTIFIER_POINTER (DECL_NAME (arg)));
   else
-    {
-      pedwarn ("%s of read-only location", buf);
-    }
+    pedwarn ("%s of read-only location", _(msgid));
 }
 \f
 /* Mark EXP saying that we need to be able to take the
@@ -3294,11 +3227,13 @@ mark_addressable (exp)
       {
       case COMPONENT_REF:
        if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
-         error ("cannot take address of bitfield `%s'",
-                IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
-       return 0;
+         {
+           error ("cannot take address of bitfield `%s'",
+                  IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
+           return 0;
+         }
 
-       /* ... fall through ... */
+       /* ... fall through ...  */
 
       case ADDR_EXPR:
       case ARRAY_REF:
@@ -3378,15 +3313,6 @@ build_conditional_expr (ifexp, op1, op2)
   register tree result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
 
-  /* If second operand is omitted, it is the same as the first one;
-     make sure it is calculated only once.  */
-  if (op1 == 0)
-    {
-      if (pedantic)
-       pedwarn ("ANSI C forbids omitting the middle term of a ?: expression");
-      ifexp = op1 = save_expr (ifexp);
-    }
-
   ifexp = truthvalue_conversion (default_conversion (ifexp));
 
 #if 0 /* Produces wrong result if within sizeof.  */
@@ -3436,6 +3362,35 @@ build_conditional_expr (ifexp, op1, op2)
            && (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
     {
       result_type = common_type (type1, type2);
+
+      /* If -Wsign-compare, warn here if type1 and type2 have
+        different signedness.  We'll promote the signed to unsigned
+        and later code won't know it used to be different.
+        Do this check on the original types, so that explicit casts
+        will be considered, but default promotions won't.  */
+      if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare)
+         && !skip_evaluation)
+       {
+         int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1));
+         int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2));
+
+         if (unsigned_op1 ^ unsigned_op2)
+           {
+             /* Do not warn if the result type is signed, since the
+                signed type will only be chosen if it can represent
+                all the values of the unsigned type.  */
+             if (! TREE_UNSIGNED (result_type))
+               /* OK */;
+             /* Do not warn if the signed quantity is an unsuffixed
+                integer literal (or some static constant expression
+                involving such literals) and it is non-negative.  */
+             else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
+                      || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
+               /* OK */;
+             else
+               warning ("signed and unsigned type in conditional expression");
+           }
+       }
     }
   else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
     {
@@ -3522,43 +3477,6 @@ build_conditional_expr (ifexp, op1, op2)
   if (result_type != TREE_TYPE (op2))
     op2 = convert_and_check (result_type, op2);
     
-#if 0
-  if (code1 == RECORD_TYPE || code1 == UNION_TYPE)
-    {
-      result_type = TREE_TYPE (op1);
-      if (TREE_CONSTANT (ifexp))
-       return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
-
-      if (TYPE_MODE (result_type) == BLKmode)
-       {
-         register tree tempvar
-           = build_decl (VAR_DECL, NULL_TREE, result_type);
-         register tree xop1 = build_modify_expr (tempvar, op1);
-         register tree xop2 = build_modify_expr (tempvar, op2);
-         register tree result = fold (build (COND_EXPR, result_type,
-                                             ifexp, xop1, xop2));
-
-         layout_decl (tempvar, TYPE_ALIGN (result_type));
-         /* No way to handle variable-sized objects here.
-            I fear that the entire handling of BLKmode conditional exprs
-            needs to be redone.  */
-         if (TREE_CODE (DECL_SIZE (tempvar)) != INTEGER_CST)
-           abort ();
-         DECL_RTL (tempvar)
-           = assign_stack_local (DECL_MODE (tempvar),
-                                 (TREE_INT_CST_LOW (DECL_SIZE (tempvar))
-                                  + BITS_PER_UNIT - 1)
-                                 / BITS_PER_UNIT,
-                                 0);
-
-         TREE_SIDE_EFFECTS (result)
-           = TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
-             | TREE_SIDE_EFFECTS (op2);
-         return build (COMPOUND_EXPR, result_type, result, tempvar);
-       }
-    }
-#endif /* 0 */
-    
   if (TREE_CODE (ifexp) == INTEGER_CST)
     return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
 
@@ -3688,7 +3606,7 @@ build_c_cast (type, expr)
 
       if (field)
        {
-         char *name;
+         const char *name;
          tree t;
 
          if (pedantic)
@@ -3733,12 +3651,27 @@ build_c_cast (type, expr)
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
        {
-         if (TYPE_VOLATILE (TREE_TYPE (otype))
-             && ! TYPE_VOLATILE (TREE_TYPE (type)))
-           pedwarn ("cast discards `volatile' from pointer target type");
-         if (TYPE_READONLY (TREE_TYPE (otype))
-             && ! TYPE_READONLY (TREE_TYPE (type)))
-           pedwarn ("cast discards `const' from pointer target type");
+         tree in_type = type;
+         tree in_otype = otype;
+         int warn = 0;
+
+         /* Check that the qualifiers on IN_TYPE are a superset of
+            the qualifiers of IN_OTYPE.  The outermost level of
+            POINTER_TYPE nodes is uninteresting and we stop as soon
+            as we hit a non-POINTER_TYPE node on either type.  */
+         do
+           {
+             in_otype = TREE_TYPE (in_otype);
+             in_type = TREE_TYPE (in_type);
+             warn |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+           }
+         while (TREE_CODE (in_type) == POINTER_TYPE
+                && TREE_CODE (in_otype) == POINTER_TYPE);
+
+         if (warn)
+           /* There are qualifiers present in IN_OTYPE that are not
+              present in IN_TYPE.  */
+           pedwarn ("cast discards qualifiers from pointer target type");
        }
 
       /* Warn about possible alignment problems.  */
@@ -3747,6 +3680,11 @@ build_c_cast (type, expr)
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+         /* Don't warn about opaque types, where the actual alignment
+            restriction is unknown.  */
+         && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
+               || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
+              && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
          && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
        warning ("cast increases required alignment of target type");
 
@@ -3834,8 +3772,7 @@ build_modify_expr (lhs, modifycode, rhs)
       /* Handle (a, b) used as an "lvalue".  */
     case COMPOUND_EXPR:
       pedantic_lvalue_warning (COMPOUND_EXPR);
-      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
-                                 modifycode, rhs);
+      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
       if (TREE_CODE (newrhs) == ERROR_MARK)
        return error_mark_node;
       return build (COMPOUND_EXPR, lhstype,
@@ -3863,6 +3800,8 @@ build_modify_expr (lhs, modifycode, rhs)
                      /* But cast it to void to avoid an "unused" error.  */
                      convert (void_type_node, rhs), cond);
       }
+    default:
+      break;
     }
 
   /* If a binary op has been requested, combine the old LHS value with the RHS
@@ -3904,12 +3843,15 @@ build_modify_expr (lhs, modifycode, rhs)
        pedantic_lvalue_warning (CONVERT_EXPR);
        return convert (TREE_TYPE (lhs), result);
       }
+      
+    default:
+      break;
     }
 
   /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
      Reject anything strange now.  */
 
-  if (!lvalue_or_else (lhs, "assignment"))
+  if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
     return error_mark_node;
 
   /* Warn about storing in something that is `const'.  */
@@ -3942,7 +3884,7 @@ build_modify_expr (lhs, modifycode, rhs)
 
   /* Convert new value to destination type.  */
 
-  newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
+  newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"),
                                   NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
@@ -3957,7 +3899,7 @@ build_modify_expr (lhs, modifycode, rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  return convert_for_assignment (olhstype, result, "assignment",
+  return convert_for_assignment (olhstype, result, _("assignment"),
                                 NULL_TREE, NULL_TREE, 0);
 }
 \f
@@ -3968,9 +3910,7 @@ build_modify_expr (lhs, modifycode, rhs)
    for assignments that are not allowed in C.
    ERRTYPE is a string to use in error messages:
    "assignment", "return", etc.  If it is null, this is parameter passing
-   for a function call (and different error messages are output).  Otherwise,
-   it may be a name stored in the spelling stack and interpreted by
-   get_spelling.
+   for a function call (and different error messages are output).
 
    FUNNAME is the name of the function being called,
    as an IDENTIFIER_NODE, or null.
@@ -3979,7 +3919,7 @@ build_modify_expr (lhs, modifycode, rhs)
 static tree
 convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
      tree type, rhs;
-     char *errtype;
+     const char *errtype;
      tree fundecl, funname;
      int parmnum;
 {
@@ -4019,33 +3959,55 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+  /* A type converts to a reference to it.  
+     This code doesn't fully support references, it's just for the
+     special case of va_start and va_copy.  */
+  if (codel == REFERENCE_TYPE
+      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
+    {
+      if (mark_addressable (rhs) == 0)
+       return error_mark_node;
+      rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+
+      /* We already know that these two types are compatible, but they
+        may not be exactly identical.  In fact, `TREE_TYPE (type)' is
+        likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
+        likely to be va_list, a typedef to __builtin_va_list, which
+        is different enough that it will cause problems later.  */
+      if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
+       rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+
+      rhs = build1 (NOP_EXPR, type, rhs);
+      return rhs;
+    }
   /* Arithmetic types all interconvert, and enum is treated like int.  */
-  if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
-       || codel == COMPLEX_TYPE)
-      && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE
-         || coder == COMPLEX_TYPE))
+  else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 
+           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE)
+          && (coder == INTEGER_TYPE || coder == REAL_TYPE 
+              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE))
     return convert_and_check (type, rhs);
 
-  /* Conversion to a union from its member types.  */
-  else if (codel == UNION_TYPE)
+  /* Conversion to a transparent union from its member types.
+     This applies only to function arguments.  */
+  else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype)
     {
       tree memb_types;
+      tree marginal_memb_type = 0;
 
       for (memb_types = TYPE_FIELDS (type); memb_types;
           memb_types = TREE_CHAIN (memb_types))
        {
-         if (comptypes (TREE_TYPE (memb_types), TREE_TYPE (rhs)))
-           {
-             if (pedantic
-                 && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl)))
-               pedwarn ("ANSI C prohibits argument conversion to union type");
-             return build1 (NOP_EXPR, type, rhs);
-           }
+         tree memb_type = TREE_TYPE (memb_types);
+
+         if (comptypes (TYPE_MAIN_VARIANT (memb_type),
+                        TYPE_MAIN_VARIANT (rhstype)))
+           break;
+
+         if (TREE_CODE (memb_type) != POINTER_TYPE)
+           continue;
 
-         else if (coder == POINTER_TYPE
-                  && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
+         if (coder == POINTER_TYPE)
            {
-             tree memb_type = TREE_TYPE (memb_types);
              register tree ttl = TREE_TYPE (memb_type);
              register tree ttr = TREE_TYPE (rhstype);
 
@@ -4057,55 +4019,71 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                  || TYPE_MAIN_VARIANT (ttr) == void_type_node
                  || comp_target_types (memb_type, rhstype))
                {
-                 /* Const and volatile mean something different for function
-                    types, so the usual warnings are not appropriate.  */
-                 if (TREE_CODE (ttr) != FUNCTION_TYPE
-                     || TREE_CODE (ttl) != FUNCTION_TYPE)
-                   {
-                     if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
-                       warn_for_assignment ("%s discards `const' from pointer target type",
-                                            get_spelling (errtype), funname,
-                                            parmnum);
-                     if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
-                       warn_for_assignment ("%s discards `volatile' from pointer target type",
-                                            get_spelling (errtype), funname,
-                                            parmnum);
-                   }
-                 else
-                   {
-                     /* Because const and volatile on functions are
-                        restrictions that say the function will not do
-                        certain things, it is okay to use a const or volatile
-                        function where an ordinary one is wanted, but not
-                        vice-versa.  */
-                     if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
-                       warn_for_assignment ("%s makes `const *' function pointer from non-const",
-                                            get_spelling (errtype), funname,
-                                            parmnum);
-                     if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
-                       warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
-                                            get_spelling (errtype), funname,
-                                            parmnum);
-                   }
-
-                 if (pedantic
-                     && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl)))
-                   pedwarn ("ANSI C prohibits argument conversion to union type");
-                 return build1 (NOP_EXPR, type, rhs);
+                 /* If this type won't generate any warnings, use it.  */
+                 if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+                     || ((TREE_CODE (ttr) == FUNCTION_TYPE
+                          && TREE_CODE (ttl) == FUNCTION_TYPE)
+                         ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+                            == TYPE_QUALS (ttr))
+                         : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+                            == TYPE_QUALS (ttl))))
+                   break;
+
+                 /* Keep looking for a better type, but remember this one.  */
+                 if (! marginal_memb_type)
+                   marginal_memb_type = memb_type;
                }
            }
 
          /* Can convert integer zero to any pointer type.  */
-         else if (TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE
-                  && (integer_zerop (rhs)
-                      || (TREE_CODE (rhs) == NOP_EXPR
-                          && integer_zerop (TREE_OPERAND (rhs, 0)))))
-           return build1 (NOP_EXPR, type, null_pointer_node);
+         if (integer_zerop (rhs)
+             || (TREE_CODE (rhs) == NOP_EXPR
+                 && integer_zerop (TREE_OPERAND (rhs, 0))))
+           {
+             rhs = null_pointer_node;
+             break;
+           }
+       }
+
+      if (memb_types || marginal_memb_type)
+       {
+         if (! memb_types)
+           {
+             /* We have only a marginally acceptable member type;
+                it needs a warning.  */
+             register tree ttl = TREE_TYPE (marginal_memb_type);
+             register tree ttr = TREE_TYPE (rhstype);
+
+             /* Const and volatile mean something different for function
+                types, so the usual warnings are not appropriate.  */
+             if (TREE_CODE (ttr) == FUNCTION_TYPE
+                 && TREE_CODE (ttl) == FUNCTION_TYPE)
+               {
+                 /* Because const and volatile on functions are
+                    restrictions that say the function will not do
+                    certain things, it is okay to use a const or volatile
+                    function where an ordinary one is wanted, but not
+                    vice-versa.  */
+                 if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+                   warn_for_assignment ("%s makes qualified function pointer from unqualified",
+                                        errtype, funname, parmnum);
+               }
+             else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+               warn_for_assignment ("%s discards qualifiers from pointer target type",
+                                    errtype, funname,
+                                    parmnum);
+           }
+         
+         if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
+           pedwarn ("ANSI C prohibits argument conversion to union type");
+
+         return build1 (NOP_EXPR, type, rhs);
        }
     }
 
   /* Conversions among pointers */
-  else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
+  else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+          && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
     {
       register tree ttl = TREE_TYPE (type);
       register tree ttr = TREE_TYPE (rhstype);
@@ -4129,18 +4107,15 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
            warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
-                                get_spelling (errtype), funname, parmnum);
+                                errtype, funname, parmnum);
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
-             if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
-               warn_for_assignment ("%s discards `const' from pointer target type",
-                                    get_spelling (errtype), funname, parmnum);
-             else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
-               warn_for_assignment ("%s discards `volatile' from pointer target type",
-                                    get_spelling (errtype), funname, parmnum);
+             if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+               warn_for_assignment ("%s discards qualifiers from pointer target type",
+                                    errtype, funname, parmnum);
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
@@ -4150,7 +4125,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
              /* If there is a mismatch, do warn.  */
              else if (pedantic)
                warn_for_assignment ("pointer targets in %s differ in signedness",
-                                    get_spelling (errtype), funname, parmnum);
+                                    errtype, funname, parmnum);
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
                   && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -4159,17 +4134,14 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                 that say the function will not do certain things,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
-             if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
-               warn_for_assignment ("%s makes `const *' function pointer from non-const",
-                                    get_spelling (errtype), funname, parmnum);
-             if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
-               warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
-                                    get_spelling (errtype), funname, parmnum);
+             if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+               warn_for_assignment ("%s makes qualified function pointer from unqualified",
+                                    errtype, funname, parmnum);
            }
        }
       else
        warn_for_assignment ("%s from incompatible pointer type",
-                            get_spelling (errtype), funname, parmnum);
+                            errtype, funname, parmnum);
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
@@ -4185,7 +4157,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
             && integer_zerop (TREE_OPERAND (rhs, 0))))
        {
          warn_for_assignment ("%s makes pointer from integer without a cast",
-                              get_spelling (errtype), funname, parmnum);
+                              errtype, funname, parmnum);
          return convert (type, rhs);
        }
       return null_pointer_node;
@@ -4193,7 +4165,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
       warn_for_assignment ("%s makes integer from pointer without a cast",
-                          get_spelling (errtype), funname, parmnum);
+                          errtype, funname, parmnum);
       return convert (type, rhs);
     }
 
@@ -4215,30 +4187,28 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
               parmnum);
     }
   else
-    error ("incompatible types in %s", get_spelling (errtype));
+    error ("incompatible types in %s", errtype);
 
   return error_mark_node;
 }
 
-/* Print a warning using MSG.
+/* Print a warning using MSGID.
    It gets OPNAME as its one parameter.
    If OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
    FUNCTION and ARGNUM are handled specially if we are building an
    Objective-C selector.  */
 
 static void
-warn_for_assignment (msg, opname, function, argnum)
-     char *msg;
-     char *opname;
+warn_for_assignment (msgid, opname, function, argnum)
+     const char *msgid;
+     const char *opname;
      tree function;
      int argnum;
 {
-  static char argstring[] = "passing arg %d of `%s'";
-  static char argnofun[] =  "passing arg %d";
-
   if (opname == 0)
     {
       tree selector = maybe_building_objc_message_expr ();
+      char * new_opname;
       
       if (selector && argnum > 2)
        {
@@ -4248,152 +4218,25 @@ warn_for_assignment (msg, opname, function, argnum)
       if (function)
        {
          /* Function name is known; supply it.  */
-         opname = (char *) alloca (IDENTIFIER_LENGTH (function)
-                                   + sizeof (argstring) + 25 /*%d*/ + 1);
-         sprintf (opname, argstring, argnum, IDENTIFIER_POINTER (function));
+         const char *argstring = _("passing arg %d of `%s'");
+         new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+                                       + strlen (argstring) + 1 + 25
+                                       /*%d*/ + 1);
+         sprintf (new_opname, argstring, argnum,
+                  IDENTIFIER_POINTER (function));
        }
       else
        {
-         /* Function name unknown (call through ptr); just give arg number.  */
-         opname = (char *) alloca (sizeof (argnofun) + 25 /*%d*/ + 1);
-         sprintf (opname, argnofun, argnum);
+         /* Function name unknown (call through ptr); just give arg number.*/
+         const char *argnofun = _("passing arg %d of pointer to function");
+         new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
+         sprintf (new_opname, argnofun, argnum);
        }
+      opname = new_opname;
     }
-  pedwarn (msg, opname);
+  pedwarn (msgid, opname);
 }
 \f
-/* Return nonzero if VALUE is a valid constant-valued expression
-   for use in initializing a static variable; one that can be an
-   element of a "constant" initializer.
-
-   Return null_pointer_node if the value is absolute;
-   if it is relocatable, return the variable that determines the relocation.
-   We assume that VALUE has been folded as much as possible;
-   therefore, we do not need to check for such things as
-   arithmetic-combinations of integers.  */
-
-tree
-initializer_constant_valid_p (value, endtype)
-     tree value;
-     tree endtype;
-{
-  switch (TREE_CODE (value))
-    {
-    case CONSTRUCTOR:
-      if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
-          || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
-         && TREE_CONSTANT (value))
-       return
-         initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
-                                       endtype);
-       
-      return TREE_STATIC (value) ? null_pointer_node : 0;
-
-    case INTEGER_CST:
-    case REAL_CST:
-    case STRING_CST:
-    case COMPLEX_CST:
-      return null_pointer_node;
-
-    case ADDR_EXPR:
-      return TREE_OPERAND (value, 0);
-
-    case NON_LVALUE_EXPR:
-      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-    case CONVERT_EXPR:
-    case NOP_EXPR:
-      /* Allow conversions between pointer types.  */
-      if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow conversions between real types.  */
-      if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow length-preserving conversions between integer types.  */
-      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (value))
-             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
-      /* Allow conversions between other integer types only if
-        explicit value.  */
-      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
-       {
-         tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                    endtype);
-         if (inner == null_pointer_node)
-           return null_pointer_node;
-         return 0;
-       }
-
-      /* Allow (int) &foo provided int is as wide as a pointer.  */
-      if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (value))
-             >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                            endtype);
-
-      /* Likewise conversions from int to pointers.  */
-      if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (value))
-             <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                            endtype);
-
-      /* Allow conversions to union types if the value inside is okay.  */
-      if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
-       return initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                            endtype);
-      return 0;
-
-    case PLUS_EXPR:
-      if (TREE_CODE (endtype) == INTEGER_TYPE
-         && TYPE_PRECISION (endtype) < POINTER_SIZE)
-       return 0;
-      {
-       tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                   endtype);
-       tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
-                                                   endtype);
-       /* If either term is absolute, use the other terms relocation.  */
-       if (valid0 == null_pointer_node)
-         return valid1;
-       if (valid1 == null_pointer_node)
-         return valid0;
-       return 0;
-      }
-
-    case MINUS_EXPR:
-      if (TREE_CODE (endtype) == INTEGER_TYPE
-         && TYPE_PRECISION (endtype) < POINTER_SIZE)
-       return 0;
-      {
-       tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                   endtype);
-       tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
-                                                   endtype);
-       /* Win if second argument is absolute.  */
-       if (valid1 == null_pointer_node)
-         return valid0;
-       /* Win if both arguments have the same relocation.
-          Then the value is absolute.  */
-       if (valid0 == valid1)
-         return null_pointer_node;
-       return 0;
-      }
-    }
-
-  return 0;
-}
-
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
 
@@ -4491,7 +4334,7 @@ struct spelling
   union
     {
       int i;
-      char *s;
+      const char *s;
     } u;
 };
 
@@ -4547,7 +4390,7 @@ static int spelling_size;         /* Size of the spelling stack.  */
 
 static void
 push_string (string)
-     char *string;
+     const char *string;
 {
   PUSH_SPELLING (SPELLING_STRING, string, u.s);
 }
@@ -4559,7 +4402,7 @@ push_member_name (decl)
      tree decl;
      
 {
-  char *string
+  const char *string
     = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
   PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
 }
@@ -4599,7 +4442,6 @@ print_spelling (buffer)
      register char *buffer;
 {
   register char *d = buffer;
-  register char *s;
   register struct spelling *p;
 
   for (p = spelling_base; p < spelling; p++)
@@ -4610,124 +4452,62 @@ print_spelling (buffer)
       }
     else
       {
+       register const char *s;
        if (p->kind == SPELLING_MEMBER)
          *d++ = '.';
-       for (s = p->u.s; *d = *s++; d++)
+       for (s = p->u.s; (*d = *s++); d++)
          ;
       }
   *d++ = '\0';
   return buffer;
 }
 
-/* Provide a means to pass component names derived from the spelling stack.  */
-
-char initialization_message;
-
-/* Interpret the spelling of the given ERRTYPE message.  */
-
-static char *
-get_spelling (errtype)
-     char *errtype;
-{
-  static char *buffer;
-  static int size = -1;
-
-  if (errtype == &initialization_message)
-    {
-      /* Avoid counting chars */
-      static char message[] = "initialization of `%s'";
-      register int needed = sizeof (message) + spelling_length () + 1;
-      char *temp;
-
-      if (size < 0)
-       buffer = (char *) xmalloc (size = needed);
-      if (needed > size)
-       buffer = (char *) xrealloc (buffer, size = needed);
-
-      temp = (char *) alloca (needed);
-      sprintf (buffer, message, print_spelling (temp));
-      return buffer;
-    }
-
-  return errtype;
-}
-
 /* Issue an error message for a bad initializer component.
-   FORMAT describes the message.  OFWHAT is the name for the component.
-   LOCAL is a format string for formatting the insertion of the name
-   into the message.
-
-   If OFWHAT is null, the component name is stored on the spelling stack.
-   If the component name is a null string, then LOCAL is omitted entirely.  */
+   MSGID identifies the message.
+   The component name is taken from the spelling stack.  */
 
 void
-error_init (format, local, ofwhat)
-     char *format, *local, *ofwhat;
+error_init (msgid)
+     const char *msgid;
 {
-  char *buffer;
-
-  if (ofwhat == 0)
-    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+  char *ofwhat;
 
+  error ("%s", msgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    sprintf (buffer, local, ofwhat);
-  else
-    buffer[0] = 0;
-
-  error (format, buffer);
+    error ("(near initialization for `%s')", ofwhat);
 }
 
 /* Issue a pedantic warning for a bad initializer component.
-   FORMAT describes the message.  OFWHAT is the name for the component.
-   LOCAL is a format string for formatting the insertion of the name
-   into the message.
-
-   If OFWHAT is null, the component name is stored on the spelling stack.
-   If the component name is a null string, then LOCAL is omitted entirely.  */
+   MSGID identifies the message.
+   The component name is taken from the spelling stack.  */
 
 void
-pedwarn_init (format, local, ofwhat)
-     char *format, *local, *ofwhat;
+pedwarn_init (msgid)
+     const char *msgid;
 {
-  char *buffer;
-
-  if (ofwhat == 0)
-    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+  char *ofwhat;
 
+  pedwarn ("%s", msgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    sprintf (buffer, local, ofwhat);
-  else
-    buffer[0] = 0;
-
-  pedwarn (format, buffer);
+    pedwarn ("(near initialization for `%s')", ofwhat);
 }
 
 /* Issue a warning for a bad initializer component.
-   FORMAT describes the message.  OFWHAT is the name for the component.
-   LOCAL is a format string for formatting the insertion of the name
-   into the message.
-
-   If OFWHAT is null, the component name is stored on the spelling stack.
-   If the component name is a null string, then LOCAL is omitted entirely.  */
+   MSGID identifies the message.
+   The component name is taken from the spelling stack.  */
 
 static void
-warning_init (format, local, ofwhat)
-     char *format, *local, *ofwhat;
+warning_init (msgid)
+     const char *msgid;
 {
-  char *buffer;
-
-  if (ofwhat == 0)
-    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+  char *ofwhat;
 
+  warning ("%s", msgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    sprintf (buffer, local, ofwhat);
-  else
-    buffer[0] = 0;
-
-  warning (format, buffer);
+    warning ("(near initialization for `%s')", ofwhat);
 }
 \f
 /* Digest the parser output INIT as an initializer for type TYPE.
@@ -4745,8 +4525,8 @@ digest_init (type, init, require_constant, constructor_constant)
   enum tree_code code = TREE_CODE (type);
   tree inside_init = init;
 
-  if (init == error_mark_node)
-    return init;
+  if (type == error_mark_node || init == error_mark_node)
+    return error_mark_node;
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
@@ -4775,36 +4555,32 @@ digest_init (type, init, require_constant, constructor_constant)
               != char_type_node)
              && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
            {
-             error_init ("char-array%s initialized from wide string",
-                         " `%s'", NULL);
+             error_init ("char-array initialized from wide string");
              return error_mark_node;
            }
          if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
               == char_type_node)
              && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
            {
-             error_init ("int-array%s initialized from non-wide string",
-                         " `%s'", NULL);
+             error_init ("int-array initialized from non-wide string");
              return error_mark_node;
            }
 
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
-             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
-           {
-             register int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
-             size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
+             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
              /* Subtract 1 (or sizeof (wchar_t))
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
-             if (size < TREE_STRING_LENGTH (inside_init)
-                 - (TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)
-                    ? TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT
-                    : 1))
-               pedwarn_init (
-                 "initializer-string for array of chars%s is too long",
-                 " `%s'", NULL);
-           }
+             && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+                                      TREE_STRING_LENGTH (inside_init)
+                                      - ((TYPE_PRECISION (typ1)
+                                          != TYPE_PRECISION (char_type_node))
+                                         ? (TYPE_PRECISION (wchar_type_node)
+                                            / BITS_PER_UNIT)
+                                         : 1)))
+           pedwarn_init ("initializer-string for array of chars is too long");
+
          return inside_init;
        }
     }
@@ -4830,8 +4606,7 @@ digest_init (type, init, require_constant, constructor_constant)
       else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
               && TREE_CODE (inside_init) != CONSTRUCTOR)
        {
-         error_init ("array%s initialized from non-constant array expression",
-                     " `%s'", NULL);
+         error_init ("array initialized from non-constant array expression");
          return error_mark_node;
        }
 
@@ -4848,25 +4623,21 @@ digest_init (type, init, require_constant, constructor_constant)
            = valid_compound_expr_initializer (inside_init,
                                               TREE_TYPE (inside_init));
          if (inside_init == error_mark_node)
-           error_init ("initializer element%s is not constant",
-                       " for `%s'", NULL);
+           error_init ("initializer element is not constant");
          else
-           pedwarn_init ("initializer element%s is not constant",
-                         " for `%s'", NULL);
+           pedwarn_init ("initializer element is not constant");
          if (flag_pedantic_errors)
            inside_init = error_mark_node;
        }
       else if (require_constant && ! TREE_CONSTANT (inside_init))
        {
-         error_init ("initializer element%s is not constant",
-                     " for `%s'", NULL);
+         error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        }
       else if (require_constant
               && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
        {
-         error_init ("initializer element%s is not computable at load time",
-                     " for `%s'", NULL);
+         error_init ("initializer element is not computable at load time");
          inside_init = error_mark_node;
        }
 
@@ -4882,20 +4653,18 @@ digest_init (type, init, require_constant, constructor_constant)
         for arrays and functions.  We must not call it in the
         case where inside_init is a null pointer constant.  */
       inside_init
-       = convert_for_assignment (type, init, "initialization",
+       = convert_for_assignment (type, init, _("initialization"),
                                  NULL_TREE, NULL_TREE, 0);
 
       if (require_constant && ! TREE_CONSTANT (inside_init))
        {
-         error_init ("initializer element%s is not constant",
-                     " for `%s'", NULL);
+         error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        }
       else if (require_constant
               && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
        {
-         error_init ("initializer element%s is not computable at load time",
-                     " for `%s'", NULL);
+         error_init ("initializer element is not computable at load time");
          inside_init = error_mark_node;
        }
 
@@ -4904,10 +4673,9 @@ digest_init (type, init, require_constant, constructor_constant)
 
   /* Come here only for records and arrays.  */
 
-  if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
     {
-      error_init ("variable-sized object%s may not be initialized",
-                 " `%s'", NULL);
+      error_init ("variable-sized object may not be initialized");
       return error_mark_node;
     }
 
@@ -4933,7 +4701,7 @@ digest_init (type, init, require_constant, constructor_constant)
            type = TREE_TYPE (TYPE_FIELDS (type));
          else
            {
-             error_init ("invalid initializer%s", " for `%s'", NULL);
+             error_init ("invalid initializer");
              return error_mark_node;
            }
        }
@@ -4949,7 +4717,7 @@ digest_init (type, init, require_constant, constructor_constant)
       else
        return error_mark_node;
     }
-  error_init ("invalid initializer%s", " for `%s'", NULL);
+  error_init ("invalid initializer");
   return error_mark_node;
 }
 \f
@@ -4964,8 +4732,7 @@ static tree constructor_type;
 static tree constructor_fields;
 
 /* For an ARRAY_TYPE, this is the specified index
-   at which to store the next element we get.
-   This is a special INTEGER_CST node that we modify in place.  */
+   at which to store the next element we get.  */
 static tree constructor_index;
 
 /* For an ARRAY_TYPE, this is the end index of the range
@@ -4980,13 +4747,11 @@ static tree constructor_max_index;
 static tree constructor_unfilled_fields;
 
 /* For an ARRAY_TYPE, this is the index of the first element
-   not yet written out.
-   This is a special INTEGER_CST node that we modify in place.  */
+   not yet written out.  */
 static tree constructor_unfilled_index;
 
 /* In a RECORD_TYPE, the byte index of the next consecutive field.
-   This is so we can generate gaps between fields, when appropriate.
-   This is a special INTEGER_CST node that we modify in place.  */
+   This is so we can generate gaps between fields, when appropriate.  */
 static tree constructor_bit_index;
 
 /* If we are saving up the elements rather than allocating them,
@@ -5006,20 +4771,30 @@ static int constructor_erroneous;
 /* 1 if have called defer_addressed_constants.  */
 static int constructor_subconstants_deferred;
 
-/* List of pending elements at this constructor level.
+/* Structure for managing pending initializer elements, organized as an
+   AVL tree.  */
+
+struct init_node
+{
+  struct init_node *left, *right;
+  struct init_node *parent;
+  int balance;
+  tree purpose;
+  tree value;
+};
+
+/* Tree of pending elements at this constructor level.
    These are elements encountered out of order
    which belong at places we haven't reached yet in actually
-   writing the output.  */
-static tree constructor_pending_elts;
+   writing the output.
+   Will never hold tree nodes across GC runs.  */
+static struct init_node *constructor_pending_elts;
 
 /* The SPELLING_DEPTH of this constructor.  */
 static int constructor_depth;
 
 /* 0 if implicitly pushing constructor levels is allowed.  */
-int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */
-
-/* 1 if this constructor level was entered implicitly.  */
-static int constructor_implicit;
+int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages.  */
 
 static int require_constant_value;
 static int require_constant_elements;
@@ -5039,9 +4814,6 @@ static char *constructor_asmspec;
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
-/* When we finish reading a constructor expression
-   (constructor_decl is 0), the CONSTRUCTOR goes here.  */
-static tree constructor_result;
 \f
 /* This stack has a level for each implicit or explicit level of
    structuring in the initializer, including the outermost one.  It
@@ -5060,7 +4832,7 @@ struct constructor_stack
   tree bit_index;
   tree elements;
   int offset;
-  tree pending_elts;
+  struct init_node *pending_elts;
   int depth;
   /* If nonzero, this value should replace the entire
      constructor at this level.  */
@@ -5106,7 +4878,7 @@ start_init (decl, asmspec_tree, top_level)
      tree asmspec_tree;
      int top_level;
 {
-  char *locus;
+  const char *locus;
   struct initializer_stack *p
     = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
   char *asmspec = 0;
@@ -5259,11 +5031,12 @@ really_start_incremental_init (type)
     {
       constructor_fields = TYPE_FIELDS (constructor_type);
       /* Skip any nameless bit fields at the beginning.  */
-      while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
        constructor_fields = TREE_CHAIN (constructor_fields);
+
       constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = copy_node (integer_zero_node);
+      constructor_bit_index = bitsize_zero_node;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
@@ -5273,11 +5046,13 @@ really_start_incremental_init (type)
          constructor_max_index
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
          constructor_index
-           = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+           = convert (bitsizetype,
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
        }
       else
-       constructor_index = copy_node (integer_zero_node);
-      constructor_unfilled_index = copy_node (constructor_index);
+       constructor_index = bitsize_zero_node;
+
+      constructor_unfilled_index = constructor_index;
     }
   else
     {
@@ -5288,19 +5063,10 @@ really_start_incremental_init (type)
 
   if (constructor_incremental)
     {
-      int momentary = suspend_momentary ();
-      push_obstacks_nochange ();
-      if (TREE_PERMANENT (constructor_decl))
-       end_temporary_allocation ();
       make_decl_rtl (constructor_decl, constructor_asmspec,
                     constructor_top_level);
       assemble_variable (constructor_decl, constructor_top_level, 0, 1);
-      pop_obstacks ();
-      resume_momentary (momentary);
-    }
 
-  if (constructor_incremental)
-    {
       defer_addressed_constants ();
       constructor_subconstants_deferred = 1;
     }
@@ -5332,23 +5098,28 @@ push_init_level (implicit)
        break;
     }
 
-  /* Structure elements may require alignment.  Do this now
-     if necessary for the subaggregate.  */
+  /* Structure elements may require alignment.  Do this now if necessary
+     for the subaggregate, and if it comes next in sequence.  Don't do
+     this for subaggregates that will go on the pending list.  */
   if (constructor_incremental && constructor_type != 0
-      && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields)
+      && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
+      && constructor_fields == constructor_unfilled_fields)
     {
       /* Advance to offset of this element.  */
       if (! tree_int_cst_equal (constructor_bit_index,
-                               DECL_FIELD_BITPOS (constructor_fields)))
-       {
-         int next = (TREE_INT_CST_LOW
-                     (DECL_FIELD_BITPOS (constructor_fields))
-                     / BITS_PER_UNIT);
-         int here = (TREE_INT_CST_LOW (constructor_bit_index)
-                     / BITS_PER_UNIT);
-
-         assemble_zeros (next - here);
-       }
+                               bit_position (constructor_fields)))
+       assemble_zeros
+         (tree_low_cst
+          (size_binop (TRUNC_DIV_EXPR,
+                       size_binop (MINUS_EXPR,
+                                   bit_position (constructor_fields),
+                                   constructor_bit_index),
+                       bitsize_unit_node),
+           1));
+
+      /* Indicate that we have now filled the structure up to the current
+        field.  */
+      constructor_unfilled_fields = constructor_fields;
     }
 
   p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
@@ -5401,7 +5172,7 @@ push_init_level (implicit)
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
       constructor_type = TREE_TYPE (constructor_type);
-      push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+      push_array_bounds (tree_low_cst (constructor_index, 0));
       constructor_depth++;
       if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
          || constructor_range_end != 0)
@@ -5410,8 +5181,7 @@ push_init_level (implicit)
 
   if (constructor_type == 0)
     {
-      error_init ("extra brace group at end of initializer%s",
-                 " for `%s'", NULL);
+      error_init ("extra brace group at end of initializer");
       constructor_fields = 0;
       constructor_unfilled_fields = 0;
       return;
@@ -5423,7 +5193,7 @@ push_init_level (implicit)
   if (implicit && warn_missing_braces && !missing_braces_mentioned)
     {
       missing_braces_mentioned = 1;
-      warning_init ("missing braces around initializer%s", " for `%s'", NULL);
+      warning_init ("missing braces around initializer");
     }
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5431,11 +5201,12 @@ push_init_level (implicit)
     {
       constructor_fields = TYPE_FIELDS (constructor_type);
       /* Skip any nameless bit fields at the beginning.  */
-      while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
        constructor_fields = TREE_CHAIN (constructor_fields);
+
       constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = copy_node (integer_zero_node);
+      constructor_bit_index = bitsize_zero_node;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
@@ -5445,15 +5216,18 @@ push_init_level (implicit)
          constructor_max_index
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
          constructor_index
-           = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+           = convert (bitsizetype, 
+                                 TYPE_MIN_VALUE
+                                 (TYPE_DOMAIN (constructor_type)));
        }
       else
-       constructor_index = copy_node (integer_zero_node);
-      constructor_unfilled_index = copy_node (constructor_index);
+       constructor_index = bitsize_zero_node;
+
+      constructor_unfilled_index = constructor_index;
     }
   else
     {
-      warning_init ("braces around scalar initializer%s", " for `%s'", NULL);
+      warning_init ("braces around scalar initializer");
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -5473,9 +5247,7 @@ check_init_type_bitfields (type)
       for (tail = TYPE_FIELDS (type); tail;
           tail = TREE_CHAIN (tail))
        {
-         if (DECL_BIT_FIELD (tail)
-             /* This catches cases like `int foo : 8;'.  */
-             || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
+         if (DECL_C_BIT_FIELD (tail))
            {
              constructor_incremental = 0;
              break;
@@ -5485,6 +5257,17 @@ check_init_type_bitfields (type)
        }
     }
 
+  else if (TREE_CODE (type) == UNION_TYPE)
+    {
+      tree tail = TYPE_FIELDS (type);
+      if (tail && DECL_C_BIT_FIELD (tail))
+       /* We also use the nonincremental algorithm for initiliazation
+          of unions whose first member is a bitfield, becuase the
+          incremental algorithm has no code for dealing with
+          bitfields. */
+       constructor_incremental = 0;
+    }
+
   else if (TREE_CODE (type) == ARRAY_TYPE)
     check_init_type_bitfields (TREE_TYPE (type));
 }
@@ -5502,7 +5285,7 @@ pop_init_level (implicit)
      int implicit;
 {
   struct constructor_stack *p;
-  int size = 0;
+  HOST_WIDE_INT size = 0;
   tree constructor = 0;
 
   if (implicit == 0)
@@ -5518,6 +5301,17 @@ pop_init_level (implicit)
   if (constructor_type != 0)
     size = int_size_in_bytes (constructor_type);
 
+  /* Warn when some struct elements are implicitly initialized to zero.  */
+  if (extra_warnings
+      && constructor_type
+      && TREE_CODE (constructor_type) == RECORD_TYPE
+      && constructor_unfilled_fields)
+    {
+      push_member_name (constructor_unfilled_fields);
+      warning_init ("missing initializer");
+      RESTORE_SPELLING_DEPTH (constructor_depth);
+    }
+
   /* Now output all pending elements.  */
   output_pending_init_elements (1);
 
@@ -5527,7 +5321,7 @@ pop_init_level (implicit)
       && (TREE_CODE (constructor_type) == ARRAY_TYPE
          ? integer_zerop (constructor_unfilled_index)
          : constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
-    pedwarn_init ("empty braces in initializer%s", " for `%s'", NULL);
+    pedwarn_init ("empty braces in initializer");
 #endif
 
   /* Pad out the end of the structure.  */
@@ -5552,29 +5346,15 @@ pop_init_level (implicit)
          if (TREE_CODE (constructor_type) == ARRAY_TYPE
              && TYPE_DOMAIN (constructor_type) == 0)
            {
-             int failure;
-             int momentary_p;
-
-             push_obstacks_nochange ();
-             if (TREE_PERMANENT (constructor_type))
-               end_temporary_allocation ();
-
-             momentary_p = suspend_momentary ();
-
              /* We shouldn't have an incomplete array type within
                 some other type.  */
              if (constructor_stack->next)
                abort ();
 
-             failure
-               = complete_array_type (constructor_type,
-                                      constructor, 0);
-             if (failure)
+             if (complete_array_type (constructor_type, constructor, 0))
                abort ();
 
              size = int_size_in_bytes (constructor_type);
-             resume_momentary (momentary_p);
-             pop_obstacks ();
            }
 
          output_constant (constructor, size);
@@ -5591,14 +5371,12 @@ pop_init_level (implicit)
         the element, after verifying there is just one.  */
       if (constructor_elements == 0)
        {
-         error_init ("empty scalar initializer%s",
-                     " for `%s'", NULL);
+         error_init ("empty scalar initializer");
          constructor = error_mark_node;
        }
       else if (TREE_CHAIN (constructor_elements) != 0)
        {
-         error_init ("extra elements in scalar initializer%s",
-                     " for `%s'", NULL);
+         error_init ("extra elements in scalar initializer");
          constructor = TREE_VALUE (constructor_elements);
        }
       else
@@ -5610,31 +5388,24 @@ pop_init_level (implicit)
        constructor = error_mark_node;
       else
        {
-         int momentary = suspend_momentary ();
-
          constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
                               nreverse (constructor_elements));
          if (constructor_constant)
            TREE_CONSTANT (constructor) = 1;
          if (constructor_constant && constructor_simple)
            TREE_STATIC (constructor) = 1;
-
-         resume_momentary (momentary);
        }
     }
   else
     {
       tree filled;
-      int momentary = suspend_momentary ();
 
       if (TREE_CODE (constructor_type) == RECORD_TYPE
          || TREE_CODE (constructor_type) == UNION_TYPE)
-       {
-         /* Find the offset of the end of that field.  */
-         filled = size_binop (CEIL_DIV_EXPR,
-                              constructor_bit_index,
-                              size_int (BITS_PER_UNIT));
-       }
+       /* Find the offset of the end of that field.  */
+       filled = size_binop (CEIL_DIV_EXPR, constructor_bit_index,
+                            bitsize_unit_node);
+
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
        {
          /* If initializing an array of unknown size,
@@ -5643,14 +5414,9 @@ pop_init_level (implicit)
              && TYPE_DOMAIN (constructor_type) == 0)
            {
              tree maxindex
-               = size_binop (MINUS_EXPR,
-                             constructor_unfilled_index,
-                             integer_one_node);
-
-             push_obstacks_nochange ();
-             if (TREE_PERMANENT (constructor_type))
-               end_temporary_allocation ();
-             maxindex = copy_node (maxindex);
+               = copy_node (size_diffop (constructor_unfilled_index,
+                                         bitsize_one_node));
+
              TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
              TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
 
@@ -5658,25 +5424,27 @@ pop_init_level (implicit)
                 in the array, because we start counting at zero.  Therefore,
                 warn only if the value is less than zero.  */
              if (pedantic
-                 && (tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+                 && (tree_int_cst_sgn
+                     (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
                      < 0))
                error_with_decl (constructor_decl,
                                 "zero or negative array size `%s'");
+
              layout_type (constructor_type);
              size = int_size_in_bytes (constructor_type);
-             pop_obstacks ();
            }
 
-         filled = size_binop (MULT_EXPR, constructor_unfilled_index,
-                              size_in_bytes (TREE_TYPE (constructor_type)));
+         filled
+           = size_binop (MULT_EXPR, constructor_unfilled_index,
+                         convert (bitsizetype,
+                                  TYPE_SIZE_UNIT
+                                  (TREE_TYPE (constructor_type))));
        }
       else
        filled = 0;
 
       if (filled != 0)
-       assemble_zeros (size - TREE_INT_CST_LOW (filled));
-
-      resume_momentary (momentary);
+       assemble_zeros (size - tree_low_cst (filled, 1));
     }
 
          
@@ -5722,35 +5490,36 @@ set_init_index (first, last)
          || TREE_CODE (first) == NON_LVALUE_EXPR)
         && (TYPE_MODE (TREE_TYPE (first))
             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
-    (first) = TREE_OPERAND (first, 0);
+    first = TREE_OPERAND (first, 0);
+
   if (last)
     while ((TREE_CODE (last) == NOP_EXPR
            || TREE_CODE (last) == CONVERT_EXPR
            || TREE_CODE (last) == NON_LVALUE_EXPR)
           && (TYPE_MODE (TREE_TYPE (last))
               == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0)))))
-      (last) = TREE_OPERAND (last, 0);
+      last = TREE_OPERAND (last, 0);
 
   if (TREE_CODE (first) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+    error_init ("nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+    error_init ("nonconstant array index in initializer");
+  else if (! constructor_unfilled_index)
+    error_init ("array index in non-array initializer");
   else if (tree_int_cst_lt (first, constructor_unfilled_index))
-    error_init ("duplicate array index in initializer%s", " for `%s'", NULL);
+    error_init ("duplicate array index in initializer");
   else
     {
-      TREE_INT_CST_LOW (constructor_index)
-       = TREE_INT_CST_LOW (first);
-      TREE_INT_CST_HIGH (constructor_index)
-       = TREE_INT_CST_HIGH (first);
+      constructor_index = convert (bitsizetype, first);
 
       if (last != 0 && tree_int_cst_lt (last, first))
-       error_init ("empty index range in initializer%s", " for `%s'", NULL);
+       error_init ("empty index range in initializer");
       else
        {
          if (pedantic)
            pedwarn ("ANSI C forbids specifying element to initialize");
-         constructor_range_end = last;
+
+         constructor_range_end = last ? convert (bitsizetype, last) : 0;
        }
     }
 }
@@ -5792,6 +5561,250 @@ set_init_label (fieldname)
     }
 }
 \f
+/* Add a new initializer to the tree of pending initializers.  PURPOSE
+   indentifies the initializer, either array index or field in a structure. 
+   VALUE is the value of that index or field.  */
+
+static void
+add_pending_init (purpose, value)
+     tree purpose, value;
+{
+  struct init_node *p, **q, *r;
+
+  q = &constructor_pending_elts;
+  p = 0;
+
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      while (*q != 0)
+       {
+         p = *q;
+         if (tree_int_cst_lt (purpose, p->purpose))
+           q = &p->left;
+         else if (p->purpose != purpose)
+           q = &p->right;
+         else
+           abort ();
+       }
+    }
+  else
+    {
+      while (*q != NULL)
+       {
+         p = *q;
+         if (tree_int_cst_lt (bit_position (purpose),
+                              bit_position (p->purpose)))
+           q = &p->left;
+         else if (p->purpose != purpose)
+           q = &p->right;
+         else
+           abort ();
+       }
+    }
+
+  r = (struct init_node *) ggc_alloc_obj (sizeof (struct init_node), 0);
+  r->purpose = purpose;
+  r->value = value;
+
+  *q = r;
+  r->parent = p;
+  r->left = 0;
+  r->right = 0;
+  r->balance = 0;
+
+  while (p)
+    {
+      struct init_node *s;
+
+      if (r == p->left)
+       {
+         if (p->balance == 0)
+           p->balance = -1;
+         else if (p->balance < 0)
+           {
+             if (r->balance < 0)
+               {
+                 /* L rotation. */
+                 p->left = r->right;
+                 if (p->left)
+                   p->left->parent = p;
+                 r->right = p;
+
+                 p->balance = 0;
+                 r->balance = 0;
+
+                 s = p->parent;
+                 p->parent = r;
+                 r->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = r;
+                     else
+                       s->right = r;
+                   }
+                 else
+                   constructor_pending_elts = r;
+               }
+             else
+               {
+                 /* LR rotation. */
+                 struct init_node *t = r->right;
+
+                 r->right = t->left;
+                 if (r->right)
+                   r->right->parent = r;
+                 t->left = r;
+
+                 p->left = t->right;
+                 if (p->left)
+                   p->left->parent = p;
+                 t->right = p;
+
+                 p->balance = t->balance < 0;
+                 r->balance = -(t->balance > 0);
+                 t->balance = 0;
+
+                 s = p->parent;
+                 p->parent = t;
+                 r->parent = t;
+                 t->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = t;
+                     else
+                       s->right = t;
+                   }
+                 else
+                   constructor_pending_elts = t;
+               }
+             break;
+           }
+         else
+           {
+             /* p->balance == +1; growth of left side balances the node.  */
+             p->balance = 0;
+             break;
+           }
+       }
+      else /* r == p->right */
+       {
+         if (p->balance == 0)
+           /* Growth propagation from right side.  */
+           p->balance++;
+         else if (p->balance > 0)
+           {
+             if (r->balance > 0)
+               {
+                 /* R rotation. */
+                 p->right = r->left;
+                 if (p->right)
+                   p->right->parent = p;
+                 r->left = p;
+
+                 p->balance = 0;
+                 r->balance = 0;
+
+                 s = p->parent;
+                 p->parent = r;
+                 r->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = r;
+                     else
+                       s->right = r;
+                   }
+                 else
+                   constructor_pending_elts = r;
+               }
+             else /* r->balance == -1 */
+               {
+                 /* RL rotation */
+                 struct init_node *t = r->left;
+
+                 r->left = t->right;
+                 if (r->left)
+                   r->left->parent = r;
+                 t->right = r;
+
+                 p->right = t->left;
+                 if (p->right)
+                   p->right->parent = p;
+                 t->left = p;
+
+                 r->balance = (t->balance < 0);
+                 p->balance = -(t->balance > 0);
+                 t->balance = 0;
+
+                 s = p->parent;
+                 p->parent = t;
+                 r->parent = t;
+                 t->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = t;
+                     else
+                       s->right = t;
+                   }
+                 else
+                   constructor_pending_elts = t;
+               }
+             break;
+           }
+         else
+           {
+             /* p->balance == -1; growth of right side balances the node. */
+             p->balance = 0;
+             break;
+           }
+       }
+
+      r = p;
+      p = p->parent;
+    }
+}
+
+/* Return nonzero if FIELD is equal to the index of a pending initializer.  */
+
+static int
+pending_init_member (field)
+     tree field;
+{
+  struct init_node *p;
+
+  p = constructor_pending_elts;
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      while (p)
+       {
+         if (field == p->purpose)
+           return 1;
+         else if (tree_int_cst_lt (field, p->purpose))
+           p = p->left;
+         else
+           p = p->right;
+       }
+    }
+  else
+    {
+      while (p)
+       {
+         if (field == p->purpose)
+           return 1;
+         else if (tree_int_cst_lt (bit_position (field),
+                                   bit_position (p->purpose)))
+           p = p->left;
+         else
+           p = p->right;
+       }
+    }
+
+  return 0;
+}
+
 /* "Output" the next constructor element.
    At top level, really output it to assembler code now.
    Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
@@ -5825,20 +5838,19 @@ output_init_element (value, type, field, pending)
   else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0
           || ((TREE_CODE (constructor_type) == RECORD_TYPE
                || TREE_CODE (constructor_type) == UNION_TYPE)
-              && DECL_BIT_FIELD (field) && TREE_CODE (value) != INTEGER_CST))
+              && DECL_C_BIT_FIELD (field)
+              && TREE_CODE (value) != INTEGER_CST))
     constructor_simple = 0;
 
   if (require_constant_value && ! TREE_CONSTANT (value))
     {
-      error_init ("initializer element%s is not constant",
-                 " for `%s'", NULL);
+      error_init ("initializer element is not constant");
       value = error_mark_node;
     }
   else if (require_constant_elements
           && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
     {
-      error_init ("initializer element%s is not computable at load time",
-                 " for `%s'", NULL);
+      error_init ("initializer element is not computable at load time");
       value = error_mark_node;
     }
 
@@ -5849,27 +5861,12 @@ output_init_element (value, type, field, pending)
   if (pending)
     {
       if (TREE_CODE (constructor_type) == RECORD_TYPE
-         || TREE_CODE (constructor_type) == UNION_TYPE)
+         || TREE_CODE (constructor_type) == UNION_TYPE
+         || TREE_CODE (constructor_type) == ARRAY_TYPE)
        {
-         if (purpose_member (field, constructor_pending_elts))
-           {
-             error_init ("duplicate initializer%s", " for `%s'", NULL);
-             duplicate = 1;
-           }
-       }
-      if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         tree tail;
-         for (tail = constructor_pending_elts; tail;
-              tail = TREE_CHAIN (tail))
-           if (TREE_PURPOSE (tail) != 0
-               && TREE_CODE (TREE_PURPOSE (tail)) == INTEGER_CST
-               && tree_int_cst_equal (TREE_PURPOSE (tail), constructor_index))
-             break;
-
-         if (tail != 0)
+         if (pending_init_member (field))
            {
-             error_init ("duplicate initializer%s", " for `%s'", NULL);
+             error_init ("duplicate initializer");
              duplicate = 1;
            }
        }
@@ -5878,16 +5875,12 @@ output_init_element (value, type, field, pending)
   /* If this element doesn't come next in sequence,
      put it on constructor_pending_elts.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE
-      && !tree_int_cst_equal (field, constructor_unfilled_index))
+      && ! tree_int_cst_equal (field, constructor_unfilled_index))
     {
       if (! duplicate)
-       /* The copy_node is needed in case field is actually
-          constructor_index, which is modified in place.  */
-       constructor_pending_elts
-         = tree_cons (copy_node (field),
-                      digest_init (type, value, require_constant_value, 
-                                   require_constant_elements),
-                      constructor_pending_elts);
+       add_pending_init (field,
+                         digest_init (type, value, require_constant_value, 
+                                      require_constant_elements));
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
           && field != constructor_unfilled_fields)
@@ -5896,11 +5889,9 @@ output_init_element (value, type, field, pending)
         no matter which field is specified, it can be initialized
         right away since it starts at the beginning of the union.  */
       if (!duplicate)
-       constructor_pending_elts
-         = tree_cons (field,
-                      digest_init (type, value, require_constant_value, 
-                                   require_constant_elements),
-                      constructor_pending_elts);
+       add_pending_init (field,
+                         digest_init (type, value, require_constant_value, 
+                                      require_constant_elements));
     }
   else
     {
@@ -5923,20 +5914,18 @@ output_init_element (value, type, field, pending)
            {
              /* Structure elements may require alignment.
                 Do this, if necessary.  */
-             if (TREE_CODE (constructor_type) == RECORD_TYPE)
-               {
-                 /* Advance to offset of this element.  */
-                 if (! tree_int_cst_equal (constructor_bit_index,
-                                           DECL_FIELD_BITPOS (field)))
-                   {
-                     int next = (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
-                                 / BITS_PER_UNIT);
-                     int here = (TREE_INT_CST_LOW (constructor_bit_index)
-                                 / BITS_PER_UNIT);
+             if (TREE_CODE (constructor_type) == RECORD_TYPE
+                 && ! tree_int_cst_equal (constructor_bit_index,
+                                          bit_position (field)))
+               /* Advance to offset of this element.  */
+               assemble_zeros
+                 (tree_low_cst
+                  (size_binop (TRUNC_DIV_EXPR,
+                               size_binop (MINUS_EXPR, bit_position (field),
+                                           constructor_bit_index),
+                               bitsize_unit_node),
+                   0));
 
-                     assemble_zeros (next - here);
-                   }
-               }
              output_constant (digest_init (type, value,
                                            require_constant_value,
                                            require_constant_elements),
@@ -5946,29 +5935,29 @@ output_init_element (value, type, field, pending)
                 keep track of end position of last field.  */
              if (TREE_CODE (constructor_type) == RECORD_TYPE
                  || TREE_CODE (constructor_type) == UNION_TYPE)
-               {
-                 tree temp = size_binop (PLUS_EXPR, DECL_FIELD_BITPOS (field),
-                                         DECL_SIZE (field));
-                 TREE_INT_CST_LOW (constructor_bit_index)
-                   = TREE_INT_CST_LOW (temp);
-                 TREE_INT_CST_HIGH (constructor_bit_index)
-                   = TREE_INT_CST_HIGH (temp);
-               }
+               constructor_bit_index
+                 = size_binop (PLUS_EXPR, bit_position (field),
+                               DECL_SIZE (field));
            }
        }
 
       /* Advance the variable that indicates sequential elements output.  */
       if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+       constructor_unfilled_index
+         = size_binop (PLUS_EXPR, constructor_unfilled_index,
+                       bitsize_one_node);
+      else if (TREE_CODE (constructor_type) == RECORD_TYPE)
        {
-         tree tem = size_binop (PLUS_EXPR, constructor_unfilled_index,
-                                integer_one_node);
-         TREE_INT_CST_LOW (constructor_unfilled_index)
-           = TREE_INT_CST_LOW (tem);
-         TREE_INT_CST_HIGH (constructor_unfilled_index)
-           = TREE_INT_CST_HIGH (tem);
+         constructor_unfilled_fields
+           = TREE_CHAIN (constructor_unfilled_fields);
+
+         /* Skip any nameless bit fields.  */
+         while (constructor_unfilled_fields != 0
+                && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+                && DECL_NAME (constructor_unfilled_fields) == 0)
+           constructor_unfilled_fields =
+             TREE_CHAIN (constructor_unfilled_fields);
        }
-      else if (TREE_CODE (constructor_type) == RECORD_TYPE)
-       constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        constructor_unfilled_fields = 0;
 
@@ -5993,56 +5982,110 @@ static void
 output_pending_init_elements (all)
      int all;
 {
-  tree tail;
+  struct init_node *elt = constructor_pending_elts;
   tree next;
 
  retry:
 
-  /* Look thru the whole pending list.
+  /* Look thru the whole pending tree.
      If we find an element that should be output now,
      output it.  Otherwise, set NEXT to the element
      that comes first among those still pending.  */
      
   next = 0;
-  for (tail = constructor_pending_elts; tail;
-       tail = TREE_CHAIN (tail))
+  while (elt)
     {
       if (TREE_CODE (constructor_type) == ARRAY_TYPE)
        {
-         if (tree_int_cst_equal (TREE_PURPOSE (tail),
+         if (tree_int_cst_equal (elt->purpose,
                                  constructor_unfilled_index))
+           output_init_element (elt->value,
+                                TREE_TYPE (constructor_type),
+                                constructor_unfilled_index, 0);
+         else if (tree_int_cst_lt (constructor_unfilled_index,
+                                   elt->purpose))
            {
-             output_init_element (TREE_VALUE (tail),
-                                  TREE_TYPE (constructor_type),
-                                  constructor_unfilled_index, 0);
-             goto retry;
+             /* Advance to the next smaller node.  */
+             if (elt->left)
+               elt = elt->left;
+             else
+               {
+                 /* We have reached the smallest node bigger than the
+                    current unfilled index.  Fill the space first.  */
+                 next = elt->purpose;
+                 break;
+               }
+           }
+         else
+           {
+             /* Advance to the next bigger node.  */
+             if (elt->right)
+               elt = elt->right;
+             else
+               {
+                 /* We have reached the biggest node in a subtree.  Find
+                    the parent of it, which is the next bigger node.  */
+                 while (elt->parent && elt->parent->right == elt)
+                   elt = elt->parent;
+                 elt = elt->parent;
+                 if (elt && tree_int_cst_lt (constructor_unfilled_index,
+                                             elt->purpose))
+                   {
+                     next = elt->purpose;
+                     break;
+                   }
+               }
            }
-         else if (tree_int_cst_lt (TREE_PURPOSE (tail),
-                                   constructor_unfilled_index))
-           ;
-         else if (next == 0
-                  || tree_int_cst_lt (TREE_PURPOSE (tail), next))
-           next = TREE_PURPOSE (tail);
        }
       else if (TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
        {
-         if (TREE_PURPOSE (tail) == constructor_unfilled_fields)
+         /* If the current record is complete we are done.  */
+         if (constructor_unfilled_fields == 0)
+           break;
+         if (elt->purpose == constructor_unfilled_fields)
            {
-             output_init_element (TREE_VALUE (tail),
+             output_init_element (elt->value,
                                   TREE_TYPE (constructor_unfilled_fields),
                                   constructor_unfilled_fields,
                                   0);
-             goto retry;
            }
-         else if (constructor_unfilled_fields == 0
-                  || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
-                                      DECL_FIELD_BITPOS (constructor_unfilled_fields)))
-           ;
-         else if (next == 0
-                  || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
-                                      DECL_FIELD_BITPOS (next)))
-           next = TREE_PURPOSE (tail);
+         else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields),
+                                   bit_position (elt->purpose)))
+           {
+             /* Advance to the next smaller node.  */
+             if (elt->left)
+               elt = elt->left;
+             else
+               {
+                 /* We have reached the smallest node bigger than the
+                    current unfilled field.  Fill the space first.  */
+                 next = elt->purpose;
+                 break;
+               }
+           }
+         else
+           {
+             /* Advance to the next bigger node.  */
+             if (elt->right)
+               elt = elt->right;
+             else
+               {
+                 /* We have reached the biggest node in a subtree.  Find
+                    the parent of it, which is the next bigger node.  */
+                 while (elt->parent && elt->parent->right == elt)
+                   elt = elt->parent;
+                 elt = elt->parent;
+                 if (elt
+                     && (tree_int_cst_lt
+                         (bit_position (constructor_unfilled_fields),
+                          bit_position (elt->purpose))))
+                   {
+                     next = elt->purpose;
+                     break;
+                   }
+               }
+           }
        }
     }
 
@@ -6055,11 +6098,13 @@ output_pending_init_elements (all)
   if (constructor_incremental)
     {
       tree filled;
-      tree nextpos_tree = size_int (0);
+      tree nextpos_tree = bitsize_zero_node;
 
       if (TREE_CODE (constructor_type) == RECORD_TYPE
          || TREE_CODE (constructor_type) == UNION_TYPE)
        {
+         tree tail;
+
          /* Find the last field written out, if any.  */
          for (tail = TYPE_FIELDS (constructor_type); tail;
               tail = TREE_CHAIN (tail))
@@ -6069,44 +6114,34 @@ output_pending_init_elements (all)
          if (tail)
            /* Find the offset of the end of that field.  */
            filled = size_binop (CEIL_DIV_EXPR,
-                                size_binop (PLUS_EXPR,
-                                            DECL_FIELD_BITPOS (tail),
+                                size_binop (PLUS_EXPR, bit_position (tail),
                                             DECL_SIZE (tail)),
-                                size_int (BITS_PER_UNIT));
+                                bitsize_unit_node);
          else
-           filled = size_int (0);
-
-         nextpos_tree = size_binop (CEIL_DIV_EXPR,
-                                    DECL_FIELD_BITPOS (next),
-                                    size_int (BITS_PER_UNIT));
+           filled = bitsize_zero_node;
 
-         TREE_INT_CST_HIGH (constructor_bit_index)
-           = TREE_INT_CST_HIGH (DECL_FIELD_BITPOS (next));
-         TREE_INT_CST_LOW (constructor_bit_index)
-           = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (next));
+         nextpos_tree = convert (bitsizetype, byte_position (next));
+         constructor_bit_index = bit_position (next);
          constructor_unfilled_fields = next;
        }
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
        {
-         filled = size_binop (MULT_EXPR, constructor_unfilled_index,
-                              size_in_bytes (TREE_TYPE (constructor_type)));
+         filled
+           = size_binop (MULT_EXPR, constructor_unfilled_index,
+                         convert (bitsizetype,
+                                  TYPE_SIZE_UNIT
+                                  (TREE_TYPE (constructor_type))));
          nextpos_tree
            = size_binop (MULT_EXPR, next,
-                         size_in_bytes (TREE_TYPE (constructor_type)));
-         TREE_INT_CST_LOW (constructor_unfilled_index)
-           = TREE_INT_CST_LOW (next);
-         TREE_INT_CST_HIGH (constructor_unfilled_index)
-           = TREE_INT_CST_HIGH (next);
+                         convert (bitsizetype, TYPE_SIZE_UNIT
+                                  (TREE_TYPE (constructor_type))));
+         constructor_unfilled_index = next;
        }
       else
        filled = 0;
 
       if (filled)
-       {
-         int nextpos = TREE_INT_CST_LOW (nextpos_tree);
-
-         assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
-       }
+       assemble_zeros (tree_low_cst (size_diffop (nextpos_tree, filled), 1));
     }
   else
     {
@@ -6117,14 +6152,11 @@ output_pending_init_elements (all)
          || TREE_CODE (constructor_type) == UNION_TYPE)
        constructor_unfilled_fields = next;
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         TREE_INT_CST_LOW (constructor_unfilled_index)
-           = TREE_INT_CST_LOW (next);
-         TREE_INT_CST_HIGH (constructor_unfilled_index)
-           = TREE_INT_CST_HIGH (next);
-       }
+       constructor_unfilled_index = next;
     }
 
+  /* ELT now points to the node in the pending tree with the next
+     initializer to output.  */
   goto retry;
 }
 \f
@@ -6157,14 +6189,15 @@ process_init_element (value)
       && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
       && integer_zerop (constructor_unfilled_index))
     {
+      if (constructor_stack->replacement_value)
+        error_init ("excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
 
   if (constructor_stack->replacement_value != 0)
     {
-      error_init ("excess elements in struct initializer%s",
-                 " after `%s'", NULL_PTR);
+      error_init ("excess elements in struct initializer");
       return;
     }
 
@@ -6182,7 +6215,9 @@ process_init_element (value)
          && constructor_fields == 0)
        process_init_element (pop_init_level (1));
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE
-              && tree_int_cst_lt (constructor_max_index, constructor_index))
+              && (constructor_max_index == 0
+                  || tree_int_cst_lt (constructor_max_index,
+                                      constructor_index)))
        process_init_element (pop_init_level (1));
       else
        break;
@@ -6197,8 +6232,7 @@ process_init_element (value)
 
          if (constructor_fields == 0)
            {
-             pedwarn_init ("excess elements in struct initializer%s",
-                           " after `%s'", NULL_PTR);
+             pedwarn_init ("excess elements in struct initializer");
              break;
            }
 
@@ -6236,20 +6270,24 @@ process_init_element (value)
               directly output as a constructor.  */
            {
              /* For a record, keep track of end position of last field.  */
-             tree temp = size_binop (PLUS_EXPR,
-                                     DECL_FIELD_BITPOS (constructor_fields),
-                                     DECL_SIZE (constructor_fields));
-             TREE_INT_CST_LOW (constructor_bit_index)
-               = TREE_INT_CST_LOW (temp);
-             TREE_INT_CST_HIGH (constructor_bit_index)
-               = TREE_INT_CST_HIGH (temp);
+             constructor_bit_index
+               = size_binop (PLUS_EXPR,
+                             bit_position (constructor_fields),
+                             DECL_SIZE (constructor_fields));
 
              constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+             /* Skip any nameless bit fields.  */
+             while (constructor_unfilled_fields != 0
+                    && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+                    && DECL_NAME (constructor_unfilled_fields) == 0)
+               constructor_unfilled_fields =
+                 TREE_CHAIN (constructor_unfilled_fields);
            }
 
          constructor_fields = TREE_CHAIN (constructor_fields);
          /* Skip any nameless bit fields at the beginning.  */
-         while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+         while (constructor_fields != 0
+                && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
            constructor_fields = TREE_CHAIN (constructor_fields);
          break;
@@ -6261,8 +6299,7 @@ process_init_element (value)
 
          if (constructor_fields == 0)
            {
-             pedwarn_init ("excess elements in union initializer%s",
-                           " after `%s'", NULL_PTR);
+             pedwarn_init ("excess elements in union initializer");
              break;
            }
 
@@ -6299,11 +6336,7 @@ process_init_element (value)
            /* Do the bookkeeping for an element that was
               directly output as a constructor.  */
            {
-             TREE_INT_CST_LOW (constructor_bit_index)
-               = TREE_INT_CST_LOW (DECL_SIZE (constructor_fields));
-             TREE_INT_CST_HIGH (constructor_bit_index)
-               = TREE_INT_CST_HIGH (DECL_SIZE (constructor_fields));
-
+             constructor_bit_index = DECL_SIZE (constructor_fields);
              constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
            }
 
@@ -6336,46 +6369,44 @@ process_init_element (value)
          if (constructor_max_index != 0
              && tree_int_cst_lt (constructor_max_index, constructor_index))
            {
-             pedwarn_init ("excess elements in array initializer%s",
-                           " after `%s'", NULL_PTR);
+             pedwarn_init ("excess elements in array initializer");
              break;
            }
 
-         /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
+         /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once.  */
          if (constructor_range_end)
-           value = save_expr (value);
+           {
+             if (constructor_max_index != 0
+                 && tree_int_cst_lt (constructor_max_index, 
+                                     constructor_range_end))
+               {
+                 pedwarn_init ("excess elements in array initializer");
+                 constructor_range_end = constructor_max_index;
+               }
+
+             value = save_expr (value);
+           }
 
          /* Now output the actual element.
             Ordinarily, output once.
             If there is a range, repeat it till we advance past the range.  */
          do
            {
-             tree tem;
-
              if (value)
                {
-                 push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+                 push_array_bounds (tree_low_cst (constructor_index, 0));
                  output_init_element (value, elttype, constructor_index, 1);
                  RESTORE_SPELLING_DEPTH (constructor_depth);
                }
 
-             tem = size_binop (PLUS_EXPR, constructor_index,
-                               integer_one_node);
-             TREE_INT_CST_LOW (constructor_index)
-               = TREE_INT_CST_LOW (tem);
-             TREE_INT_CST_HIGH (constructor_index)
-               = TREE_INT_CST_HIGH (tem);
+             constructor_index
+               = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-             if (!value)
+             if (! value)
                /* If we are doing the bookkeeping for an element that was
-                  directly output as a constructor,
-                  we must update constructor_unfilled_index.  */
-               {
-                 TREE_INT_CST_LOW (constructor_unfilled_index)
-                   = TREE_INT_CST_LOW (constructor_index);
-                 TREE_INT_CST_HIGH (constructor_unfilled_index)
-                   = TREE_INT_CST_HIGH (constructor_index);
-               }
+                  directly output as a constructor, we must update
+                  constructor_unfilled_index.  */
+               constructor_unfilled_index = constructor_index;
            }
          while (! (constructor_range_end == 0
                    || tree_int_cst_lt (constructor_range_end,
@@ -6388,8 +6419,7 @@ process_init_element (value)
         for a scalar variable.  */
       if (constructor_fields == 0)
        {
-         pedwarn_init ("excess elements in scalar initializer%s",
-                       " after `%s'", NULL_PTR);
+         pedwarn_init ("excess elements in scalar initializer");
          break;
        }
 
@@ -6398,12 +6428,6 @@ process_init_element (value)
       constructor_fields = 0;
       break;
     }
-
-  /* If the (lexically) previous elments are not now saved,
-     we can discard the storage for them.  */
-  if (constructor_incremental && constructor_pending_elts == 0 && value != 0
-      && constructor_stack == 0)
-    clear_momentary ();
 }
 \f
 /* Expand an ASM statement with operands, handling output operands
@@ -6435,7 +6459,26 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
 
   /* Record the contents of OUTPUTS before it is modified.  */
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
-    o[i] = TREE_VALUE (tail);
+    {
+      tree output = TREE_VALUE (tail);
+
+      /* We can remove conversions that just change the type, not the mode.  */
+      STRIP_NOPS (output);
+      o[i] = output;
+
+      /* Allow conversions as LHS here.  build_modify_expr as called below
+        will do the right thing with them.  */
+      while (TREE_CODE (output) == NOP_EXPR
+            || TREE_CODE (output) == CONVERT_EXPR
+            || TREE_CODE (output) == FLOAT_EXPR
+            || TREE_CODE (output) == FIX_TRUNC_EXPR
+            || TREE_CODE (output) == FIX_FLOOR_EXPR
+            || TREE_CODE (output) == FIX_ROUND_EXPR
+            || TREE_CODE (output) == FIX_CEIL_EXPR)
+       output = TREE_OPERAND (output, 0);
+
+      lvalue_or_else (o[i], "invalid lvalue in asm statement");
+    }
 
   /* Perform default conversions on array and function inputs.  */
   /* Don't do this for other types--
@@ -6456,7 +6499,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
       if (o[i] != TREE_VALUE (tail))
        {
          expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
-                      0, VOIDmode, 0);
+                      NULL_RTX, VOIDmode, EXPAND_NORMAL);
          free_temp_slots ();
        }
       /* Detect modification of read-only values.
@@ -6506,7 +6549,7 @@ c_expand_return (retval)
     }
   else
     {
-      tree t = convert_for_assignment (valtype, retval, "return",
+      tree t = convert_for_assignment (valtype, retval, _("return"),
                                       NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
@@ -6559,6 +6602,9 @@ c_expand_return (retval)
                  && DECL_CONTEXT (inner) == current_function_decl)
                warning ("function returns address of local variable");
              break;
+
+           default:
+             break;
            }
 
          break;
@@ -6578,8 +6624,14 @@ tree
 c_expand_start_case (exp)
      tree exp;
 {
-  register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
-  tree type = TREE_TYPE (exp);
+  register enum tree_code code;
+  tree type;
+
+  if (TREE_CODE (exp) == ERROR_MARK)
+    return exp;
+
+  code = TREE_CODE (TREE_TYPE (exp));
+  type = TREE_TYPE (exp);
 
   if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
     {
@@ -6592,6 +6644,7 @@ c_expand_start_case (exp)
       type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
 
       if (warn_traditional
+         && ! in_system_header
          && (type == long_integer_type_node
              || type == long_unsigned_type_node))
        pedwarn ("`long' switch expression not converted to `int' in ANSI C");