OSDN Git Service

Fix mips64vr4100-elf build failure.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 9e40abd..f8f0705 100644 (file)
@@ -1,5 +1,5 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 91-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -29,20 +29,20 @@ 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 "flags.h"
 #include "output.h"
+#include "rtl.h"
+#include "expr.h"
+#include "toplev.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 tree qualify_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));
@@ -71,6 +71,8 @@ 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 void add_pending_init           PROTO((tree, tree));
+static int pending_init_member         PROTO((tree));
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -192,40 +194,8 @@ common_type (t1, t2)
   if (t2 == error_mark_node)
     return t1;
 
-  /* Merge the attributes */
-
-  { register tree a1, a2;
-    a1 = TYPE_ATTRIBUTES (t1);
-    a2 = TYPE_ATTRIBUTES (t2);
-
-    /* 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;
-             }
-       }
-  }
+  /* Merge the attributes.  */
+  attributes = merge_machine_type_attributes (t1, t2);
 
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
@@ -293,6 +263,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))
@@ -427,7 +403,7 @@ common_type (t1, t2)
          }
 
        t1 = build_function_type (valtype, newargs);
-       /* ... falls through ... */
+       /* ... falls through ...  */
       }
 
     default:
@@ -450,7 +426,8 @@ 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;
 
   /* Treat an enum type as the integer type of the same width and 
@@ -477,7 +454,7 @@ comptypes (type1, type2)
 
   /* 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;
@@ -539,6 +516,9 @@ comptypes (type1, type2)
       if (maybe_objc_comptypes (t1, t2, 0) == 1)
        val = 1;
       break;
+
+    default:
+      break;
     }
   return attrval == 2 && val == 1 ? 2 : val;
 }
@@ -553,7 +533,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)),
@@ -759,7 +739,16 @@ unsigned_type (type)
     return long_unsigned_type_node;
   if (type1 == long_long_integer_type_node)
     return long_long_unsigned_type_node;
-  return type;
+  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 signed_or_unsigned_type (1, type);
 }
 
 /* Return a signed type the same as TYPE in other respects.  */
@@ -779,7 +768,16 @@ signed_type (type)
     return long_integer_type_node;
   if (type1 == long_long_unsigned_type_node)
     return long_long_integer_type_node;
-  return type;
+  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 signed_or_unsigned_type (0, type);
 }
 
 /* Return a type the same as TYPE except unsigned or
@@ -790,7 +788,8 @@ signed_or_unsigned_type (unsignedp, type)
      int unsignedp;
      tree type;
 {
-  if (! INTEGRAL_TYPE_P (type))
+  if ((! INTEGRAL_TYPE_P (type) && ! POINTER_TYPE_P (type))
+      || TREE_UNSIGNED (type) == unsignedp)
     return type;
   if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
@@ -838,6 +837,7 @@ c_sizeof (type)
   /* 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)));
+  t = convert (sizetype, t);
   /* 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;
@@ -861,6 +861,7 @@ c_sizeof_nowarn (type)
   /* 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)));
+  t = convert (sizetype, t);
   force_fit_type (t, 0);
   return t;
 }
@@ -889,6 +890,7 @@ c_size_in_bytes (type)
   /* Convert in case a char is more than one unit.  */
   t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), 
                     size_int (BITS_PER_UNIT));
+  t = convert (sizetype, t);
   force_fit_type (t, 0);
   return t;
 }
@@ -924,7 +926,7 @@ 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);
@@ -954,16 +956,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)
@@ -1021,11 +1023,30 @@ 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)))
+    {
+      tree width = DECL_SIZE (TREE_OPERAND (exp, 1));
+      HOST_WIDE_INT low = TREE_INT_CST_LOW (width);
+
+      /* If it's thinner than an int, promote it like a
+        C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone.  */
+
+      if (low < TYPE_PRECISION (integer_type_node))
+       {
+         if (flag_traditional && TREE_UNSIGNED (type))
+           return convert (unsigned_type_node, exp);
+         else
+           return convert (integer_type_node, exp);
+       }
+    }
+
   if (C_PROMOTING_INTEGER_TYPE_P (type))
     {
       /* Traditionally, unsignedness is preserved in default promotions.
@@ -1080,7 +1101,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");
@@ -1138,8 +1159,6 @@ lookup_field (type, component, indirect)
       top = TYPE_LANG_SPECIFIC (type)->len;
       while (top - bot > 1)
        {
-         HOST_WIDE_INT cmp;
-
          half = (top - bot + 1) >> 1;
          field = field_array[bot+half];
 
@@ -1148,10 +1167,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;
@@ -1167,10 +1189,9 @@ lookup_field (type, component, indirect)
              continue;
            }
 
-         cmp = (HOST_WIDE_INT) DECL_NAME (field) - (HOST_WIDE_INT) component;
-         if (cmp == 0)
+         if (DECL_NAME (field) == component)
            break;
-         if (cmp < 0)
+         if (DECL_NAME (field) < component)
            bot += half;
          else
            top = bot + half;
@@ -1188,7 +1209,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;
@@ -1232,6 +1258,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.  */
@@ -1318,7 +1347,7 @@ build_indirect_ref (ptr, errorstring)
              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,
@@ -1452,6 +1481,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)
       {
@@ -1463,7 +1500,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;
@@ -1554,6 +1592,8 @@ build_function_call (function, params)
        if (coerced_params == 0)
          return integer_zero_node;
        return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
+      default:
+       break;
       }
 
   {
@@ -1721,7 +1761,7 @@ 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
@@ -1810,6 +1850,9 @@ parser_build_binary_op (code, arg1, arg2)
              || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of |");
+         /* Check cases like x|y==z */
+         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+           warning ("suggest parentheses around comparison in operand of |");
        }
 
       if (code == BIT_XOR_EXPR)
@@ -1819,6 +1862,9 @@ parser_build_binary_op (code, arg1, arg2)
              || code2 == BIT_AND_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around arithmetic in operand of ^");
+         /* Check cases like x^y==z */
+         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+           warning ("suggest parentheses around comparison in operand of ^");
        }
 
       if (code == BIT_AND_EXPR)
@@ -1826,6 +1872,9 @@ parser_build_binary_op (code, arg1, arg2)
          if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
            warning ("suggest parentheses around + or - in operand of &");
+         /* Check cases like x&y==z */
+         if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+           warning ("suggest parentheses around comparison in operand of &");
        }
     }
 
@@ -2087,7 +2136,7 @@ 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");
@@ -2119,7 +2168,7 @@ 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");
@@ -2147,7 +2196,7 @@ 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");
@@ -2305,6 +2354,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            pedwarn ("comparison between pointer and integer");
        }
       break;
+      
+    default:
+      break;
     }
 
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
@@ -2449,7 +2501,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          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));
@@ -2491,9 +2544,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
                  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))
+                           && 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))))))
+                              && int_fits_type_p (xop0, signed_type (result_type)))))
                /* OK */;
              else
                warning ("comparison between signed and unsigned");
@@ -2635,7 +2688,13 @@ pointer_int_sum (resultcode, ptrop, intop)
       && TREE_CONSTANT (size_exp)
       /* If the constant comes from pointer subtraction,
         skip this optimization--it would cause an error.  */
-      && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE)
+      && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
+      /* If the constant is unsigned, and smaller than the pointer size,
+        then we must skip this optimization.  This is because it could cause
+        an overflow error if the constant is negative but INTOP is not.  */
+      && (! TREE_UNSIGNED (TREE_TYPE (intop))
+         || (TYPE_PRECISION (TREE_TYPE (intop))
+             == TYPE_PRECISION (TREE_TYPE (ptrop)))))
     {
       enum tree_code subcode = resultcode;
       tree int_type = TREE_TYPE (intop);
@@ -2649,11 +2708,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
@@ -2694,10 +2755,12 @@ 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)
     error ("arithmetic on pointer to an incomplete type");
@@ -3042,7 +3105,7 @@ 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)));
@@ -3073,6 +3136,9 @@ build_unary_op (code, xarg, noconvert)
          TREE_CONSTANT (addr) = 1;
        return addr;
       }
+
+    default:
+      break;
     }
 
   if (!errstring)
@@ -3141,12 +3207,16 @@ 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;
@@ -3178,7 +3248,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);
     }
@@ -3187,6 +3262,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),
@@ -3259,8 +3337,17 @@ mark_addressable (exp)
   while (1)
     switch (TREE_CODE (x))
       {
-      case ADDR_EXPR:
       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;
+         }
+
+       /* ... fall through ...  */
+
+      case ADDR_EXPR:
       case ARRAY_REF:
       case REALPART_EXPR:
       case IMAGPART_EXPR:
@@ -3338,15 +3425,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.  */
@@ -3693,11 +3771,18 @@ 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)))
+         /* Go to the innermost object being pointed to.  */
+         tree in_type = type;
+         tree in_otype = otype;
+
+         while (TREE_CODE (in_type) == POINTER_TYPE)
+           in_type = TREE_TYPE (in_type);
+         while (TREE_CODE (in_otype) == POINTER_TYPE)
+           in_otype = TREE_TYPE (in_otype);
+           
+         if (TYPE_VOLATILE (in_otype) && ! TYPE_VOLATILE (in_type))
            pedwarn ("cast discards `volatile' from pointer target type");
-         if (TYPE_READONLY (TREE_TYPE (otype))
-             && ! TYPE_READONLY (TREE_TYPE (type)))
+         if (TYPE_READONLY (in_otype) && ! TYPE_READONLY (in_type))
            pedwarn ("cast discards `const' from pointer target type");
        }
 
@@ -3707,6 +3792,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");
 
@@ -3823,6 +3913,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
@@ -3864,6 +3956,9 @@ 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.
@@ -3986,26 +4081,27 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
          || 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);
 
-         else if (coder == POINTER_TYPE
-                  && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
+         if (comptypes (TYPE_MAIN_VARIANT (memb_type),
+                        TYPE_MAIN_VARIANT (rhstype)))
+           break;
+
+         if (TREE_CODE (memb_type) != POINTER_TYPE)
+           continue;
+
+         if (coder == POINTER_TYPE)
            {
-             tree memb_type = TREE_TYPE (memb_types);
              register tree ttl = TREE_TYPE (memb_type);
              register tree ttr = TREE_TYPE (rhstype);
 
@@ -4017,50 +4113,76 @@ 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 ((TREE_CODE (ttr) == FUNCTION_TYPE
+                      && TREE_CODE (ttl) == FUNCTION_TYPE)
+                     ? ((! TYPE_READONLY (ttl) | TYPE_READONLY (ttr))
+                        & (! TYPE_VOLATILE (ttl) | TYPE_VOLATILE (ttr)))
+                     : ((TYPE_READONLY (ttl) | ! TYPE_READONLY (ttr))
+                        & (TYPE_VOLATILE (ttl) | ! TYPE_VOLATILE (ttr))))
+                   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_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);
+               }
+             else
+               {
+                 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);
+               }
+           }
+         
+         if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
+           pedwarn ("ANSI C prohibits argument conversion to union type");
+
+         return build1 (NOP_EXPR, type, rhs);
        }
     }
 
@@ -4242,7 +4364,8 @@ initializer_constant_valid_p (value, endtype)
     case CONSTRUCTOR:
       if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
           || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
-         && TREE_CONSTANT (value))
+         && TREE_CONSTANT (value)
+         && CONSTRUCTOR_ELTS (value))
        return
          initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
                                        endtype);
@@ -4349,9 +4472,10 @@ initializer_constant_valid_p (value, endtype)
          return null_pointer_node;
        return 0;
       }
-    }
 
-  return 0;
+    default:
+      return 0;
+    }
 }
 
 /* If VALUE is a compound expr all of whose expressions are constant, then
@@ -4572,7 +4696,7 @@ print_spelling (buffer)
       {
        if (p->kind == SPELLING_MEMBER)
          *d++ = '.';
-       for (s = p->u.s; *d = *s++; d++)
+       for (s = p->u.s; (*d = *s++); d++)
          ;
       }
   *d++ = '\0';
@@ -4875,7 +4999,7 @@ digest_init (type, init, require_constant, constructor_constant)
      and it initializes the first element of x to 0.  */
   if (flag_traditional)
     {
-      tree top = 0, prev = 0;
+      tree top = 0, prev = 0, otype = type;
       while (TREE_CODE (type) == RECORD_TYPE
             || TREE_CODE (type) == ARRAY_TYPE
             || TREE_CODE (type) == QUAL_UNION_TYPE
@@ -4897,11 +5021,17 @@ digest_init (type, init, require_constant, constructor_constant)
              return error_mark_node;
            }
        }
-      TREE_OPERAND (prev, 1)
-       = build_tree_list (NULL_TREE,
-                          digest_init (type, init, require_constant,
-                                       constructor_constant));
-      return top;
+
+      if (otype != type)
+       {
+         TREE_OPERAND (prev, 1)
+           = build_tree_list (NULL_TREE,
+                              digest_init (type, init, require_constant,
+                                           constructor_constant));
+         return top;
+       }
+      else
+       return error_mark_node;
     }
   error_init ("invalid initializer%s", " for `%s'", NULL);
   return error_mark_node;
@@ -4960,20 +5090,29 @@ 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;
+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;
@@ -4993,9 +5132,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
@@ -5014,7 +5150,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.  */
@@ -5212,12 +5348,13 @@ really_start_incremental_init (type)
       || TREE_CODE (constructor_type) == UNION_TYPE)
     {
       constructor_fields = TYPE_FIELDS (constructor_type);
-      /* Skip any nameless bit fields atthe beginning.  */
-      while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+      /* Skip any nameless bit fields at the beginning.  */
+      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);
+      TREE_TYPE (constructor_bit_index) = sbitsizetype;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
@@ -5286,23 +5423,32 @@ 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);
+         /* By using unsigned arithmetic, the result will be correct even
+            in case of overflows, if BITS_PER_UNIT is a power of two.  */
+         unsigned next = (TREE_INT_CST_LOW
+                          (DECL_FIELD_BITPOS (constructor_fields))
+                          / (unsigned)BITS_PER_UNIT);
+         unsigned here = (TREE_INT_CST_LOW (constructor_bit_index)
+                          / (unsigned)BITS_PER_UNIT);
+
+         assemble_zeros ((next - here)
+                         * (unsigned)BITS_PER_UNIT
+                         / (unsigned)BITS_PER_UNIT);
        }
+      /* 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));
@@ -5384,12 +5530,13 @@ push_init_level (implicit)
           || TREE_CODE (constructor_type) == UNION_TYPE)
     {
       constructor_fields = TYPE_FIELDS (constructor_type);
-      /* Skip any nameless bit fields atthe beginning.  */
-      while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+      /* Skip any nameless bit fields at the beginning.  */
+      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);
+      TREE_TYPE (constructor_bit_index) = sbitsizetype;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
@@ -5427,7 +5574,7 @@ check_init_type_bitfields (type)
       for (tail = TYPE_FIELDS (type); tail;
           tail = TREE_CHAIN (tail))
        {
-         if (DECL_BIT_FIELD (tail)
+         if (DECL_C_BIT_FIELD (tail)
              /* This catches cases like `int foo : 8;'.  */
              || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
            {
@@ -5689,14 +5836,14 @@ set_init_index (first, last)
     error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
     error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+  else if (! constructor_unfilled_index)
+    error_init ("array index in non-array initializer%s", " for `%s'", NULL);
   else if (tree_int_cst_lt (first, constructor_unfilled_index))
     error_init ("duplicate array index in initializer%s", " for `%s'", NULL);
   else
     {
-      TREE_INT_CST_LOW (constructor_index)
-       = TREE_INT_CST_LOW (first);
-      TREE_INT_CST_HIGH (constructor_index)
-       = TREE_INT_CST_HIGH (first);
+      TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (first);
+      TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (first);
 
       if (last != 0 && tree_int_cst_lt (last, first))
        error_init ("empty index range in initializer%s", " for `%s'", NULL);
@@ -5718,6 +5865,11 @@ set_init_label (fieldname)
   tree tail;
   int passed = 0;
 
+  /* Don't die if an entire brace-pair level is superfluous
+     in the containing level.  */
+  if (constructor_type == 0)
+    return;
+
   for (tail = TYPE_FIELDS (constructor_type); tail;
        tail = TREE_CHAIN (tail))
     {
@@ -5741,6 +5893,251 @@ 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 (tree_int_cst_lt (p->purpose, purpose))
+           q = &p->right;
+         else
+           abort ();
+       }
+    }
+  else
+    {
+      while (*q != NULL)
+       {
+         p = *q;
+         if (tree_int_cst_lt (DECL_FIELD_BITPOS (purpose),
+                              DECL_FIELD_BITPOS (p->purpose)))
+           q = &p->left;
+         else if (tree_int_cst_lt (DECL_FIELD_BITPOS (p->purpose),
+                                   DECL_FIELD_BITPOS (purpose)))
+           q = &p->right;
+         else
+           abort ();
+       }
+    }
+
+  r = (struct init_node *) oballoc (sizeof (struct init_node));
+  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 (tree_int_cst_equal (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 (DECL_FIELD_BITPOS (field),
+                                   DECL_FIELD_BITPOS (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.
@@ -5774,7 +6171,8 @@ 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))
@@ -5798,25 +6196,10 @@ 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);
              duplicate = 1;
@@ -5832,11 +6215,9 @@ output_init_element (value, type, field, pending)
       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 (copy_node (field),
+                         digest_init (type, value, require_constant_value, 
+                                      require_constant_elements));
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
           && field != constructor_unfilled_fields)
@@ -5845,11 +6226,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
     {
@@ -5878,12 +6257,19 @@ output_init_element (value, type, field, pending)
                  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);
-
-                     assemble_zeros (next - here);
+                     /* By using unsigned arithmetic, the result will be
+                        correct even in case of overflows, if BITS_PER_UNIT
+                        is a power of two.  */
+                     unsigned next = (TREE_INT_CST_LOW
+                                      (DECL_FIELD_BITPOS (field))
+                                      / (unsigned)BITS_PER_UNIT);
+                     unsigned here = (TREE_INT_CST_LOW
+                                      (constructor_bit_index)
+                                      / (unsigned)BITS_PER_UNIT);
+
+                     assemble_zeros ((next - here)
+                                     * (unsigned)BITS_PER_UNIT
+                                     / (unsigned)BITS_PER_UNIT);
                    }
                }
              output_constant (digest_init (type, value,
@@ -5942,56 +6328,109 @@ 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 (DECL_FIELD_BITPOS (constructor_unfilled_fields),
+                                   DECL_FIELD_BITPOS (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 (DECL_FIELD_BITPOS (constructor_unfilled_fields),
+                                         DECL_FIELD_BITPOS (elt->purpose)))
+                   {
+                     next = elt->purpose;
+                     break;
+                   }
+               }
+           }
        }
     }
 
@@ -6009,6 +6448,7 @@ output_pending_init_elements (all)
       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))
@@ -6074,6 +6514,8 @@ output_pending_init_elements (all)
        }
     }
 
+  /* ELT now points to the node in the pending tree with the next
+     initializer to output.  */
   goto retry;
 }
 \f
@@ -6131,7 +6573,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 +6641,9 @@ process_init_element (value)
            }
 
          constructor_fields = TREE_CHAIN (constructor_fields);
-         /* Skip any nameless bit fields atthe beginning.  */
-         while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+         /* Skip any nameless bit fields at the beginning.  */
+         while (constructor_fields != 0
+                && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
            constructor_fields = TREE_CHAIN (constructor_fields);
          break;
@@ -6290,9 +6735,23 @@ process_init_element (value)
              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%s",
+                               " after `%s'", NULL_PTR);
+                 TREE_INT_CST_HIGH (constructor_range_end)
+                   = TREE_INT_CST_HIGH (constructor_max_index);
+                 TREE_INT_CST_LOW (constructor_range_end)
+                   = TREE_INT_CST_LOW (constructor_max_index);
+               }
+
+             value = save_expr (value);
+           }
 
          /* Now output the actual element.
             Ordinarily, output once.
@@ -6310,10 +6769,8 @@ process_init_element (value)
 
              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);
+             TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (tem);
+             TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (tem);
 
              if (!value)
                /* If we are doing the bookkeeping for an element that was
@@ -6413,7 +6870,8 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
       else
        {
          tree type = TREE_TYPE (o[i]);
-         if (TYPE_READONLY (type)
+         if (TREE_READONLY (o[i])
+             || TYPE_READONLY (type)
              || ((TREE_CODE (type) == RECORD_TYPE
                   || TREE_CODE (type) == UNION_TYPE)
                  && C_TYPE_FIELDS_READONLY (type)))
@@ -6507,6 +6965,9 @@ c_expand_return (retval)
                  && DECL_CONTEXT (inner) == current_function_decl)
                warning ("function returns address of local variable");
              break;
+
+           default:
+             break;
            }
 
          break;