OSDN Git Service

* doc/fragments.texi, doc/trouble.texi: Remove links to old
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 2b76981..64f0f07 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
 
 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 /* This file is part of the C front end.
 
 
 /* This file is part of the C front end.
@@ -40,8 +40,8 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "toplev.h"
 #include "intl.h"
 #include "expr.h"
 #include "toplev.h"
 #include "intl.h"
-#include "defaults.h"
 #include "ggc.h"
 #include "ggc.h"
+#include "target.h"
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
@@ -55,11 +55,12 @@ static int comp_target_types                PARAMS ((tree, tree));
 static int function_types_compatible_p PARAMS ((tree, tree));
 static int type_lists_compatible_p     PARAMS ((tree, tree));
 static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
 static int function_types_compatible_p PARAMS ((tree, tree));
 static int type_lists_compatible_p     PARAMS ((tree, tree));
 static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
-static tree lookup_field               PARAMS ((tree, tree, tree *));
+static tree default_function_array_conversion  PARAMS ((tree));
+static tree lookup_field               PARAMS ((tree, tree));
 static tree convert_arguments          PARAMS ((tree, tree, tree, tree));
 static tree pointer_int_sum            PARAMS ((enum tree_code, tree, tree));
 static tree pointer_diff               PARAMS ((tree, tree));
 static tree convert_arguments          PARAMS ((tree, tree, tree, tree));
 static tree pointer_int_sum            PARAMS ((enum tree_code, tree, tree));
 static tree pointer_diff               PARAMS ((tree, tree));
-static tree unary_complex_lvalue       PARAMS ((enum tree_code, tree));
+static tree unary_complex_lvalue       PARAMS ((enum tree_code, tree, int));
 static void pedantic_lvalue_warning    PARAMS ((enum tree_code));
 static tree internal_build_compound_expr PARAMS ((tree, int));
 static tree convert_for_assignment     PARAMS ((tree, tree, const char *,
 static void pedantic_lvalue_warning    PARAMS ((enum tree_code));
 static tree internal_build_compound_expr PARAMS ((tree, int));
 static tree convert_for_assignment     PARAMS ((tree, tree, const char *,
@@ -191,8 +192,8 @@ tree
 common_type (t1, t2)
      tree t1, t2;
 {
 common_type (t1, t2)
      tree t1, t2;
 {
-  register enum tree_code code1;
-  register enum tree_code code2;
+  enum tree_code code1;
+  enum tree_code code2;
   tree attributes;
 
   /* Save time if the two types are the same.  */
   tree attributes;
 
   /* Save time if the two types are the same.  */
@@ -206,7 +207,7 @@ common_type (t1, t2)
     return t1;
 
   /* Merge the attributes.  */
     return t1;
 
   /* Merge the attributes.  */
-  attributes = merge_machine_type_attributes (t1, t2);
+  attributes = (*targetm.merge_type_attributes) (t1, t2);
 
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
 
   /* Treat an enum type as the unsigned integer type of the same width.  */
 
@@ -354,6 +355,9 @@ common_type (t1, t2)
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
 
+       pushlevel (0);
+       declare_parm_level (1);
+
        len = list_length (p1);
        newargs = 0;
 
        len = list_length (p1);
        newargs = 0;
 
@@ -413,6 +417,8 @@ common_type (t1, t2)
          parm_done: ;
          }
 
          parm_done: ;
          }
 
+       poplevel (0, 0, 0);
+
        t1 = build_function_type (valtype, newargs);
        /* ... falls through ...  */
       }
        t1 = build_function_type (valtype, newargs);
        /* ... falls through ...  */
       }
@@ -431,8 +437,8 @@ int
 comptypes (type1, type2)
      tree type1, type2;
 {
 comptypes (type1, type2)
      tree type1, type2;
 {
-  register tree t1 = type1;
-  register tree t2 = type2;
+  tree t1 = type1;
+  tree t2 = type2;
   int attrval, val;
 
   /* Suppress errors caused by previously reported errors.  */
   int attrval, val;
 
   /* Suppress errors caused by previously reported errors.  */
@@ -478,12 +484,8 @@ comptypes (type1, type2)
   if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return 1;
 
   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.  */
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+  if (! (attrval = (*targetm.comp_type_attributes) (t1, t2)))
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -504,6 +506,8 @@ comptypes (type1, type2)
       {
        tree d1 = TYPE_DOMAIN (t1);
        tree d2 = TYPE_DOMAIN (t2);
       {
        tree d1 = TYPE_DOMAIN (t1);
        tree d2 = TYPE_DOMAIN (t2);
+       bool d1_variable, d2_variable;
+       bool d1_zero, d2_zero;
        val = 1;
 
        /* Target types must match incl. qualifiers.  */
        val = 1;
 
        /* Target types must match incl. qualifiers.  */
@@ -512,14 +516,25 @@ comptypes (type1, type2)
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
-       if (d1 == 0 || d2 == 0 || d1 == d2
-           || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
-           || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
-           || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
-           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
+       if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
 
          break;
 
-       if (! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
+       d1_zero = ! TYPE_MAX_VALUE (d1);
+       d2_zero = ! TYPE_MAX_VALUE (d2);
+
+       d1_variable = (! d1_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
+       d2_variable = (! d2_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+
+       if (d1_variable || d2_variable)
+         break;
+       if (d1_zero && d2_zero)
+         break;
+       if (d1_zero || d2_zero
+           || ! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
            || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
            || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
@@ -647,7 +662,8 @@ type_lists_compatible_p (args1, args2)
          if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
            return 0;
        }
          if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
            return 0;
        }
-      else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2))))
+      else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), 
+                                     TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
@@ -781,82 +797,7 @@ c_size_in_bytes (type)
                     size_int (TYPE_PRECISION (char_type_node)
                               / BITS_PER_UNIT));
 }
                     size_int (TYPE_PRECISION (char_type_node)
                               / BITS_PER_UNIT));
 }
-
-/* Implement the __alignof keyword: Return the minimum required
-   alignment of TYPE, measured in bytes.  */
-
-tree
-c_alignof (type)
-     tree type;
-{
-  enum tree_code code = TREE_CODE (type);
-  tree t;
-
-  if (code == FUNCTION_TYPE)
-    t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-  else if (code == VOID_TYPE || code == ERROR_MARK)
-    t = size_one_node;
-  else if (code == ERROR_MARK)
-    t = size_one_node;
-  else if (!COMPLETE_TYPE_P (type))
-    {
-      error ("__alignof__ applied to an incomplete type");
-      t = size_zero_node;
-    }
-  else
-    t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
-
-  return fold (build1 (NOP_EXPR, c_size_type_node, t));
-}
 \f
 \f
-/* Implement the __alignof keyword: Return the minimum required
-   alignment of EXPR, measured in bytes.  For VAR_DECL's and
-   FIELD_DECL's return DECL_ALIGN (which can be set from an
-   "aligned" __attribute__ specification).  */
-
-tree
-c_alignof_expr (expr)
-     tree expr;
-{
-  tree t;
-
-  if (TREE_CODE (expr) == VAR_DECL)
-    t = size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
-  else if (TREE_CODE (expr) == COMPONENT_REF
-          && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
-    {
-      error ("`__alignof' applied to a bit-field");
-      t = size_one_node;
-    }
-  else if (TREE_CODE (expr) == COMPONENT_REF
-      && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
-    t = size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
-  else if (TREE_CODE (expr) == INDIRECT_REF)
-    {
-      tree t = TREE_OPERAND (expr, 0);
-      tree best = t;
-      int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
-      while (TREE_CODE (t) == NOP_EXPR
-             && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
-       {
-         int thisalign;
-
-         t = TREE_OPERAND (t, 0);
-         thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
-         if (thisalign > bestalign)
-           best = t, bestalign = thisalign;
-       }
-      return c_alignof (TREE_TYPE (TREE_TYPE (best)));
-    }
-  else
-    return c_alignof (TREE_TYPE (expr));
-
-  return fold (build1 (NOP_EXPR, c_size_type_node, t));
-}
-
 /* Return either DECL or its known constant value (if it has one).  */
 
 tree
 /* Return either DECL or its known constant value (if it has one).  */
 
 tree
@@ -898,6 +839,110 @@ decl_constant_value_for_broken_optimization (decl)
     return decl_constant_value (decl);
 }
 
     return decl_constant_value (decl);
 }
 
+
+/* Perform the default conversion of arrays and functions to pointers.
+   Return the result of converting EXP.  For any other expression, just
+   return EXP.  */
+
+static tree
+default_function_array_conversion (exp)
+     tree exp;
+{
+  tree orig_exp;
+  tree type = TREE_TYPE (exp);
+  enum tree_code code = TREE_CODE (type);
+  int not_lvalue = 0;
+
+  /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
+     an lvalue. 
+
+     Do not use STRIP_NOPS here!  It will remove conversions from pointer
+     to integer and cause infinite recursion.  */
+  orig_exp = exp;
+  while (TREE_CODE (exp) == NON_LVALUE_EXPR
+        || (TREE_CODE (exp) == NOP_EXPR
+            && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
+    {
+      if (TREE_CODE (exp) == NON_LVALUE_EXPR)
+       not_lvalue = 1;
+      exp = TREE_OPERAND (exp, 0);
+    }
+
+  /* Preserve the original expression code.  */
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
+    C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
+
+  if (code == FUNCTION_TYPE)
+    {
+      return build_unary_op (ADDR_EXPR, exp, 0);
+    }
+  if (code == ARRAY_TYPE)
+    {
+      tree adr;
+      tree restype = TREE_TYPE (type);
+      tree ptrtype;
+      int constp = 0;
+      int volatilep = 0;
+      int lvalue_array_p;
+
+      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
+       {
+         constp = TREE_READONLY (exp);
+         volatilep = TREE_THIS_VOLATILE (exp);
+       }
+
+      if (TYPE_QUALS (type) || constp || volatilep)
+       restype 
+         = c_build_qualified_type (restype,
+                                   TYPE_QUALS (type) 
+                                   | (constp * TYPE_QUAL_CONST)
+                                   | (volatilep * TYPE_QUAL_VOLATILE));
+
+      if (TREE_CODE (exp) == INDIRECT_REF)
+       return convert (TYPE_POINTER_TO (restype),
+                       TREE_OPERAND (exp, 0));
+
+      if (TREE_CODE (exp) == COMPOUND_EXPR)
+       {
+         tree op1 = default_conversion (TREE_OPERAND (exp, 1));
+         return build (COMPOUND_EXPR, TREE_TYPE (op1),
+                       TREE_OPERAND (exp, 0), op1);
+       }
+
+      lvalue_array_p = !not_lvalue && lvalue_p (exp);
+      if (!flag_isoc99 && !lvalue_array_p
+         && !(TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
+       {
+         /* Before C99, non-lvalue arrays do not decay to pointers.
+            Normally, using such an array would be invalid; but it can
+            be used correctly inside sizeof or as a statement expression.
+            Thus, do not give an error here; an error will result later.  */
+         return exp;
+       }
+
+      ptrtype = build_pointer_type (restype);
+
+      if (TREE_CODE (exp) == VAR_DECL)
+       {
+         /* ??? This is not really quite correct
+            in that the type of the operand of ADDR_EXPR
+            is not the target type of the type of the ADDR_EXPR itself.
+            Question is, can this lossage be avoided?  */
+         adr = build1 (ADDR_EXPR, ptrtype, exp);
+         if (mark_addressable (exp) == 0)
+           return error_mark_node;
+         TREE_CONSTANT (adr) = staticp (exp);
+         TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
+         return adr;
+       }
+      /* This way is better for a COMPONENT_REF since it can
+        simplify the offset for a component.  */
+      adr = build_unary_op (ADDR_EXPR, exp, 1);
+      return convert (ptrtype, adr);
+    }
+  return exp;
+}
+
 /* Perform default promotions for C data used in expressions.
    Arrays and functions are converted to pointers;
    enumeral types or short or char, to int.
 /* Perform default promotions for C data used in expressions.
    Arrays and functions are converted to pointers;
    enumeral types or short or char, to int.
@@ -907,8 +952,12 @@ tree
 default_conversion (exp)
      tree exp;
 {
 default_conversion (exp)
      tree exp;
 {
-  register tree type = TREE_TYPE (exp);
-  register enum tree_code code = TREE_CODE (type);
+  tree orig_exp;
+  tree type = TREE_TYPE (exp);
+  enum tree_code code = TREE_CODE (type);
+
+  if (code == FUNCTION_TYPE || code == ARRAY_TYPE)
+    return default_function_array_conversion (exp);
 
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
 
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
@@ -928,11 +977,16 @@ default_conversion (exp)
 
      Do not use STRIP_NOPS here!  It will remove conversions from pointer
      to integer and cause infinite recursion.  */
 
      Do not use STRIP_NOPS here!  It will remove conversions from pointer
      to integer and cause infinite recursion.  */
+  orig_exp = exp;
   while (TREE_CODE (exp) == NON_LVALUE_EXPR
         || (TREE_CODE (exp) == NOP_EXPR
             && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
     exp = TREE_OPERAND (exp, 0);
 
   while (TREE_CODE (exp) == NON_LVALUE_EXPR
         || (TREE_CODE (exp) == NOP_EXPR
             && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
     exp = TREE_OPERAND (exp, 0);
 
+  /* Preserve the original expression code.  */
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
+    C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
+
   /* Normally convert enums to int,
      but convert wide enums to something wider.  */
   if (code == ENUMERAL_TYPE)
   /* Normally convert enums to int,
      but convert wide enums to something wider.  */
   if (code == ENUMERAL_TYPE)
@@ -950,14 +1004,14 @@ default_conversion (exp)
   if (TREE_CODE (exp) == COMPONENT_REF
       && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
       /* If it's thinner than an int, promote it like a
   if (TREE_CODE (exp) == COMPONENT_REF
       && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
       /* If it's thinner than an int, promote it like a
-        C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone.  */
+        c_promoting_integer_type_p, otherwise leave it alone.  */
       && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
                               TYPE_PRECISION (integer_type_node)))
     return convert (flag_traditional && TREE_UNSIGNED (type)
                    ? unsigned_type_node : integer_type_node,
                    exp);
 
       && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
                               TYPE_PRECISION (integer_type_node)))
     return convert (flag_traditional && TREE_UNSIGNED (type)
                    ? unsigned_type_node : integer_type_node,
                    exp);
 
-  if (C_PROMOTING_INTEGER_TYPE_P (type))
+  if (c_promoting_integer_type_p (type))
     {
       /* Traditionally, unsignedness is preserved in default promotions.
          Also preserve unsignedness if not really getting any wider.  */
     {
       /* Traditionally, unsignedness is preserved in default promotions.
          Also preserve unsignedness if not really getting any wider.  */
@@ -969,9 +1023,6 @@ default_conversion (exp)
       return convert (integer_type_node, exp);
     }
 
       return convert (integer_type_node, exp);
     }
 
-  if (code == BOOLEAN_TYPE)
-    return convert (integer_type_node, exp);
-
   if (flag_traditional && !flag_allow_single_precision
       && TYPE_MAIN_VARIANT (type) == float_type_node)
     return convert (double_type_node, exp);
   if (flag_traditional && !flag_allow_single_precision
       && TYPE_MAIN_VARIANT (type) == float_type_node)
     return convert (double_type_node, exp);
@@ -981,83 +1032,23 @@ default_conversion (exp)
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
-  if (code == FUNCTION_TYPE)
-    {
-      return build_unary_op (ADDR_EXPR, exp, 0);
-    }
-  if (code == ARRAY_TYPE)
-    {
-      register tree adr;
-      tree restype = TREE_TYPE (type);
-      tree ptrtype;
-      int constp = 0;
-      int volatilep = 0;
-
-      if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp))
-       {
-         constp = TREE_READONLY (exp);
-         volatilep = TREE_THIS_VOLATILE (exp);
-       }
-
-      if (TYPE_QUALS (type) || constp || volatilep)
-       restype 
-         = c_build_qualified_type (restype,
-                                   TYPE_QUALS (type) 
-                                   | (constp * TYPE_QUAL_CONST)
-                                   | (volatilep * TYPE_QUAL_VOLATILE));
-
-      if (TREE_CODE (exp) == INDIRECT_REF)
-       return convert (TYPE_POINTER_TO (restype),
-                       TREE_OPERAND (exp, 0));
-
-      if (TREE_CODE (exp) == COMPOUND_EXPR)
-       {
-         tree op1 = default_conversion (TREE_OPERAND (exp, 1));
-         return build (COMPOUND_EXPR, TREE_TYPE (op1),
-                       TREE_OPERAND (exp, 0), op1);
-       }
-
-      if (! lvalue_p (exp)
-         && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
-       {
-         error ("invalid use of non-lvalue array");
-         return error_mark_node;
-       }
-
-      ptrtype = build_pointer_type (restype);
-
-      if (TREE_CODE (exp) == VAR_DECL)
-       {
-         /* ??? This is not really quite correct
-            in that the type of the operand of ADDR_EXPR
-            is not the target type of the type of the ADDR_EXPR itself.
-            Question is, can this lossage be avoided?  */
-         adr = build1 (ADDR_EXPR, ptrtype, exp);
-         if (mark_addressable (exp) == 0)
-           return error_mark_node;
-         TREE_CONSTANT (adr) = staticp (exp);
-         TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
-         return adr;
-       }
-      /* This way is better for a COMPONENT_REF since it can
-        simplify the offset for a component.  */
-      adr = build_unary_op (ADDR_EXPR, exp, 1);
-      return convert (ptrtype, adr);
-    }
   return exp;
 }
 \f
   return exp;
 }
 \f
-/* Look up component name in the structure type definition.
-
-   If this component name is found indirectly within an anonymous union,
-   store in *INDIRECT the component which directly contains
-   that anonymous union.  Otherwise, set *INDIRECT to 0.  */
+/* Look up COMPONENT in a structure or union DECL.
+
+   If the component name is not found, returns NULL_TREE.  Otherwise,
+   the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
+   stepping down the chain to the component, which is in the last
+   TREE_VALUE of the list.  Normally the list is of length one, but if
+   the component is embedded within (nested) anonymous structures or
+   unions, the list steps down the chain to the component.  */
      
 static tree
      
 static tree
-lookup_field (type, component, indirect)
-     tree type, component;
-     tree *indirect;
+lookup_field (decl, component)
+     tree decl, component;
 {
 {
+  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1083,18 +1074,15 @@ lookup_field (type, component, indirect)
              /* Step through all anon unions in linear fashion.  */
              while (DECL_NAME (field_array[bot]) == NULL_TREE)
                {
              /* Step through all anon unions in linear fashion.  */
              while (DECL_NAME (field_array[bot]) == NULL_TREE)
                {
-                 tree anon = 0, junk;
-
                  field = field_array[bot++];
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                  field = field_array[bot++];
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-                   anon = lookup_field (TREE_TYPE (field), component, &junk);
-
-                 if (anon != NULL_TREE)
                    {
                    {
-                     *indirect = field;
-                     return anon;
-                   }
+                     tree anon = lookup_field (field, component);
+
+                     if (anon)
+                       return tree_cons (NULL_TREE, field, anon);
+                   } 
                }
 
              /* Entire record is only anon unions.  */
                }
 
              /* Entire record is only anon unions.  */
@@ -1116,35 +1104,31 @@ lookup_field (type, component, indirect)
       if (DECL_NAME (field_array[bot]) == component)
        field = field_array[bot];
       else if (DECL_NAME (field) != component)
       if (DECL_NAME (field_array[bot]) == component)
        field = field_array[bot];
       else if (DECL_NAME (field) != component)
-       field = 0;
+       return NULL_TREE;
     }
   else
     {
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        {
     }
   else
     {
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        {
-         if (DECL_NAME (field) == NULL_TREE)
+         if (DECL_NAME (field) == NULL_TREE
+             && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
            {
-             tree junk;
-             tree anon = 0;
-
-             if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-               anon = lookup_field (TREE_TYPE (field), component, &junk);
+             tree anon = lookup_field (field, component);
 
 
-             if (anon != NULL_TREE)
-               {
-                 *indirect = field;
-                 return anon;
-               }
+             if (anon)
+               return tree_cons (NULL_TREE, field, anon);
            }
 
          if (DECL_NAME (field) == component)
            break;
        }
            }
 
          if (DECL_NAME (field) == component)
            break;
        }
+
+      if (field == NULL_TREE)
+       return NULL_TREE;
     }
 
     }
 
-  *indirect = NULL_TREE;
-  return field;
+  return tree_cons (NULL_TREE, field, NULL_TREE);
 }
 
 /* Make an expression to refer to the COMPONENT field of
 }
 
 /* Make an expression to refer to the COMPONENT field of
@@ -1154,27 +1138,27 @@ tree
 build_component_ref (datum, component)
      tree datum, component;
 {
 build_component_ref (datum, component)
      tree datum, component;
 {
-  register tree type = TREE_TYPE (datum);
-  register enum tree_code code = TREE_CODE (type);
-  register tree field = NULL;
-  register tree ref;
+  tree type = TREE_TYPE (datum);
+  enum tree_code code = TREE_CODE (type);
+  tree field = NULL;
+  tree ref;
 
 
-  /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it
-     unless we are not to support things not strictly ANSI.  */
+  /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
+     If pedantic ensure that the arguments are not lvalues; otherwise,
+     if the component is an array, it would wrongly decay to a pointer in
+     C89 mode.
+     We cannot do this with a COND_EXPR, because in a conditional expression
+     the default promotions are applied to both sides, and this would yield
+     the wrong type of the result; for example, if the components have
+     type "char".  */
   switch (TREE_CODE (datum))
     {
     case COMPOUND_EXPR:
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
        return build (COMPOUND_EXPR, TREE_TYPE (value),
   switch (TREE_CODE (datum))
     {
     case COMPOUND_EXPR:
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
        return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (datum, 0), value);
+                     TREE_OPERAND (datum, 0), pedantic_non_lvalue (value));
       }
       }
-    case COND_EXPR:
-      return build_conditional_expr
-       (TREE_OPERAND (datum, 0),
-        build_component_ref (TREE_OPERAND (datum, 1), component),
-        build_component_ref (TREE_OPERAND (datum, 2), component));
-
     default:
       break;
     }
     default:
       break;
     }
@@ -1183,15 +1167,13 @@ build_component_ref (datum, component)
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
     {
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
     {
-      tree indirect = 0;
-
       if (!COMPLETE_TYPE_P (type))
        {
          incomplete_type_error (NULL_TREE, type);
          return error_mark_node;
        }
 
       if (!COMPLETE_TYPE_P (type))
        {
          incomplete_type_error (NULL_TREE, type);
          return error_mark_node;
        }
 
-      field = lookup_field (type, component, &indirect);
+      field = lookup_field (datum, component);
 
       if (!field)
        {
 
       if (!field)
        {
@@ -1200,29 +1182,27 @@ build_component_ref (datum, component)
                 IDENTIFIER_POINTER (component));
          return error_mark_node;
        }
                 IDENTIFIER_POINTER (component));
          return error_mark_node;
        }
-      if (TREE_TYPE (field) == error_mark_node)
-       return error_mark_node;
 
 
-      /* If FIELD was found buried within an anonymous union,
-        make one COMPONENT_REF to get that anonymous union,
-        then fall thru to make a second COMPONENT_REF to get FIELD.  */
-      if (indirect != 0)
+      /* Chain the COMPONENT_REFs if necessary down to the FIELD.
+        This might be better solved in future the way the C++ front
+        end does it - by giving the anonymous entities each a
+        separate name and type, and then have build_component_ref
+        recursively call itself.  We can't do that here.  */
+      for (; field; field = TREE_CHAIN (field))
        {
        {
-         ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
-         if (TREE_READONLY (datum) || TREE_READONLY (indirect))
+         tree subdatum = TREE_VALUE (field);
+
+         if (TREE_TYPE (subdatum) == error_mark_node)
+           return error_mark_node;
+
+         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
+         if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
            TREE_READONLY (ref) = 1;
-         if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
+         if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
            TREE_THIS_VOLATILE (ref) = 1;
          datum = ref;
        }
 
            TREE_THIS_VOLATILE (ref) = 1;
          datum = ref;
        }
 
-      ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
-      if (TREE_READONLY (datum) || TREE_READONLY (field))
-       TREE_READONLY (ref) = 1;
-      if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
-       TREE_THIS_VOLATILE (ref) = 1;
-
       return ref;
     }
   else if (code != ERROR_MARK)
       return ref;
     }
   else if (code != ERROR_MARK)
@@ -1241,8 +1221,8 @@ build_indirect_ref (ptr, errorstring)
      tree ptr;
      const char *errorstring;
 {
      tree ptr;
      const char *errorstring;
 {
-  register tree pointer = default_conversion (ptr);
-  register tree type = TREE_TYPE (pointer);
+  tree pointer = default_conversion (ptr);
+  tree type = TREE_TYPE (pointer);
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
@@ -1254,8 +1234,7 @@ build_indirect_ref (ptr, errorstring)
       else
        {
          tree t = TREE_TYPE (type);
       else
        {
          tree t = TREE_TYPE (type);
-         register tree ref = build1 (INDIRECT_REF,
-                                     TYPE_MAIN_VARIANT (t), pointer);
+         tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer);
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
@@ -1525,8 +1504,8 @@ tree
 build_function_call (function, params)
      tree function, params;
 {
 build_function_call (function, params)
      tree function, params;
 {
-  register tree fntype, fundecl = 0;
-  register tree coerced_params;
+  tree fntype, fundecl = 0;
+  tree coerced_params;
   tree name = NULL_TREE, assembler_name = NULL_TREE, result;
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   tree name = NULL_TREE, assembler_name = NULL_TREE, result;
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
@@ -1573,8 +1552,8 @@ build_function_call (function, params)
 
   /* Check for errors in format strings.  */
 
 
   /* Check for errors in format strings.  */
 
-  if (warn_format && (name || assembler_name))
-    check_function_format (NULL, name, assembler_name, coerced_params);
+  if (warn_format)
+    check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
 
   /* Recognize certain built-in functions so we can make tree-codes
      other than CALL_EXPR.  We do this when it enables fold-const.c
 
   /* Recognize certain built-in functions so we can make tree-codes
      other than CALL_EXPR.  We do this when it enables fold-const.c
@@ -1622,8 +1601,8 @@ static tree
 convert_arguments (typelist, values, name, fundecl)
      tree typelist, values, name, fundecl;
 {
 convert_arguments (typelist, values, name, fundecl)
      tree typelist, values, name, fundecl;
 {
-  register tree typetail, valtail;
-  register tree result = NULL;
+  tree typetail, valtail;
+  tree result = NULL;
   int parmnum;
 
   /* Scan the given expressions and types, producing individual
   int parmnum;
 
   /* Scan the given expressions and types, producing individual
@@ -1633,8 +1612,8 @@ convert_arguments (typelist, values, name, fundecl)
        valtail;
        valtail = TREE_CHAIN (valtail), parmnum++)
     {
        valtail;
        valtail = TREE_CHAIN (valtail), parmnum++)
     {
-      register tree type = typetail ? TREE_VALUE (typetail) : 0;
-      register tree val = TREE_VALUE (valtail);
+      tree type = typetail ? TREE_VALUE (typetail) : 0;
+      tree val = TREE_VALUE (valtail);
 
       if (type == void_type_node)
        {
 
       if (type == void_type_node)
        {
@@ -1652,9 +1631,7 @@ convert_arguments (typelist, values, name, fundecl)
       if (TREE_CODE (val) == NON_LVALUE_EXPR)
        val = TREE_OPERAND (val, 0);
 
       if (TREE_CODE (val) == NON_LVALUE_EXPR)
        val = TREE_OPERAND (val, 0);
 
-      if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
-         || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE)
-       val = default_conversion (val);
+      val = default_function_array_conversion (val);
 
       val = require_complete_type (val);
 
 
       val = require_complete_type (val);
 
@@ -1672,19 +1649,25 @@ convert_arguments (typelist, values, name, fundecl)
            {
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
            {
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
-             if (warn_conversion)
+             if (warn_conversion || warn_traditional)
                {
                  int formal_prec = TYPE_PRECISION (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);
                {
                  int formal_prec = TYPE_PRECISION (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);
+                 if (INTEGRAL_TYPE_P (type)
+                     && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
+                   warn_for_assignment ("%s as integer rather than complex 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
                           && 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) == 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
                           && 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) == COMPLEX_TYPE
+                          && INTEGRAL_TYPE_P (TREE_TYPE (val)))
+                   warn_for_assignment ("%s as complex 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);
                  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);
@@ -1699,15 +1682,18 @@ convert_arguments (typelist, values, name, fundecl)
                      if (formal_prec == TYPE_PRECISION (float_type_node))
                        warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
                    }
                      if (formal_prec == TYPE_PRECISION (float_type_node))
                        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 (INTEGRAL_TYPE_P (type)
+                 /* Detect integer changing in width or signedness.
+                    These warnings are only activated with
+                    -Wconversion, not with -Wtraditional.  */
+                 else if (warn_conversion && INTEGRAL_TYPE_P (type)
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    {
                      tree would_have_been = default_conversion (val);
                      tree type1 = TREE_TYPE (would_have_been);
 
                      if (TREE_CODE (type) == ENUMERAL_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
                    {
                      tree would_have_been = default_conversion (val);
                      tree type1 = TREE_TYPE (would_have_been);
 
                      if (TREE_CODE (type) == ENUMERAL_TYPE
-                         && type == TREE_TYPE (val))
+                         && (TYPE_MAIN_VARIANT (type)
+                             == TYPE_MAIN_VARIANT (TREE_TYPE (val))))
                        /* No warning if function asks for enum
                           and the actual arg is that enum type.  */
                        ;
                        /* No warning if function asks for enum
                           and the actual arg is that enum type.  */
                        ;
@@ -1757,9 +1743,7 @@ convert_arguments (typelist, values, name, fundecl)
                                                fundecl, name, parmnum + 1);
              
              if (PROMOTE_PROTOTYPES
                                                fundecl, name, parmnum + 1);
              
              if (PROMOTE_PROTOTYPES
-                 && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE
-                     || TREE_CODE (type) == BOOLEAN_TYPE)
+                 && INTEGRAL_TYPE_P (type)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
@@ -1809,11 +1793,9 @@ parser_build_binary_op (code, arg1, arg2)
   enum tree_code code1 = ERROR_MARK;
   enum tree_code code2 = ERROR_MARK;
 
   enum tree_code code1 = ERROR_MARK;
   enum tree_code code2 = ERROR_MARK;
 
-  if (class1 == 'e' || class1 == '1'
-      || class1 == '2' || class1 == '<')
+  if (IS_EXPR_CODE_CLASS (class1))
     code1 = C_EXP_ORIGINAL_CODE (arg1);
     code1 = C_EXP_ORIGINAL_CODE (arg1);
-  if (class2 == 'e' || class2 == '1'
-      || class2 == '2' || class2 == '<')
+  if (IS_EXPR_CODE_CLASS (class2))
     code2 = C_EXP_ORIGINAL_CODE (arg2);
 
   /* Check for cases such as x+y<<z which users are likely
     code2 = C_EXP_ORIGINAL_CODE (arg2);
 
   /* Check for cases such as x+y<<z which users are likely
@@ -1883,8 +1865,7 @@ parser_build_binary_op (code, arg1, arg2)
 
   /* Record the code that was specified in the source,
      for the sake of warnings about confusing nesting.  */
 
   /* Record the code that was specified in the source,
      for the sake of warnings about confusing nesting.  */
-  if (class == 'e' || class == '1'
-      || class == '2' || class == '<')
+  if (IS_EXPR_CODE_CLASS (class))
     C_SET_EXP_ORIGINAL_CODE (result, code);
   else
     {
     C_SET_EXP_ORIGINAL_CODE (result, code);
   else
     {
@@ -1923,17 +1904,17 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
      int convert_p;
 {
   tree type0, type1;
      int convert_p;
 {
   tree type0, type1;
-  register enum tree_code code0, code1;
+  enum tree_code code0, code1;
   tree op0, op1;
 
   /* Expression code to give to the expression when it is built.
      Normally this is CODE, which is what the caller asked for,
      but in some special cases we change it.  */
   tree op0, op1;
 
   /* Expression code to give to the expression when it is built.
      Normally this is CODE, which is what the caller asked for,
      but in some special cases we change it.  */
-  register enum tree_code resultcode = code;
+  enum tree_code resultcode = code;
 
   /* Data type in which the computation is to be performed.
      In the simplest cases this is the common type of the arguments.  */
 
   /* Data type in which the computation is to be performed.
      In the simplest cases this is the common type of the arguments.  */
-  register tree result_type = NULL;
+  tree result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -2031,6 +2012,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
+      /* Floating point division by zero is a legitimate way to obtain
+        infinities and NaNs.  */
+      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
+       warning ("division by zero");
+
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -2084,6 +2070,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
+      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
+       warning ("division by zero");
+
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
          /* Although it would be tempting to shorten always here, that loses
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
          /* Although it would be tempting to shorten always here, that loses
@@ -2221,8 +2210,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         register tree tt0 = TREE_TYPE (type0);
-         register tree tt1 = TREE_TYPE (type1);
+         tree tt0 = TREE_TYPE (type0);
+         tree tt1 = TREE_TYPE (type1);
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
@@ -2464,22 +2453,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
-             /* If arg is sign-extended and then unsigned-shifted,
-                we can simulate this with a signed shift in arg's type
-                only if the extended result is at least twice as wide
-                as the arg.  Otherwise, the shift could use up all the
-                ones made by sign-extension and bring in zeros.
-                We can't optimize that case at all, but in most machines
-                it never happens because available widths are 2**N.  */
-             && (!TREE_UNSIGNED (final_type)
-                 || unsigned_arg
-                 || (2 * TYPE_PRECISION (TREE_TYPE (arg0))
-                     <= TYPE_PRECISION (result_type))))
+             /* We cannot drop an unsigned shift after sign-extension.  */
+             && (!TREE_UNSIGNED (final_type) || unsigned_arg))
            {
              /* Do an unsigned shift if the operand was zero-extended.  */
              result_type
            {
              /* Do an unsigned shift if the operand was zero-extended.  */
              result_type
-               = signed_or_unsigned_type (unsigned_arg,
-                                          TREE_TYPE (arg0));
+               = signed_or_unsigned_type (unsigned_arg, TREE_TYPE (arg0));
              /* Convert value-to-be-shifted to that type.  */
              if (TREE_TYPE (op0) != result_type)
                op0 = convert (result_type, op0);
              /* Convert value-to-be-shifted to that type.  */
              if (TREE_TYPE (op0) != result_type)
                op0 = convert (result_type, op0);
@@ -2652,8 +2631,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     build_type = result_type;
 
   {
     build_type = result_type;
 
   {
-    register tree result = build (resultcode, build_type, op0, op1);
-    register tree folded;
+    tree result = build (resultcode, build_type, op0, op1);
+    tree folded;
 
     folded = fold (result);
     if (folded == result)
 
     folded = fold (result);
     if (folded == result)
@@ -2670,16 +2649,16 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
 static tree
 pointer_int_sum (resultcode, ptrop, intop)
      enum tree_code resultcode;
 static tree
 pointer_int_sum (resultcode, ptrop, intop)
      enum tree_code resultcode;
-     register tree ptrop, intop;
+     tree ptrop, intop;
 {
   tree size_exp;
 
 {
   tree size_exp;
 
-  register tree result;
-  register tree folded;
+  tree result;
+  tree folded;
 
   /* The result is a pointer of the same type that is being added.  */
 
 
   /* The result is a pointer of the same type that is being added.  */
 
-  register tree result_type = TREE_TYPE (ptrop);
+  tree result_type = TREE_TYPE (ptrop);
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
@@ -2758,12 +2737,14 @@ pointer_int_sum (resultcode, ptrop, intop)
 
 static tree
 pointer_diff (op0, op1)
 
 static tree
 pointer_diff (op0, op1)
-     register tree op0, op1;
+     tree op0, op1;
 {
 {
-  register tree result, folded;
+  tree result, folded;
   tree restype = ptrdiff_type_node;
 
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree restype = ptrdiff_type_node;
 
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
+  tree con0, con1, lit0, lit1;
+  tree orig_op1 = op1;
 
   if (pedantic || warn_pointer_arith)
     {
 
   if (pedantic || warn_pointer_arith)
     {
@@ -2773,6 +2754,40 @@ pointer_diff (op0, op1)
        pedwarn ("pointer to a function used in subtraction");
     }
 
        pedwarn ("pointer to a function used in subtraction");
     }
 
+  /* If the conversion to ptrdiff_type does anything like widening or
+     converting a partial to an integral mode, we get a convert_expression
+     that is in the way to do any simplifications.
+     (fold-const.c doesn't know that the extra bits won't be needed.
+     split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
+     different mode in place.)
+     So first try to find a common term here 'by hand'; we want to cover
+     at least the cases that occur in legal static initializers.  */
+  con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0;
+  con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1;
+
+  if (TREE_CODE (con0) == PLUS_EXPR)
+    {
+      lit0 = TREE_OPERAND (con0, 1);
+      con0 = TREE_OPERAND (con0, 0);
+    }
+  else
+    lit0 = integer_zero_node;
+
+  if (TREE_CODE (con1) == PLUS_EXPR)
+    {
+      lit1 = TREE_OPERAND (con1, 1);
+      con1 = TREE_OPERAND (con1, 0);
+    }
+  else
+    lit1 = integer_zero_node;
+
+  if (operand_equal_p (con0, con1, 0))
+    {
+      op0 = lit0;
+      op1 = lit1;
+    }
+
+
   /* First do the subtraction as integers;
      then drop through to build the divide operator.
      Do not do default conversions on the minus operator
   /* First do the subtraction as integers;
      then drop through to build the divide operator.
      Do not do default conversions on the minus operator
@@ -2781,7 +2796,7 @@ pointer_diff (op0, op1)
   op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
                         convert (restype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
   op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
                         convert (restype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
-  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op1))))
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
     error ("arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
     error ("arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
@@ -2799,20 +2814,25 @@ pointer_diff (op0, op1)
 \f
 /* Construct and perhaps optimize a tree representation
    for a unary operation.  CODE, a tree_code, specifies the operation
 \f
 /* Construct and perhaps optimize a tree representation
    for a unary operation.  CODE, a tree_code, specifies the operation
-   and XARG is the operand.  NOCONVERT nonzero suppresses
-   the default promotions (such as from short to int).  */
+   and XARG is the operand.
+   For any CODE other than ADDR_EXPR, FLAG nonzero suppresses
+   the default promotions (such as from short to int).
+   For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
+   allows non-lvalues; this is only used to handle conversion of non-lvalue
+   arrays to pointers in C99.  */
 
 tree
 
 tree
-build_unary_op (code, xarg, noconvert)
+build_unary_op (code, xarg, flag)
      enum tree_code code;
      tree xarg;
      enum tree_code code;
      tree xarg;
-     int noconvert;
+     int flag;
 {
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
 {
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
-  register tree arg = xarg;
-  register tree argtype = 0;
-  register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
+  tree arg = xarg;
+  tree argtype = 0;
+  enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
   tree val;
   tree val;
+  int noconvert = flag;
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
@@ -2926,7 +2946,7 @@ build_unary_op (code, xarg, noconvert)
       /* Handle complex lvalues (when permitted)
         by reduction to simpler cases.  */
 
       /* Handle complex lvalues (when permitted)
         by reduction to simpler cases.  */
 
-      val = unary_complex_lvalue (code, arg);
+      val = unary_complex_lvalue (code, arg, 0);
       if (val != 0)
        return val;
 
       if (val != 0)
        return val;
 
@@ -2951,14 +2971,16 @@ build_unary_op (code, xarg, noconvert)
       if (typecode != POINTER_TYPE
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
       if (typecode != POINTER_TYPE
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
-         error ("wrong type argument to %s",
-                code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
-                ? "increment" : "decrement");
+         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+            error ("wrong type argument to increment");
+          else
+            error ("wrong type argument to decrement");
+
          return error_mark_node;
        }
 
       {
          return error_mark_node;
        }
 
       {
-       register tree inc;
+       tree inc;
        tree result_type = TREE_TYPE (arg);
 
        arg = get_unwidened (arg, 0);
        tree result_type = TREE_TYPE (arg);
 
        arg = get_unwidened (arg, 0);
@@ -2971,15 +2993,22 @@ build_unary_op (code, xarg, noconvert)
            /* If pointer target is an undefined struct,
               we just cannot know how to do the arithmetic.  */
            if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
            /* If pointer target is an undefined struct,
               we just cannot know how to do the arithmetic.  */
            if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
-             error ("%s of pointer to unknown structure",
-                    code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
-                    ? "increment" : "decrement");
+             {
+               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+                 error ("increment of pointer to unknown structure");
+               else
+                 error ("decrement of pointer to unknown structure");
+             }
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
-             pedwarn ("wrong type argument to %s",
-                      code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
-                      ? "increment" : "decrement");
+              {
+               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+                 pedwarn ("wrong type argument to increment");
+               else
+                 pedwarn ("wrong type argument to decrement");
+             }
+
            inc = c_size_in_bytes (TREE_TYPE (result_type));
          }
        else
            inc = c_size_in_bytes (TREE_TYPE (result_type));
          }
        else
@@ -3050,7 +3079,7 @@ build_unary_op (code, xarg, noconvert)
          readonly_warning (arg, 
                            ((code == PREINCREMENT_EXPR
                              || code == POSTINCREMENT_EXPR)
          readonly_warning (arg, 
                            ((code == PREINCREMENT_EXPR
                              || code == POSTINCREMENT_EXPR)
-                            ? "increment" : "decrement"));
+                            ? _("increment") : _("decrement")));
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -3064,8 +3093,7 @@ build_unary_op (code, xarg, noconvert)
       }
 
     case ADDR_EXPR:
       }
 
     case ADDR_EXPR:
-      /* Note that this operation never does default_conversion
-        regardless of NOCONVERT.  */
+      /* Note that this operation never does default_conversion.  */
 
       /* Let &* cancel out to simplify resulting code.  */
       if (TREE_CODE (arg) == INDIRECT_REF)
 
       /* Let &* cancel out to simplify resulting code.  */
       if (TREE_CODE (arg) == INDIRECT_REF)
@@ -3087,7 +3115,7 @@ build_unary_op (code, xarg, noconvert)
 
       /* Handle complex lvalues (when permitted)
         by reduction to simpler cases.  */
 
       /* Handle complex lvalues (when permitted)
         by reduction to simpler cases.  */
-      val = unary_complex_lvalue (code, arg);
+      val = unary_complex_lvalue (code, arg, flag);
       if (val != 0)
        return val;
 
       if (val != 0)
        return val;
 
@@ -3118,8 +3146,8 @@ build_unary_op (code, xarg, noconvert)
       if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
        ;
       /* Anything not already handled and not a true memory reference
       if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
        ;
       /* Anything not already handled and not a true memory reference
-        is an error.  */
-      else if (typecode != FUNCTION_TYPE
+        or a non-lvalue array is an error.  */
+      else if (typecode != FUNCTION_TYPE && !flag
               && !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
        return error_mark_node;
 
               && !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
        return error_mark_node;
 
@@ -3148,7 +3176,7 @@ build_unary_op (code, xarg, noconvert)
          {
            tree field = TREE_OPERAND (arg, 1);
 
          {
            tree field = TREE_OPERAND (arg, 1);
 
-           addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
+           addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
 
            if (DECL_C_BIT_FIELD (field))
              {
 
            if (DECL_C_BIT_FIELD (field))
              {
@@ -3219,7 +3247,7 @@ int
 lvalue_p (ref)
      tree ref;
 {
 lvalue_p (ref)
      tree ref;
 {
-  register enum tree_code code = TREE_CODE (ref);
+  enum tree_code code = TREE_CODE (ref);
 
   switch (code)
     {
 
   switch (code)
     {
@@ -3267,14 +3295,17 @@ lvalue_or_else (ref, msgid)
 
 /* Apply unary lvalue-demanding operator CODE to the expression ARG
    for certain kinds of expressions which are not really lvalues
 
 /* Apply unary lvalue-demanding operator CODE to the expression ARG
    for certain kinds of expressions which are not really lvalues
-   but which we can accept as lvalues.
+   but which we can accept as lvalues.  If FLAG is nonzero, then
+   non-lvalues are OK since we may be converting a non-lvalue array to
+   a pointer in C99.
 
    If ARG is not a kind of expression we can handle, return zero.  */
    
 static tree
 
    If ARG is not a kind of expression we can handle, return zero.  */
    
 static tree
-unary_complex_lvalue (code, arg)
+unary_complex_lvalue (code, arg, flag)
      enum tree_code code;
      tree arg;
      enum tree_code code;
      tree arg;
+     int flag;
 {
   /* Handle (a, b) used as an "lvalue".  */
   if (TREE_CODE (arg) == COMPOUND_EXPR)
 {
   /* Handle (a, b) used as an "lvalue".  */
   if (TREE_CODE (arg) == COMPOUND_EXPR)
@@ -3283,7 +3314,7 @@ unary_complex_lvalue (code, arg)
 
       /* If this returns a function type, it isn't really being used as
         an lvalue, so don't issue a warning about it.  */
 
       /* If this returns a function type, it isn't really being used as
         an lvalue, so don't issue a warning about it.  */
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
        pedantic_lvalue_warning (COMPOUND_EXPR);
 
       return build (COMPOUND_EXPR, TREE_TYPE (real_result),
        pedantic_lvalue_warning (COMPOUND_EXPR);
 
       return build (COMPOUND_EXPR, TREE_TYPE (real_result),
@@ -3293,14 +3324,15 @@ unary_complex_lvalue (code, arg)
   /* Handle (a ? b : c) used as an "lvalue".  */
   if (TREE_CODE (arg) == COND_EXPR)
     {
   /* Handle (a ? b : c) used as an "lvalue".  */
   if (TREE_CODE (arg) == COND_EXPR)
     {
-      pedantic_lvalue_warning (COND_EXPR);
-      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
+      if (!flag)
+       pedantic_lvalue_warning (COND_EXPR);
+      if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE && !flag)
        pedantic_lvalue_warning (COMPOUND_EXPR);
 
       return (build_conditional_expr
              (TREE_OPERAND (arg, 0),
        pedantic_lvalue_warning (COMPOUND_EXPR);
 
       return (build_conditional_expr
              (TREE_OPERAND (arg, 0),
-              build_unary_op (code, TREE_OPERAND (arg, 1), 0),
-              build_unary_op (code, TREE_OPERAND (arg, 2), 0)));
+              build_unary_op (code, TREE_OPERAND (arg, 1), flag),
+              build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
     }
 
   return 0;
     }
 
   return 0;
@@ -3358,7 +3390,7 @@ int
 mark_addressable (exp)
      tree exp;
 {
 mark_addressable (exp)
      tree exp;
 {
-  register tree x = exp;
+  tree x = exp;
   while (1)
     switch (TREE_CODE (x))
       {
   while (1)
     switch (TREE_CODE (x))
       {
@@ -3443,11 +3475,11 @@ tree
 build_conditional_expr (ifexp, op1, op2)
      tree ifexp, op1, op2;
 {
 build_conditional_expr (ifexp, op1, op2)
      tree ifexp, op1, op2;
 {
-  register tree type1;
-  register tree type2;
-  register enum tree_code code1;
-  register enum tree_code code2;
-  register tree result_type = NULL;
+  tree type1;
+  tree type2;
+  enum tree_code code1;
+  enum tree_code code2;
+  tree result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
 
   ifexp = truthvalue_conversion (default_conversion (ifexp));
   tree orig_op1 = op1, orig_op2 = op2;
 
   ifexp = truthvalue_conversion (default_conversion (ifexp));
@@ -3631,10 +3663,16 @@ internal_build_compound_expr (list, first_p)
      tree list;
      int first_p;
 {
      tree list;
      int first_p;
 {
-  register tree rest;
+  tree rest;
 
   if (TREE_CHAIN (list) == 0)
     {
 
   if (TREE_CHAIN (list) == 0)
     {
+      /* Convert arrays and functions to pointers when there
+        really is a comma operator.  */
+      if (!first_p)
+       TREE_VALUE (list)
+         = default_function_array_conversion (TREE_VALUE (list));
+
 #if 0 /* If something inside inhibited lvalueness, we should not override.  */
       /* Consider (x, y+0), which is not an lvalue since y+0 is not.  */
 
 #if 0 /* If something inside inhibited lvalueness, we should not override.  */
       /* Consider (x, y+0), which is not an lvalue since y+0 is not.  */
 
@@ -3649,14 +3687,6 @@ internal_build_compound_expr (list, first_p)
       return TREE_VALUE (list);
     }
 
       return TREE_VALUE (list);
     }
 
-  if (TREE_CHAIN (list) != 0 && TREE_CHAIN (TREE_CHAIN (list)) == 0)
-    {
-      /* Convert arrays to pointers when there really is a comma operator.  */
-      if (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (list)))) == ARRAY_TYPE)
-       TREE_VALUE (TREE_CHAIN (list))
-         = default_conversion (TREE_VALUE (TREE_CHAIN (list)));
-    }
-
   rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
 
   if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
   rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
 
   if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
@@ -3689,10 +3719,10 @@ internal_build_compound_expr (list, first_p)
 
 tree
 build_c_cast (type, expr)
 
 tree
 build_c_cast (type, expr)
-     register tree type;
+     tree type;
      tree expr;
 {
      tree expr;
 {
-  register tree value = expr;
+  tree value = expr;
   
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
   
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
@@ -3716,7 +3746,7 @@ build_c_cast (type, expr)
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  if (type == TREE_TYPE (value))
+  if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
       if (pedantic)
        {
     {
       if (pedantic)
        {
@@ -3728,9 +3758,7 @@ build_c_cast (type, expr)
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
-      if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
-         || TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE)
-       value = default_conversion (value);
+      value = default_function_array_conversion (value);
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
@@ -3773,9 +3801,7 @@ build_c_cast (type, expr)
 
       /* Convert functions and arrays to pointers,
         but don't convert any other types.  */
 
       /* Convert functions and arrays to pointers,
         but don't convert any other types.  */
-      if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
-         || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE)
-       value = default_conversion (value);
+      value = default_function_array_conversion (value);
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
@@ -3850,7 +3876,7 @@ build_c_cast (type, expr)
        }
     }
 
        }
     }
 
-  /* Pedantically, don't ley (void *) (FOO *) 0 be a null pointer constant.  */
+  /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant.  */
   if (pedantic && TREE_CODE (value) == INTEGER_CST
       && TREE_CODE (expr) == INTEGER_CST
       && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
   if (pedantic && TREE_CODE (value) == INTEGER_CST
       && TREE_CODE (expr) == INTEGER_CST
       && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
@@ -3862,6 +3888,24 @@ build_c_cast (type, expr)
 
   return value;
 }
 
   return value;
 }
+
+/* Interpret a cast of expression EXPR to type TYPE.  */
+tree
+c_cast_expr (type, expr)
+     tree type, expr;
+{
+  int saved_wsp = warn_strict_prototypes;
+
+  /* This avoids warnings about unprototyped casts on
+     integers.  E.g. "#define SIG_DFL (void(*)())0".  */
+  if (TREE_CODE (expr) == INTEGER_CST)
+    warn_strict_prototypes = 0;
+  type = groktypename (type);
+  warn_strict_prototypes = saved_wsp;
+
+  return build_c_cast (type, expr);
+}
+
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
@@ -3873,7 +3917,7 @@ build_modify_expr (lhs, modifycode, rhs)
      tree lhs, rhs;
      enum tree_code modifycode;
 {
      tree lhs, rhs;
      enum tree_code modifycode;
 {
-  register tree result;
+  tree result;
   tree newrhs;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
   tree newrhs;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
@@ -3957,9 +4001,7 @@ build_modify_expr (lhs, modifycode, rhs)
     case FIX_FLOOR_EXPR:
     case FIX_ROUND_EXPR:
     case FIX_CEIL_EXPR:
     case FIX_FLOOR_EXPR:
     case FIX_ROUND_EXPR:
     case FIX_CEIL_EXPR:
-      if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
-         || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE)
-       newrhs = default_conversion (newrhs);
+      newrhs = default_function_array_conversion (newrhs);
       {
        tree inner_lhs = TREE_OPERAND (lhs, 0);
        tree result;
       {
        tree inner_lhs = TREE_OPERAND (lhs, 0);
        tree result;
@@ -4054,9 +4096,9 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
      tree fundecl, funname;
      int parmnum;
 {
      tree fundecl, funname;
      int parmnum;
 {
-  register enum tree_code codel = TREE_CODE (type);
-  register tree rhstype;
-  register enum tree_code coder;
+  enum tree_code codel = TREE_CODE (type);
+  tree rhstype;
+  enum tree_code coder;
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
@@ -4141,8 +4183,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
 
          if (coder == POINTER_TYPE)
            {
 
          if (coder == POINTER_TYPE)
            {
-             register tree ttl = TREE_TYPE (memb_type);
-             register tree ttr = TREE_TYPE (rhstype);
+             tree ttl = TREE_TYPE (memb_type);
+             tree ttr = TREE_TYPE (rhstype);
 
              /* Any non-function converts to a [const][volatile] void *
                 and vice versa; otherwise, targets must be the same.
 
              /* Any non-function converts to a [const][volatile] void *
                 and vice versa; otherwise, targets must be the same.
@@ -4183,8 +4225,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
            {
              /* We have only a marginally acceptable member type;
                 it needs a warning.  */
            {
              /* 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);
+             tree ttl = TREE_TYPE (marginal_memb_type);
+             tree ttr = TREE_TYPE (rhstype);
 
              /* Const and volatile mean something different for function
                 types, so the usual warnings are not appropriate.  */
 
              /* Const and volatile mean something different for function
                 types, so the usual warnings are not appropriate.  */
@@ -4217,8 +4259,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
   else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
           && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
     {
   else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
           && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
     {
-      register tree ttl = TREE_TYPE (type);
-      register tree ttr = TREE_TYPE (rhstype);
+      tree ttl = TREE_TYPE (type);
+      tree ttr = TREE_TYPE (rhstype);
 
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
 
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
@@ -4349,7 +4391,7 @@ warn_for_assignment (msgid, opname, function, argnum)
       if (function)
        {
          /* Function name is known; supply it.  */
       if (function)
        {
          /* Function name is known; supply it.  */
-         const char *argstring = _("passing arg %d of `%s'");
+         const char *const argstring = _("passing arg %d of `%s'");
          new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                                        + strlen (argstring) + 1 + 25
                                        /*%d*/ + 1);
          new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                                        + strlen (argstring) + 1 + 25
                                        /*%d*/ + 1);
@@ -4359,7 +4401,7 @@ warn_for_assignment (msgid, opname, function, argnum)
       else
        {
          /* Function name unknown (call through ptr); just give arg number.*/
       else
        {
          /* Function name unknown (call through ptr); just give arg number.*/
-         const char *argnofun = _("passing arg %d of pointer to function");
+         const char *const argnofun = _("passing arg %d of pointer to function");
          new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argnofun, argnum);
        }
          new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argnofun, argnum);
        }
@@ -4403,7 +4445,7 @@ void
 store_init_value (decl, init)
      tree decl, init;
 {
 store_init_value (decl, init)
      tree decl, init;
 {
-  register tree value, type;
+  tree value, type;
 
   /* If variable's type was invalidly declared, just ignore it.  */
 
 
   /* If variable's type was invalidly declared, just ignore it.  */
 
@@ -4485,7 +4527,7 @@ static int spelling_size;         /* Size of the spelling stack.  */
    Alternative to SAVE_SPELLING_STACK.  */
 
 #define SPELLING_DEPTH() (spelling - spelling_base)
    Alternative to SAVE_SPELLING_STACK.  */
 
 #define SPELLING_DEPTH() (spelling - spelling_base)
-#define RESTORE_SPELLING_DEPTH(depth) (spelling = spelling_base + depth)
+#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
 
 /* Save and restore the spelling stack around arbitrary C code.  */
 
 
 /* Save and restore the spelling stack around arbitrary C code.  */
 
@@ -4537,7 +4579,7 @@ push_member_name (decl)
      tree decl;
      
 {
      tree decl;
      
 {
-  const char *string
+  const char *const string
     = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
   PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
 }
     = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
   PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
 }
@@ -4556,8 +4598,8 @@ push_array_bounds (bounds)
 static int
 spelling_length ()
 {
 static int
 spelling_length ()
 {
-  register int size = 0;
-  register struct spelling *p;
+  int size = 0;
+  struct spelling *p;
 
   for (p = spelling_base; p < spelling; p++)
     {
 
   for (p = spelling_base; p < spelling; p++)
     {
@@ -4574,10 +4616,10 @@ spelling_length ()
 
 static char *
 print_spelling (buffer)
 
 static char *
 print_spelling (buffer)
-     register char *buffer;
+     char *buffer;
 {
 {
-  register char *d = buffer;
-  register struct spelling *p;
+  char *d = buffer;
+  struct spelling *p;
 
   for (p = spelling_base; p < spelling; p++)
     if (p->kind == SPELLING_BOUNDS)
 
   for (p = spelling_base; p < spelling; p++)
     if (p->kind == SPELLING_BOUNDS)
@@ -4587,7 +4629,7 @@ print_spelling (buffer)
       }
     else
       {
       }
     else
       {
-       register const char *s;
+       const char *s;
        if (p->kind == SPELLING_MEMBER)
          *d++ = '.';
        for (s = p->u.s; (*d = *s++); d++)
        if (p->kind == SPELLING_MEMBER)
          *d++ = '.';
        for (s = p->u.s; (*d = *s++); d++)
@@ -4671,6 +4713,8 @@ digest_init (type, init, require_constant, constructor_constant)
   if (TREE_CODE (init) == NON_LVALUE_EXPR)
     inside_init = TREE_OPERAND (init, 0);
 
   if (TREE_CODE (init) == NON_LVALUE_EXPR)
     inside_init = TREE_OPERAND (init, 0);
 
+  inside_init = fold (inside_init);
+
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
 
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
 
@@ -4705,6 +4749,7 @@ digest_init (type, init, require_constant, constructor_constant)
 
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
 
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
+             && TYPE_SIZE (type) != 0
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
              /* Subtract 1 (or sizeof (wchar_t))
                 because it's ok to ignore the terminating null char
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
              /* Subtract 1 (or sizeof (wchar_t))
                 because it's ok to ignore the terminating null char
@@ -4736,10 +4781,8 @@ digest_init (type, init, require_constant, constructor_constant)
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
                            TREE_TYPE (type)))))
     {
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
                            TREE_TYPE (type)))))
     {
-      if (code == POINTER_TYPE
-         && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
-             || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
-       inside_init = default_conversion (inside_init);
+      if (code == POINTER_TYPE)
+       inside_init = default_function_array_conversion (inside_init);
       else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
               && TREE_CODE (inside_init) != CONSTRUCTOR)
        {
       else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
               && TREE_CODE (inside_init) != CONSTRUCTOR)
        {
@@ -4766,14 +4809,21 @@ digest_init (type, init, require_constant, constructor_constant)
          if (flag_pedantic_errors)
            inside_init = error_mark_node;
        }
          if (flag_pedantic_errors)
            inside_init = error_mark_node;
        }
-      else if (require_constant && ! TREE_CONSTANT (inside_init))
+      else if (require_constant 
+              && (!TREE_CONSTANT (inside_init)
+                  /* This test catches things like `7 / 0' which
+                     result in an expression for which TREE_CONSTANT
+                     is true, but which is not actually something
+                     that is a legal constant.  We really should not
+                     be using this function, because it is a part of
+                     the back-end.  Instead, the expression should
+                     already have been turned into ERROR_MARK_NODE.  */
+                  || !initializer_constant_valid_p (inside_init,
+                                                    TREE_TYPE (inside_init))))
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        }
        {
          error_init ("initializer element is not constant");
          inside_init = error_mark_node;
        }
-      else if (require_constant
-              && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
-       pedwarn ("initializer element is not computable at load time");
 
       return inside_init;
     }
 
       return inside_init;
     }
@@ -4943,6 +4993,9 @@ static const char *constructor_asmspec;
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
+/* Nonzero if there were any member designators in this initializer.  */
+static int constructor_designated;
+
 /* Nesting depth of designator list.  */
 static int designator_depth;
 
 /* Nesting depth of designator list.  */
 static int designator_depth;
 
@@ -4980,6 +5033,7 @@ struct constructor_stack
   char erroneous;
   char outer;
   char incremental;
   char erroneous;
   char outer;
   char incremental;
+  char designated;
 };
 
 struct constructor_stack *constructor_stack;
 };
 
 struct constructor_stack *constructor_stack;
@@ -5056,6 +5110,7 @@ start_init (decl, asmspec_tree, top_level)
   constructor_decl = decl;
   constructor_asmspec = asmspec;
   constructor_subconstants_deferred = 0;
   constructor_decl = decl;
   constructor_asmspec = asmspec;
   constructor_subconstants_deferred = 0;
+  constructor_designated = 0;
   constructor_top_level = top_level;
 
   if (decl != 0)
   constructor_top_level = top_level;
 
   if (decl != 0)
@@ -5165,6 +5220,7 @@ really_start_incremental_init (type)
   p->range_stack = 0;
   p->outer = 0;
   p->incremental = constructor_incremental;
   p->range_stack = 0;
   p->outer = 0;
   p->incremental = constructor_incremental;
+  p->designated = constructor_designated;
   p->next = 0;
   constructor_stack = p;
 
   p->next = 0;
   constructor_stack = p;
 
@@ -5175,6 +5231,7 @@ really_start_incremental_init (type)
   constructor_pending_elts = 0;
   constructor_type = type;
   constructor_incremental = 1;
   constructor_pending_elts = 0;
   constructor_type = type;
   constructor_incremental = 1;
+  constructor_designated = 0;
   designator_depth = 0;
   designator_errorneous = 0;
 
   designator_depth = 0;
   designator_errorneous = 0;
 
@@ -5198,7 +5255,8 @@ really_start_incremental_init (type)
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
 
          /* Detect non-empty initializations of zero-length arrays.  */
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
 
          /* Detect non-empty initializations of zero-length arrays.  */
-         if (constructor_max_index == NULL_TREE)
+         if (constructor_max_index == NULL_TREE
+             && TYPE_SIZE (constructor_type))
            constructor_max_index = build_int_2 (-1, -1);
 
          constructor_index
            constructor_max_index = build_int_2 (-1, -1);
 
          constructor_index
@@ -5275,6 +5333,7 @@ push_init_level (implicit)
   p->implicit = implicit;
   p->outer = 0;
   p->incremental = constructor_incremental;
   p->implicit = implicit;
   p->outer = 0;
   p->incremental = constructor_incremental;
+  p->designated = constructor_designated;
   p->next = constructor_stack;
   p->range_stack = 0;
   constructor_stack = p;
   p->next = constructor_stack;
   p->range_stack = 0;
   constructor_stack = p;
@@ -5284,6 +5343,7 @@ push_init_level (implicit)
   constructor_depth = SPELLING_DEPTH ();
   constructor_elements = 0;
   constructor_incremental = 1;
   constructor_depth = SPELLING_DEPTH ();
   constructor_elements = 0;
   constructor_incremental = 1;
+  constructor_designated = 0;
   constructor_pending_elts = 0;
   if (!implicit)
     {
   constructor_pending_elts = 0;
   if (!implicit)
     {
@@ -5360,14 +5420,15 @@ push_init_level (implicit)
        {
          constructor_max_index
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
        {
          constructor_max_index
            = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+
+         /* Detect non-empty initializations of zero-length arrays.  */
+         if (constructor_max_index == NULL_TREE
+             && TYPE_SIZE (constructor_type))
+           constructor_max_index = build_int_2 (-1, -1);
+
          constructor_index
            = convert (bitsizetype, 
                       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
          constructor_index
            = convert (bitsizetype, 
                       TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
-
-         /* ??? For GCC 3.1, remove special case initialization of
-            zero-length array members from pop_init_level and set
-            constructor_max_index such that we get the normal
-            "excess elements" warning.  */
        }
       else
        constructor_index = bitsize_zero_node;
        }
       else
        constructor_index = bitsize_zero_node;
@@ -5402,7 +5463,6 @@ pop_init_level (implicit)
      int implicit;
 {
   struct constructor_stack *p;
      int implicit;
 {
   struct constructor_stack *p;
-  HOST_WIDE_INT size = 0;
   tree constructor = 0;
 
   if (implicit == 0)
   tree constructor = 0;
 
   if (implicit == 0)
@@ -5418,9 +5478,6 @@ pop_init_level (implicit)
 
   p = constructor_stack;
 
 
   p = constructor_stack;
 
-  if (constructor_type != 0)
-    size = int_size_in_bytes (constructor_type);
-
   /* Error for initializing a flexible array member, or a zero-length
      array member in an inappropriate context.  */
   if (constructor_type && constructor_fields
   /* Error for initializing a flexible array member, or a zero-length
      array member in an inappropriate context.  */
   if (constructor_type && constructor_fields
@@ -5439,26 +5496,16 @@ pop_init_level (implicit)
          else if (pedantic)
            pedwarn_init ("initialization of a flexible array member");
 
          else if (pedantic)
            pedwarn_init ("initialization of a flexible array member");
 
-         /* We have already issued an error message for the existance
+         /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
             Discard the initializer so that we do not abort later.  */
          if (TREE_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
       else
             of a flexible array member not at the end of the structure.
             Discard the initializer so that we do not abort later.  */
          if (TREE_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
       else
-       {
-         warning_init ("deprecated initialization of zero-length array");
-
-         /* We must be initializing the last member of a top-level struct.  */
-         if (TREE_CHAIN (constructor_fields) != NULL_TREE)
-           {
-             error_init ("initialization of zero-length array before end of structure");
-             /* Discard the initializer so that we do not abort later.  */
-             constructor_type = NULL_TREE;
-           }
-         else if (constructor_depth > 2)
-           error_init ("initialization of zero-length array inside a nested context");
-       }
+       /* Zero-length arrays are no longer special, so we should no longer
+          get here.  */
+       abort();
     }
 
   /* Warn when some struct elements are implicitly initialized to zero.  */
     }
 
   /* Warn when some struct elements are implicitly initialized to zero.  */
@@ -5473,7 +5520,9 @@ pop_init_level (implicit)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
          constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
 
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
          constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
 
-       if (constructor_unfilled_fields)
+       /* Do not warn if this level of the initializer uses member
+          designators; it is likely to be deliberate.  */
+       if (constructor_unfilled_fields && !constructor_designated)
          {
            push_member_name (constructor_unfilled_fields);
            warning_init ("missing initializer");
          {
            push_member_name (constructor_unfilled_fields);
            warning_init ("missing initializer");
@@ -5539,6 +5588,7 @@ pop_init_level (implicit)
   constructor_simple = p->simple;
   constructor_erroneous = p->erroneous;
   constructor_incremental = p->incremental;
   constructor_simple = p->simple;
   constructor_erroneous = p->erroneous;
   constructor_incremental = p->incremental;
+  constructor_designated = p->designated;
   constructor_pending_elts = p->pending_elts;
   constructor_depth = p->depth;
   if (!p->implicit)
   constructor_pending_elts = p->pending_elts;
   constructor_depth = p->depth;
   if (!p->implicit)
@@ -5585,6 +5635,7 @@ set_designator (array)
         braces.  */
       while (constructor_stack->implicit)
        process_init_element (pop_init_level (1));
         braces.  */
       while (constructor_stack->implicit)
        process_init_element (pop_init_level (1));
+      constructor_designated = 1;
       return 0;
     }
 
       return 0;
     }
 
@@ -5620,6 +5671,7 @@ set_designator (array)
       return 1;
     }
 
       return 1;
     }
 
+  constructor_designated = 1;
   push_init_level (2);
   return 0;
 }
   push_init_level (2);
   return 0;
 }
@@ -5689,21 +5741,27 @@ set_init_index (first, last)
     {
       constructor_index = convert (bitsizetype, first);
 
     {
       constructor_index = convert (bitsizetype, first);
 
-      if (last != 0 && tree_int_cst_lt (last, first))
+      if (last)
        {
        {
-         error_init ("empty index range in initializer");
-         last = 0;
-       }
-      else if (last)
-       {
-         last = convert (bitsizetype, last);
-         if (constructor_max_index != 0
-             && tree_int_cst_lt (constructor_max_index, last))
+         if (tree_int_cst_equal (first, last))
+           last = 0;
+         else if (tree_int_cst_lt (last, first))
            {
            {
-             error_init ("array index range in initializer exceeds array bounds");
+             error_init ("empty index range in initializer");
              last = 0;
            }
              last = 0;
            }
+         else
+           {
+             last = convert (bitsizetype, last);
+             if (constructor_max_index != 0
+                 && tree_int_cst_lt (constructor_max_index, last))
+               {
+                 error_init ("array index range in initializer exceeds array bounds");
+                 last = 0;
+               }
+           }
        }
        }
+
       designator_depth++;
       designator_errorneous = 0;
       if (constructor_range_stack || last)
       designator_depth++;
       designator_errorneous = 0;
       if (constructor_range_stack || last)
@@ -5752,7 +5810,7 @@ set_init_label (fieldname)
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
-   indentifies the initializer, either array index or field in a structure. 
+   identifies the initializer, either array index or field in a structure. 
    VALUE is the value of that index or field.  */
 
 static void
    VALUE is the value of that index or field.  */
 
 static void
@@ -5826,7 +5884,7 @@ add_pending_init (purpose, value)
            {
              if (r->balance < 0)
                {
            {
              if (r->balance < 0)
                {
-                 /* L rotation. */
+                 /* L rotation.  */
                  p->left = r->right;
                  if (p->left)
                    p->left->parent = p;
                  p->left = r->right;
                  if (p->left)
                    p->left->parent = p;
@@ -5850,7 +5908,7 @@ add_pending_init (purpose, value)
                }
              else
                {
                }
              else
                {
-                 /* LR rotation. */
+                 /* LR rotation.  */
                  struct init_node *t = r->right;
 
                  r->right = t->left;
                  struct init_node *t = r->right;
 
                  r->right = t->left;
@@ -5899,7 +5957,7 @@ add_pending_init (purpose, value)
            {
              if (r->balance > 0)
                {
            {
              if (r->balance > 0)
                {
-                 /* R rotation. */
+                 /* R rotation.  */
                  p->right = r->left;
                  if (p->right)
                    p->right->parent = p;
                  p->right = r->left;
                  if (p->right)
                    p->right->parent = p;
@@ -5958,7 +6016,7 @@ add_pending_init (purpose, value)
            }
          else
            {
            }
          else
            {
-             /* p->balance == -1; growth of right side balances the node. */
+             /* p->balance == -1; growth of right side balances the node.  */
              p->balance = 0;
              break;
            }
              p->balance = 0;
              break;
            }
@@ -6591,8 +6649,12 @@ process_init_element (value)
             under the assumption that the zero initializer in user
             code appears conditioned on e.g. __STDC__ to avoid
             "missing initializer" warnings and relies on default
             under the assumption that the zero initializer in user
             code appears conditioned on e.g. __STDC__ to avoid
             "missing initializer" warnings and relies on default
-            initialization to zero in the traditional C case.  */
-         if (warn_traditional && !in_system_header
+            initialization to zero in the traditional C case.
+            We also skip the warning if the initializer is designated,
+            again on the assumption that this must be conditional on
+            __STDC__ anyway (and we've already complained about the
+            member-designator already).  */
+         if (warn_traditional && !in_system_header && !constructor_designated
              && !(value && (integer_zerop (value) || real_zerop (value))))
            warning ("traditional C rejects initialization of unions");
 
              && !(value && (integer_zerop (value) || real_zerop (value))))
            warning ("traditional C rejects initialization of unions");
 
@@ -6750,6 +6812,33 @@ process_init_element (value)
   constructor_range_stack = 0;
 }
 \f
   constructor_range_stack = 0;
 }
 \f
+/* Build a simple asm-statement, from one string literal.  */
+tree
+simple_asm_stmt (expr)
+     tree expr;
+{
+  STRIP_NOPS (expr);
+
+  if (TREE_CODE (expr) == ADDR_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+
+  if (TREE_CODE (expr) == STRING_CST)
+    {
+      tree stmt;
+
+      if (TREE_CHAIN (expr))
+       expr = combine_strings (expr);
+      stmt = add_stmt (build_stmt (ASM_STMT, NULL_TREE, expr,
+                                  NULL_TREE, NULL_TREE,
+                                  NULL_TREE));
+      ASM_INPUT_P (stmt) = 1;
+      return stmt;
+    }
+
+  error ("argument of `asm' is not a constant string");
+  return NULL_TREE;
+}
+
 /* Build an asm-statement, whose components are a CV_QUALIFIER, a
    STRING, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
 
 /* Build an asm-statement, whose components are a CV_QUALIFIER, a
    STRING, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
 
@@ -6814,9 +6903,7 @@ build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
      Don't do this for other types as it would screw up operands
      expected to be in memory.  */
   for (tail = inputs; tail; tail = TREE_CHAIN (tail))
      Don't do this for other types as it would screw up operands
      expected to be in memory.  */
   for (tail = inputs; tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
-       || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
-      TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
+    TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
 
   return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
                               outputs, inputs, clobbers));
 
   return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
                               outputs, inputs, clobbers));
@@ -6836,10 +6923,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
      int line;
 {
   int noutputs = list_length (outputs);
      int line;
 {
   int noutputs = list_length (outputs);
-  register int i;
+  int i;
   /* o[I] is the place that output number I should be written.  */
   /* o[I] is the place that output number I should be written.  */
-  register tree *o = (tree *) alloca (noutputs * sizeof (tree));
-  register tree tail;
+  tree *o = (tree *) alloca (noutputs * sizeof (tree));
+  tree tail;
 
   /* Record the contents of OUTPUTS before it is modified.  */
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
 
   /* Record the contents of OUTPUTS before it is modified.  */
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
@@ -7004,7 +7091,7 @@ tree
 c_start_case (exp)
      tree exp;
 {
 c_start_case (exp)
      tree exp;
 {
-  register enum tree_code code;
+  enum tree_code code;
   tree type;
   struct c_switch *cs;
 
   tree type;
   struct c_switch *cs;
 
@@ -7013,8 +7100,7 @@ c_start_case (exp)
       code = TREE_CODE (TREE_TYPE (exp));
       type = TREE_TYPE (exp);
 
       code = TREE_CODE (TREE_TYPE (exp));
       type = TREE_TYPE (exp);
 
-      if (code != INTEGER_TYPE 
-         && code != ENUMERAL_TYPE 
+      if (! INTEGRAL_TYPE_P (type)
          && code != ERROR_MARK)
        {
          error ("switch quantity not an integer");
          && code != ERROR_MARK)
        {
          error ("switch quantity not an integer");