OSDN Git Service

Fix mips64vr4100-elf build failure.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 412f3c3..f8f0705 100644 (file)
@@ -1,5 +1,5 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 91-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file is part of the C front end.
@@ -28,19 +29,20 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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));
@@ -69,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.)  */
@@ -178,6 +182,7 @@ common_type (t1, t2)
 {
   register enum tree_code code1;
   register enum tree_code code2;
+  tree attributes;
 
   /* Save time if the two types are the same.  */
 
@@ -189,6 +194,9 @@ common_type (t1, t2)
   if (t2 == error_mark_node)
     return t1;
 
+  /* Merge the attributes.  */
+  attributes = merge_machine_type_attributes (t1, t2);
+
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
   if (TREE_CODE (t1) == ENUMERAL_TYPE)
@@ -209,11 +217,12 @@ common_type (t1, t2)
       tree subtype = common_type (subtype1, subtype2);
 
       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
-       return t1;
+       return build_type_attribute_variant (t1, attributes);
       else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
-       return t2;
+       return build_type_attribute_variant (t2, attributes);
       else
-       return build_complex_type (subtype);
+       return build_type_attribute_variant (build_complex_type (subtype),
+                                            attributes);
     }
 
   switch (code1)
@@ -223,23 +232,24 @@ common_type (t1, t2)
       /* If only one is real, use it as the result.  */
 
       if (code1 == REAL_TYPE && code2 != REAL_TYPE)
-       return t1;
+       return build_type_attribute_variant (t1, attributes);
 
       if (code2 == REAL_TYPE && code1 != REAL_TYPE)
-       return t2;
+       return build_type_attribute_variant (t2, attributes);
 
       /* Both real or both integers; use the one with greater precision.  */
 
       if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
-       return t1;
+       return build_type_attribute_variant (t1, attributes);
       else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
-       return t2;
+       return build_type_attribute_variant (t2, attributes);
 
       /* Same precision.  Prefer longs to ints even when same size.  */
 
       if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
          || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
-       return long_unsigned_type_node;
+       return build_type_attribute_variant (long_unsigned_type_node,
+                                            attributes);
 
       if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
          || TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
@@ -247,15 +257,24 @@ common_type (t1, t2)
          /* But preserve unsignedness from the other type,
             since long cannot hold all the values of an unsigned int.  */
          if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
-           return long_unsigned_type_node;
-         return long_integer_type_node;
+            t1 = long_unsigned_type_node;
+         else
+            t1 = long_integer_type_node;
+         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))
-       return t1;
-      else return t2;
+       return build_type_attribute_variant (t1, attributes);
+      else
+       return build_type_attribute_variant (t2, attributes);
 
     case POINTER_TYPE:
       /* For two pointers, do this recursively on the target type,
@@ -270,10 +289,13 @@ common_type (t1, t2)
          = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
        int volatilep
          = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
-       return build_pointer_type (c_build_type_variant (target, constp, volatilep));
+       t1 = build_pointer_type (c_build_type_variant (target, constp,
+                                volatilep));
+       return build_type_attribute_variant (t1, attributes);
       }
 #if 0
-      return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
+      t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
+      return build_type_attribute_variant (t1, attributes);
 #endif
 
     case ARRAY_TYPE:
@@ -281,11 +303,12 @@ common_type (t1, t2)
        tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
-         return t1;
+         return build_type_attribute_variant (t1, attributes);
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
-         return t2;
+         return build_type_attribute_variant (t2, attributes);
        /* Merge the element types, and have a size if either arg has one.  */
-       return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+       return build_type_attribute_variant (t1, attributes);
       }
 
     case FUNCTION_TYPE:
@@ -301,15 +324,21 @@ common_type (t1, t2)
 
        /* Save space: see if the result is identical to one of the args.  */
        if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2))
-         return t1;
+         return build_type_attribute_variant (t1, attributes);
        if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))
-         return t2;
+         return build_type_attribute_variant (t2, attributes);
 
        /* Simple way if one arg fails to specify argument types.  */
        if (TYPE_ARG_TYPES (t1) == 0)
-         return build_function_type (valtype, TYPE_ARG_TYPES (t2));
+        {
+          t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
+          return build_type_attribute_variant (t1, attributes);
+        }
        if (TYPE_ARG_TYPES (t2) == 0)
-         return build_function_type (valtype, TYPE_ARG_TYPES (t1));
+        {
+          t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
+          return build_type_attribute_variant (t1, attributes);
+        }
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
@@ -373,11 +402,12 @@ common_type (t1, t2)
          parm_done: ;
          }
 
-       return build_function_type (valtype, newargs);
+       t1 = build_function_type (valtype, newargs);
+       /* ... falls through ...  */
       }
 
     default:
-      return t1;
+      return build_type_attribute_variant (t1, attributes);
     }
 
 }
@@ -392,18 +422,21 @@ comptypes (type1, type2)
 {
   register tree t1 = type1;
   register tree t2 = type2;
+  int attrval, val;
 
   /* 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 unsigned integer type of the same width.  */
+  /* Treat an enum type as the integer type of the same width and 
+     signedness.  */
 
   if (TREE_CODE (t1) == ENUMERAL_TYPE)
-    t1 = type_for_size (TYPE_PRECISION (t1), 1);
+    t1 = type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
   if (TREE_CODE (t2) == ENUMERAL_TYPE)
-    t2 = type_for_size (TYPE_PRECISION (t2), 1);
+    t2 = type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
 
   if (t1 == t2)
     return 1;
@@ -421,26 +454,38 @@ 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;
 
+#ifndef COMP_TYPE_ATTRIBUTES
+#define COMP_TYPE_ATTRIBUTES(t1,t2)    1
+#endif
+
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+     return 0;
+
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  val = 0;
+
   switch (TREE_CODE (t1))
     {
     case POINTER_TYPE:
-      return (TREE_TYPE (t1) == TREE_TYPE (t2)
+      val = (TREE_TYPE (t1) == TREE_TYPE (t2)
              ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
+      break;
 
     case FUNCTION_TYPE:
-      return function_types_compatible_p (t1, t2);
+      val = function_types_compatible_p (t1, t2);
+      break;
 
     case ARRAY_TYPE:
       {
-       /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-       int val = 1;
        tree d1 = TYPE_DOMAIN (t1);
        tree d2 = TYPE_DOMAIN (t2);
+       val = 1;
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
@@ -453,24 +498,29 @@ comptypes (type1, type2)
            || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
            || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
            || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
-         return val;
+         break;
 
-       return (((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
+       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);
+                    == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))))
+          val = 0;
+        break;
       }
 
     case RECORD_TYPE:
       if (maybe_objc_comptypes (t1, t2, 0) == 1)
-       return 1;
+       val = 1;
+      break;
+
+    default:
+      break;
     }
-  return 0;
+  return attrval == 2 && val == 1 ? 2 : val;
 }
 
 /* Return 1 if TTL and TTR are pointers to types that are equivalent,
@@ -483,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)),
@@ -588,7 +638,8 @@ type_lists_compatible_p (args1, args2)
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
-             && TYPE_NAME (TREE_VALUE (args1)) == 0
+             && (TYPE_NAME (TREE_VALUE (args1)) == 0
+                 || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1)))
              && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST
              && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)),
                                     TYPE_SIZE (TREE_VALUE (args2))))
@@ -602,7 +653,8 @@ type_lists_compatible_p (args1, args2)
                return 0;
            }
          else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
-                  && TYPE_NAME (TREE_VALUE (args2)) == 0
+                  && (TYPE_NAME (TREE_VALUE (args2)) == 0
+                      || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2)))
                   && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST
                   && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)),
                                          TYPE_SIZE (TREE_VALUE (args1))))
@@ -687,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.  */
@@ -707,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
@@ -718,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;
@@ -766,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;
@@ -789,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;
 }
@@ -817,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;
 }
@@ -852,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);
@@ -882,18 +956,19 @@ 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)
       && DECL_INITIAL (decl) != 0
       && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
       /* This is invalid if initial value is not constant.
@@ -922,13 +997,11 @@ default_conversion (exp)
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
     exp = DECL_INITIAL (exp);
-  /* Replace a nonvolatile const static variable with its value.  */
-  else if (optimize
-          && TREE_CODE (exp) == VAR_DECL
-          && TREE_READONLY (exp)
-          /* But not for iterators!  */
-          && !ITERATOR_P (exp)
-          && DECL_MODE (exp) != BLKmode)
+
+  /* Replace a nonvolatile const static variable with its value unless
+     it is an array, in which case we must be sure that taking the
+     address of the array produces consistent results.  */
+  else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
     {
       exp = decl_constant_value (exp);
       type = TREE_TYPE (exp);
@@ -950,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.
@@ -1009,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");
@@ -1067,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];
 
@@ -1077,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;
@@ -1096,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;
@@ -1117,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;
@@ -1161,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.  */
@@ -1247,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,
@@ -1381,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)
       {
@@ -1392,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;
@@ -1483,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;
       }
 
   {
@@ -1567,49 +1678,28 @@ convert_arguments (typelist, values, name, fundecl)
            }
          else
            {
-             tree parmname;
-             tree type0 = type;
-#ifdef PROMOTE_PROTOTYPES
-             /* Rather than truncating and then reextending,
-                convert directly to int, if that's the type we will want.  */
-             if (! flag_traditional
-                 && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE)
-                 && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-               type = integer_type_node;
-#endif
-
-#if 0 /* This turns out not to win--there's no way to write a prototype
-        for a function whose arg type is a union with no tag.  */
-             /* Nameless union automatically casts the types it contains.  */
-             if (TREE_CODE (type) == UNION_TYPE && TYPE_NAME (type) == 0)
-               {
-                 tree field;
-
-                 for (field = TYPE_FIELDS (type); field;
-                      field = TREE_CHAIN (field))
-                   if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-                                  TYPE_MAIN_VARIANT (TREE_TYPE (val))))
-                     break;
-
-                 if (field)
-                   val = build1 (CONVERT_EXPR, type, val);
-               }
-#endif
-
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
              if (warn_conversion)
                {
                  int formal_prec = TYPE_PRECISION (type);
 
-                 if (TREE_CODE (type) != REAL_TYPE
+                 if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
                    warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
+                 else if (TREE_CODE (type) == COMPLEX_TYPE
+                          && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
+                   warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
                  else if (TREE_CODE (type) == REAL_TYPE
-                     && TREE_CODE (TREE_TYPE (val)) != REAL_TYPE)
+                          && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
                  else if (TREE_CODE (type) == REAL_TYPE
+                          && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
+                   warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
+                 /* ??? At some point, messages should be written about
+                    conversions between complex types, but that's too messy
+                    to do now.  */
+                 else if (TREE_CODE (type) == REAL_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
                    {
                      /* Warn if any argument is passed as `float',
@@ -1618,10 +1708,8 @@ convert_arguments (typelist, values, name, fundecl)
                        warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
                    }
                  /* Detect integer changing in width or signedness.  */
-                 else if ((TREE_CODE (type) == INTEGER_TYPE
-                           || TREE_CODE (type) == ENUMERAL_TYPE)
-                          && (TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
-                              || TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE))
+                 else if (INTEGRAL_TYPE_P (type)
+                          && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    {
                      tree would_have_been = default_conversion (val);
                      tree type1 = TREE_TYPE (would_have_been);
@@ -1673,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
@@ -1762,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)
@@ -1771,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)
@@ -1778,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 &");
        }
     }
 
@@ -1851,8 +1948,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
      Zero means they need to be converted to RESULT_TYPE.  */
   int converted = 0;
 
+  /* Nonzero means create the expression with this type, rather than
+     RESULT_TYPE.  */
+  tree build_type = 0;
+
   /* Nonzero means after finally constructing the expression
-     give it this type.  Otherwise, give it type RESULT_TYPE.  */
+     convert it to this type.  */
   tree final_type = 0;
 
   /* Nonzero if this is an operation like MIN or MAX which can
@@ -2035,9 +2136,9 @@ 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_lt (op1, integer_zero_node))
+             if (tree_int_cst_sgn (op1) < 0)
                warning ("right shift count is negative");
              else
                {
@@ -2067,9 +2168,9 @@ 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_lt (op1, integer_zero_node))
+             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)
@@ -2095,9 +2196,9 @@ 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_lt (op1, integer_zero_node))
+             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)
@@ -2123,8 +2224,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case NE_EXPR:
       /* Result of comparison is always int,
         but don't convert the args to int!  */
-      result_type = integer_type_node;
-      converted = 1;
+      build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -2138,7 +2238,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          if (comp_target_types (type0, type1))
-           ;
+           result_type = common_type (type0, type1);
          else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
            {
              /* op0 != orig_op0 detects the case of something
@@ -2155,29 +2255,28 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            }
          else
            pedwarn ("comparison of distinct pointer types lacks a cast");
+
+         if (result_type == NULL_TREE)
+           result_type = ptr_type_node;
        }
       else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
               && integer_zerop (op1))
-       op1 = null_pointer_node;
+       result_type = type0;
       else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
               && integer_zerop (op0))
-       op0 = null_pointer_node;
+       result_type = type1;
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
+         result_type = type0;
          if (! flag_traditional)
            pedwarn ("comparison between pointer and integer");
-         op1 = convert (TREE_TYPE (op0), op1);
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
+         result_type = type1;
          if (! flag_traditional)
            pedwarn ("comparison between pointer and integer");
-         op0 = convert (TREE_TYPE (op1), op0);
        }
-      else
-       /* If args are not valid, clear out RESULT_TYPE
-          to cause an error message later.  */
-       result_type = 0;
       break;
 
     case MAX_EXPR:
@@ -2187,12 +2286,18 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
        shorten = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (! comp_target_types (type0, type1))
-           pedwarn ("comparison of distinct pointer types lacks a cast");
-         else if (pedantic 
-                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
-         result_type = common_type (type0, type1);
+         if (comp_target_types (type0, type1))
+           {
+             result_type = common_type (type0, type1);
+             if (pedantic 
+                 && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
+               pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+           }
+         else
+           {
+             result_type = ptr_type_node;
+             pedwarn ("comparison of distinct pointer types lacks a cast");
+           }
        }
       break;
 
@@ -2200,52 +2305,57 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+      build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (! comp_target_types (type0, type1))
-           pedwarn ("comparison of distinct pointer types lacks a cast");
-         else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
-                  != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
-           pedwarn ("comparison of complete and incomplete pointers");
-         else if (pedantic 
-                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
-         result_type = integer_type_node;
+         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))
+               pedwarn ("comparison of complete and incomplete pointers");
+             else if (pedantic 
+                      && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
+               pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+           }
+         else
+           {
+             result_type = ptr_type_node;
+             pedwarn ("comparison of distinct pointer types lacks a cast");
+           }
        }
       else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
               && integer_zerop (op1))
        {
-         result_type = integer_type_node;
-         op1 = null_pointer_node;
-         if (pedantic)
+         result_type = type0;
+         if (pedantic || extra_warnings)
            pedwarn ("ordered comparison of pointer with integer zero");
        }
       else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
               && integer_zerop (op0))
        {
-         result_type = integer_type_node;
-         op0 = null_pointer_node;
+         result_type = type1;
          if (pedantic)
            pedwarn ("ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         result_type = integer_type_node;
+         result_type = type0;
          if (! flag_traditional)
            pedwarn ("comparison between pointer and integer");
-         op1 = convert (TREE_TYPE (op0), op1);
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
-         result_type = integer_type_node;
+         result_type = type1;
          if (! flag_traditional)
            pedwarn ("comparison between pointer and integer");
-         op0 = convert (TREE_TYPE (op1), op0);
        }
-      converted = 1;
+      break;
+      
+    default:
       break;
     }
 
@@ -2346,6 +2456,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
 
          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)
              /* 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
@@ -2383,43 +2497,114 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
            = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
          if (val != 0)
            return val;
-         op0 = xop0, op1 = xop1, result_type = xresult_type;
+         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)
            {
-             tree op0_type = TREE_TYPE (orig_op0);
-             tree op1_type = TREE_TYPE (orig_op1);
-             int op0_unsigned = TREE_UNSIGNED (op0_type);
-             int op1_unsigned = TREE_UNSIGNED (op1_type);
+             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 will fail.  Do not warn if the signed quantity
-                is an unsuffixed integer literal (or some static constant
-                expression involving such literals) and it is positive.
-                Do not warn if the width of the unsigned quantity is less
-                than that of the signed quantity, since in this case all
-                values of the unsigned quantity fit in the signed quantity.
-                Do not warn if the signed type is the same size as the
-                result_type since sign extension does not cause trouble in
-                this case.  */
+                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.  */
-             if (op0_unsigned != op1_unsigned
-                 && ((op0_unsigned
-                      && TYPE_PRECISION (op0_type) >= TYPE_PRECISION (op1_type)
-                      && TYPE_PRECISION (op0_type) < TYPE_PRECISION (result_type)
-                      && (TREE_CODE (op1) != INTEGER_CST
-                          || (TREE_CODE (op1) == INTEGER_CST
-                              && INT_CST_LT (op1, integer_zero_node))))
-                     ||
-                     (op1_unsigned
-                      && TYPE_PRECISION (op1_type) >= TYPE_PRECISION (op0_type)
-                      && TYPE_PRECISION (op1_type) < TYPE_PRECISION (result_type)
-                      && (TREE_CODE (op0) != INTEGER_CST
-                          || (TREE_CODE (op0) == INTEGER_CST
-                              && INT_CST_LT (op0, integer_zero_node))))))
+
+             /* 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.  */
+              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");
+
+             /* Warn if two unsigned values are being compared in a size
+                larger than their original size, and one (and only one) is the
+                result of a `~' operator.  This comparison will always fail.
+
+                Also warn if one operand is a constant, and the constant
+                does not have all bits set that are set in the ~ operand
+                when it is extended.  */
+
+             if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
+                 != (TREE_CODE (primop1) == BIT_NOT_EXPR))
+               {
+                 if (TREE_CODE (primop0) == BIT_NOT_EXPR)
+                   primop0 = get_narrower (TREE_OPERAND (primop0, 0),
+                                           &unsignedp0);
+                 else
+                   primop1 = get_narrower (TREE_OPERAND (primop1, 0),
+                                           &unsignedp1);
+             
+                 if (TREE_CODE (primop0) == INTEGER_CST
+                     || TREE_CODE (primop1) == INTEGER_CST)
+                   {
+                     tree primop;
+                     long constant, mask;
+                     int unsignedp, bits;
+
+                     if (TREE_CODE (primop0) == INTEGER_CST)
+                       {
+                         primop = primop1;
+                         unsignedp = unsignedp1;
+                         constant = TREE_INT_CST_LOW (primop0);
+                       }
+                     else
+                       {
+                         primop = primop0;
+                         unsignedp = unsignedp0;
+                         constant = TREE_INT_CST_LOW (primop1);
+                       }
+
+                     bits = TYPE_PRECISION (TREE_TYPE (primop));
+                     if (bits < TYPE_PRECISION (result_type)
+                         && bits < HOST_BITS_PER_LONG && unsignedp)
+                       {
+                         mask = (~0L) << bits;
+                         if ((mask & constant) != mask)
+                           warning ("comparison of promoted ~unsigned with constant");
+                       }
+                   }
+                 else if (unsignedp0 && unsignedp1
+                          && (TYPE_PRECISION (TREE_TYPE (primop0))
+                              < TYPE_PRECISION (result_type))
+                          && (TYPE_PRECISION (TREE_TYPE (primop1))
+                              < TYPE_PRECISION (result_type)))
+                   warning ("comparison of promoted ~unsigned with unsigned");
+               }
            }
        }
     }
@@ -2444,8 +2629,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
        op1 = convert (result_type, op1); 
     }
 
+  if (build_type == NULL_TREE)
+    build_type = result_type;
+
   {
-    register tree result = build (resultcode, result_type, op0, op1);
+    register tree result = build (resultcode, build_type, op0, op1);
     register tree folded;
 
     folded = fold (result);
@@ -2500,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);
@@ -2514,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
@@ -2559,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");
@@ -2747,7 +2945,7 @@ build_unary_op (code, xarg, noconvert)
                       ((code == PREINCREMENT_EXPR
                         || code == POSTINCREMENT_EXPR)
                        ? "increment" : "decrement"));
-           inc = c_sizeof_nowarn (TREE_TYPE (result_type));
+           inc = c_size_in_bytes (TREE_TYPE (result_type));
          }
        else
          inc = integer_one_node;
@@ -2907,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)));
@@ -2938,6 +3136,9 @@ build_unary_op (code, xarg, noconvert)
          TREE_CONSTANT (addr) = 1;
        return addr;
       }
+
+    default:
+      break;
     }
 
   if (!errstring)
@@ -3006,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;
@@ -3043,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);
     }
@@ -3052,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),
@@ -3124,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:
@@ -3160,6 +3382,18 @@ mark_addressable (exp)
                       IDENTIFIER_POINTER (DECL_NAME (x)));
                return 0;
              }
+
+           /* If we are making this addressable due to its having
+              volatile components, give a different error message.  Also
+              handle the case of an unnamed parameter by not trying
+              to give the name.  */
+
+           else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
+             {
+               error ("cannot put object with volatile field into register");
+               return 0;
+             }
+
            pedwarn ("address of register variable `%s' requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
@@ -3191,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.  */
@@ -3421,10 +3646,28 @@ internal_build_compound_expr (list, first_p)
 
   rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
 
-  /* When pedantic, a compound expression can be neither an lvalue
-     nor an integer constant expression.  */
-  if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
-    return rest;
+  if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
+    {
+      /* The left-hand operand of a comma expression is like an expression
+         statement: with -W or -Wunused, we should warn if it doesn't have
+        any side-effects, unless it was explicitly cast to (void).  */
+      if ((extra_warnings || warn_unused)
+           && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
+                && TREE_TYPE (TREE_VALUE (list)) == void_type_node))
+        warning ("left-hand operand of comma expression has no effect");
+
+      /* When pedantic, a compound expression can be neither an lvalue
+         nor an integer constant expression.  */
+      if (! pedantic)
+        return rest;
+    }
+
+  /* With -Wunused, we should also warn if the left-hand operand does have
+     side-effects, but computes a value which is not used.  For example, in
+     `foo() + bar(), baz()' the result of the `+' operator is not used,
+     so we should issue a warning.  */
+  else if (warn_unused)
+    warn_if_unused_value (TREE_VALUE (list));
 
   return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
 }
@@ -3528,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");
        }
 
@@ -3542,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");
 
@@ -3551,6 +3806,11 @@ build_c_cast (type, expr)
          && !TREE_CONSTANT (value))
        warning ("cast from pointer to integer of different size");
 
+      if (warn_bad_function_cast
+         && TREE_CODE (value) == CALL_EXPR
+         && TREE_CODE (type) != TREE_CODE (otype))
+       warning ("cast does not match function type");
+
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
          && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
@@ -3653,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
@@ -3694,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.
@@ -3786,6 +4051,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
   if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
       || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
     rhs = default_conversion (rhs);
+  else if (optimize && TREE_CODE (rhs) == VAR_DECL)
+    rhs = decl_constant_value (rhs);
 
   rhstype = TREE_TYPE (rhs);
   coder = TREE_CODE (rhstype);
@@ -3810,71 +4077,115 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
   /* 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))
+      && (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);
-           }
-         else if (coder == POINTER_TYPE
-                  && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
+         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;
+
+         if (coder == POINTER_TYPE)
            {
-             tree memb_type = TREE_TYPE (memb_types);
              register tree ttl = TREE_TYPE (memb_type);
              register tree ttr = TREE_TYPE (rhstype);
 
              /* Any non-function converts to a [const][volatile] void *
                 and vice versa; otherwise, targets must be the same.
-                Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
+                Meanwhile, the lhs target must have all the qualifiers of
+                the rhs.  */
              if (TYPE_MAIN_VARIANT (ttl) == void_type_node
                  || 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.  */
+         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);
        }
     }
+
   /* Conversions among pointers */
   else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
     {
@@ -3904,7 +4215,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, 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)
+                  && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
                warn_for_assignment ("%s discards `const' from pointer target type",
@@ -3923,7 +4234,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                warn_for_assignment ("pointer targets in %s differ in signedness",
                                     get_spelling (errtype), funname, parmnum);
            }
-         else
+         else if (TREE_CODE (ttl) == FUNCTION_TYPE
+                  && TREE_CODE (ttr) == FUNCTION_TYPE)
            {
              /* Because const and volatile on functions are restrictions
                 that say the function will not do certain things,
@@ -4050,8 +4362,10 @@ initializer_constant_valid_p (value, endtype)
   switch (TREE_CODE (value))
     {
     case CONSTRUCTOR:
-      if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
-         && TREE_CONSTANT (value))
+      if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
+          || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
+         && TREE_CONSTANT (value)
+         && CONSTRUCTOR_ELTS (value))
        return
          initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
                                        endtype);
@@ -4076,17 +4390,21 @@ initializer_constant_valid_p (value, endtype)
       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
-         && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)),
-                                TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
+         && (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 integer types only if explicit value.  */
+
+      /* 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)
        {
@@ -4096,13 +4414,23 @@ initializer_constant_valid_p (value, endtype)
            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
-         && ! tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (value)),
-                               TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
+         && (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),
@@ -4144,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
@@ -4367,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';
@@ -4590,8 +4919,7 @@ digest_init (type, init, require_constant, constructor_constant)
          return error_mark_node;
        }
 
-      if (optimize && TREE_READONLY (inside_init)
-         && TREE_CODE (inside_init) == VAR_DECL)
+      if (optimize && TREE_CODE (inside_init) == VAR_DECL)
        inside_init = decl_constant_value (inside_init);
 
       /* Compound expressions can only occur here if -pedantic or
@@ -4671,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
@@ -4693,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;
@@ -4719,7 +5053,7 @@ static tree constructor_fields;
 static tree constructor_index;
 
 /* For an ARRAY_TYPE, this is the end index of the range
-   to intitialize with the next element, or NULL in the ordinary case
+   to initialize with the next element, or NULL in the ordinary case
    where the element is used just once.  */
 static tree constructor_range_end;
 
@@ -4756,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;
@@ -4789,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
@@ -4810,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.  */
@@ -5008,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)
     {
@@ -5082,23 +5423,32 @@ push_init_level (implicit)
        break;
     }
 
-  /* Structure elements may require alignment.  Do this now
-     if necessary for the subaggregate.  */
-  if (constructor_incremental && TREE_CODE (constructor_type) == RECORD_TYPE
-      && constructor_fields)
+  /* 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
+      && 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));
@@ -5143,12 +5493,19 @@ push_init_level (implicit)
        {
          constructor_type = TREE_TYPE (constructor_fields);
          push_member_name (constructor_fields);
+         constructor_depth++;
+         if (constructor_fields != constructor_unfilled_fields)
+           constructor_incremental = 0;
        }
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
       constructor_type = TREE_TYPE (constructor_type);
       push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+      constructor_depth++;
+      if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
+         || constructor_range_end != 0)
+       constructor_incremental = 0;
     }
 
   if (constructor_type == 0)
@@ -5173,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)
     {
@@ -5216,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)))
            {
@@ -5287,7 +5645,8 @@ pop_init_level (implicit)
          && constructor_incremental)
        {
          constructor = digest_init (constructor_type, constructor,
-                                    0, 0);
+                                    require_constant_value,
+                                    require_constant_elements);
 
          /* If initializing an array of unknown size,
             determine the size now.  */
@@ -5396,10 +5755,14 @@ pop_init_level (implicit)
              TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
              TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
 
+             /* TYPE_MAX_VALUE is always one less than the number of elements
+                in the array, because we start counting at zero.  Therefore,
+                warn only if the value is less than zero.  */
              if (pedantic
-                 && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)),
-                                     integer_zero_node))
-               error_with_decl (constructor_decl, "zero-size array `%s'");
+                 && (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 ();
@@ -5473,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);
@@ -5502,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))
     {
@@ -5525,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.
@@ -5555,7 +6168,11 @@ output_init_element (value, type, field, pending)
     constructor_erroneous = 1;
   else if (!TREE_CONSTANT (value))
     constructor_constant = 0;
-  else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
+  else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0
+          || ((TREE_CODE (constructor_type) == RECORD_TYPE
+               || TREE_CODE (constructor_type) == UNION_TYPE)
+              && DECL_C_BIT_FIELD (field)
+              && TREE_CODE (value) != INTEGER_CST))
     constructor_simple = 0;
 
   if (require_constant_value && ! TREE_CONSTANT (value))
@@ -5579,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;
@@ -5613,10 +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, 0, 0),
-                      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)
@@ -5625,10 +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, 0, 0),
-                      constructor_pending_elts);
+       add_pending_init (field,
+                         digest_init (type, value, require_constant_value, 
+                                      require_constant_elements));
     }
   else
     {
@@ -5642,7 +6242,9 @@ output_init_element (value, type, field, pending)
              if (field && TREE_CODE (field) == INTEGER_CST)
                field = copy_node (field);
              constructor_elements
-               = tree_cons (field, digest_init (type, value, 0, 0),
+               = tree_cons (field, digest_init (type, value,
+                                                require_constant_value, 
+                                                require_constant_elements),
                             constructor_elements);
            }
          else
@@ -5655,15 +6257,24 @@ 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, 0, 0),
+             output_constant (digest_init (type, value,
+                                           require_constant_value,
+                                           require_constant_elements),
                               int_size_in_bytes (type));
 
              /* For a record or union,
@@ -5717,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;
+                   }
+               }
+           }
        }
     }
 
@@ -5784,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))
@@ -5849,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
@@ -5906,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;
@@ -5926,7 +6595,9 @@ process_init_element (value)
              break;
            }
 
-         fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+         fieldtype = TREE_TYPE (constructor_fields);
+         if (fieldtype != error_mark_node)
+           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
          fieldcode = TREE_CODE (fieldtype);
 
          /* Accept a string constant to initialize a subarray.  */
@@ -5938,6 +6609,7 @@ process_init_element (value)
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
          else if (value != 0 && !constructor_no_implicit
+                  && value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
@@ -5969,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;
@@ -5987,7 +6660,9 @@ process_init_element (value)
              break;
            }
 
-         fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+         fieldtype = TREE_TYPE (constructor_fields);
+         if (fieldtype != error_mark_node)
+           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
          fieldcode = TREE_CODE (fieldtype);
 
          /* Accept a string constant to initialize a subarray.  */
@@ -5999,6 +6674,7 @@ process_init_element (value)
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
          else if (value != 0 && !constructor_no_implicit
+                  && value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
@@ -6042,6 +6718,7 @@ process_init_element (value)
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
          else if (value != 0 && !constructor_no_implicit
+                  && value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE))
@@ -6058,6 +6735,24 @@ process_init_element (value)
              break;
            }
 
+         /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once.  */
+         if (constructor_range_end)
+           {
+             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.
             If there is a range, repeat it till we advance past the range.  */
@@ -6074,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
@@ -6114,7 +6807,8 @@ process_init_element (value)
 
   /* 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)
+  if (constructor_incremental && constructor_pending_elts == 0 && value != 0
+      && constructor_stack == 0)
     clear_momentary ();
 }
 \f
@@ -6176,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)))
@@ -6229,25 +6924,53 @@ c_expand_return (retval)
 
       /* Strip any conversions, additions, and subtractions, and see if
         we are returning the address of a local variable.  Warn if so.  */
-      while (TREE_CODE (inner) == NOP_EXPR
-            || TREE_CODE (inner) == NON_LVALUE_EXPR
-            || TREE_CODE (inner) == CONVERT_EXPR
-            || TREE_CODE (inner) == PLUS_EXPR
-            || TREE_CODE (inner) == MINUS_EXPR)
-       inner = TREE_OPERAND (inner, 0);
-
-      if (TREE_CODE (inner) == ADDR_EXPR)
+      while (1)
        {
-         inner = TREE_OPERAND (inner, 0);
+         switch (TREE_CODE (inner))
+           {
+           case NOP_EXPR:   case NON_LVALUE_EXPR:  case CONVERT_EXPR:
+           case PLUS_EXPR:
+             inner = TREE_OPERAND (inner, 0);
+             continue;
+
+           case MINUS_EXPR:
+             /* If the second operand of the MINUS_EXPR has a pointer
+                type (or is converted from it), this may be valid, so
+                don't give a warning.  */
+             {
+               tree op1 = TREE_OPERAND (inner, 1);
+
+               while (! POINTER_TYPE_P (TREE_TYPE (op1))
+                      && (TREE_CODE (op1) == NOP_EXPR
+                          || TREE_CODE (op1) == NON_LVALUE_EXPR
+                          || TREE_CODE (op1) == CONVERT_EXPR))
+                 op1 = TREE_OPERAND (op1, 0);
 
-         while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
-           inner = TREE_OPERAND (inner, 0);
+               if (POINTER_TYPE_P (TREE_TYPE (op1)))
+                 break;
 
-         if (TREE_CODE (inner) == VAR_DECL
-             && ! DECL_EXTERNAL (inner)
-             && ! TREE_STATIC (inner)
-             && DECL_CONTEXT (inner) == current_function_decl)
-           warning ("function returns address of local variable");
+               inner = TREE_OPERAND (inner, 0);
+               continue;
+             }
+             
+           case ADDR_EXPR:
+             inner = TREE_OPERAND (inner, 0);
+
+             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
+               inner = TREE_OPERAND (inner, 0);
+
+             if (TREE_CODE (inner) == VAR_DECL
+                 && ! DECL_EXTERNAL (inner)
+                 && ! TREE_STATIC (inner)
+                 && DECL_CONTEXT (inner) == current_function_decl)
+               warning ("function returns address of local variable");
+             break;
+
+           default:
+             break;
+           }
+
+         break;
        }
 
       t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);