OSDN Git Service

* doc/fragments.texi, doc/trouble.texi: Remove links to old
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index d1d16bd..64f0f07 100644 (file)
@@ -1,23 +1,23 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000 Free Software Foundation, Inc.
+   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
-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.
@@ -40,23 +40,27 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "toplev.h"
 #include "intl.h"
-#include "defaults.h"
 #include "ggc.h"
+#include "target.h"
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 static int missing_braces_mentioned;
 
+/* 1 if we explained undeclared var errors.  */
+static int undeclared_variable_notice;
+
 static tree qualify_type               PARAMS ((tree, tree));
 static int comp_target_types           PARAMS ((tree, tree));
 static int function_types_compatible_p PARAMS ((tree, tree));
 static int type_lists_compatible_p     PARAMS ((tree, tree));
-static tree decl_constant_value                PARAMS ((tree));
-static tree lookup_field               PARAMS ((tree, tree, tree *));
+static tree decl_constant_value_for_broken_optimization PARAMS ((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 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 *,
@@ -71,11 +75,14 @@ static int spelling_length          PARAMS ((void));
 static char *print_spelling            PARAMS ((char *));
 static void warning_init               PARAMS ((const char *));
 static tree digest_init                        PARAMS ((tree, tree, int, int));
-static void check_init_type_bitfields  PARAMS ((tree));
 static void output_init_element                PARAMS ((tree, tree, tree, int));
 static void output_pending_init_elements PARAMS ((int));
+static int set_designator              PARAMS ((int));
+static void push_range_stack           PARAMS ((tree));
 static void add_pending_init           PARAMS ((tree, tree));
-static int pending_init_member         PARAMS ((tree));
+static void set_nonincremental_init    PARAMS ((void));
+static void set_nonincremental_init_from_string        PARAMS ((tree));
+static tree find_init_member           PARAMS ((tree));
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -90,8 +97,7 @@ require_complete_type (value)
     return error_mark_node;
 
   /* First, detect a valid value with a complete type.  */
-  if (TYPE_SIZE (type) != 0
-      && type != void_type_node)
+  if (COMPLETE_TYPE_P (type))
     return value;
 
   incomplete_type_error (value, type);
@@ -186,8 +192,8 @@ tree
 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.  */
@@ -201,7 +207,7 @@ common_type (t1, t2)
     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.  */
 
@@ -349,6 +355,9 @@ common_type (t1, t2)
        /* 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;
 
@@ -386,7 +395,7 @@ common_type (t1, t2)
                    {
                      TREE_VALUE (n) = TREE_VALUE (p2);
                      if (pedantic)
-                       pedwarn ("function types not truly compatible in ANSI C");
+                       pedwarn ("function types not truly compatible in ISO C");
                      goto parm_done;
                    }
              }
@@ -400,7 +409,7 @@ common_type (t1, t2)
                    {
                      TREE_VALUE (n) = TREE_VALUE (p1);
                      if (pedantic)
-                       pedwarn ("function types not truly compatible in ANSI C");
+                       pedwarn ("function types not truly compatible in ISO C");
                      goto parm_done;
                    }
              }
@@ -408,6 +417,8 @@ common_type (t1, t2)
          parm_done: ;
          }
 
+       poplevel (0, 0, 0);
+
        t1 = build_function_type (valtype, newargs);
        /* ... falls through ...  */
       }
@@ -426,8 +437,8 @@ int
 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.  */
@@ -473,12 +484,8 @@ comptypes (type1, type2)
   if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return 1;
 
-#ifndef COMP_TYPE_ATTRIBUTES
-#define COMP_TYPE_ATTRIBUTES(t1,t2)    1
-#endif
-
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+  if (! (attrval = (*targetm.comp_type_attributes) (t1, t2)))
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -499,6 +506,8 @@ comptypes (type1, type2)
       {
        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.  */
@@ -507,14 +516,25 @@ comptypes (type1, type2)
          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;
 
-       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;
 
@@ -642,7 +662,8 @@ type_lists_compatible_p (args1, args2)
          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.  */
@@ -696,33 +717,38 @@ c_sizeof (type)
      tree type;
 {
   enum tree_code code = TREE_CODE (type);
+  tree size;
 
   if (code == FUNCTION_TYPE)
     {
       if (pedantic || warn_pointer_arith)
        pedwarn ("sizeof applied to a function type");
-      return size_one_node;
+      size = size_one_node;
     }
-  if (code == VOID_TYPE)
+  else if (code == VOID_TYPE)
     {
       if (pedantic || warn_pointer_arith)
        pedwarn ("sizeof applied to a void type");
-      return size_one_node;
+      size = size_one_node;
     }
-
-  if (code == ERROR_MARK)
-    return size_one_node;
-
-  if (TYPE_SIZE (type) == 0)
+  else if (code == ERROR_MARK)
+    size = size_one_node;
+  else if (!COMPLETE_TYPE_P (type))
     {
       error ("sizeof applied to an incomplete type");
-      return size_zero_node;
+      size = size_zero_node;
     }
-
-  /* Convert in case a char is more than one unit.  */
-  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                    size_int (TYPE_PRECISION (char_type_node)
-                              / BITS_PER_UNIT));
+  else
+    /* Convert in case a char is more than one unit.  */
+    size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                      size_int (TYPE_PRECISION (char_type_node)
+                                / BITS_PER_UNIT));
+
+  /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
+     TYPE_IS_SIZETYPE means that certain things (like overflow) will
+     never happen.  However, this node should really have type
+     `size_t', which is just a typedef for an ordinary integer type.  */
+  return fold (build1 (NOP_EXPR, c_size_type_node, size));
 }
 
 tree
@@ -730,17 +756,23 @@ c_sizeof_nowarn (type)
      tree type;
 {
   enum tree_code code = TREE_CODE (type);
+  tree size;
 
   if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
-    return size_one_node;
-
-  if (TYPE_SIZE (type) == 0)
-    return size_zero_node;
-
-  /* Convert in case a char is more than one unit.  */
-  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                    size_int (TYPE_PRECISION (char_type_node)
-                              / BITS_PER_UNIT));
+    size = size_one_node;
+  else if (!COMPLETE_TYPE_P (type))
+    size = size_zero_node;
+  else
+    /* Convert in case a char is more than one unit.  */
+    size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                      size_int (TYPE_PRECISION (char_type_node)
+                                / BITS_PER_UNIT));
+
+  /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
+     TYPE_IS_SIZETYPE means that certain things (like overflow) will
+     never happen.  However, this node should really have type
+     `size_t', which is just a typedef for an ordinary integer type.  */
+  return fold (build1 (NOP_EXPR, c_size_type_node, size));
 }
 
 /* Compute the size to increment a pointer by.  */
@@ -754,7 +786,7 @@ c_size_in_bytes (type)
   if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
     return size_one_node;
 
-  if (TYPE_SIZE (type) == 0)
+  if (!COMPLETE_OR_VOID_TYPE_P (type))
     {
       error ("arithmetic on pointer to an incomplete type");
       return size_one_node;
@@ -765,87 +797,18 @@ c_size_in_bytes (type)
                     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);
-
-  if (code == FUNCTION_TYPE)
-    return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-
-  if (code == VOID_TYPE || code == ERROR_MARK)
-    return size_one_node;
-
-  if (TYPE_SIZE (type) == 0)
-    {
-      error ("__alignof__ applied to an incomplete type");
-      return size_zero_node;
-    }
-
-  return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
-}
 \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;
-{
-  if (TREE_CODE (expr) == VAR_DECL)
-    return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
-  if (TREE_CODE (expr) == COMPONENT_REF
-      && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
-    {
-      error ("`__alignof' applied to a bit-field");
-      return size_one_node;
-    }
-  else if (TREE_CODE (expr) == COMPONENT_REF
-      && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
-    return size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
-  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 either DECL or its known constant value (if it has one).  */
 
-static tree
+tree
 decl_constant_value (decl)
      tree decl;
 {
   if (/* Don't change a variable array bound or initial value to a constant
         in a place where a variable is invalid.  */
       current_function_decl != 0
-      && ! pedantic
       && ! TREE_THIS_VOLATILE (decl)
-      && TREE_READONLY (decl) && ! ITERATOR_P (decl)
+      && TREE_READONLY (decl)
       && DECL_INITIAL (decl) != 0
       && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
       /* This is invalid if initial value is not constant.
@@ -853,12 +816,133 @@ decl_constant_value (decl)
         or a variable, then re-evaluating it could give different results.  */
       && TREE_CONSTANT (DECL_INITIAL (decl))
       /* Check for cases where this is sub-optimal, even though valid.  */
-      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
-      && DECL_MODE (decl) != BLKmode)
+      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
     return DECL_INITIAL (decl);
   return decl;
 }
 
+/* Return either DECL or its known constant value (if it has one), but
+   return DECL if pedantic or DECL has mode BLKmode.  This is for
+   bug-compatibility with the old behavior of decl_constant_value
+   (before GCC 3.0); every use of this function is a bug and it should
+   be removed before GCC 3.1.  It is not appropriate to use pedantic
+   in a way that affects optimization, and BLKmode is probably not the
+   right test for avoiding misoptimizations either.  */
+
+static tree
+decl_constant_value_for_broken_optimization (decl)
+     tree decl;
+{
+  if (pedantic || DECL_MODE (decl) == BLKmode)
+    return decl;
+  else
+    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.
@@ -868,8 +952,12 @@ tree
 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)
@@ -880,7 +968,7 @@ default_conversion (exp)
      address of the array produces consistent results.  */
   else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
     {
-      exp = decl_constant_value (exp);
+      exp = decl_constant_value_for_broken_optimization (exp);
       type = TREE_TYPE (exp);
     }
 
@@ -889,11 +977,16 @@ default_conversion (exp)
 
      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);
 
+  /* 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)
@@ -911,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
-        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);
 
-  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.  */
@@ -939,84 +1032,23 @@ default_conversion (exp)
       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'
-         || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
-       {
-         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
-/* 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
-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
@@ -1042,18 +1074,15 @@ lookup_field (type, component, indirect)
              /* 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)
-                   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.  */
@@ -1075,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)
-       field = 0;
+       return NULL_TREE;
     }
   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 (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
@@ -1113,27 +1138,27 @@ tree
 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;
-
-  /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it
-     unless we are not to support things not strictly ANSI.  */
+  tree type = TREE_TYPE (datum);
+  enum tree_code code = TREE_CODE (type);
+  tree field = NULL;
+  tree ref;
+
+  /* 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),
-                     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;
     }
@@ -1142,15 +1167,13 @@ build_component_ref (datum, component)
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
     {
-      tree indirect = 0;
-
-      if (TYPE_SIZE (type) == 0)
+      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)
        {
@@ -1159,29 +1182,27 @@ build_component_ref (datum, component)
                 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;
-         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;
        }
 
-      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)
@@ -1200,8 +1221,8 @@ build_indirect_ref (ptr, 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)
     {
@@ -1213,15 +1234,14 @@ build_indirect_ref (ptr, errorstring)
       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 (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
+         if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
              error ("dereferencing pointer to incomplete type");
              return error_mark_node;
            }
-         if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
+         if (VOID_TYPE_P (t) && skip_evaluation == 0)
            warning ("dereferencing `void *' pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -1296,7 +1316,7 @@ build_array_ref (array, index)
         address arithmetic on its address.
         Likewise an array of elements of variable size.  */
       if (TREE_CODE (index) != INTEGER_CST
-         || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
+         || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
              && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
        {
          if (mark_addressable (array) == 0)
@@ -1314,21 +1334,15 @@ build_array_ref (array, index)
            return error_mark_node;
        }
 
-      if (pedantic && !lvalue_p (array))
-       {
-         if (DECL_REGISTER (array))
-           pedwarn ("ANSI C forbids subscripting `register' array");
-         else
-           pedwarn ("ANSI C forbids subscripting non-lvalue array");
-       }
-
       if (pedantic)
        {
          tree foo = array;
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
-           pedwarn ("ANSI C forbids subscripting non-lvalue array");
+           pedwarn ("ISO C forbids subscripting `register' array");
+         else if (! flag_isoc99 && ! lvalue_p (foo))
+           pedwarn ("ISO C89 forbids subscripting non-lvalue array");
        }
 
       type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
@@ -1391,32 +1405,122 @@ build_array_ref (array, index)
   }
 }
 \f
-/* Build a function call to function FUNCTION with parameters PARAMS.
-   PARAMS is a list--a chain of TREE_LIST nodes--in which the
-   TREE_VALUE of each node is a parameter-expression.
-   FUNCTION's data type may be a function type or a pointer-to-function.  */
-
+/* Build an external reference to identifier ID.  FUN indicates
+   whether this will be used for a function call.  */
 tree
-build_function_call (function, params)
-     tree function, params;
+build_external_ref (id, fun)
+     tree id;
+     int fun;
 {
-  register tree fntype, fundecl = 0;
-  register tree coerced_params;
-  tree name = NULL_TREE, assembler_name = NULL_TREE, result;
+  tree ref;
+  tree decl = lookup_name (id);
+  tree objc_ivar = lookup_objc_ivar (id);
 
-  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
-  STRIP_TYPE_NOPS (function);
-
-  /* Convert anything with function type to a pointer-to-function.  */
-  if (TREE_CODE (function) == FUNCTION_DECL)
+  if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl))
     {
-      name = DECL_NAME (function);
-      assembler_name = DECL_ASSEMBLER_NAME (function);
-
-      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
-        (because calling an inline function does not mean the function
-        needs to be separately compiled).  */
-      fntype = build_type_variant (TREE_TYPE (function),
+      if (objc_ivar)
+       ref = objc_ivar;
+      else if (fun)
+       {
+         if (!decl || decl == error_mark_node)
+           /* Ordinary implicit function declaration.  */
+           ref = implicitly_declare (id);
+         else
+           {
+             /* Implicit declaration of built-in function.  Don't
+                change the built-in declaration, but don't let this
+                go by silently, either.  */
+             implicit_decl_warning (id);
+
+             /* only issue this warning once */
+             C_DECL_ANTICIPATED (decl) = 0;
+             ref = decl;
+           }
+       }
+      else
+       {
+         /* Reference to undeclared variable, including reference to
+            builtin outside of function-call context.  */
+         if (current_function_decl == 0)
+           error ("`%s' undeclared here (not in a function)",
+                  IDENTIFIER_POINTER (id));
+         else
+           {
+             if (IDENTIFIER_GLOBAL_VALUE (id) != error_mark_node
+                 || IDENTIFIER_ERROR_LOCUS (id) != current_function_decl)
+               {
+                 error ("`%s' undeclared (first use in this function)",
+                        IDENTIFIER_POINTER (id));
+
+                 if (! undeclared_variable_notice)
+                   {
+                     error ("(Each undeclared identifier is reported only once");
+                     error ("for each function it appears in.)");
+                     undeclared_variable_notice = 1;
+                   }
+               }
+             IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
+             IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
+           }
+         return error_mark_node;
+       }
+    }
+  else
+    {
+      /* Properly declared variable or function reference.  */
+      if (!objc_ivar)
+       ref = decl;
+      else if (decl != objc_ivar && IDENTIFIER_LOCAL_VALUE (id))
+       {
+         warning ("local declaration of `%s' hides instance variable",
+                  IDENTIFIER_POINTER (id));
+         ref = decl;
+       }
+      else
+       ref = objc_ivar;
+    }
+
+  if (TREE_TYPE (ref) == error_mark_node)
+    return error_mark_node;
+
+  assemble_external (ref);
+  TREE_USED (ref) = 1;
+
+  if (TREE_CODE (ref) == CONST_DECL)
+    {
+      ref = DECL_INITIAL (ref);
+      TREE_CONSTANT (ref) = 1;
+    }
+
+  return ref;
+}
+
+/* Build a function call to function FUNCTION with parameters PARAMS.
+   PARAMS is a list--a chain of TREE_LIST nodes--in which the
+   TREE_VALUE of each node is a parameter-expression.
+   FUNCTION's data type may be a function type or a pointer-to-function.  */
+
+tree
+build_function_call (function, params)
+     tree function, 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.  */
+  STRIP_TYPE_NOPS (function);
+
+  /* Convert anything with function type to a pointer-to-function.  */
+  if (TREE_CODE (function) == FUNCTION_DECL)
+    {
+      name = DECL_NAME (function);
+      assembler_name = DECL_ASSEMBLER_NAME (function);
+
+      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
+        (because calling an inline function does not mean the function
+        needs to be separately compiled).  */
+      fntype = build_type_variant (TREE_TYPE (function),
                                   TREE_READONLY (function),
                                   TREE_THIS_VOLATILE (function));
       fundecl = function;
@@ -1448,8 +1552,8 @@ build_function_call (function, params)
 
   /* Check for errors in format strings.  */
 
-  if (warn_format && (name || assembler_name))
-    check_function_format (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
@@ -1467,9 +1571,10 @@ build_function_call (function, params)
 
   result = build (CALL_EXPR, TREE_TYPE (fntype),
                  function, coerced_params, NULL_TREE);
-
   TREE_SIDE_EFFECTS (result) = 1;
-  if (TREE_TYPE (result) == void_type_node)
+  result = fold (result);
+
+  if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
   return require_complete_type (result);
 }
@@ -1496,8 +1601,8 @@ static tree
 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
@@ -1507,8 +1612,8 @@ convert_arguments (typelist, values, name, fundecl)
        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)
        {
@@ -1526,9 +1631,7 @@ convert_arguments (typelist, values, name, fundecl)
       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);
 
@@ -1537,7 +1640,7 @@ convert_arguments (typelist, values, name, fundecl)
          /* Formal parm type is specified by a function prototype.  */
          tree parmval;
 
-         if (TYPE_SIZE (type) == 0)
+         if (!COMPLETE_TYPE_P (type))
            {
              error ("type of formal parameter %d is incomplete", parmnum + 1);
              parmval = val;
@@ -1546,19 +1649,25 @@ convert_arguments (typelist, values, name, fundecl)
            {
              /* 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);
+                 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
+                          && 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);
@@ -1573,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);
                    }
-                 /* 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
-                         && 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.  */
                        ;
@@ -1631,8 +1743,7 @@ convert_arguments (typelist, values, name, fundecl)
                                                fundecl, name, parmnum + 1);
              
              if (PROMOTE_PROTOTYPES
-                 && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE)
+                 && INTEGRAL_TYPE_P (type)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
@@ -1682,11 +1793,9 @@ parser_build_binary_op (code, arg1, arg2)
   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);
-  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
@@ -1756,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.  */
-  if (class == 'e' || class == '1'
-      || class == '2' || class == '<')
+  if (IS_EXPR_CODE_CLASS (class))
     C_SET_EXP_ORIGINAL_CODE (result, code);
   else
     {
@@ -1796,17 +1904,17 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
      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.  */
-  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.  */
-  register tree result_type = NULL;
+  tree result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -1904,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:
+      /* 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
@@ -1957,6 +2070,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
 
     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
@@ -2094,26 +2210,26 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
        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.  */
          if (comp_target_types (type0, type1))
            result_type = common_type (type0, type1);
-         else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
+         else if (VOID_TYPE_P (tt0))
            {
              /* op0 != orig_op0 detects the case of something
                 whose value is 0 but which isn't a valid null ptr const.  */
              if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
-               pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
+               pedwarn ("ISO C forbids comparison of `void *' with function pointer");
            }
-         else if (TYPE_MAIN_VARIANT (tt1) == void_type_node)
+         else if (VOID_TYPE_P (tt1))
            {
              if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
-               pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
+               pedwarn ("ISO C forbids comparison of `void *' with function pointer");
            }
          else
            pedwarn ("comparison of distinct pointer types lacks a cast");
@@ -2153,7 +2269,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
              result_type = common_type (type0, type1);
              if (pedantic 
                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-               pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+               pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
            }
          else
            {
@@ -2176,12 +2292,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
          if (comp_target_types (type0, type1))
            {
              result_type = common_type (type0, type1);
-             if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
-                 != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
+             if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
+                 != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
                pedwarn ("comparison of complete and incomplete pointers");
              else if (pedantic 
                       && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-               pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
+               pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
            }
          else
            {
@@ -2337,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
-             /* 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
-               = 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);
@@ -2418,11 +2524,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
                  else
                    sop = xop1, uop = xop0;
 
-                 /* Do not warn if the signed quantity is an unsuffixed
-                    integer literal (or some static constant expression
-                    involving such literals) and it is non-negative.  */
-                 if (TREE_CODE (sop) == INTEGER_CST
-                     && tree_int_cst_sgn (sop) >= 0)
+                 /* Do not warn if the signed quantity is an
+                    unsuffixed integer literal (or some static
+                    constant expression involving such literals or a
+                    conditional expression involving such literals)
+                    and it is non-negative.  */
+                 if (tree_expr_nonnegative_p (sop))
                    /* OK */;
                  /* Do not warn if the comparison is an equality operation,
                     the unsigned quantity is an integral constant, and it
@@ -2524,8 +2631,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
     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)
@@ -2542,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;
-     register tree ptrop, intop;
+     tree ptrop, intop;
 {
   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.  */
 
-  register tree result_type = TREE_TYPE (ptrop);
+  tree result_type = TREE_TYPE (ptrop);
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
@@ -2630,12 +2737,14 @@ pointer_int_sum (resultcode, ptrop, intop)
 
 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 con0, con1, lit0, lit1;
+  tree orig_op1 = op1;
 
   if (pedantic || warn_pointer_arith)
     {
@@ -2645,6 +2754,40 @@ pointer_diff (op0, op1)
        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
@@ -2653,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.  */
-  if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
+  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.  */
@@ -2671,24 +2814,29 @@ pointer_diff (op0, op1)
 \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
-build_unary_op (code, xarg, noconvert)
+build_unary_op (code, xarg, flag)
      enum tree_code code;
      tree xarg;
-     int noconvert;
+     int flag;
 {
   /* 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;
+  int noconvert = flag;
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
-  if (typecode == ENUMERAL_TYPE)
+  if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
     typecode = INTEGER_TYPE;
 
   switch (code)
@@ -2722,6 +2870,8 @@ build_unary_op (code, xarg, noconvert)
       if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
+         if (pedantic)
+           pedwarn ("ISO C does not support `~' for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
        }
@@ -2796,7 +2946,7 @@ build_unary_op (code, xarg, noconvert)
       /* 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;
 
@@ -2806,6 +2956,9 @@ build_unary_op (code, xarg, noconvert)
        {
          tree real, imag;
 
+         if (pedantic)
+           pedwarn ("ISO C does not support `++' and `--' on complex types");
+
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
@@ -2818,14 +2971,16 @@ build_unary_op (code, xarg, noconvert)
       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;
        }
 
       {
-       register tree inc;
+       tree inc;
        tree result_type = TREE_TYPE (arg);
 
        arg = get_unwidened (arg, 0);
@@ -2837,16 +2992,23 @@ build_unary_op (code, xarg, noconvert)
          {
            /* If pointer target is an undefined struct,
               we just cannot know how to do the arithmetic.  */
-           if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
-             error ("%s of pointer to unknown structure",
-                    code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
-                    ? "increment" : "decrement");
+           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
+             {
+               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))
-             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
@@ -2878,18 +3040,23 @@ build_unary_op (code, xarg, noconvert)
              else
                {
                  tree incremented, modify, value;
-                 arg = stabilize_reference (arg);
-                 if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
-                   value = arg;
+                 if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+                   value = boolean_increment (code, arg);
                  else
-                   value = save_expr (arg);
-                 incremented = build (((code == PREINCREMENT_EXPR
-                                        || code == POSTINCREMENT_EXPR)
-                                       ? PLUS_EXPR : MINUS_EXPR),
-                                      argtype, value, inc);
-                 TREE_SIDE_EFFECTS (incremented) = 1;
-                 modify = build_modify_expr (arg, NOP_EXPR, incremented);
-                 value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+                   {
+                     arg = stabilize_reference (arg);
+                     if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+                       value = arg;
+                     else
+                       value = save_expr (arg);
+                     incremented = build (((code == PREINCREMENT_EXPR
+                                            || code == POSTINCREMENT_EXPR)
+                                           ? PLUS_EXPR : MINUS_EXPR),
+                                          argtype, value, inc);
+                     TREE_SIDE_EFFECTS (incremented) = 1;
+                     modify = build_modify_expr (arg, NOP_EXPR, incremented);
+                     value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+                   }
                  TREE_USED (value) = 1;
                  return value;
                }
@@ -2912,9 +3079,12 @@ build_unary_op (code, xarg, noconvert)
          readonly_warning (arg, 
                            ((code == PREINCREMENT_EXPR
                              || code == POSTINCREMENT_EXPR)
-                            ? "increment" : "decrement"));
+                            ? _("increment") : _("decrement")));
 
-       val = build (code, TREE_TYPE (arg), arg, inc);
+       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+         val = boolean_increment (code, arg);
+       else
+         val = build (code, TREE_TYPE (arg), arg, inc);
        TREE_SIDE_EFFECTS (val) = 1;
        val = convert (result_type, val);
        if (TREE_CODE (val) != code)
@@ -2923,8 +3093,7 @@ build_unary_op (code, xarg, noconvert)
       }
 
     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)
@@ -2946,7 +3115,7 @@ build_unary_op (code, xarg, noconvert)
 
       /* 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;
 
@@ -2965,7 +3134,7 @@ build_unary_op (code, xarg, noconvert)
        case FIX_ROUND_EXPR:
        case FIX_CEIL_EXPR:
          if (pedantic)
-           pedwarn ("ANSI C forbids the address of a cast expression");
+           pedwarn ("ISO C forbids the address of a cast expression");
          return convert (build_pointer_type (TREE_TYPE (arg)),
                          build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0),
                                          0));
@@ -2977,25 +3146,23 @@ build_unary_op (code, xarg, noconvert)
       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;
 
       /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
       argtype = TREE_TYPE (arg);
+
       /* If the lvalue is const or volatile, merge that into the type
          to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
-      if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
-         || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
-       {
-         if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
-           argtype = c_build_type_variant (argtype,
-                                           TREE_READONLY (arg),
-                                           TREE_THIS_VOLATILE (arg));
-       }
+      if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
+         argtype = c_build_type_variant (argtype,
+                                         TREE_READONLY (arg),
+                                         TREE_THIS_VOLATILE (arg));
 
       argtype = build_pointer_type (argtype);
 
@@ -3009,7 +3176,7 @@ build_unary_op (code, xarg, noconvert)
          {
            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))
              {
@@ -3018,19 +3185,9 @@ build_unary_op (code, xarg, noconvert)
                return error_mark_node;
              }
 
-           addr = convert (argtype, addr);
-
-           if (! integer_zerop (bit_position (field)))
-             {
-               tree offset
-                 = size_binop (EASY_DIV_EXPR, bit_position (field),
-                               bitsize_int (BITS_PER_UNIT));
-               int flag = TREE_CONSTANT (addr);
-
-               addr = fold (build (PLUS_EXPR, argtype,
-                                   addr, convert (argtype, offset)));
-               TREE_CONSTANT (addr) = flag;
-             }
+           addr = fold (build (PLUS_EXPR, argtype,
+                               convert (argtype, addr),
+                               convert (argtype, byte_position (field))));
          }
        else
          addr = build1 (code, argtype, arg);
@@ -3090,7 +3247,7 @@ int
 lvalue_p (ref)
      tree ref;
 {
-  register enum tree_code code = TREE_CODE (ref);
+  enum tree_code code = TREE_CODE (ref);
 
   switch (code)
     {
@@ -3138,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
-   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
-unary_complex_lvalue (code, arg)
+unary_complex_lvalue (code, arg, flag)
      enum tree_code code;
      tree arg;
+     int flag;
 {
   /* Handle (a, b) used as an "lvalue".  */
   if (TREE_CODE (arg) == COMPOUND_EXPR)
@@ -3154,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 (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),
@@ -3164,14 +3324,15 @@ unary_complex_lvalue (code, arg)
   /* 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),
-              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;
@@ -3188,13 +3349,13 @@ pedantic_lvalue_warning (code)
     switch (code)
       {
       case COND_EXPR:
-       pedwarn ("ANSI C forbids use of conditional expressions as lvalues");
+       pedwarn ("ISO C forbids use of conditional expressions as lvalues");
        break;
       case COMPOUND_EXPR:
-       pedwarn ("ANSI C forbids use of compound expressions as lvalues");
+       pedwarn ("ISO C forbids use of compound expressions as lvalues");
        break;
       default:
-       pedwarn ("ANSI C forbids use of cast expressions as lvalues");
+       pedwarn ("ISO C forbids use of cast expressions as lvalues");
        break;
       }
 }
@@ -3206,11 +3367,6 @@ readonly_warning (arg, msgid)
      tree arg;
      const char *msgid;
 {
-  /* Forbid assignments to iterators.  */
-  if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
-    pedwarn ("%s of iterator `%s'",  _(msgid), 
-            IDENTIFIER_POINTER (DECL_NAME (arg)));
-
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
@@ -3234,7 +3390,7 @@ int
 mark_addressable (exp)
      tree exp;
 {
-  register tree x = exp;
+  tree x = exp;
   while (1)
     switch (TREE_CODE (x))
       {
@@ -3319,11 +3475,11 @@ tree
 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));
@@ -3371,8 +3527,10 @@ build_conditional_expr (ifexp, op1, op2)
       else
        result_type = TYPE_MAIN_VARIANT (type1);
     }
-  else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
-           && (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
+  else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
+            || code1 == COMPLEX_TYPE)
+           && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+               || code2 == COMPLEX_TYPE))
     {
       result_type = common_type (type1, type2);
 
@@ -3397,10 +3555,8 @@ build_conditional_expr (ifexp, op1, op2)
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
                 involving such literals) and it is non-negative.  */
-             else if ((unsigned_op2 && TREE_CODE (op1) == INTEGER_CST
-                       && tree_int_cst_sgn (op1) >= 0)
-                      || (unsigned_op1 && TREE_CODE (op2) == INTEGER_CST
-                          && tree_int_cst_sgn (op2) >= 0))
+             else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
+                      || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
                /* OK */;
              else
                warning ("signed and unsigned type in conditional expression");
@@ -3410,7 +3566,7 @@ build_conditional_expr (ifexp, op1, op2)
   else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
     {
       if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
-       pedwarn ("ANSI C forbids conditional expr with only one void side");
+       pedwarn ("ISO C forbids conditional expr with only one void side");
       result_type = void_type_node;
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
@@ -3423,17 +3579,19 @@ build_conditional_expr (ifexp, op1, op2)
       else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
               && TREE_CODE (orig_op2) != NOP_EXPR)
        result_type = qualify_type (type1, type2);
-      else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
+      else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
-         result_type = qualify_type (type1, type2);
+           pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+         result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
+                                                         TREE_TYPE (type2)));
        }
-      else if (TYPE_MAIN_VARIANT (TREE_TYPE (type2)) == void_type_node)
+      else if (VOID_TYPE_P (TREE_TYPE (type2)))
        {
          if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
-         result_type = qualify_type (type2, type1);
+           pedwarn ("ISO C forbids conditional expr between `void *' and function pointer");
+         result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
+                                                         TREE_TYPE (type1)));
        }
       else
        {
@@ -3448,10 +3606,6 @@ build_conditional_expr (ifexp, op1, op2)
       else
        {
          op2 = null_pointer_node;
-#if 0  /* The spec seems to say this is permitted.  */
-         if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
-#endif
        }
       result_type = type1;
     }
@@ -3462,10 +3616,6 @@ build_conditional_expr (ifexp, op1, op2)
       else
        {
          op1 = null_pointer_node;
-#if 0  /* The spec seems to say this is permitted.  */
-         if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
-           pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
-#endif
        }
       result_type = type2;
     }
@@ -3513,10 +3663,16 @@ internal_build_compound_expr (list, first_p)
      tree list;
      int first_p;
 {
-  register tree rest;
+  tree rest;
 
   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.  */
 
@@ -3531,14 +3687,6 @@ internal_build_compound_expr (list, first_p)
       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)))
@@ -3546,9 +3694,9 @@ internal_build_compound_expr (list, first_p)
       /* The left-hand operand of a comma expression is like an expression
          statement: with -W or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
-      if ((extra_warnings || warn_unused)
+      if ((extra_warnings || warn_unused_value)
            && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
-                && TREE_TYPE (TREE_VALUE (list)) == void_type_node))
+                && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
         warning ("left-hand operand of comma expression has no effect");
 
       /* When pedantic, a compound expression can be neither an lvalue
@@ -3561,7 +3709,7 @@ internal_build_compound_expr (list, first_p)
      side-effects, but computes a value which is not used.  For example, in
      `foo() + bar(), baz()' the result of the `+' operator is not used,
      so we should issue a warning.  */
-  else if (warn_unused)
+  else if (warn_unused_value)
     warn_if_unused_value (TREE_VALUE (list));
 
   return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
@@ -3571,10 +3719,10 @@ internal_build_compound_expr (list, first_p)
 
 tree
 build_c_cast (type, expr)
-     register tree type;
+     tree type;
      tree expr;
 {
-  register tree value = expr;
+  tree value = expr;
   
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
@@ -3598,21 +3746,19 @@ build_c_cast (type, expr)
       return error_mark_node;
     }
 
-  if (type == TREE_TYPE (value))
+  if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
       if (pedantic)
        {
          if (TREE_CODE (type) == RECORD_TYPE
              || TREE_CODE (type) == UNION_TYPE)
-           pedwarn ("ANSI C forbids casting nonscalar to the same type");
+           pedwarn ("ISO C forbids casting nonscalar to the same type");
        }
     }
   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)),
@@ -3625,7 +3771,7 @@ build_c_cast (type, expr)
          tree t;
 
          if (pedantic)
-           pedwarn ("ANSI C forbids casts to union type");
+           pedwarn ("ISO C forbids casts to union type");
          if (TYPE_NAME (type) != 0)
            {
              if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -3655,9 +3801,7 @@ build_c_cast (type, expr)
 
       /* 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.  */
@@ -3686,7 +3830,7 @@ build_c_cast (type, expr)
          if (warn)
            /* There are qualifiers present in IN_OTYPE that are not
               present in IN_TYPE.  */
-           pedwarn ("cast discards qualifiers from pointer target type");
+           warning ("cast discards qualifiers from pointer target type");
        }
 
       /* Warn about possible alignment problems.  */
@@ -3717,11 +3861,6 @@ build_c_cast (type, expr)
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
          && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-#if 0
-         /* Don't warn about converting 0 to pointer,
-            provided the 0 was explicit--not cast or made by folding.  */
-         && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value))
-#endif
          /* Don't warn about converting any constant.  */
          && !TREE_CONSTANT (value))
        warning ("cast to pointer from integer of different size");
@@ -3737,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)
@@ -3749,6 +3888,24 @@ build_c_cast (type, expr)
 
   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
@@ -3760,7 +3917,7 @@ build_modify_expr (lhs, modifycode, rhs)
      tree lhs, rhs;
      enum tree_code modifycode;
 {
-  register tree result;
+  tree result;
   tree newrhs;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
@@ -3844,9 +4001,7 @@ build_modify_expr (lhs, modifycode, rhs)
     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;
@@ -3884,6 +4039,7 @@ build_modify_expr (lhs, modifycode, rhs)
 
   if (TREE_CODE (lhs) == COMPONENT_REF
       && (TREE_CODE (lhstype) == INTEGER_TYPE
+         || TREE_CODE (lhstype) == BOOLEAN_TYPE
          || TREE_CODE (lhstype) == REAL_TYPE
          || TREE_CODE (lhstype) == ENUMERAL_TYPE))
     lhstype = TREE_TYPE (get_unwidened (lhs, 0));
@@ -3904,6 +4060,8 @@ build_modify_expr (lhs, modifycode, rhs)
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
+  /* Scan operands */
+
   result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
 
@@ -3938,9 +4096,9 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, 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
@@ -3952,7 +4110,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
       || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
     rhs = default_conversion (rhs);
   else if (optimize && TREE_CODE (rhs) == VAR_DECL)
-    rhs = decl_constant_value (rhs);
+    rhs = decl_constant_value_for_broken_optimization (rhs);
 
   rhstype = TREE_TYPE (rhs);
   coder = TREE_CODE (rhstype);
@@ -3974,11 +4132,34 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+  /* A type converts to a reference to it.  
+     This code doesn't fully support references, it's just for the
+     special case of va_start and va_copy.  */
+  if (codel == REFERENCE_TYPE
+      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
+    {
+      if (mark_addressable (rhs) == 0)
+       return error_mark_node;
+      rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+
+      /* We already know that these two types are compatible, but they
+        may not be exactly identical.  In fact, `TREE_TYPE (type)' is
+        likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
+        likely to be va_list, a typedef to __builtin_va_list, which
+        is different enough that it will cause problems later.  */
+      if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
+       rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+
+      rhs = build1 (NOP_EXPR, type, rhs);
+      return rhs;
+    }
   /* Arithmetic types all interconvert, and enum is treated like int.  */
-  if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
-       || codel == COMPLEX_TYPE)
-      && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE
-         || coder == COMPLEX_TYPE))
+  else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 
+           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
+           || codel == BOOLEAN_TYPE)
+          && (coder == INTEGER_TYPE || coder == REAL_TYPE 
+              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
+              || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
 
   /* Conversion to a transparent union from its member types.
@@ -4002,15 +4183,14 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
 
          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.
                 Meanwhile, the lhs target must have all the qualifiers of
                 the rhs.  */
-             if (TYPE_MAIN_VARIANT (ttl) == void_type_node
-                 || TYPE_MAIN_VARIANT (ttr) == void_type_node
+             if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
                  || comp_target_types (memb_type, rhstype))
                {
                  /* If this type won't generate any warnings, use it.  */
@@ -4045,8 +4225,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
            {
              /* 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.  */
@@ -4069,37 +4249,36 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
            }
          
          if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn ("ANSI C prohibits argument conversion to union type");
+           pedwarn ("ISO C prohibits argument conversion to union type");
 
          return build1 (NOP_EXPR, type, rhs);
        }
     }
 
   /* Conversions among pointers */
-  else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
+  else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+          && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
     {
-      register tree ttl = TREE_TYPE (type);
-      register tree ttr = TREE_TYPE (rhstype);
+      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.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
-      if (TYPE_MAIN_VARIANT (ttl) == void_type_node
-         || TYPE_MAIN_VARIANT (ttr) == void_type_node
+      if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
          || comp_target_types (type, rhstype)
          || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
              == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
        {
          if (pedantic
-             && ((TYPE_MAIN_VARIANT (ttl) == void_type_node
-                  && TREE_CODE (ttr) == FUNCTION_TYPE)
+             && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
                  ||
-                 (TYPE_MAIN_VARIANT (ttr) == void_type_node
+                 (VOID_TYPE_P (ttr)
                   /* Check TREE_CODE to catch cases like (void *) (char *) 0
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
+           warn_for_assignment ("ISO C forbids %s between function pointer and `void *'",
                                 errtype, funname, parmnum);
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
@@ -4111,8 +4290,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                                     errtype, funname, parmnum);
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
-             else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
-                      || TYPE_MAIN_VARIANT (ttr) == void_type_node
+             else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
                       || comp_target_types (type, rhstype))
                ;
              /* If there is a mismatch, do warn.  */
@@ -4161,6 +4339,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                           errtype, funname, parmnum);
       return convert (type, rhs);
     }
+  else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+    return convert (type, rhs);
 
   if (!errtype)
     {
@@ -4211,7 +4391,7 @@ warn_for_assignment (msgid, opname, function, argnum)
       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);
@@ -4221,7 +4401,7 @@ warn_for_assignment (msgid, opname, function, argnum)
       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);
        }
@@ -4265,7 +4445,7 @@ void
 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.  */
 
@@ -4276,7 +4456,7 @@ store_init_value (decl, init)
   /* Digest the specified initializer into an expression.  */
 
   value = digest_init (type, init, TREE_STATIC (decl),
-                      TREE_STATIC (decl) || pedantic);
+                      TREE_STATIC (decl) || (pedantic && !flag_isoc99));
 
   /* Store the expression if valid; else report error.  */
 
@@ -4309,6 +4489,10 @@ store_init_value (decl, init)
     }
 #endif
 
+  if (warn_traditional && !in_system_header
+      && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl))
+    warning ("traditional C rejects automatic aggregate initialization");
+
   DECL_INITIAL (decl) = value;
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
@@ -4343,7 +4527,7 @@ static int spelling_size;         /* Size of the spelling stack.  */
    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.  */
 
@@ -4395,7 +4579,7 @@ push_member_name (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);
 }
@@ -4414,8 +4598,8 @@ push_array_bounds (bounds)
 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++)
     {
@@ -4432,10 +4616,10 @@ spelling_length ()
 
 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)
@@ -4445,7 +4629,7 @@ print_spelling (buffer)
       }
     else
       {
-       register const char *s;
+       const char *s;
        if (p->kind == SPELLING_MEMBER)
          *d++ = '.';
        for (s = p->u.s; (*d = *s++); d++)
@@ -4518,7 +4702,9 @@ digest_init (type, init, require_constant, constructor_constant)
   enum tree_code code = TREE_CODE (type);
   tree inside_init = init;
 
-  if (type == error_mark_node || init == error_mark_node)
+  if (type == error_mark_node
+      || init == error_mark_node
+      || TREE_TYPE (init)  == error_mark_node)
     return error_mark_node;
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
@@ -4527,6 +4713,8 @@ digest_init (type, init, require_constant, constructor_constant)
   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.  */
 
@@ -4561,6 +4749,7 @@ digest_init (type, init, require_constant, constructor_constant)
 
          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
@@ -4592,10 +4781,8 @@ digest_init (type, init, require_constant, constructor_constant)
              && 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)
        {
@@ -4604,7 +4791,7 @@ digest_init (type, init, require_constant, constructor_constant)
        }
 
       if (optimize && TREE_CODE (inside_init) == VAR_DECL)
-       inside_init = decl_constant_value (inside_init);
+       inside_init = decl_constant_value_for_broken_optimization (inside_init);
 
       /* Compound expressions can only occur here if -pedantic or
         -pedantic-errors is specified.  In the later case, we always want
@@ -4622,17 +4809,21 @@ digest_init (type, init, require_constant, constructor_constant)
          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;
        }
-      else if (require_constant
-              && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
-       {
-         error_init ("initializer element is not computable at load time");
-         inside_init = error_mark_node;
-       }
 
       return inside_init;
     }
@@ -4640,7 +4831,7 @@ digest_init (type, init, require_constant, constructor_constant)
   /* Handle scalar types, including conversions.  */
 
   if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
-      || code == ENUMERAL_TYPE || code == COMPLEX_TYPE)
+      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE)
     {
       /* Note that convert_for_assignment calls default_conversion
         for arrays and functions.  We must not call it in the
@@ -4666,7 +4857,7 @@ digest_init (type, init, require_constant, constructor_constant)
 
   /* Come here only for records and arrays.  */
 
-  if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
     {
       error_init ("variable-sized object may not be initialized");
       return error_mark_node;
@@ -4728,11 +4919,6 @@ static tree constructor_fields;
    at which to store the next element we get.  */
 static tree constructor_index;
 
-/* For an ARRAY_TYPE, this is the end index of the range
-   to initialize with the next element, or NULL in the ordinary case
-   where the element is used just once.  */
-static tree constructor_range_end;
-
 /* For an ARRAY_TYPE, this is the maximum index.  */
 static tree constructor_max_index;
 
@@ -4752,6 +4938,10 @@ static tree constructor_bit_index;
    most recent first).  */
 static tree constructor_elements;
 
+/* 1 if constructor should be incrementally stored into a constructor chain,
+   0 if all the elements should be kept in AVL tree.  */
+static int constructor_incremental;
+
 /* 1 if so far this constructor's elements are all compile-time constants.  */
 static int constructor_constant;
 
@@ -4792,54 +4982,77 @@ int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages.  */
 static int require_constant_value;
 static int require_constant_elements;
 
-/* 1 if it is ok to output this constructor as we read it.
-   0 means must accumulate a CONSTRUCTOR expression.  */
-static int constructor_incremental;
-
 /* DECL node for which an initializer is being read.
    0 means we are reading a constructor expression
    such as (struct foo) {...}.  */
 static tree constructor_decl;
 
 /* start_init saves the ASMSPEC arg here for really_start_incremental_init.  */
-static char *constructor_asmspec;
+static const char *constructor_asmspec;
 
 /* 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;
+
+/* Nonzero if there were diagnosed errors in this designator list.  */
+static int designator_errorneous;
+
 \f
 /* This stack has a level for each implicit or explicit level of
    structuring in the initializer, including the outermost one.  It
    saves the values of most of the variables above.  */
 
+struct constructor_range_stack;
+
 struct constructor_stack
 {
   struct constructor_stack *next;
   tree type;
   tree fields;
   tree index;
-  tree range_end;
   tree max_index;
   tree unfilled_index;
   tree unfilled_fields;
   tree bit_index;
   tree elements;
-  int offset;
   struct init_node *pending_elts;
+  int offset;
   int depth;
   /* If nonzero, this value should replace the entire
      constructor at this level.  */
   tree replacement_value;
+  struct constructor_range_stack *range_stack;
   char constant;
   char simple;
   char implicit;
-  char incremental;
   char erroneous;
   char outer;
+  char incremental;
+  char designated;
 };
 
 struct constructor_stack *constructor_stack;
 
+/* This stack represents designators from some range designator up to
+   the last designator in the list.  */
+
+struct constructor_range_stack
+{
+  struct constructor_range_stack *next, *prev;
+  struct constructor_stack *stack;
+  tree range_start;
+  tree index;
+  tree range_end;
+  tree fields;
+};
+
+struct constructor_range_stack *constructor_range_stack;
+
 /* This stack records separate initializers that are nested.
    Nested initializers can't happen in ANSI C, but GNU C allows them
    in cases like { ... (struct foo) { ... } ... }.  */
@@ -4848,14 +5061,14 @@ struct initializer_stack
 {
   struct initializer_stack *next;
   tree decl;
-  char *asmspec;
+  const char *asmspec;
   struct constructor_stack *constructor_stack;
+  struct constructor_range_stack *constructor_range_stack;
   tree elements;
   struct spelling *spelling;
   struct spelling *spelling_base;
   int spelling_size;
   char top_level;
-  char incremental;
   char require_constant_value;
   char require_constant_elements;
   char deferred;
@@ -4874,17 +5087,17 @@ start_init (decl, asmspec_tree, top_level)
   const char *locus;
   struct initializer_stack *p
     = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
-  char *asmspec = 0;
+  const char *asmspec = 0;
 
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   p->decl = constructor_decl;
   p->asmspec = constructor_asmspec;
-  p->incremental = constructor_incremental;
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
+  p->constructor_range_stack = constructor_range_stack;
   p->elements = constructor_elements;
   p->spelling = spelling;
   p->spelling_base = spelling_base;
@@ -4895,16 +5108,16 @@ start_init (decl, asmspec_tree, top_level)
   initializer_stack = p;
 
   constructor_decl = decl;
-  constructor_incremental = top_level;
   constructor_asmspec = asmspec;
   constructor_subconstants_deferred = 0;
+  constructor_designated = 0;
   constructor_top_level = top_level;
 
   if (decl != 0)
     {
       require_constant_value = TREE_STATIC (decl);
       require_constant_elements
-       = ((TREE_STATIC (decl) || pedantic)
+       = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
           /* For a scalar, you can always use any value to initialize,
              even within braces.  */
           && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
@@ -4912,7 +5125,6 @@ start_init (decl, asmspec_tree, top_level)
               || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
               || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
       locus = IDENTIFIER_POINTER (DECL_NAME (decl));
-      constructor_incremental |= TREE_STATIC (decl);
     }
   else
     {
@@ -4922,6 +5134,7 @@ start_init (decl, asmspec_tree, top_level)
     }
 
   constructor_stack = 0;
+  constructor_range_stack = 0;
 
   missing_braces_mentioned = 0;
 
@@ -4952,13 +5165,16 @@ finish_init ()
       free (q);
     }
 
+  if (constructor_range_stack)
+    abort ();
+
   /* Pop back to the data of the outer initializer (if any).  */
   constructor_decl = p->decl;
   constructor_asmspec = p->asmspec;
-  constructor_incremental = p->incremental;
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
+  constructor_range_stack = p->constructor_range_stack;
   constructor_elements = p->elements;
   spelling = p->spelling;
   spelling_base = p->spelling_base;
@@ -4986,15 +5202,9 @@ really_start_incremental_init (type)
   if (type == 0)
     type = TREE_TYPE (constructor_decl);
 
-  /* Turn off constructor_incremental if type is a struct with bitfields.
-     Do this before the first push, so that the corrected value
-     is available in finish_init.  */
-  check_init_type_bitfields (type);
-
   p->type = constructor_type;
   p->fields = constructor_fields;
   p->index = constructor_index;
-  p->range_end = constructor_range_end;
   p->max_index = constructor_max_index;
   p->unfilled_index = constructor_unfilled_index;
   p->unfilled_fields = constructor_unfilled_fields;
@@ -5007,8 +5217,10 @@ really_start_incremental_init (type)
   p->depth = constructor_depth;
   p->replacement_value = 0;
   p->implicit = 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;
 
@@ -5018,6 +5230,10 @@ really_start_incremental_init (type)
   constructor_elements = 0;
   constructor_pending_elts = 0;
   constructor_type = type;
+  constructor_incremental = 1;
+  constructor_designated = 0;
+  designator_depth = 0;
+  designator_errorneous = 0;
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
       || TREE_CODE (constructor_type) == UNION_TYPE)
@@ -5029,21 +5245,26 @@ really_start_incremental_init (type)
        constructor_fields = TREE_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = bitsize_int (0);
+      constructor_bit_index = bitsize_zero_node;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
-      constructor_range_end = 0;
       if (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)));
        }
       else
-       constructor_index = bitsize_int (0);
+       constructor_index = bitsize_zero_node;
 
       constructor_unfilled_index = constructor_index;
     }
@@ -5053,28 +5274,19 @@ really_start_incremental_init (type)
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
-
-  if (constructor_incremental)
-    {
-      make_decl_rtl (constructor_decl, constructor_asmspec,
-                    constructor_top_level);
-      assemble_variable (constructor_decl, constructor_top_level, 0, 1);
-
-      defer_addressed_constants ();
-      constructor_subconstants_deferred = 1;
-    }
 }
 \f
 /* Push down into a subobject, for initialization.
    If this is for an explicit set of braces, IMPLICIT is 0.
    If it is because the next element belongs at a lower level,
-   IMPLICIT is 1.  */
+   IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
 push_init_level (implicit)
      int implicit;
 {
   struct constructor_stack *p;
+  tree value = NULL_TREE;
 
   /* If we've exhausted any levels that didn't have braces,
      pop them now.  */
@@ -5091,35 +5303,22 @@ push_init_level (implicit)
        break;
     }
 
-  /* Structure elements may require alignment.  Do this now if necessary
-     for the subaggregate, and if it comes next in sequence.  Don't do
-     this for subaggregates that will go on the pending list.  */
-  if (constructor_incremental && constructor_type != 0
-      && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
-      && constructor_fields == constructor_unfilled_fields)
-    {
-      /* Advance to offset of this element.  */
-      if (! tree_int_cst_equal (constructor_bit_index,
-                               bit_position (constructor_fields)))
-       assemble_zeros
-         (tree_low_cst
-          (size_binop (TRUNC_DIV_EXPR,
-                       size_binop (MINUS_EXPR,
-                                   bit_position (constructor_fields),
-                                   constructor_bit_index),
-                       bitsize_int (BITS_PER_UNIT)),
-           1));
-
-      /* Indicate that we have now filled the structure up to the current
-        field.  */
-      constructor_unfilled_fields = constructor_fields;
+  /* Unless this is an explicit brace, we need to preserve previous
+     content if any.  */
+  if (implicit)
+    {
+      if ((TREE_CODE (constructor_type) == RECORD_TYPE
+          || TREE_CODE (constructor_type) == UNION_TYPE)
+         && constructor_fields)
+       value = find_init_member (constructor_fields);
+      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+       value = find_init_member (constructor_index);
     }
 
   p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
   p->type = constructor_type;
   p->fields = constructor_fields;
   p->index = constructor_index;
-  p->range_end = constructor_range_end;
   p->max_index = constructor_max_index;
   p->unfilled_index = constructor_unfilled_index;
   p->unfilled_fields = constructor_unfilled_fields;
@@ -5132,16 +5331,27 @@ push_init_level (implicit)
   p->depth = constructor_depth;
   p->replacement_value = 0;
   p->implicit = implicit;
-  p->incremental = constructor_incremental;
   p->outer = 0;
+  p->incremental = constructor_incremental;
+  p->designated = constructor_designated;
   p->next = constructor_stack;
+  p->range_stack = 0;
   constructor_stack = p;
 
   constructor_constant = 1;
   constructor_simple = 1;
   constructor_depth = SPELLING_DEPTH ();
   constructor_elements = 0;
+  constructor_incremental = 1;
+  constructor_designated = 0;
   constructor_pending_elts = 0;
+  if (!implicit)
+    {
+      p->range_stack = constructor_range_stack;
+      constructor_range_stack = 0;
+      designator_depth = 0;
+      designator_errorneous = 0;
+    }
 
   /* Don't die if an entire brace-pair level is superfluous
      in the containing level.  */
@@ -5158,8 +5368,6 @@ push_init_level (implicit)
          constructor_type = TREE_TYPE (constructor_fields);
          push_member_name (constructor_fields);
          constructor_depth++;
-         if (constructor_fields != constructor_unfilled_fields)
-           constructor_incremental = 0;
        }
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -5167,9 +5375,6 @@ push_init_level (implicit)
       constructor_type = TREE_TYPE (constructor_type);
       push_array_bounds (tree_low_cst (constructor_index, 0));
       constructor_depth++;
-      if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
-         || constructor_range_end != 0)
-       constructor_incremental = 0;
     }
 
   if (constructor_type == 0)
@@ -5180,10 +5385,18 @@ push_init_level (implicit)
       return;
     }
 
-  /* Turn off constructor_incremental if type is a struct with bitfields.  */
-  check_init_type_bitfields (constructor_type);
+  if (value && TREE_CODE (value) == CONSTRUCTOR)
+    {
+      constructor_constant = TREE_CONSTANT (value);
+      constructor_simple = TREE_STATIC (value);
+      constructor_elements = TREE_OPERAND (value, 1);
+      if (constructor_elements
+         && (TREE_CODE (constructor_type) == RECORD_TYPE
+             || TREE_CODE (constructor_type) == ARRAY_TYPE))
+       set_nonincremental_init ();
+    }
 
-  if (implicit && warn_missing_braces && !missing_braces_mentioned)
+  if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
     {
       missing_braces_mentioned = 1;
       warning_init ("missing braces around initializer");
@@ -5199,24 +5412,35 @@ push_init_level (implicit)
        constructor_fields = TREE_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = bitsize_int (0);
+      constructor_bit_index = bitsize_zero_node;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
-      constructor_range_end = 0;
       if (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)));
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
        }
       else
-       constructor_index = bitsize_int (0);
+       constructor_index = bitsize_zero_node;
 
       constructor_unfilled_index = constructor_index;
+      if (value && TREE_CODE (value) == STRING_CST)
+       {
+         /* We need to split the char/wchar array into individual
+            characters, so that we don't have to special case it
+            everywhere.  */
+         set_nonincremental_init_from_string (value);
+       }
     }
   else
     {
@@ -5226,45 +5450,6 @@ push_init_level (implicit)
     }
 }
 
-/* Don't read a struct incrementally if it has any bitfields,
-   because the incremental reading code doesn't know how to
-   handle bitfields yet.  */
-
-static void
-check_init_type_bitfields (type)
-     tree type;
-{
-  if (TREE_CODE (type) == RECORD_TYPE)
-    {
-      tree tail;
-      for (tail = TYPE_FIELDS (type); tail;
-          tail = TREE_CHAIN (tail))
-       {
-         if (DECL_C_BIT_FIELD (tail))
-           {
-             constructor_incremental = 0;
-             break;
-           }
-
-         check_init_type_bitfields (TREE_TYPE (tail));
-       }
-    }
-
-  else if (TREE_CODE (type) == UNION_TYPE)
-    {
-      tree tail = TYPE_FIELDS (type);
-      if (tail && DECL_C_BIT_FIELD (tail))
-       /* We also use the nonincremental algorithm for initiliazation
-          of unions whose first member is a bitfield, becuase the
-          incremental algorithm has no code for dealing with
-          bitfields. */
-       constructor_incremental = 0;
-    }
-
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    check_init_type_bitfields (TREE_TYPE (type));
-}
-
 /* At the end of an implicit or explicit brace level, 
    finish up that level of constructor.
    If we were outputting the elements as they are read, return 0
@@ -5278,7 +5463,6 @@ pop_init_level (implicit)
      int implicit;
 {
   struct constructor_stack *p;
-  HOST_WIDE_INT size = 0;
   tree constructor = 0;
 
   if (implicit == 0)
@@ -5287,12 +5471,42 @@ pop_init_level (implicit)
         pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
        process_init_element (pop_init_level (1));
+
+      if (constructor_range_stack)
+       abort ();
     }
 
   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
+      && TREE_CODE (constructor_type) == ARRAY_TYPE
+      && TYPE_DOMAIN (constructor_type)
+      && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+    {
+      /* Silently discard empty initializations.  The parser will
+        already have pedwarned for empty brackets.  */
+      if (integer_zerop (constructor_unfilled_index))
+       constructor_type = NULL_TREE;
+      else if (! TYPE_SIZE (constructor_type))
+       {
+         if (constructor_depth > 2)
+           error_init ("initialization of flexible array member in a nested context");
+         else if (pedantic)
+           pedwarn_init ("initialization of a flexible array member");
+
+         /* 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
+       /* 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.  */
   if (extra_warnings
@@ -5300,71 +5514,43 @@ pop_init_level (implicit)
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
-      push_member_name (constructor_unfilled_fields);
-      warning_init ("missing initializer");
-      RESTORE_SPELLING_DEPTH (constructor_depth);
+       /* Do not warn for flexible array members or zero-length arrays.  */
+       while (constructor_unfilled_fields
+              && (! DECL_SIZE (constructor_unfilled_fields)
+                  || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
+         constructor_unfilled_fields = TREE_CHAIN (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");
+           RESTORE_SPELLING_DEPTH (constructor_depth);
+         }
     }
 
   /* Now output all pending elements.  */
+  constructor_incremental = 1;
   output_pending_init_elements (1);
 
-#if 0 /* c-parse.in warns about {}.  */
-  /* In ANSI, each brace level must have at least one element.  */
-  if (! implicit && pedantic
-      && (TREE_CODE (constructor_type) == ARRAY_TYPE
-         ? integer_zerop (constructor_unfilled_index)
-         : constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
-    pedwarn_init ("empty braces in initializer");
-#endif
-
   /* Pad out the end of the structure.  */
-  
   if (p->replacement_value)
-    {
-      /* If this closes a superfluous brace pair,
-        just pass out the element between them.  */
-      constructor = p->replacement_value;
-      /* If this is the top level thing within the initializer,
-        and it's for a variable, then since we already called
-        assemble_variable, we must output the value now.  */
-      if (p->next == 0 && constructor_decl != 0
-         && constructor_incremental)
-       {
-         constructor = digest_init (constructor_type, constructor,
-                                    require_constant_value,
-                                    require_constant_elements);
-
-         /* If initializing an array of unknown size,
-            determine the size now.  */
-         if (TREE_CODE (constructor_type) == ARRAY_TYPE
-             && TYPE_DOMAIN (constructor_type) == 0)
-           {
-             /* We shouldn't have an incomplete array type within
-                some other type.  */
-             if (constructor_stack->next)
-               abort ();
-
-             if (complete_array_type (constructor_type, constructor, 0))
-               abort ();
-
-             size = int_size_in_bytes (constructor_type);
-           }
-
-         output_constant (constructor, size);
-       }
-    }
+    /* If this closes a superfluous brace pair,
+       just pass out the element between them.  */
+    constructor = p->replacement_value;
   else if (constructor_type == 0)
     ;
   else if (TREE_CODE (constructor_type) != RECORD_TYPE
           && TREE_CODE (constructor_type) != UNION_TYPE
-          && TREE_CODE (constructor_type) != ARRAY_TYPE
-          && ! constructor_incremental)
+          && TREE_CODE (constructor_type) != ARRAY_TYPE)
     {
       /* A nonincremental scalar initializer--just return
         the element, after verifying there is just one.  */
       if (constructor_elements == 0)
        {
-         error_init ("empty scalar initializer");
+         if (!constructor_erroneous)
+           error_init ("empty scalar initializer");
          constructor = error_mark_node;
        }
       else if (TREE_CHAIN (constructor_elements) != 0)
@@ -5375,7 +5561,7 @@ pop_init_level (implicit)
       else
        constructor = TREE_VALUE (constructor_elements);
     }
-  else if (! constructor_incremental)
+  else
     {
       if (constructor_erroneous)
        constructor = error_mark_node;
@@ -5389,63 +5575,10 @@ pop_init_level (implicit)
            TREE_STATIC (constructor) = 1;
        }
     }
-  else
-    {
-      tree filled;
-
-      if (TREE_CODE (constructor_type) == RECORD_TYPE
-         || TREE_CODE (constructor_type) == UNION_TYPE)
-       /* Find the offset of the end of that field.  */
-       filled = size_binop (CEIL_DIV_EXPR,
-                            constructor_bit_index,
-                            bitsize_int (BITS_PER_UNIT));
-
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         /* If initializing an array of unknown size,
-            determine the size now.  */
-         if (TREE_CODE (constructor_type) == ARRAY_TYPE
-             && TYPE_DOMAIN (constructor_type) == 0)
-           {
-             tree maxindex
-               = copy_node (size_diffop (constructor_unfilled_index,
-                                         bitsize_int (1)));
-
-             TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
-             TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
-
-             /* TYPE_MAX_VALUE is always one less than the number of elements
-                in the array, because we start counting at zero.  Therefore,
-                warn only if the value is less than zero.  */
-             if (pedantic
-                 && (tree_int_cst_sgn
-                     (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
-                     < 0))
-               error_with_decl (constructor_decl,
-                                "zero or negative array size `%s'");
-
-             layout_type (constructor_type);
-             size = int_size_in_bytes (constructor_type);
-           }
 
-         filled
-           = size_binop (MULT_EXPR, constructor_unfilled_index,
-                         convert (bitsizetype,
-                                  TYPE_SIZE_UNIT
-                                  (TREE_TYPE (constructor_type))));
-       }
-      else
-       filled = 0;
-
-      if (filled != 0)
-       assemble_zeros (size - tree_low_cst (filled, 1));
-    }
-
-         
   constructor_type = p->type;
   constructor_fields = p->fields;
   constructor_index = p->index;
-  constructor_range_end = p->range_end;
   constructor_max_index = p->max_index;
   constructor_unfilled_index = p->unfilled_index;
   constructor_unfilled_fields = p->unfilled_fields;
@@ -5454,9 +5587,12 @@ pop_init_level (implicit)
   constructor_constant = p->constant;
   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;
-  constructor_incremental = p->incremental;
+  if (!p->implicit)
+    constructor_range_stack = p->range_stack;
   RESTORE_SPELLING_DEPTH (constructor_depth);
 
   constructor_stack = p->next;
@@ -5471,24 +5607,122 @@ pop_init_level (implicit)
   return constructor;
 }
 
-/* Within an array initializer, specify the next index to be initialized.
-   FIRST is that index.  If LAST is nonzero, then initialize a range
-   of indices, running from FIRST through LAST.  */
+/* Common handling for both array range and field name designators.
+   ARRAY argument is non-zero for array ranges.  Returns zero for success.  */
 
-void
-set_init_index (first, last)
-     tree first, last;
+static int
+set_designator (array)
+     int array;
 {
-  while ((TREE_CODE (first) == NOP_EXPR
-         || TREE_CODE (first) == CONVERT_EXPR
-         || TREE_CODE (first) == NON_LVALUE_EXPR)
-        && (TYPE_MODE (TREE_TYPE (first))
-            == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
-    first = TREE_OPERAND (first, 0);
+  tree subtype;
+  enum tree_code subcode;
 
-  if (last)
-    while ((TREE_CODE (last) == NOP_EXPR
-           || TREE_CODE (last) == CONVERT_EXPR
+  /* Don't die if an entire brace-pair level is superfluous
+     in the containing level.  */
+  if (constructor_type == 0)
+    return 1;
+
+  /* If there were errors in this designator list already, bail out silently.  */
+  if (designator_errorneous)
+    return 1;
+
+  if (!designator_depth)
+    {
+      if (constructor_range_stack)
+       abort ();
+
+      /* Designator list starts at the level of closest explicit
+        braces.  */
+      while (constructor_stack->implicit)
+       process_init_element (pop_init_level (1));
+      constructor_designated = 1;
+      return 0;
+    }
+
+  if (constructor_no_implicit)
+    {
+      error_init ("initialization designators may not nest");
+      return 1;
+    }
+
+  if (TREE_CODE (constructor_type) == RECORD_TYPE
+      || TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      subtype = TREE_TYPE (constructor_fields);
+      if (subtype != error_mark_node)
+       subtype = TYPE_MAIN_VARIANT (subtype);
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+    }
+  else
+    abort ();
+
+  subcode = TREE_CODE (subtype);
+  if (array && subcode != ARRAY_TYPE)
+    {
+      error_init ("array index in non-array initializer");
+      return 1;
+    }
+  else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
+    {
+      error_init ("field name not in record or union initializer");
+      return 1;
+    }
+
+  constructor_designated = 1;
+  push_init_level (2);
+  return 0;
+}
+
+/* If there are range designators in designator list, push a new designator
+   to constructor_range_stack.  RANGE_END is end of such stack range or
+   NULL_TREE if there is no range designator at this level.  */
+
+static void
+push_range_stack (range_end)
+     tree range_end;
+{
+  struct constructor_range_stack *p;
+
+  p = (struct constructor_range_stack *)
+      ggc_alloc (sizeof (struct constructor_range_stack));
+  p->prev = constructor_range_stack;
+  p->next = 0;
+  p->fields = constructor_fields;
+  p->range_start = constructor_index;
+  p->index = constructor_index;
+  p->stack = constructor_stack;
+  p->range_end = range_end;
+  if (constructor_range_stack)
+    constructor_range_stack->next = p;
+  constructor_range_stack = p;
+}
+
+/* Within an array initializer, specify the next index to be initialized.
+   FIRST is that index.  If LAST is nonzero, then initialize a range
+   of indices, running from FIRST through LAST.  */
+
+void
+set_init_index (first, last)
+     tree first, last;
+{
+  if (set_designator (1))
+    return;
+
+  designator_errorneous = 1;
+
+  while ((TREE_CODE (first) == NOP_EXPR
+         || TREE_CODE (first) == CONVERT_EXPR
+         || TREE_CODE (first) == NON_LVALUE_EXPR)
+        && (TYPE_MODE (TREE_TYPE (first))
+            == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
+    first = TREE_OPERAND (first, 0);
+
+  if (last)
+    while ((TREE_CODE (last) == NOP_EXPR
+           || TREE_CODE (last) == CONVERT_EXPR
            || TREE_CODE (last) == NON_LVALUE_EXPR)
           && (TYPE_MODE (TREE_TYPE (last))
               == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0)))))
@@ -5498,23 +5732,40 @@ set_init_index (first, last)
     error_init ("nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
     error_init ("nonconstant array index in initializer");
-  else if (! constructor_unfilled_index)
+  else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
     error_init ("array index in non-array initializer");
-  else if (tree_int_cst_lt (first, constructor_unfilled_index))
-    error_init ("duplicate array index in initializer");
+  else if (constructor_max_index
+          && tree_int_cst_lt (constructor_max_index, first))
+    error_init ("array index in initializer exceeds array bounds");
   else
     {
       constructor_index = convert (bitsizetype, first);
 
-      if (last != 0 && tree_int_cst_lt (last, first))
-       error_init ("empty index range in initializer");
-      else
+      if (last)
        {
-         if (pedantic)
-           pedwarn ("ANSI C forbids specifying element to initialize");
-
-         constructor_range_end = last ? convert (bitsizetype, last) : 0;
+         if (tree_int_cst_equal (first, last))
+           last = 0;
+         else if (tree_int_cst_lt (last, first))
+           {
+             error_init ("empty index range in initializer");
+             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)
+       push_range_stack (last);
     }
 }
 
@@ -5525,18 +5776,22 @@ set_init_label (fieldname)
      tree fieldname;
 {
   tree tail;
-  int passed = 0;
 
-  /* Don't die if an entire brace-pair level is superfluous
-     in the containing level.  */
-  if (constructor_type == 0)
+  if (set_designator (0))
     return;
 
+  designator_errorneous = 1;
+
+  if (TREE_CODE (constructor_type) != RECORD_TYPE
+      && TREE_CODE (constructor_type) != UNION_TYPE)
+    {
+      error_init ("field name not in record or union initializer");
+      return;
+    }
+    
   for (tail = TYPE_FIELDS (constructor_type); tail;
        tail = TREE_CHAIN (tail))
     {
-      if (tail == constructor_unfilled_fields)
-       passed = 1;
       if (DECL_NAME (tail) == fieldname)
        break;
     }
@@ -5544,19 +5799,18 @@ set_init_label (fieldname)
   if (tail == 0)
     error ("unknown field `%s' specified in initializer",
           IDENTIFIER_POINTER (fieldname));
-  else if (!passed)
-    error ("field `%s' already initialized",
-          IDENTIFIER_POINTER (fieldname));
   else
     {
       constructor_fields = tail;
-      if (pedantic)
-       pedwarn ("ANSI C forbids specifying structure member to initialize");
+      designator_depth++;
+      designator_errorneous = 0;
+      if (constructor_range_stack)
+       push_range_stack (NULL_TREE);
     }
 }
 \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
@@ -5575,28 +5829,40 @@ add_pending_init (purpose, value)
          p = *q;
          if (tree_int_cst_lt (purpose, p->purpose))
            q = &p->left;
-         else if (p->purpose != purpose)
+         else if (tree_int_cst_lt (p->purpose, purpose))
            q = &p->right;
          else
-           abort ();
+           {
+             if (TREE_SIDE_EFFECTS (p->value))
+               warning_init ("initialized field with side-effects overwritten");
+             p->value = value;
+             return;
+           }
        }
     }
   else
     {
+      tree bitpos;
+
+      bitpos = bit_position (purpose);
       while (*q != NULL)
        {
          p = *q;
-         if (tree_int_cst_lt (bit_position (purpose),
-                              bit_position (p->purpose)))
+         if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
            q = &p->left;
          else if (p->purpose != purpose)
            q = &p->right;
          else
-           abort ();
+           {
+             if (TREE_SIDE_EFFECTS (p->value))
+               warning_init ("initialized field with side-effects overwritten");
+             p->value = value;
+             return;
+           }
        }
     }
 
-  r = (struct init_node *) ggc_alloc_obj (sizeof (struct init_node), 0);
+  r = (struct init_node *) ggc_alloc (sizeof (struct init_node));
   r->purpose = purpose;
   r->value = value;
 
@@ -5618,7 +5884,7 @@ add_pending_init (purpose, value)
            {
              if (r->balance < 0)
                {
-                 /* L rotation. */
+                 /* L rotation.  */
                  p->left = r->right;
                  if (p->left)
                    p->left->parent = p;
@@ -5642,7 +5908,7 @@ add_pending_init (purpose, value)
                }
              else
                {
-                 /* LR rotation. */
+                 /* LR rotation.  */
                  struct init_node *t = r->right;
 
                  r->right = t->left;
@@ -5691,7 +5957,7 @@ add_pending_init (purpose, value)
            {
              if (r->balance > 0)
                {
-                 /* R rotation. */
+                 /* R rotation.  */
                  p->right = r->left;
                  if (p->right)
                    p->right->parent = p;
@@ -5750,7 +6016,7 @@ add_pending_init (purpose, value)
            }
          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;
            }
@@ -5761,41 +6027,178 @@ add_pending_init (purpose, value)
     }
 }
 
-/* Return nonzero if FIELD is equal to the index of a pending initializer.  */
+/* Build AVL tree from a sorted chain.  */
 
-static int
-pending_init_member (field)
+static void
+set_nonincremental_init ()
+{
+  tree chain;
+
+  if (TREE_CODE (constructor_type) != RECORD_TYPE
+      && TREE_CODE (constructor_type) != ARRAY_TYPE)
+    return;
+
+  for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
+    add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+  constructor_elements = 0;
+  if (TREE_CODE (constructor_type) == RECORD_TYPE)
+    {
+      constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
+      /* Skip any nameless bit fields at the beginning.  */
+      while (constructor_unfilled_fields != 0
+            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+            && DECL_NAME (constructor_unfilled_fields) == 0)
+       constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+      
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (constructor_type))
+       constructor_unfilled_index
+           = convert (bitsizetype,
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+      else
+       constructor_unfilled_index = bitsize_zero_node;
+    }
+  constructor_incremental = 0;
+}
+
+/* Build AVL tree from a string constant.  */
+
+static void
+set_nonincremental_init_from_string (str)
+     tree str;
+{
+  tree value, purpose, type;
+  HOST_WIDE_INT val[2];
+  const char *p, *end;
+  int byte, wchar_bytes, charwidth, bitpos;
+
+  if (TREE_CODE (constructor_type) != ARRAY_TYPE)
+    abort ();
+
+  if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+      == TYPE_PRECISION (char_type_node))
+    wchar_bytes = 1;
+  else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+          == TYPE_PRECISION (wchar_type_node))
+    wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+  else
+    abort ();
+
+  charwidth = TYPE_PRECISION (char_type_node);
+  type = TREE_TYPE (constructor_type);
+  p = TREE_STRING_POINTER (str);
+  end = p + TREE_STRING_LENGTH (str);
+
+  for (purpose = bitsize_zero_node;
+       p < end && !tree_int_cst_lt (constructor_max_index, purpose);
+       purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
+    {
+      if (wchar_bytes == 1)
+       {
+         val[1] = (unsigned char) *p++;
+         val[0] = 0;
+       }
+      else
+       {
+         val[0] = 0;
+         val[1] = 0;
+         for (byte = 0; byte < wchar_bytes; byte++)
+           {
+             if (BYTES_BIG_ENDIAN)
+               bitpos = (wchar_bytes - byte - 1) * charwidth;
+             else
+               bitpos = byte * charwidth;
+             val[bitpos < HOST_BITS_PER_WIDE_INT]
+               |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
+                  << (bitpos % HOST_BITS_PER_WIDE_INT);
+           }
+       }
+
+      if (!TREE_UNSIGNED (type))
+       {
+         bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
+         if (bitpos < HOST_BITS_PER_WIDE_INT)
+           {
+             if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+               {
+                 val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
+                 val[0] = -1;
+               }
+           }
+         else if (bitpos == HOST_BITS_PER_WIDE_INT)
+           {
+             if (val[1] < 0)
+               val[0] = -1;
+           }
+         else if (val[0] & (((HOST_WIDE_INT) 1)
+                            << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
+           val[0] |= ((HOST_WIDE_INT) -1)
+                     << (bitpos - HOST_BITS_PER_WIDE_INT);
+       }
+
+      value = build_int_2 (val[1], val[0]);
+      TREE_TYPE (value) = type;
+      add_pending_init (purpose, value);
+    }
+
+  constructor_incremental = 0;
+}
+
+/* Return value of FIELD in pending initializer or zero if the field was
+   not initialized yet.  */
+
+static tree
+find_init_member (field)
      tree field;
 {
   struct init_node *p;
 
-  p = constructor_pending_elts;
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
+      if (constructor_incremental
+         && tree_int_cst_lt (field, constructor_unfilled_index))
+       set_nonincremental_init ();
+
+      p = constructor_pending_elts;
       while (p)
        {
-         if (field == p->purpose)
-           return 1;
-         else if (tree_int_cst_lt (field, p->purpose))
+         if (tree_int_cst_lt (field, p->purpose))
            p = p->left;
-         else
+         else if (tree_int_cst_lt (p->purpose, field))
            p = p->right;
+         else
+           return p->value;
        }
     }
-  else
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
+      tree bitpos = bit_position (field);
+
+      if (constructor_incremental
+         && (!constructor_unfilled_fields
+             || tree_int_cst_lt (bitpos,
+                                 bit_position (constructor_unfilled_fields))))
+       set_nonincremental_init ();
+
+      p = constructor_pending_elts;
       while (p)
        {
          if (field == p->purpose)
-           return 1;
-         else if (tree_int_cst_lt (bit_position (field),
-                                   bit_position (p->purpose)))
+           return p->value;
+         else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
            p = p->left;
          else
            p = p->right;
        }
     }
-
+  else if (TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      if (constructor_elements
+         && TREE_PURPOSE (constructor_elements) == field)
+       return TREE_VALUE (constructor_elements);
+    }
   return 0;
 }
 
@@ -5814,8 +6217,6 @@ output_init_element (value, type, field, pending)
      tree value, type, field;
      int pending;
 {
-  int duplicate = 0;
-
   if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
       || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
          && !(TREE_CODE (value) == STRING_CST
@@ -5843,122 +6244,111 @@ output_init_element (value, type, field, pending)
     }
   else if (require_constant_elements
           && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
-    {
-      error_init ("initializer element is not computable at load time");
-      value = error_mark_node;
-    }
+    pedwarn ("initializer element is not computable at load time");
+
+  /* If this field is empty (and not at the end of structure),
+     don't do anything other than checking the initializer.  */
+  if (field
+      && (TREE_TYPE (field) == error_mark_node
+         || (COMPLETE_TYPE_P (TREE_TYPE (field))
+             && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
+             && (TREE_CODE (constructor_type) == ARRAY_TYPE
+                 || TREE_CHAIN (field)))))
+    return;
 
-  /* If this element duplicates one on constructor_pending_elts,
-     print a message and ignore it.  Don't do this when we're
-     processing elements taken off constructor_pending_elts,
-     because we'd always get spurious errors.  */
-  if (pending)
+  if (value == error_mark_node)
     {
-      if (TREE_CODE (constructor_type) == RECORD_TYPE
-         || TREE_CODE (constructor_type) == UNION_TYPE
-         || TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         if (pending_init_member (field))
-           {
-             error_init ("duplicate initializer");
-             duplicate = 1;
-           }
-       }
+      constructor_erroneous = 1;
+      return;
     }
 
   /* If this element doesn't come next in sequence,
      put it on constructor_pending_elts.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE
-      && ! tree_int_cst_equal (field, constructor_unfilled_index))
+      && (!constructor_incremental
+         || !tree_int_cst_equal (field, constructor_unfilled_index)))
     {
-      if (! duplicate)
-       add_pending_init (field,
-                         digest_init (type, value, require_constant_value, 
-                                      require_constant_elements));
+      if (constructor_incremental
+         && tree_int_cst_lt (field, constructor_unfilled_index))
+       set_nonincremental_init ();
+
+      add_pending_init (field,
+                       digest_init (type, value, require_constant_value, 
+                                    require_constant_elements));
+      return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
-          && field != constructor_unfilled_fields)
+          && (!constructor_incremental
+              || field != constructor_unfilled_fields))
     {
       /* We do this for records but not for unions.  In a union,
         no matter which field is specified, it can be initialized
         right away since it starts at the beginning of the union.  */
-      if (!duplicate)
-       add_pending_init (field,
-                         digest_init (type, value, require_constant_value, 
-                                      require_constant_elements));
-    }
-  else
-    {
-      /* Otherwise, output this element either to
-        constructor_elements or to the assembler file.  */
-
-      if (!duplicate)
+      if (constructor_incremental)
        {
-         if (! constructor_incremental)
-           {
-             if (field && TREE_CODE (field) == INTEGER_CST)
-               field = copy_node (field);
-             constructor_elements
-               = tree_cons (field, digest_init (type, value,
-                                                require_constant_value, 
-                                                require_constant_elements),
-                            constructor_elements);
-           }
+         if (!constructor_unfilled_fields)
+           set_nonincremental_init ();
          else
            {
-             /* Structure elements may require alignment.
-                Do this, if necessary.  */
-             if (TREE_CODE (constructor_type) == RECORD_TYPE
-                 && ! tree_int_cst_equal (constructor_bit_index,
-                                          bit_position (field)))
-               /* Advance to offset of this element.  */
-               assemble_zeros
-                 (tree_low_cst
-                  (size_binop (TRUNC_DIV_EXPR,
-                               size_binop (MINUS_EXPR, bit_position (field),
-                                           constructor_bit_index),
-                               bitsize_int (BITS_PER_UNIT)),
-                   0));
-
-             output_constant (digest_init (type, value,
-                                           require_constant_value,
-                                           require_constant_elements),
-                              int_size_in_bytes (type));
-
-             /* For a record or union,
-                keep track of end position of last field.  */
-             if (TREE_CODE (constructor_type) == RECORD_TYPE
-                 || TREE_CODE (constructor_type) == UNION_TYPE)
-               constructor_bit_index
-                 = size_binop (PLUS_EXPR, bit_position (field),
-                               DECL_SIZE (field));
+             tree bitpos, unfillpos;
+
+             bitpos = bit_position (field);
+             unfillpos = bit_position (constructor_unfilled_fields);
+
+             if (tree_int_cst_lt (bitpos, unfillpos))
+               set_nonincremental_init ();
            }
        }
 
-      /* Advance the variable that indicates sequential elements output.  */
-      if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       constructor_unfilled_index
-         = size_binop (PLUS_EXPR, constructor_unfilled_index,
-                       bitsize_int (1));
-      else if (TREE_CODE (constructor_type) == RECORD_TYPE)
-       {
-         constructor_unfilled_fields
-           = TREE_CHAIN (constructor_unfilled_fields);
-
-         /* Skip any nameless bit fields.  */
-         while (constructor_unfilled_fields != 0
-                && DECL_C_BIT_FIELD (constructor_unfilled_fields)
-                && DECL_NAME (constructor_unfilled_fields) == 0)
-           constructor_unfilled_fields =
-             TREE_CHAIN (constructor_unfilled_fields);
-       }
-      else if (TREE_CODE (constructor_type) == UNION_TYPE)
-       constructor_unfilled_fields = 0;
+      add_pending_init (field,
+                       digest_init (type, value, require_constant_value, 
+                                    require_constant_elements));
+      return;
+    }
+  else if (TREE_CODE (constructor_type) == UNION_TYPE
+          && constructor_elements)
+    {
+      if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+       warning_init ("initialized field with side-effects overwritten");
 
-      /* Now output any pending elements which have become next.  */
-      if (pending)
-       output_pending_init_elements (0);
+      /* We can have just one union field set.  */
+      constructor_elements = 0;
     }
+
+  /* Otherwise, output this element either to
+     constructor_elements or to the assembler file.  */
+
+  if (field && TREE_CODE (field) == INTEGER_CST)
+    field = copy_node (field);
+  constructor_elements
+    = tree_cons (field, digest_init (type, value,
+                                    require_constant_value, 
+                                    require_constant_elements),
+                constructor_elements);
+
+  /* Advance the variable that indicates sequential elements output.  */
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    constructor_unfilled_index
+      = size_binop (PLUS_EXPR, constructor_unfilled_index,
+                   bitsize_one_node);
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+    {
+      constructor_unfilled_fields
+       = TREE_CHAIN (constructor_unfilled_fields);
+
+      /* Skip any nameless bit fields.  */
+      while (constructor_unfilled_fields != 0
+            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+            && DECL_NAME (constructor_unfilled_fields) == 0)
+       constructor_unfilled_fields =
+         TREE_CHAIN (constructor_unfilled_fields);
+    }
+  else if (TREE_CODE (constructor_type) == UNION_TYPE)
+    constructor_unfilled_fields = 0;
+
+  /* Now output any pending elements which have become next.  */
+  if (pending)
+    output_pending_init_elements (0);
 }
 
 /* Output any pending elements which have become next.
@@ -6034,18 +6424,23 @@ output_pending_init_elements (all)
       else if (TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
        {
+         tree ctor_unfilled_bitpos, elt_bitpos;
+
          /* If the current record is complete we are done.  */
          if (constructor_unfilled_fields == 0)
            break;
-         if (elt->purpose == constructor_unfilled_fields)
+
+         ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
+         elt_bitpos = bit_position (elt->purpose);
+         /* We can't compare fields here because there might be empty
+            fields in between.  */
+         if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
            {
-             output_init_element (elt->value,
-                                  TREE_TYPE (constructor_unfilled_fields),
-                                  constructor_unfilled_fields,
-                                  0);
+             constructor_unfilled_fields = elt->purpose;
+             output_init_element (elt->value, TREE_TYPE (elt->purpose),
+                                  elt->purpose, 0);
            }
-         else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields),
-                                   bit_position (elt->purpose)))
+         else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
              /* Advance to the next smaller node.  */
              if (elt->left)
@@ -6071,9 +6466,8 @@ output_pending_init_elements (all)
                    elt = elt->parent;
                  elt = elt->parent;
                  if (elt
-                     && (tree_int_cst_lt
-                         (bit_position (constructor_unfilled_fields),
-                          bit_position (elt->purpose))))
+                     && (tree_int_cst_lt (ctor_unfilled_bitpos,
+                                          bit_position (elt->purpose))))
                    {
                      next = elt->purpose;
                      break;
@@ -6088,70 +6482,13 @@ output_pending_init_elements (all)
   if (! (all && next != 0))
     return;
 
-  /* Generate space up to the position of NEXT.  */
-  if (constructor_incremental)
-    {
-      tree filled;
-      tree nextpos_tree = bitsize_int (0);
-
-      if (TREE_CODE (constructor_type) == RECORD_TYPE
-         || TREE_CODE (constructor_type) == UNION_TYPE)
-       {
-         tree tail;
-
-         /* Find the last field written out, if any.  */
-         for (tail = TYPE_FIELDS (constructor_type); tail;
-              tail = TREE_CHAIN (tail))
-           if (TREE_CHAIN (tail) == constructor_unfilled_fields)
-             break;
-
-         if (tail)
-           /* Find the offset of the end of that field.  */
-           filled = size_binop (CEIL_DIV_EXPR,
-                                size_binop (PLUS_EXPR,
-                                            bit_position (tail),
-                                            DECL_SIZE (tail)),
-                                bitsize_int (BITS_PER_UNIT));
-         else
-           filled = bitsize_int (0);
-
-         nextpos_tree = size_binop (CEIL_DIV_EXPR,
-                                    bit_position (next),
-                                    bitsize_int (BITS_PER_UNIT));
-
-         constructor_bit_index = bit_position (next);
-         constructor_unfilled_fields = next;
-       }
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         filled
-           = size_binop (MULT_EXPR, constructor_unfilled_index,
-                         convert (bitsizetype,
-                                  TYPE_SIZE_UNIT
-                                  (TREE_TYPE (constructor_type))));
-         nextpos_tree
-           = size_binop (MULT_EXPR, next,
-                         convert (bitsizetype, TYPE_SIZE_UNIT
-                                  (TREE_TYPE (constructor_type))));
-         constructor_unfilled_index = next;
-       }
-      else
-       filled = 0;
-
-      if (filled)
-       assemble_zeros (tree_low_cst (size_diffop (nextpos_tree, filled), 1));
-    }
-  else
-    {
-      /* If it's not incremental, just skip over the gap,
-        so that after jumping to retry we will output the next
-        successive element.  */
-      if (TREE_CODE (constructor_type) == RECORD_TYPE
-         || TREE_CODE (constructor_type) == UNION_TYPE)
-       constructor_unfilled_fields = next;
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       constructor_unfilled_index = next;
-    }
+  /* If it's not incremental, just skip over the gap, so that after
+     jumping to retry we will output the next successive element.  */
+  if (TREE_CODE (constructor_type) == RECORD_TYPE
+      || TREE_CODE (constructor_type) == UNION_TYPE)
+    constructor_unfilled_fields = next;
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    constructor_unfilled_index = next;
 
   /* ELT now points to the node in the pending tree with the next
      initializer to output.  */
@@ -6164,13 +6501,7 @@ output_pending_init_elements (all)
    to handle a partly-braced initializer.
 
    Once this has found the correct level for the new element,
-   it calls output_init_element.
-
-   Note: if we are incrementally outputting this constructor,
-   this function may be called with a null argument
-   representing a sub-constructor that was already incrementally output.
-   When that happens, we output nothing, but we do the bookkeeping
-   to skip past that element of the current constructor.  */
+   it calls output_init_element.  */
 
 void
 process_init_element (value)
@@ -6179,6 +6510,9 @@ process_init_element (value)
   tree orig_value = value;
   int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
 
+  designator_depth = 0;
+  designator_errorneous = 0;
+
   /* Handle superfluous braces around string cst as in
      char x[] = {"foo"}; */
   if (string_flag
@@ -6221,6 +6555,10 @@ process_init_element (value)
        break;
     }
 
+  /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once.  */
+  if (constructor_range_stack)
+    value = save_expr (value);
+
   while (1)
     {
       if (TREE_CODE (constructor_type) == RECORD_TYPE)
@@ -6268,10 +6606,11 @@ process_init_element (value)
               directly output as a constructor.  */
            {
              /* For a record, keep track of end position of last field.  */
-             constructor_bit_index
-               = size_binop (PLUS_EXPR,
-                             bit_position (constructor_fields),
-                             DECL_SIZE (constructor_fields));
+             if (DECL_SIZE (constructor_fields))
+               constructor_bit_index
+                 = size_binop (PLUS_EXPR,
+                               bit_position (constructor_fields),
+                               DECL_SIZE (constructor_fields));
 
              constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
              /* Skip any nameless bit fields.  */
@@ -6288,9 +6627,8 @@ process_init_element (value)
                 && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
            constructor_fields = TREE_CHAIN (constructor_fields);
-         break;
        }
-      if (TREE_CODE (constructor_type) == UNION_TYPE)
+      else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
          tree fieldtype;
          enum tree_code fieldcode;
@@ -6306,6 +6644,20 @@ process_init_element (value)
            fieldtype = TYPE_MAIN_VARIANT (fieldtype);
          fieldcode = TREE_CODE (fieldtype);
 
+         /* Warn that traditional C rejects initialization of unions.
+            We skip the warning if the value is zero.  This is done
+            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.
+            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");
+
          /* Accept a string constant to initialize a subarray.  */
          if (value != 0
              && fieldcode == ARRAY_TYPE
@@ -6339,9 +6691,8 @@ process_init_element (value)
            }
 
          constructor_fields = 0;
-         break;
        }
-      if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
        {
          tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
          enum tree_code eltcode = TREE_CODE (elttype);
@@ -6365,104 +6716,166 @@ process_init_element (value)
            }
 
          if (constructor_max_index != 0
-             && tree_int_cst_lt (constructor_max_index, constructor_index))
+             && (tree_int_cst_lt (constructor_max_index, constructor_index)
+                 || integer_all_onesp (constructor_max_index)))
            {
              pedwarn_init ("excess elements in array initializer");
              break;
            }
 
-         /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once.  */
-         if (constructor_range_end)
+         /* Now output the actual element.  */
+         if (value)
            {
-             if (constructor_max_index != 0
-                 && tree_int_cst_lt (constructor_max_index, 
-                                     constructor_range_end))
-               {
-                 pedwarn_init ("excess elements in array initializer");
-                 constructor_range_end = constructor_max_index;
-               }
-
-             value = save_expr (value);
+             push_array_bounds (tree_low_cst (constructor_index, 0));
+             output_init_element (value, elttype, constructor_index, 1);
+             RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
-         /* Now output the actual element.
-            Ordinarily, output once.
-            If there is a range, repeat it till we advance past the range.  */
-         do
-           {
-             if (value)
-               {
-                 push_array_bounds (tree_low_cst (constructor_index, 0));
-                 output_init_element (value, elttype, constructor_index, 1);
-                 RESTORE_SPELLING_DEPTH (constructor_depth);
-               }
-
-             constructor_index
-               = size_binop (PLUS_EXPR, constructor_index, bitsize_int (1));
-
-             if (! value)
-               /* If we are doing the bookkeeping for an element that was
-                  directly output as a constructor, we must update
-                  constructor_unfilled_index.  */
-               constructor_unfilled_index = constructor_index;
-           }
-         while (! (constructor_range_end == 0
-                   || tree_int_cst_lt (constructor_range_end,
-                                       constructor_index)));
+         constructor_index
+           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-         break;
+         if (! value)
+           /* If we are doing the bookkeeping for an element that was
+              directly output as a constructor, we must update
+              constructor_unfilled_index.  */
+           constructor_unfilled_index = constructor_index;
        }
 
       /* Handle the sole element allowed in a braced initializer
         for a scalar variable.  */
-      if (constructor_fields == 0)
+      else if (constructor_fields == 0)
        {
          pedwarn_init ("excess elements in scalar initializer");
          break;
        }
+      else
+       {
+         if (value)
+           output_init_element (value, constructor_type, NULL_TREE, 1);
+         constructor_fields = 0;
+       }
+
+      /* Handle range initializers either at this level or anywhere higher
+        in the designator stack.  */
+      if (constructor_range_stack)
+       {
+         struct constructor_range_stack *p, *range_stack;
+         int finish = 0;
+
+         range_stack = constructor_range_stack;
+         constructor_range_stack = 0;
+         while (constructor_stack != range_stack->stack)
+           {
+             if (!constructor_stack->implicit)
+               abort ();
+             process_init_element (pop_init_level (1));
+           }
+         for (p = range_stack;
+              !p->range_end || tree_int_cst_equal (p->index, p->range_end);
+              p = p->prev)
+           {
+             if (!constructor_stack->implicit)
+               abort ();
+             process_init_element (pop_init_level (1));
+           }
+
+         p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
+         if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
+           finish = 1;
+
+         while (1)
+           {
+             constructor_index = p->index;
+             constructor_fields = p->fields;
+             if (finish && p->range_end && p->index == p->range_start)
+               {
+                 finish = 0;
+                 p->prev = 0;
+               }
+             p = p->next;
+             if (!p)
+               break;
+             push_init_level (2);
+             p->stack = constructor_stack;
+             if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
+               p->index = p->range_start;
+           }
+
+         if (!finish)
+           constructor_range_stack = range_stack;
+         continue;
+       }
 
-      if (value)
-       output_init_element (value, constructor_type, NULL_TREE, 1);
-      constructor_fields = 0;
       break;
     }
+
+  constructor_range_stack = 0;
 }
 \f
-/* Expand an ASM statement with operands, handling output operands
-   that are not variables or INDIRECT_REFS by transforming such
-   cases into cases that expand_asm_operands can handle.
+/* Build a simple asm-statement, from one string literal.  */
+tree
+simple_asm_stmt (expr)
+     tree expr;
+{
+  STRIP_NOPS (expr);
 
-   Arguments are same as for expand_asm_operands.  */
+  if (TREE_CODE (expr) == ADDR_EXPR)
+    expr = TREE_OPERAND (expr, 0);
 
-void
-c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
-     tree string, outputs, inputs, clobbers;
-     int vol;
-     char *filename;
-     int line;
+  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.  */
+
+tree
+build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
+     tree cv_qualifier;
+     tree string;
+     tree outputs;
+     tree inputs;
+     tree clobbers;
 {
-  int noutputs = list_length (outputs);
-  register int i;
-  /* o[I] is the place that output number I should be written.  */
-  register tree *o = (tree *) alloca (noutputs * sizeof (tree));
-  register tree tail;
+  tree tail;
 
-  if (TREE_CODE (string) == ADDR_EXPR)
-    string = TREE_OPERAND (string, 0);
+  if (TREE_CHAIN (string))
+    string = combine_strings (string);
   if (TREE_CODE (string) != STRING_CST)
     {
       error ("asm template is not a string constant");
-      return;
+      return NULL_TREE;
     }
 
-  /* Record the contents of OUTPUTS before it is modified.  */
-  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+  if (cv_qualifier != NULL_TREE
+      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
+    {
+      warning ("%s qualifier ignored on asm",
+              IDENTIFIER_POINTER (cv_qualifier));
+      cv_qualifier = NULL_TREE;
+    }
+
+  /* We can remove output conversions that change the type,
+     but not the mode.  */
+  for (tail = outputs; tail; tail = TREE_CHAIN (tail))
     {
       tree output = TREE_VALUE (tail);
 
-      /* We can remove conversions that just change the type, not the mode.  */
       STRIP_NOPS (output);
-      o[i] = output;
+      TREE_VALUE (tail) = output;
 
       /* Allow conversions as LHS here.  build_modify_expr as called below
         will do the right thing with them.  */
@@ -6475,20 +6888,52 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
             || TREE_CODE (output) == FIX_CEIL_EXPR)
        output = TREE_OPERAND (output, 0);
 
-      lvalue_or_else (o[i], "invalid lvalue in asm statement");
+      lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement");
+    }
+
+  /* Remove output conversions that change the type but not the mode.  */
+  for (tail = outputs; tail; tail = TREE_CHAIN (tail))
+    {
+      tree output = TREE_VALUE (tail);
+      STRIP_NOPS (output);
+      TREE_VALUE (tail) = output;
     }
 
-  /* Perform default conversions on array and function inputs.  */
-  /* Don't do this for other types--
-     it would screw up operands expected to be in memory.  */
-  for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
-    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));
+  /* Perform default conversions on array and function inputs. 
+     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))
+    TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
+
+  return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
+                              outputs, inputs, clobbers));
+}
+
+/* Expand an ASM statement with operands, handling output operands
+   that are not variables or INDIRECT_REFS by transforming such
+   cases into cases that expand_asm_operands can handle.
+
+   Arguments are same as for expand_asm_operands.  */
 
-  /* Generate the ASM_OPERANDS insn;
-     store into the TREE_VALUEs of OUTPUTS some trees for
-     where the values were actually stored.  */
+void
+c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
+     tree string, outputs, inputs, clobbers;
+     int vol;
+     const char *filename;
+     int line;
+{
+  int noutputs = list_length (outputs);
+  int i;
+  /* o[I] is the place that output number I should be written.  */
+  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++)
+    o[i] = TREE_VALUE (tail);
+
+  /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
+     OUTPUTS some trees for where the values were actually stored.  */
   expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
 
   /* Copy all the intermediate outputs into the specified outputs.  */
@@ -6499,6 +6944,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
          expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
                       NULL_RTX, VOIDmode, EXPAND_NORMAL);
          free_temp_slots ();
+
+         /* Restore the original value so that it's correct the next
+            time we expand this function.  */
+         TREE_VALUE (tail) = o[i];
        }
       /* Detect modification of read-only values.
         (Otherwise done by build_modify_expr.)  */
@@ -6522,7 +6971,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
    RETVAL is the expression for what to return,
    or a null pointer for `return;' with no value.  */
 
-void
+tree
 c_expand_return (retval)
      tree retval;
 {
@@ -6534,16 +6983,15 @@ c_expand_return (retval)
   if (!retval)
     {
       current_function_returns_null = 1;
-      if (warn_return_type && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
-       warning ("`return' with no value, in function returning non-void");
-      expand_null_return ();
+      if ((warn_return_type || flag_isoc99)
+         && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
+       pedwarn_c99 ("`return' with no value, in function returning non-void");
     }
   else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
     {
       current_function_returns_null = 1;
       if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
        pedwarn ("`return' with a value, in function returning void");
-      expand_return (retval);
     }
   else
     {
@@ -6553,7 +7001,7 @@ c_expand_return (retval)
       tree inner;
 
       if (t == error_mark_node)
-       return;
+       return NULL_TREE;
 
       inner = t = convert (TREE_TYPE (res), t);
 
@@ -6608,58 +7056,125 @@ c_expand_return (retval)
          break;
        }
 
-      t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-      expand_return (t);
+      retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
       current_function_returns_value = 1;
     }
+
+ return add_stmt (build_return_stmt (retval));
 }
 \f
-/* Start a C switch statement, testing expression EXP.
-   Return EXP if it is valid, an error node otherwise.  */
+struct c_switch {
+  /* The SWITCH_STMT being built.  */
+  tree switch_stmt;
+  /* A splay-tree mapping the low element of a case range to the high
+     element, or NULL_TREE if there is no high element.  Used to
+     determine whether or not a new case label duplicates an old case
+     label.  We need a tree, rather than simply a hash table, because
+     of the GNU case range extension.  */
+  splay_tree cases;
+  /* The next node on the stack.  */
+  struct c_switch *next;
+};
+
+/* A stack of the currently active switch statements.  The innermost
+   switch statement is on the top of the stack.  There is no need to
+   mark the stack for garbage collection because it is only active
+   during the processing of the body of a function, and we never
+   collect at that point.  */
+
+static struct c_switch *switch_stack;
+
+/* Start a C switch statement, testing expression EXP.  Return the new
+   SWITCH_STMT.  */
 
 tree
-c_expand_start_case (exp)
+c_start_case (exp)
      tree exp;
 {
-  register enum tree_code code;
+  enum tree_code code;
   tree type;
+  struct c_switch *cs;
+
+  if (exp != error_mark_node)
+    {
+      code = TREE_CODE (TREE_TYPE (exp));
+      type = TREE_TYPE (exp);
+
+      if (! INTEGRAL_TYPE_P (type)
+         && code != ERROR_MARK)
+       {
+         error ("switch quantity not an integer");
+         exp = integer_zero_node;
+       }
+      else
+       {
+         tree index;
+         type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+
+         if (warn_traditional && !in_system_header
+             && (type == long_integer_type_node
+                 || type == long_unsigned_type_node))
+           warning ("`long' switch expression not converted to `int' in ISO C");
+
+         exp = default_conversion (exp);
+         type = TREE_TYPE (exp);
+         index = get_unwidened (exp, NULL_TREE);
+         /* We can't strip a conversion from a signed type to an
+            unsigned, because if we did, int_fits_type_p would do the
+            wrong thing when checking case values for being in range,
+            and it's too hard to do the right thing.  */
+         if (TREE_UNSIGNED (TREE_TYPE (exp))
+             == TREE_UNSIGNED (TREE_TYPE (index)))
+           exp = index;
+       }
+    }
+
+  /* Add this new SWITCH_STMT to the stack.  */
+  cs = (struct c_switch *) xmalloc (sizeof (*cs));
+  cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, NULL_TREE);
+  cs->cases = splay_tree_new (case_compare, NULL, NULL);
+  cs->next = switch_stack;
+  switch_stack = cs;
+
+  return add_stmt (switch_stack->switch_stmt);
+}
 
-  if (TREE_CODE (exp) == ERROR_MARK)
-    return exp;
+/* Process a case label.  */
 
-  code = TREE_CODE (TREE_TYPE (exp));
-  type = TREE_TYPE (exp);
+tree
+do_case (low_value, high_value)
+     tree low_value;
+     tree high_value;
+{
+  tree label = NULL_TREE;
 
-  if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
+  if (switch_stack)
     {
-      error ("switch quantity not an integer");
-      exp = error_mark_node;
+      label = c_add_case_label (switch_stack->cases, 
+                               SWITCH_COND (switch_stack->switch_stmt), 
+                               low_value, high_value);
+      if (label == error_mark_node)
+       label = NULL_TREE;
     }
+  else if (low_value)
+    error ("case label not within a switch statement");
   else
-    {
-      tree index;
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+    error ("`default' label not within a switch statement");
 
-      if (warn_traditional
-         && ! in_system_header
-         && (type == long_integer_type_node
-             || type == long_unsigned_type_node))
-       pedwarn ("`long' switch expression not converted to `int' in ANSI C");
+  return label;
+}
 
-      exp = default_conversion (exp);
-      type = TREE_TYPE (exp);
-      index = get_unwidened (exp, NULL_TREE);
-      /* We can't strip a conversion from a signed type to an unsigned,
-        because if we did, int_fits_type_p would do the wrong thing
-        when checking case values for being in range,
-        and it's too hard to do the right thing.  */
-      if (TREE_UNSIGNED (TREE_TYPE (exp))
-         == TREE_UNSIGNED (TREE_TYPE (index)))
-       exp = index;
-    }
+/* Finish the switch statement.  */
 
-  expand_start_case (1, exp, type, "switch statement");
+void
+c_finish_case ()
+{
+  struct c_switch *cs = switch_stack;
 
-  return exp;
+  RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt)); 
+
+  /* Pop the stack.  */
+  switch_stack = switch_stack->next;
+  splay_tree_delete (cs->cases);
+  free (cs);
 }