OSDN Git Service

(struct function): Make frame_offset be HOST_WIDE_INT.
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 6550df2..7e5608c 100644 (file)
@@ -1,5 +1,5 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 91, 92-5, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file is part of the C front end.
@@ -32,37 +33,44 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "tree.h"
 #include "c-tree.h"
 #include "flags.h"
+#include "output.h"
 
-/* Nonzero if we've already printed a "partly bracketed initializer"
+/* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
-static int partial_bracket_mentioned = 0;
+static int missing_braces_mentioned;
 
 extern char *index ();
 extern char *rindex ();
 
-int mark_addressable ();
-static tree convert_for_assignment ();
-static void warn_for_assignment ();
-static int function_types_compatible_p ();
-static int type_lists_compatible_p ();
-int self_promoting_args_p ();
-static int self_promoting_type_p ();
-static int comp_target_types ();
-static tree pointer_int_sum ();
-static tree pointer_diff ();
-static tree convert_sequence ();
-static tree unary_complex_lvalue ();
-static tree process_init_constructor ();
-static tree convert_arguments ();
-static char *get_spelling ();
-static tree digest_init ();
-static void pedantic_lvalue_warning ();
-tree truthvalue_conversion ();
-void incomplete_type_error ();
-void readonly_warning ();
-static tree internal_build_compound_expr ();
-
-void process_init_element ();
+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));
+static int self_promoting_type_p       PROTO((tree));
+static tree decl_constant_value                PROTO((tree));
+static tree lookup_field               PROTO((tree, tree, tree *));
+static tree convert_arguments          PROTO((tree, tree, tree, tree));
+static tree pointer_int_sum            PROTO((enum tree_code, tree, tree));
+static tree pointer_diff               PROTO((tree, tree));
+static tree unary_complex_lvalue       PROTO((enum tree_code, tree));
+static void pedantic_lvalue_warning    PROTO((enum tree_code));
+static tree internal_build_compound_expr PROTO((tree, int));
+static tree convert_for_assignment     PROTO((tree, tree, char *, tree,
+                                              tree, int));
+static void warn_for_assignment                PROTO((char *, char *, tree, int));
+static tree valid_compound_expr_initializer PROTO((tree, tree));
+static void push_string                        PROTO((char *));
+static void push_member_name           PROTO((tree));
+static void push_array_bounds          PROTO((int));
+static int spelling_length             PROTO((void));
+static char *print_spelling            PROTO((char *));
+static char *get_spelling              PROTO((char *));
+static void warning_init               PROTO((char *, char *,
+                                              char *));
+static tree digest_init                        PROTO((tree, tree, int, int));
+static void check_init_type_bitfields  PROTO((tree));
+static void output_init_element                PROTO((tree, tree, tree, int));
+static void output_pending_init_elements PROTO((int));
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -172,6 +180,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.  */
 
@@ -183,6 +192,9 @@ common_type (t1, t2)
   if (t2 == error_mark_node)
     return t1;
 
+  /* Merge the attributes */
+  attributes = merge_attributes (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
+
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
   if (TREE_CODE (t1) == ENUMERAL_TYPE)
@@ -193,22 +205,22 @@ common_type (t1, t2)
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
-  /* If one type is complex, form the common type
-     of the non-complex components,
-     then make that complex.  */
+  /* If one type is complex, form the common type of the non-complex
+     components, then make that complex.  Use T1 or T2 if it is the
+     required type.  */
   if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
     {
-      tree subtype1, subtype2, subtype;
-      if (code1 == COMPLEX_TYPE)
-       subtype1 = TREE_TYPE (t1);
-      else
-       subtype1 = t1;
-      if (code2 == COMPLEX_TYPE)
-       subtype2 = TREE_TYPE (t2);
+      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+      tree subtype = common_type (subtype1, subtype2);
+
+      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+       return build_type_attribute_variant (t1, attributes);
+      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+       return build_type_attribute_variant (t2, attributes);
       else
-       subtype2 = t2;
-      subtype = common_type (subtype1, subtype2);
-      return build_complex_type (subtype);
+       return build_type_attribute_variant (build_complex_type (subtype),
+                                            attributes);
     }
 
   switch (code1)
@@ -218,23 +230,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)
@@ -242,15 +255,18 @@ 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);
        }
 
       /* 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,
@@ -265,10 +281,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:
@@ -276,11 +295,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:
@@ -296,15 +316,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.  */
@@ -368,11 +394,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);
     }
 
 }
@@ -387,18 +414,20 @@ 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)
     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,21 +450,33 @@ comptypes (type1, type2)
   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)
@@ -448,24 +489,26 @@ 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;
     }
-  return 0;
+  return attrval == 2 && val == 1 ? 2 : val;
 }
 
 /* Return 1 if TTL and TTR are pointers to types that are equivalent,
@@ -554,7 +597,7 @@ type_lists_compatible_p (args1, args2)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
-  int newval;
+  int newval = 0;
 
   while (1)
     {
@@ -583,7 +626,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))))
@@ -597,7 +641,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))))
@@ -682,7 +727,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.  */
@@ -702,7 +756,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
@@ -713,7 +776,8 @@ signed_or_unsigned_type (unsignedp, type)
      int unsignedp;
      tree type;
 {
-  if (TREE_CODE (type) != INTEGER_TYPE)
+  if (! INTEGRAL_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;
@@ -847,7 +911,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);
@@ -877,18 +941,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.
@@ -917,13 +982,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,6 +1013,24 @@ default_conversion (exp)
       return convert (type, exp);
     }
 
+  if (TREE_CODE (exp) == COMPONENT_REF
+      && DECL_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.
@@ -1062,8 +1143,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];
 
@@ -1091,10 +1170,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;
@@ -1242,7 +1320,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,
@@ -1376,6 +1454,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)
       {
@@ -1387,7 +1473,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;
@@ -1562,49 +1649,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',
@@ -1613,10 +1679,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);
@@ -1668,7 +1732,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
@@ -1757,6 +1821,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)
@@ -1766,6 +1833,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)
@@ -1773,6 +1843,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 &");
        }
     }
 
@@ -1846,8 +1919,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
@@ -1941,9 +2018,17 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
-           /* When dividing two signed integers, you have to promote to int.
-              E.g. (short) -32868 / (short) -1 doesn't fit in a short.  */
-           shorten = TREE_UNSIGNED (orig_op0);
+           {
+             /* Although it would be tempting to shorten always here, that
+                loses on some targets, since the modulo instruction is
+                undefined if the quotient can't be represented in the
+                computation mode.  We shorten only if unsigned or if
+                dividing by something we know != -1.  */
+             shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
+                        || (TREE_CODE (op1) == INTEGER_CST
+                            && (TREE_INT_CST_LOW (op1) != -1
+                                || TREE_INT_CST_HIGH (op1) != -1)));
+           }
          common = 1;
        }
       break;
@@ -1987,7 +2072,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
             on some targets, since the modulo instruction is undefined if the
             quotient can't be represented in the computation mode.  We shorten
             only if unsigned or if dividing by something we know != -1.  */
-         shorten = (TREE_UNSIGNED (orig_op0)
+         shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
                     || (TREE_CODE (op1) == INTEGER_CST
                         && (TREE_INT_CST_LOW (op1) != -1
                             || TREE_INT_CST_HIGH (op1) != -1)));
@@ -2022,9 +2107,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
                {
@@ -2054,9 +2139,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)
@@ -2082,9 +2167,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)
@@ -2110,8 +2195,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
@@ -2125,7 +2209,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
@@ -2142,29 +2226,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:
@@ -2174,12 +2257,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;
 
@@ -2187,52 +2276,54 @@ 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;
     }
 
@@ -2333,6 +2424,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
@@ -2358,7 +2453,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
       /* Comparison operations are shortened too but differently.
         They identify themselves by setting short_compare = 1.  */
 
-      if (short_compare && none_complex)
+      if (short_compare)
        {
          /* Don't write &op0, etc., because that would prevent op0
             from being kept in a register.
@@ -2370,43 +2465,113 @@ 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 && 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");
+               }
            }
        }
     }
@@ -2431,8 +2596,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);
@@ -2487,7 +2655,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);
@@ -2501,16 +2675,21 @@ 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.  */
+  /* Replace the integer argument with a suitable product by the object size.
+     Do this multiplication as signed, then convert to the appropriate
+     pointer type (actually unsigned integral).  */
 
-  intop = build_binary_op (MULT_EXPR, intop, size_exp, 1);
+  intop = convert (result_type,
+                  build_binary_op (MULT_EXPR, intop,
+                                   convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
 
@@ -2543,19 +2722,22 @@ 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");
+
   /* This generates an error if op0 is pointer to incomplete type.  */
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
 
-  result = build (EXACT_DIV_EXPR, restype, op0, op1);
+  result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
 
   folded = fold (result);
   if (folded == result)
@@ -2730,7 +2912,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;
@@ -2890,7 +3072,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)));
@@ -3107,8 +3289,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:
@@ -3143,6 +3334,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)));
          }
@@ -3174,15 +3377,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.  */
@@ -3404,10 +3598,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);
 }
@@ -3525,6 +3737,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");
 
@@ -3534,6 +3751,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)
@@ -3769,6 +3991,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);
@@ -3793,71 +4017,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)
     {
@@ -3887,7 +4155,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",
@@ -3906,7 +4174,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,
@@ -4025,7 +4294,7 @@ warn_for_assignment (msg, opname, function, argnum)
    therefore, we do not need to check for such things as
    arithmetic-combinations of integers.  */
 
-static tree
+tree
 initializer_constant_valid_p (value, endtype)
      tree value;
      tree endtype;
@@ -4033,9 +4302,13 @@ initializer_constant_valid_p (value, endtype)
   switch (TREE_CODE (value))
     {
     case CONSTRUCTOR:
-      if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
-         && TREE_CONSTANT (value))
-       return initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (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);
        
       return TREE_STATIC (value) ? null_pointer_node : 0;
 
@@ -4057,17 +4330,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)
        {
@@ -4077,13 +4354,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),
@@ -4439,6 +4726,32 @@ pedwarn_init (format, local, ofwhat)
 
   pedwarn (format, buffer);
 }
+
+/* Issue a warning for a bad initializer component.
+   FORMAT describes the message.  OFWHAT is the name for the component.
+   LOCAL is a format string for formatting the insertion of the name
+   into the message.
+
+   If OFWHAT is null, the component name is stored on the spelling stack.
+   If the component name is a null string, then LOCAL is omitted entirely.  */
+
+static void
+warning_init (format, local, ofwhat)
+     char *format, *local, *ofwhat;
+{
+  char *buffer;
+
+  if (ofwhat == 0)
+    ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+
+  if (*ofwhat)
+    sprintf (buffer, local, ofwhat);
+  else
+    buffer[0] = 0;
+
+  warning (format, buffer);
+}
 \f
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
@@ -4545,8 +4858,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
@@ -4626,7 +4938,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
@@ -4648,11 +4960,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;
@@ -4660,10 +4978,6 @@ digest_init (type, init, require_constant, constructor_constant)
 \f
 /* Handle initializers that use braces.  */
 
-static void output_init_element ();
-static void output_pending_init_elements ();
-static void check_init_type_bitfields ();
-
 /* Type of object we are accumulating a constructor for.
    This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE.  */
 static tree constructor_type;
@@ -4678,7 +4992,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;
 
@@ -4725,7 +5039,7 @@ static tree constructor_pending_elts;
 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. */
+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;
@@ -4794,6 +5108,7 @@ struct initializer_stack
   tree decl;
   char *asmspec;
   struct constructor_stack *constructor_stack;
+  tree elements;
   struct spelling *spelling;
   struct spelling *spelling_base;
   int spelling_size;
@@ -4828,6 +5143,7 @@ start_init (decl, asmspec_tree, top_level)
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
+  p->elements = constructor_elements;
   p->spelling = spelling;
   p->spelling_base = spelling_base;
   p->spelling_size = spelling_size;
@@ -4865,6 +5181,8 @@ start_init (decl, asmspec_tree, top_level)
 
   constructor_stack = 0;
 
+  missing_braces_mentioned = 0;
+
   spelling_base = 0;
   spelling_size = 0;
   RESTORE_SPELLING_DEPTH (0);
@@ -4899,6 +5217,7 @@ finish_init ()
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
+  constructor_elements = p->elements;
   spelling = p->spelling;
   spelling_base = p->spelling_base;
   spelling_size = p->spelling_size;
@@ -4938,7 +5257,7 @@ really_start_incremental_init (type)
   p->unfilled_index = constructor_unfilled_index;
   p->unfilled_fields = constructor_unfilled_fields;
   p->bit_index = constructor_bit_index;
-  p->elements = 0;
+  p->elements = constructor_elements;
   p->constant = constructor_constant;
   p->simple = constructor_simple;
   p->erroneous = constructor_erroneous;
@@ -4962,8 +5281,8 @@ 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;
@@ -5036,10 +5355,12 @@ 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,
@@ -5053,6 +5374,9 @@ push_init_level (implicit)
 
          assemble_zeros (next - here);
        }
+      /* 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));
@@ -5097,31 +5421,45 @@ 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;
     }
 
-  /* Turn off constructor_incremental if type is a struct with bitfields.  */
-  if (constructor_type != 0)
-    check_init_type_bitfields (constructor_type);
-
   if (constructor_type == 0)
     {
       error_init ("extra brace group at end of initializer%s",
                  " for `%s'", NULL);
       constructor_fields = 0;
       constructor_unfilled_fields = 0;
+      return;
     }
-  else if (TREE_CODE (constructor_type) == RECORD_TYPE
+
+  /* Turn off constructor_incremental if type is a struct with bitfields.  */
+  check_init_type_bitfields (constructor_type);
+
+  if (implicit && warn_missing_braces && !missing_braces_mentioned)
+    {
+      missing_braces_mentioned = 1;
+      warning_init ("missing braces around initializer%s", " for `%s'", NULL);
+    }
+
+  if (TREE_CODE (constructor_type) == RECORD_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;
@@ -5143,7 +5481,7 @@ push_init_level (implicit)
     }
   else
     {
-      warning ("braces around scalar initializer");
+      warning_init ("braces around scalar initializer%s", " for `%s'", NULL);
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -5162,14 +5500,21 @@ check_init_type_bitfields (type)
       tree tail;
       for (tail = TYPE_FIELDS (type); tail;
           tail = TREE_CHAIN (tail))
-       if (DECL_BIT_FIELD (tail)
-           /* This catches cases like `int foo : 8;'.  */
-           || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
-         {
-           constructor_incremental = 0;
-           break;
-         }
+       {
+         if (DECL_C_BIT_FIELD (tail)
+             /* This catches cases like `int foo : 8;'.  */
+             || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
+           {
+             constructor_incremental = 0;
+             break;
+           }
+
+         check_init_type_bitfields (TREE_TYPE (tail));
+       }
     }
+
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    check_init_type_bitfields (TREE_TYPE (type));
 }
 
 /* At the end of an implicit or explicit brace level, 
@@ -5185,7 +5530,7 @@ pop_init_level (implicit)
      int implicit;
 {
   struct constructor_stack *p;
-  int size;
+  int size = 0;
   tree constructor = 0;
 
   if (implicit == 0)
@@ -5227,7 +5572,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.  */
@@ -5235,11 +5581,14 @@ pop_init_level (implicit)
              && TYPE_DOMAIN (constructor_type) == 0)
            {
              int failure;
+             int momentary_p;
 
              push_obstacks_nochange ();
              if (TREE_PERMANENT (constructor_type))
                end_temporary_allocation ();
 
+             momentary_p = suspend_momentary ();
+
              /* We shouldn't have an incomplete array type within
                 some other type.  */
              if (constructor_stack->next)
@@ -5252,6 +5601,7 @@ pop_init_level (implicit)
                abort ();
 
              size = int_size_in_bytes (constructor_type);
+             resume_momentary (momentary_p);
              pop_obstacks ();
            }
 
@@ -5332,15 +5682,14 @@ pop_init_level (implicit)
              TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
              TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
 
-             /* We shouldn't have an incomplete array type within
-                some other type.  */
-             if (constructor_stack->next)
-               abort ();
-
+             /* 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 ();
@@ -5414,6 +5763,8 @@ 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
@@ -5443,6 +5794,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))
     {
@@ -5496,7 +5852,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))
@@ -5556,7 +5916,8 @@ output_init_element (value, type, field, pending)
           constructor_index, which is modified in place.  */
        constructor_pending_elts
          = tree_cons (copy_node (field),
-                      digest_init (type, value, 0, 0),
+                      digest_init (type, value, require_constant_value, 
+                                   require_constant_elements),
                       constructor_pending_elts);
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5568,7 +5929,8 @@ output_init_element (value, type, field, pending)
       if (!duplicate)
        constructor_pending_elts
          = tree_cons (field,
-                      digest_init (type, value, 0, 0),
+                      digest_init (type, value, require_constant_value, 
+                                   require_constant_elements),
                       constructor_pending_elts);
     }
   else
@@ -5583,7 +5945,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
@@ -5594,7 +5958,7 @@ output_init_element (value, type, field, pending)
                {
                  /* Advance to offset of this element.  */
                  if (! tree_int_cst_equal (constructor_bit_index,
-                                           DECL_FIELD_BITPOS (constructor_fields)))
+                                           DECL_FIELD_BITPOS (field)))
                    {
                      int next = (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
                                  / BITS_PER_UNIT);
@@ -5604,7 +5968,9 @@ output_init_element (value, type, field, pending)
                      assemble_zeros (next - here);
                    }
                }
-             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,
@@ -5612,9 +5978,8 @@ output_init_element (value, type, field, pending)
              if (TREE_CODE (constructor_type) == RECORD_TYPE
                  || TREE_CODE (constructor_type) == UNION_TYPE)
                {
-                 tree temp = size_binop (PLUS_EXPR,
-                                         DECL_FIELD_BITPOS (constructor_fields),
-                                         DECL_SIZE (constructor_fields));
+                 tree temp = size_binop (PLUS_EXPR, DECL_FIELD_BITPOS (field),
+                                         DECL_SIZE (field));
                  TREE_INT_CST_LOW (constructor_bit_index)
                    = TREE_INT_CST_LOW (temp);
                  TREE_INT_CST_HIGH (constructor_bit_index)
@@ -5678,7 +6043,8 @@ output_pending_init_elements (all)
          if (tree_int_cst_equal (TREE_PURPOSE (tail),
                                  constructor_unfilled_index))
            {
-             output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
+             output_init_element (TREE_VALUE (tail),
+                                  TREE_TYPE (constructor_type),
                                   constructor_unfilled_index, 0);
              goto retry;
            }
@@ -5686,8 +6052,7 @@ output_pending_init_elements (all)
                                    constructor_unfilled_index))
            ;
          else if (next == 0
-                  || tree_int_cst_lt (TREE_PURPOSE (tail),
-                                         next))
+                  || tree_int_cst_lt (TREE_PURPOSE (tail), next))
            next = TREE_PURPOSE (tail);
        }
       else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5721,25 +6086,35 @@ output_pending_init_elements (all)
   if (constructor_incremental)
     {
       tree filled;
-      tree nextpos_tree;
+      tree nextpos_tree = size_int (0);
 
       if (TREE_CODE (constructor_type) == RECORD_TYPE
          || TREE_CODE (constructor_type) == UNION_TYPE)
        {
-         /* Find the last field written out.  */
+         /* Find the last field written out, if any.  */
          for (tail = TYPE_FIELDS (constructor_type); tail;
               tail = TREE_CHAIN (tail))
            if (TREE_CHAIN (tail) == constructor_unfilled_fields)
              break;
-         /* Find the offset of the end of that field.  */
-         filled = size_binop (CEIL_DIV_EXPR,
-                              size_binop (PLUS_EXPR,
-                                          DECL_FIELD_BITPOS (tail),
-                                          DECL_SIZE (tail)),
-                              size_int (BITS_PER_UNIT));
+
+         if (tail)
+           /* Find the offset of the end of that field.  */
+           filled = size_binop (CEIL_DIV_EXPR,
+                                size_binop (PLUS_EXPR,
+                                            DECL_FIELD_BITPOS (tail),
+                                            DECL_SIZE (tail)),
+                                size_int (BITS_PER_UNIT));
+         else
+           filled = size_int (0);
+
          nextpos_tree = size_binop (CEIL_DIV_EXPR,
                                     DECL_FIELD_BITPOS (next),
                                     size_int (BITS_PER_UNIT));
+
+         TREE_INT_CST_HIGH (constructor_bit_index)
+           = TREE_INT_CST_HIGH (DECL_FIELD_BITPOS (next));
+         TREE_INT_CST_LOW (constructor_bit_index)
+           = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (next));
          constructor_unfilled_fields = next;
        }
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -5808,6 +6183,7 @@ process_init_element (value)
   /* Handle superfluous braces around string cst as in
      char x[] = {"foo"}; */
   if (string_flag
+      && constructor_type
       && TREE_CODE (constructor_type) == ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
       && integer_zerop (constructor_unfilled_index))
@@ -5857,7 +6233,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.  */
@@ -5869,6 +6247,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))
@@ -5900,8 +6279,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;
@@ -5918,7 +6298,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.  */
@@ -5930,6 +6312,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))
@@ -5973,6 +6356,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))
@@ -5989,6 +6373,10 @@ process_init_element (value)
              break;
            }
 
+         /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once.  */
+         if (constructor_range_end)
+           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.  */
@@ -6045,7 +6433,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
@@ -6107,7 +6496,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)))
@@ -6130,7 +6520,7 @@ c_expand_return (retval)
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
 
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning ("function declared `volatile' has a `return' statement");
+    warning ("function declared `noreturn' has a `return' statement");
 
   if (!retval)
     {
@@ -6151,8 +6541,62 @@ c_expand_return (retval)
       tree t = convert_for_assignment (valtype, retval, "return",
                                       NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
-      t = build (MODIFY_EXPR, TREE_TYPE (res),
-                res, convert (TREE_TYPE (res), t));
+      tree inner;
+
+      if (t == error_mark_node)
+       return;
+
+      inner = t = convert (TREE_TYPE (res), t);
+
+      /* Strip any conversions, additions, and subtractions, and see if
+        we are returning the address of a local variable.  Warn if so.  */
+      while (1)
+       {
+         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);
+
+               if (POINTER_TYPE_P (TREE_TYPE (op1)))
+                 break;
+
+               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;
+           }
+
+         break;
+       }
+
+      t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
       TREE_SIDE_EFFECTS (t) = 1;
       expand_return (t);
       current_function_returns_value = 1;