OSDN Git Service

* c-tree.h (enum c_declarator_kind, struct c_arg_info, struct
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index e8bec8f..1bab695 100644 (file)
@@ -23,11 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* This file is part of the C front end.
    It contains routines to build C expressions given their operands,
    including computing the types of the result, C-specific error checks,
-   and some optimization.
-
-   There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,
-   and to process initializations in declarations (since they work
-   like a strange sort of assignment).  */
+   and some optimization.  */
 
 #include "config.h"
 #include "system.h"
@@ -35,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "langhooks.h"
 #include "c-tree.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -44,25 +41,35 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "intl.h"
 #include "ggc.h"
 #include "target.h"
+#include "tree-iterator.h"
+#include "tree-gimple.h"
+
+/* The level of nesting inside "__alignof__".  */
+int in_alignof;
+
+/* The level of nesting inside "sizeof".  */
+int in_sizeof;
+
+/* The level of nesting inside "typeof".  */
+int in_typeof;
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 static int missing_braces_mentioned;
 
+static int require_constant_value;
+static int require_constant_elements;
+
 static tree qualify_type (tree, tree);
-static int same_translation_unit_p (tree, tree);
-static int tagged_types_tu_compatible_p (tree, tree, int);
+static int tagged_types_tu_compatible_p (tree, tree);
 static int comp_target_types (tree, tree, int);
-static int function_types_compatible_p (tree, tree, int);
-static int type_lists_compatible_p (tree, tree, int);
+static int function_types_compatible_p (tree, tree);
+static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
-static tree unary_complex_lvalue (enum tree_code, tree, int);
-static void pedantic_lvalue_warning (enum tree_code);
-static tree internal_build_compound_expr (tree, int);
 static tree convert_for_assignment (tree, tree, const char *, tree, tree,
                                    int);
 static void warn_for_assignment (const char *, const char *, tree, int);
@@ -73,8 +80,8 @@ static void push_array_bounds (int);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (const char *);
-static tree digest_init (tree, tree, int);
-static void output_init_element (tree, tree, tree, int);
+static tree digest_init (tree, tree, bool, int);
+static void output_init_element (tree, bool, tree, tree, int);
 static void output_pending_init_elements (int);
 static int set_designator (int);
 static void push_range_stack (tree);
@@ -82,6 +89,7 @@ static void add_pending_init (tree, tree);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
+static int lvalue_or_else (tree, const char *);
 \f
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
@@ -157,7 +165,7 @@ c_incomplete_type_error (tree value, tree type)
          return;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -182,7 +190,7 @@ c_type_promotes_to (tree type)
   if (c_promoting_integer_type_p (type))
     {
       /* Preserve unsignedness if not really getting any wider.  */
-      if (TREE_UNSIGNED (type)
+      if (TYPE_UNSIGNED (type)
           && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
         return unsigned_type_node;
       return integer_type_node;
@@ -201,16 +209,14 @@ qualify_type (tree type, tree like)
                                 TYPE_QUALS (type) | TYPE_QUALS (like));
 }
 \f
-/* Return the common type of two types.
-   We assume that comptypes has already been done and returned 1;
-   if that isn't so, this may crash.  In particular, we assume that qualifiers
-   match.
+/* Return the composite type of two compatible types.
 
-   This is the type for the result of most arithmetic operations
-   if the operands have the given two types.  */
+   We assume that comptypes has already been done and returned
+   nonzero; if that isn't so, this may crash.  In particular, we
+   assume that qualifiers match.  */
 
 tree
-common_type (tree t1, tree t2)
+composite_type (tree t1, tree t2)
 {
   enum tree_code code1;
   enum tree_code code2;
@@ -226,114 +232,55 @@ common_type (tree t1, tree t2)
   if (t2 == error_mark_node)
     return t1;
 
-  /* Merge the attributes.  */
-  attributes = (*targetm.merge_type_attributes) (t1, t2);
-
-  /* Treat an enum type as the unsigned integer type of the same width.  */
-
-  if (TREE_CODE (t1) == ENUMERAL_TYPE)
-    t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
-  if (TREE_CODE (t2) == ENUMERAL_TYPE)
-    t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
-
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
-  /* If one type is complex, form the common type of the non-complex
-     components, then make that complex.  Use T1 or T2 if it is the
-     required type.  */
-  if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
-    {
-      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
-      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
-      tree subtype = common_type (subtype1, subtype2);
-
-      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
-       return build_type_attribute_variant (t1, attributes);
-      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
-       return build_type_attribute_variant (t2, attributes);
-      else
-       return build_type_attribute_variant (build_complex_type (subtype),
-                                            attributes);
-    }
-
-  switch (code1)
-    {
-    case INTEGER_TYPE:
-    case REAL_TYPE:
-      /* If only one is real, use it as the result.  */
-
-      if (code1 == REAL_TYPE && code2 != REAL_TYPE)
-       return build_type_attribute_variant (t1, attributes);
-
-      if (code2 == REAL_TYPE && code1 != REAL_TYPE)
-       return build_type_attribute_variant (t2, attributes);
-
-      /* Both real or both integers; use the one with greater precision.  */
-
-      if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
-       return build_type_attribute_variant (t1, attributes);
-      else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
-       return build_type_attribute_variant (t2, attributes);
-
-      /* Same precision.  Prefer longs to ints even when same size.  */
-
-      if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
-         || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
-       return build_type_attribute_variant (long_unsigned_type_node,
-                                            attributes);
-
-      if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
-         || TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
-       {
-         /* But preserve unsignedness from the other type,
-            since long cannot hold all the values of an unsigned int.  */
-         if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
-            t1 = long_unsigned_type_node;
-         else
-            t1 = long_integer_type_node;
-         return build_type_attribute_variant (t1, attributes);
-       }
+  /* Merge the attributes.  */
+  attributes = targetm.merge_type_attributes (t1, t2);
 
-      /* Likewise, prefer long double to double even if same size.  */
-      if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
-         || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
-       return build_type_attribute_variant (long_double_type_node,
-                                            attributes);
+  /* If one is an enumerated type and the other is the compatible
+     integer type, the composite type might be either of the two
+     (DR#013 question 3).  For consistency, use the enumerated type as
+     the composite type.  */
 
-      /* Otherwise prefer the unsigned one.  */
+  if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
+    return t1;
+  if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
+    return t2;
 
-      if (TREE_UNSIGNED (t1))
-       return build_type_attribute_variant (t1, attributes);
-      else
-       return build_type_attribute_variant (t2, attributes);
+  gcc_assert (code1 == code2);
 
+  switch (code1)
+    {
     case POINTER_TYPE:
-      /* For two pointers, do this recursively on the target type,
-        and combine the qualifiers of the two types' targets.  */
-      /* This code was turned off; I don't know why.
-        But ANSI C specifies doing this with the qualifiers.
-        So I turned it on again.  */
+      /* For two pointers, do this recursively on the target type.  */
       {
        tree pointed_to_1 = TREE_TYPE (t1);
        tree pointed_to_2 = TREE_TYPE (t2);
-       tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
-                                  TYPE_MAIN_VARIANT (pointed_to_2));
-       t1 = build_pointer_type (c_build_qualified_type
-                                (target,
-                                 TYPE_QUALS (pointed_to_1) |
-                                 TYPE_QUALS (pointed_to_2)));
-       return build_type_attribute_variant (t1, attributes);
+       tree target = composite_type (pointed_to_1, pointed_to_2);
+       t1 = build_pointer_type (target);
+       t1 = build_type_attribute_variant (t1, attributes);
+       return qualify_type (t1, t2);
       }
 
     case ARRAY_TYPE:
       {
-       tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
+       tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
+       
+       /* We should not have any type quals on arrays at all.  */
+       gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
+       
        /* Save space: see if the result is identical to one of the args.  */
        if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t1, attributes);
        if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
          return build_type_attribute_variant (t2, attributes);
+       
+       if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+         return build_type_attribute_variant (t1, attributes);
+       if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+         return build_type_attribute_variant (t2, attributes);
+       
        /* Merge the element types, and have a size if either arg has one.  */
        t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
        return build_type_attribute_variant (t1, attributes);
@@ -343,7 +290,7 @@ common_type (tree t1, tree t2)
       /* Function types: prefer the one that specified arg types.
         If both do, merge the arg types.  Also merge the return types.  */
       {
-       tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
+       tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
        tree p1 = TYPE_ARG_TYPES (t1);
        tree p2 = TYPE_ARG_TYPES (t2);
        int len;
@@ -359,20 +306,22 @@ common_type (tree t1, tree t2)
        /* Simple way if one arg fails to specify argument types.  */
        if (TYPE_ARG_TYPES (t1) == 0)
         {
-          t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
-          return build_type_attribute_variant (t1, attributes);
+           t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
+           t1 = build_type_attribute_variant (t1, attributes);
+           return qualify_type (t1, t2);
         }
        if (TYPE_ARG_TYPES (t2) == 0)
         {
           t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
-          return build_type_attribute_variant (t1, attributes);
+          t1 = build_type_attribute_variant (t1, attributes);
+          return qualify_type (t1, t2);
         }
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
-
-       pushlevel (0);
-       declare_parm_level ();
+       /* Tell global_bindings_p to return false so that variable_size
+          doesn't abort on VLAs in parameter types.  */
+       c_override_global_bindings_to_false = true;
 
        len = list_length (p1);
        newargs = 0;
@@ -407,8 +356,7 @@ common_type (tree t1, tree t2)
                tree memb;
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
                     memb; memb = TREE_CHAIN (memb))
-                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2), 
-                                COMPARE_STRICT))
+                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))
                    {
                      TREE_VALUE (n) = TREE_VALUE (p2);
                      if (pedantic)
@@ -422,8 +370,7 @@ common_type (tree t1, tree t2)
                tree memb;
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
                     memb; memb = TREE_CHAIN (memb))
-                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1), 
-                                COMPARE_STRICT))
+                 if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))
                    {
                      TREE_VALUE (n) = TREE_VALUE (p1);
                      if (pedantic)
@@ -431,13 +378,13 @@ common_type (tree t1, tree t2)
                      goto parm_done;
                    }
              }
-           TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
+           TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
          parm_done: ;
          }
 
-       poplevel (0, 0, 0);
-
+       c_override_global_bindings_to_false = false;
        t1 = build_function_type (valtype, newargs);
+       t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
       }
 
@@ -446,13 +393,186 @@ common_type (tree t1, tree t2)
     }
 
 }
+
+/* Return the type of a conditional expression between pointers to
+   possibly differently qualified versions of compatible types.
+
+   We assume that comp_target_types has already been done and returned
+   nonzero; if that isn't so, this may crash.  */
+
+static tree
+common_pointer_type (tree t1, tree t2)
+{
+  tree attributes;
+  tree pointed_to_1;
+  tree pointed_to_2;
+  tree target;
+
+  /* Save time if the two types are the same.  */
+
+  if (t1 == t2) return t1;
+
+  /* If one type is nonsense, use the other.  */
+  if (t1 == error_mark_node)
+    return t2;
+  if (t2 == error_mark_node)
+    return t1;
+
+  gcc_assert (TREE_CODE (t1) == POINTER_TYPE
+             && TREE_CODE (t2) == POINTER_TYPE);
+
+  /* Merge the attributes.  */
+  attributes = targetm.merge_type_attributes (t1, t2);
+
+  /* Find the composite type of the target types, and combine the
+     qualifiers of the two types' targets.  */
+  pointed_to_1 = TREE_TYPE (t1);
+  pointed_to_2 = TREE_TYPE (t2);
+  target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
+                          TYPE_MAIN_VARIANT (pointed_to_2));
+  t1 = build_pointer_type (c_build_qualified_type
+                          (target,
+                           TYPE_QUALS (pointed_to_1) |
+                           TYPE_QUALS (pointed_to_2)));
+  return build_type_attribute_variant (t1, attributes);
+}
+
+/* Return the common type for two arithmetic types under the usual
+   arithmetic conversions.  The default conversions have already been
+   applied, and enumerated types converted to their compatible integer
+   types.  The resulting type is unqualified and has no attributes.
+
+   This is the type for the result of most arithmetic operations
+   if the operands have the given two types.  */
+
+tree
+common_type (tree t1, tree t2)
+{
+  enum tree_code code1;
+  enum tree_code code2;
+
+  /* If one type is nonsense, use the other.  */
+  if (t1 == error_mark_node)
+    return t2;
+  if (t2 == error_mark_node)
+    return t1;
+
+  if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
+    t1 = TYPE_MAIN_VARIANT (t1);
+
+  if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
+    t2 = TYPE_MAIN_VARIANT (t2);
+
+  if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
+    t1 = build_type_attribute_variant (t1, NULL_TREE);
+
+  if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
+    t2 = build_type_attribute_variant (t2, NULL_TREE);
+
+  /* Save time if the two types are the same.  */
+
+  if (t1 == t2) return t1;
+
+  code1 = TREE_CODE (t1);
+  code2 = TREE_CODE (t2);
+
+  gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
+             || code1 == REAL_TYPE || code1 == INTEGER_TYPE);
+  gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
+             || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
+
+  /* If one type is a vector type, return that type.  (How the usual
+     arithmetic conversions apply to the vector types extension is not
+     precisely specified.)  */
+  if (code1 == VECTOR_TYPE)
+    return t1;
+
+  if (code2 == VECTOR_TYPE)
+    return t2;
+
+  /* If one type is complex, form the common type of the non-complex
+     components, then make that complex.  Use T1 or T2 if it is the
+     required type.  */
+  if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+    {
+      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+      tree subtype = common_type (subtype1, subtype2);
+
+      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+       return t1;
+      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+       return t2;
+      else
+       return build_complex_type (subtype);
+    }
+
+  /* If only one is real, use it as the result.  */
+
+  if (code1 == REAL_TYPE && code2 != REAL_TYPE)
+    return t1;
+
+  if (code2 == REAL_TYPE && code1 != REAL_TYPE)
+    return t2;
+
+  /* Both real or both integers; use the one with greater precision.  */
+
+  if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
+    return t1;
+  else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
+    return t2;
+
+  /* Same precision.  Prefer long longs to longs to ints when the
+     same precision, following the C99 rules on integer type rank
+     (which are equivalent to the C90 rules for C90 types).  */
+
+  if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
+    return long_long_unsigned_type_node;
+
+  if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
+    {
+      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+       return long_long_unsigned_type_node;
+      else
+        return long_long_integer_type_node;
+    }
+
+  if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
+    return long_unsigned_type_node;
+
+  if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
+    {
+      /* But preserve unsignedness from the other type,
+        since long cannot hold all the values of an unsigned int.  */
+      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+       return long_unsigned_type_node;
+      else
+       return long_integer_type_node;
+    }
+
+  /* Likewise, prefer long double to double even if same size.  */
+  if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+    return long_double_type_node;
+
+  /* Otherwise prefer the unsigned one.  */
+
+  if (TYPE_UNSIGNED (t1))
+    return t1;
+  else
+    return t2;
+}
 \f
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
 
 int
-comptypes (tree type1, tree type2, int flags)
+comptypes (tree type1, tree type2)
 {
   tree t1 = type1;
   tree t2 = type2;
@@ -467,30 +587,32 @@ comptypes (tree type1, tree type2, int flags)
   /* If either type is the internal version of sizetype, return the
      language version.  */
   if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
-      && TYPE_DOMAIN (t1) != 0)
-    t1 = TYPE_DOMAIN (t1);
+      && TYPE_ORIG_SIZE_TYPE (t1))
+    t1 = TYPE_ORIG_SIZE_TYPE (t1);
 
   if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
-      && TYPE_DOMAIN (t2) != 0)
-    t2 = TYPE_DOMAIN (t2);
+      && TYPE_ORIG_SIZE_TYPE (t2))
+    t2 = TYPE_ORIG_SIZE_TYPE (t2);
+
 
   /* Enumerated types are compatible with integer types, but this is
      not transitive: two enumerated types in the same translation unit
      are compatible with each other only if they are the same type.  */
 
   if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
-    t1 = c_common_type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
+    t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
   else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
-    t2 = c_common_type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
+    t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
 
   if (t1 == t2)
     return 1;
 
   /* Different classes of types can't be compatible.  */
 
-  if (TREE_CODE (t1) != TREE_CODE (t2)) return 0;
+  if (TREE_CODE (t1) != TREE_CODE (t2))
+    return 0;
 
-  /* Qualifiers must match.  */
+  /* Qualifiers must match. C99 6.7.3p9 */
 
   if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
     return 0;
@@ -503,7 +625,7 @@ comptypes (tree type1, tree type2, int flags)
     return 1;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (! (attrval = (*targetm.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.  */
@@ -517,11 +639,11 @@ comptypes (tree type1, tree type2, int flags)
       if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
+            ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, flags);
+      val = function_types_compatible_p (t1, t2);
       break;
 
     case ARRAY_TYPE:
@@ -534,8 +656,7 @@ comptypes (tree type1, tree type2, int flags)
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
-           && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2),
-                                     flags)))
+           && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
@@ -573,13 +694,12 @@ comptypes (tree type1, tree type2, int flags)
     case ENUMERAL_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
-       val = tagged_types_tu_compatible_p (t1, t2, flags);
+       val = tagged_types_tu_compatible_p (t1, t2);
       break;
 
     case VECTOR_TYPE:
-      /* The target might allow certain vector types to be compatible.  */
-      val = (*targetm.vector_opaque_p) (t1)
-       || (*targetm.vector_opaque_p) (t2);
+      val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+           && comptypes (TREE_TYPE (t1), TREE_TYPE (t2));
       break;
 
     default:
@@ -605,7 +725,7 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
     return val;
 
   val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
-                  TYPE_MAIN_VARIANT (TREE_TYPE (ttr)), COMPARE_STRICT);
+                  TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
 
   if (val == 2 && pedantic)
     pedwarn ("types are not quite compatible");
@@ -614,11 +734,11 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
 \f
 /* Subroutines of `comptypes'.  */
 
-/* Determine whether two types derive from the same translation unit.
-   If the CONTEXT chain ends in a null, that type's context is still
-   being parsed, so if two types have context chains ending in null,
+/* Determine whether two trees derive from the same translation unit.
+   If the CONTEXT chain ends in a null, that tree's context is still
+   being parsed, so if two trees have context chains ending in null,
    they're in the same translation unit.  */
-static int
+int
 same_translation_unit_p (tree t1, tree t2)
 {
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
@@ -626,17 +746,17 @@ same_translation_unit_p (tree t1, tree t2)
       {
       case 'd': t1 = DECL_CONTEXT (t1); break;
       case 't': t1 = TYPE_CONTEXT (t1); break;
-      case 'b': t1 = BLOCK_SUPERCONTEXT (t1); break;
-      default: abort ();
+      case 'x': t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
+      default: gcc_unreachable ();
       }
 
   while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t2)))
       {
-      case 'd': t2 = DECL_CONTEXT (t1); break;
+      case 'd': t2 = DECL_CONTEXT (t2); break;
       case 't': t2 = TYPE_CONTEXT (t2); break;
-      case 'b': t2 = BLOCK_SUPERCONTEXT (t2); break;
-      default: abort ();
+      case 'x': t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
+      default: gcc_unreachable ();
       }
 
   return t1 == t2;
@@ -665,46 +785,73 @@ static const struct tagged_tu_seen * tagged_tu_seen_base;
    rules.  */
 
 static int
-tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
+tagged_types_tu_compatible_p (tree t1, tree t2)
 {
   tree s1, s2;
   bool needs_warning = false;
-  
+
   /* We have to verify that the tags of the types are the same.  This
      is harder than it looks because this may be a typedef, so we have
      to go look at the original type.  It may even be a typedef of a
-     typedef...  */
-  while (TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL)
+     typedef...
+     In the case of compiler-created builtin structs the TYPE_DECL
+     may be a dummy, with no DECL_ORIGINAL_TYPE.  Don't fault.  */
+  while (TYPE_NAME (t1)
+        && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
+        && DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
     t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
 
-  while (TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL)
+  while (TYPE_NAME (t2)
+        && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
+        && DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
     t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
 
   /* C90 didn't have the requirement that the two tags be the same.  */
   if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
     return 0;
-  
+
   /* C90 didn't say what happened if one or both of the types were
      incomplete; we choose to follow C99 rules here, which is that they
      are compatible.  */
   if (TYPE_SIZE (t1) == NULL
       || TYPE_SIZE (t2) == NULL)
     return 1;
-  
+
   {
     const struct tagged_tu_seen * tts_i;
     for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
       if (tts_i->t1 == t1 && tts_i->t2 == t2)
        return 1;
   }
-  
+
   switch (TREE_CODE (t1))
     {
     case ENUMERAL_TYPE:
       {
+
+        /* Speed up the case where the type values are in the same order.  */
+        tree tv1 = TYPE_VALUES (t1);
+        tree tv2 = TYPE_VALUES (t2);
+
+        if (tv1 == tv2)
+          return 1;
+
+        for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
+          {
+            if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
+              break;
+            if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
+              return 0;
+          }
+
+        if (tv1 == NULL_TREE && tv2 == NULL_TREE)
+          return 1;
+        if (tv1 == NULL_TREE || tv2 == NULL_TREE)
+          return 0;
+
        if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
          return 0;
-       
+
        for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
          {
            s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
@@ -729,18 +876,18 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
            tts.t1 = t1;
            tts.t2 = t2;
            tagged_tu_seen_base = &tts;
-       
+
            if (DECL_NAME (s1) != NULL)
-             for (s2 = TYPE_VALUES (t2); s2; s2 = TREE_CHAIN (s2))
+             for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
                if (DECL_NAME (s1) == DECL_NAME (s2))
                  {
                    int result;
-                   result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
+                   result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
                    if (result == 0)
                      break;
                    if (result == 2)
                      needs_warning = true;
-                   
+
                    if (TREE_CODE (s1) == FIELD_DECL
                        && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
                                             DECL_FIELD_BIT_OFFSET (s2)) != 1)
@@ -759,13 +906,13 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
     case RECORD_TYPE:
       {
        struct tagged_tu_seen tts;
-       
+
        tts.next = tagged_tu_seen_base;
        tts.t1 = t1;
        tts.t2 = t2;
        tagged_tu_seen_base = &tts;
-         
-       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); 
+
+       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
             s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
          {
@@ -773,12 +920,12 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
+           result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
            if (result == 0)
              break;
            if (result == 2)
              needs_warning = true;
-           
+
            if (TREE_CODE (s1) == FIELD_DECL
                && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
                                     DECL_FIELD_BIT_OFFSET (s2)) != 1)
@@ -791,7 +938,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
       }
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -803,7 +950,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
    Otherwise, the argument types must match.  */
 
 static int
-function_types_compatible_p (tree f1, tree f2, int flags)
+function_types_compatible_p (tree f1, tree f2)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -814,9 +961,9 @@ function_types_compatible_p (tree f1, tree f2, int flags)
   ret1 = TREE_TYPE (f1);
   ret2 = TREE_TYPE (f2);
 
-  /* 'volatile' qualifiers on a function's return type mean the function
-     is noreturn.  */
-  if (pedantic && TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
+  /* 'volatile' qualifiers on a function's return type used to mean
+     the function is noreturn.  */
+  if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
     pedwarn ("function return types not compatible due to `volatile'");
   if (TYPE_VOLATILE (ret1))
     ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
@@ -824,7 +971,7 @@ function_types_compatible_p (tree f1, tree f2, int flags)
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes (ret1, ret2, flags);
+  val = comptypes (ret1, ret2);
   if (val == 0)
     return 0;
 
@@ -842,8 +989,7 @@ function_types_compatible_p (tree f1, tree f2, int flags)
         compare that with the other type's arglist.
         If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
-         && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
-                                          flags))
+         && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
        val = 2;
       return val;
     }
@@ -852,14 +998,13 @@ function_types_compatible_p (tree f1, tree f2, int flags)
       if (!self_promoting_args_p (args1))
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
-         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
-                                          flags))
+         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, flags);
+  val1 = type_lists_compatible_p (args1, args2);
   return val1 != 1 ? val1 : val;
 }
 
@@ -868,7 +1013,7 @@ function_types_compatible_p (tree f1, tree f2, int flags)
    or 2 for compatible with warning.  */
 
 static int
-type_lists_compatible_p (tree args1, tree args2, int flags)
+type_lists_compatible_p (tree args1, tree args2)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -901,8 +1046,7 @@ type_lists_compatible_p (tree args1, tree args2, int flags)
               || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK)
        ;
       else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
-                                     TYPE_MAIN_VARIANT (TREE_VALUE (args2)),
-                                     flags)))
+                                     TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
@@ -916,8 +1060,7 @@ type_lists_compatible_p (tree args1, tree args2, int flags)
              tree memb;
              for (memb = TYPE_FIELDS (TREE_VALUE (args1));
                   memb; memb = TREE_CHAIN (memb))
-               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2),
-                              flags))
+               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
                  break;
              if (memb == 0)
                return 0;
@@ -932,8 +1075,7 @@ type_lists_compatible_p (tree args1, tree args2, int flags)
              tree memb;
              for (memb = TYPE_FIELDS (TREE_VALUE (args2));
                   memb; memb = TREE_CHAIN (memb))
-               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1),
-                              flags))
+               if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
                  break;
              if (memb == 0)
                return 0;
@@ -979,8 +1121,10 @@ tree
 decl_constant_value (tree decl)
 {
   if (/* Don't change a variable array bound or initial value to a constant
-        in a place where a variable is invalid.  */
+        in a place where a variable is invalid.  Note that DECL_INITIAL
+        isn't valid for a PARM_DECL.  */
       current_function_decl != 0
+      && TREE_CODE (decl) != PARM_DECL
       && ! TREE_THIS_VOLATILE (decl)
       && TREE_READONLY (decl)
       && DECL_INITIAL (decl) != 0
@@ -1040,9 +1184,8 @@ default_function_array_conversion (tree 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));
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
 
   if (code == FUNCTION_TYPE)
     {
@@ -1071,14 +1214,14 @@ default_function_array_conversion (tree exp)
                                    | (volatilep * TYPE_QUAL_VOLATILE));
 
       if (TREE_CODE (exp) == INDIRECT_REF)
-       return convert (TYPE_POINTER_TO (restype),
+       return convert (build_pointer_type (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);
+         return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+                        TREE_OPERAND (exp, 0), op1);
        }
 
       lvalue_array_p = !not_lvalue && lvalue_p (exp);
@@ -1095,14 +1238,13 @@ default_function_array_conversion (tree exp)
 
       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?  */
+         /* We are making an ADDR_EXPR of ptrtype.  This is a valid
+            ADDR_EXPR because it's the best way of representing what
+            happens in C when we take the address of an array and place
+            it in a pointer to the element type.  */
          adr = build1 (ADDR_EXPR, ptrtype, exp);
          if (!c_mark_addressable (exp))
            return error_mark_node;
-         TREE_CONSTANT (adr) = staticp (exp);
          TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
          return adr;
        }
@@ -1153,9 +1295,8 @@ default_conversion (tree exp)
             && 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));
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
 
   /* Normally convert enums to int,
      but convert wide enums to something wider.  */
@@ -1165,7 +1306,7 @@ default_conversion (tree exp)
                                          TYPE_PRECISION (integer_type_node)),
                                     ((TYPE_PRECISION (type)
                                       >= TYPE_PRECISION (integer_type_node))
-                                     && TREE_UNSIGNED (type)));
+                                     && TYPE_UNSIGNED (type)));
 
       return convert (type, exp);
     }
@@ -1181,7 +1322,7 @@ default_conversion (tree exp)
   if (c_promoting_integer_type_p (type))
     {
       /* Preserve unsignedness if not really getting any wider.  */
-      if (TREE_UNSIGNED (type)
+      if (TYPE_UNSIGNED (type)
          && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
        return convert (unsigned_type_node, exp);
 
@@ -1302,8 +1443,11 @@ build_component_ref (tree datum, tree component)
   tree field = NULL;
   tree ref;
 
+  if (!objc_is_public (datum, component))
+    return error_mark_node;
+
   /* If DATUM is a COMPOUND_EXPR, move our reference inside it.
-     If pedantic ensure that the arguments are not lvalues; otherwise,
+     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
@@ -1315,8 +1459,8 @@ build_component_ref (tree datum, tree component)
     case COMPOUND_EXPR:
       {
        tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
-       return build (COMPOUND_EXPR, TREE_TYPE (value),
-                     TREE_OPERAND (datum, 0), pedantic_non_lvalue (value));
+       return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+                      TREE_OPERAND (datum, 0), non_lvalue (value));
       }
     default:
       break;
@@ -1354,7 +1498,8 @@ build_component_ref (tree datum, tree component)
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
-         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
+         ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
+                       NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
          if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
@@ -1448,8 +1593,7 @@ build_array_ref (tree array, tree index)
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
-      && TREE_CODE (array) != INDIRECT_REF)
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
       tree rval, type;
 
@@ -1489,8 +1633,8 @@ build_array_ref (tree array, tree index)
         would get a crash in store_bit_field/extract_bit_field when trying
         to access a non-existent part of the register.  */
       if (TREE_CODE (index) == INTEGER_CST
-         && TYPE_VALUES (TREE_TYPE (array))
-         && ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array))))
+         && TYPE_DOMAIN (TREE_TYPE (array))
+         && ! int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
        {
          if (!c_mark_addressable (array))
            return error_mark_node;
@@ -1501,14 +1645,14 @@ build_array_ref (tree array, tree index)
          tree foo = array;
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
-         if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
+         if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
            pedwarn ("ISO C forbids subscripting `register' array");
          else if (! flag_isoc99 && ! lvalue_p (foo))
            pedwarn ("ISO C90 forbids subscripting non-lvalue array");
        }
 
       type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
-      rval = build (ARRAY_REF, type, array, index);
+      rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
          or if the array is.  */
       TREE_READONLY (rval)
@@ -1574,7 +1718,7 @@ build_external_ref (tree id, int fun)
 {
   tree ref;
   tree decl = lookup_name (id);
-  tree objc_ivar = lookup_objc_ivar (id);
+  tree objc_ivar = objc_lookup_ivar (id);
 
   if (decl && decl != error_mark_node)
     {
@@ -1615,10 +1759,21 @@ build_external_ref (tree id, int fun)
     assemble_external (ref);
   TREE_USED (ref) = 1;
 
+  if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
+    {
+      if (!in_sizeof && !in_typeof)
+       C_DECL_USED (ref) = 1;
+      else if (DECL_INITIAL (ref) == 0
+              && DECL_EXTERNAL (ref)
+              && !TREE_PUBLIC (ref))
+       record_maybe_used_decl (ref);
+    }
+
   if (TREE_CODE (ref) == CONST_DECL)
     {
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
+      TREE_INVARIANT (ref) = 1;
     }
   else if (current_function_decl != 0
           && !DECL_FILE_SCOPE_P (current_function_decl)
@@ -1635,6 +1790,86 @@ build_external_ref (tree id, int fun)
   return ref;
 }
 
+/* Record details of decls possibly used inside sizeof or typeof.  */
+struct maybe_used_decl
+{
+  /* The decl.  */
+  tree decl;
+  /* The level seen at (in_sizeof + in_typeof).  */
+  int level;
+  /* The next one at this level or above, or NULL.  */
+  struct maybe_used_decl *next;
+};
+
+static struct maybe_used_decl *maybe_used_decls;
+
+/* Record that DECL, an undefined static function reference seen
+   inside sizeof or typeof, might be used if the operand of sizeof is
+   a VLA type or the operand of typeof is a variably modified
+   type.  */
+
+void
+record_maybe_used_decl (tree decl)
+{
+  struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
+  t->decl = decl;
+  t->level = in_sizeof + in_typeof;
+  t->next = maybe_used_decls;
+  maybe_used_decls = t;
+}
+
+/* Pop the stack of decls possibly used inside sizeof or typeof.  If
+   USED is false, just discard them.  If it is true, mark them used
+   (if no longer inside sizeof or typeof) or move them to the next
+   level up (if still inside sizeof or typeof).  */
+
+void
+pop_maybe_used (bool used)
+{
+  struct maybe_used_decl *p = maybe_used_decls;
+  int cur_level = in_sizeof + in_typeof;
+  while (p && p->level > cur_level)
+    {
+      if (used)
+       {
+         if (cur_level == 0)
+           C_DECL_USED (p->decl) = 1;
+         else
+           p->level = cur_level;
+       }
+      p = p->next;
+    }
+  if (!used || cur_level == 0)
+    maybe_used_decls = p;
+}
+
+/* Return the result of sizeof applied to EXPR.  */
+
+struct c_expr
+c_expr_sizeof_expr (struct c_expr expr)
+{
+  struct c_expr ret;
+  ret.value = c_sizeof (TREE_TYPE (expr.value));
+  ret.original_code = ERROR_MARK;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
+  return ret;
+}
+
+/* Return the result of sizeof applied to T, a structure for the type
+   name passed to sizeof (rather than the type itself).  */
+
+struct c_expr
+c_expr_sizeof_type (struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  type = groktypename (t);
+  ret.value = c_sizeof (type);
+  ret.original_code = ERROR_MARK;
+  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  return ret;
+}
+
 /* 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.
@@ -1699,7 +1934,7 @@ build_function_call (tree function, tree params)
       && TREE_CODE (function) == NOP_EXPR
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
-      && ! comptypes (fntype, TREE_TYPE (tem), COMPARE_STRICT))
+      && ! comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
       tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
@@ -1710,6 +1945,10 @@ build_function_call (tree function, tree params)
         executions of the program must execute the code.  */
       warning ("function called through a non-compatible type");
 
+      /* We can, however, treat "undefined" any way we please.
+        Call abort to encourage the user to fix the program.  */
+      inform ("if this code is reached, the program will abort");
+
       if (VOID_TYPE_P (return_type))
        return trap;
       else
@@ -1723,7 +1962,7 @@ build_function_call (tree function, tree params)
          else
            rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node));
 
-         return build (COMPOUND_EXPR, return_type, trap, rhs);
+         return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
     }
 
@@ -1737,24 +1976,21 @@ build_function_call (tree function, tree params)
 
   check_function_arguments (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
-     to do something useful.  */
+  result = build3 (CALL_EXPR, TREE_TYPE (fntype),
+                  function, coerced_params, NULL_TREE);
+  TREE_SIDE_EFFECTS (result) = 1;
 
-  if (TREE_CODE (function) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
-      && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
+  if (require_constant_value)
     {
-      result = expand_tree_builtin (TREE_OPERAND (function, 0),
-                                   params, coerced_params);
-      if (result)
-       return result;
-    }
+      result = fold_initializer (result);
 
-  result = build (CALL_EXPR, TREE_TYPE (fntype),
-                 function, coerced_params, NULL_TREE);
-  TREE_SIDE_EFFECTS (result) = 1;
-  result = fold (result);
+      if (TREE_CONSTANT (result)
+         && (name == NULL_TREE
+             || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
+       pedwarn_init ("initializer element is not constant");
+    }
+  else
+    result = fold (result);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
@@ -1832,7 +2068,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                 differ from the default conversions.  */
              if (warn_conversion || warn_traditional)
                {
-                 int formal_prec = TYPE_PRECISION (type);
+                 unsigned int formal_prec = TYPE_PRECISION (type);
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
@@ -1880,7 +2116,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
                        warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1);
-                     else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1))
+                     else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
                         is an enum, because we can't tell now whether
@@ -1902,9 +2138,9 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                         pass it as signed or unsigned; the value
                         certainly is the same either way.  */
                      else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type)
-                              && TREE_UNSIGNED (TREE_TYPE (val)))
+                              && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
-                     else if (TREE_UNSIGNED (type))
+                     else if (TYPE_UNSIGNED (type))
                        warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);
                      else
                        warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1);
@@ -1953,28 +2189,23 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
    we check for operands that were written with other binary operators
    in a way that is likely to confuse the user.  */
 
-tree
-parser_build_binary_op (enum tree_code code, tree arg1, tree arg2)
+struct c_expr
+parser_build_binary_op (enum tree_code code, struct c_expr arg1,
+                       struct c_expr arg2)
 {
-  tree result = build_binary_op (code, arg1, arg2, 1);
+  struct c_expr result;
 
-  char class;
-  char class1 = TREE_CODE_CLASS (TREE_CODE (arg1));
-  char class2 = TREE_CODE_CLASS (TREE_CODE (arg2));
-  enum tree_code code1 = ERROR_MARK;
-  enum tree_code code2 = ERROR_MARK;
+  enum tree_code code1 = arg1.original_code;
+  enum tree_code code2 = arg2.original_code;
 
-  if (TREE_CODE (result) == ERROR_MARK)
-    return error_mark_node;
+  result.value = build_binary_op (code, arg1.value, arg2.value, 1);
+  result.original_code = code;
 
-  if (IS_EXPR_CODE_CLASS (class1))
-    code1 = C_EXP_ORIGINAL_CODE (arg1);
-  if (IS_EXPR_CODE_CLASS (class2))
-    code2 = C_EXP_ORIGINAL_CODE (arg2);
+  if (TREE_CODE (result.value) == ERROR_MARK)
+    return result;
 
   /* Check for cases such as x+y<<z which users are likely
-     to misinterpret.  If parens are used, C_EXP_ORIGINAL_CODE
-     is cleared to prevent these warnings.  */
+     to misinterpret.  */
   if (warn_parentheses)
     {
       if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
@@ -2024,65 +2255,27 @@ parser_build_binary_op (enum tree_code code, tree arg1, tree arg2)
          if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
            warning ("suggest parentheses around comparison in operand of &");
        }
-    }
-
-  /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
-  if (TREE_CODE_CLASS (code) == '<' && extra_warnings
-      && (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<'))
-    warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
-
-  unsigned_conversion_warning (result, arg1);
-  unsigned_conversion_warning (result, arg2);
-  overflow_warning (result);
+      /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
+      if (TREE_CODE_CLASS (code) == '<'
+         && (TREE_CODE_CLASS (code1) == '<'
+             || TREE_CODE_CLASS (code2) == '<'))
+       warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
 
-  class = TREE_CODE_CLASS (TREE_CODE (result));
-
-  /* Record the code that was specified in the source,
-     for the sake of warnings about confusing nesting.  */
-  if (IS_EXPR_CODE_CLASS (class))
-    C_SET_EXP_ORIGINAL_CODE (result, code);
-  else
-    {
-      int flag = TREE_CONSTANT (result);
-      /* We used to use NOP_EXPR rather than NON_LVALUE_EXPR
-        so that convert_for_assignment wouldn't strip it.
-        That way, we got warnings for things like p = (1 - 1).
-        But it turns out we should not get those warnings.  */
-      result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
-      C_SET_EXP_ORIGINAL_CODE (result, code);
-      TREE_CONSTANT (result) = flag;
     }
 
+  unsigned_conversion_warning (result.value, arg1.value);
+  unsigned_conversion_warning (result.value, arg2.value);
+  overflow_warning (result.value);
+
   return result;
 }
 \f
-
-/* Return true if `t' is known to be non-negative.  */
-
-int
-c_tree_expr_nonnegative_p (tree t)
-{
-  if (TREE_CODE (t) == STMT_EXPR)
-    {
-      t = COMPOUND_BODY (STMT_EXPR_STMT (t));
-
-      /* Find the last statement in the chain, ignoring the final
-            * scope statement */
-      while (TREE_CHAIN (t) != NULL_TREE
-             && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT)
-        t = TREE_CHAIN (t);
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    }
-  return tree_expr_nonnegative_p (t);
-}
-
 /* Return a tree for the difference of pointers OP0 and OP1.
    The resulting tree has type int.  */
 
 static tree
 pointer_diff (tree op0, tree op1)
 {
-  tree result, folded;
   tree restype = ptrdiff_type_node;
 
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
@@ -2146,13 +2339,7 @@ pointer_diff (tree op0, tree op1)
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-
-  result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
-
-  folded = fold (result);
-  if (folded == result)
-    TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
-  return folded;
+  return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)));
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -2186,7 +2373,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         is enough to prevent anybody from looking inside for
         associativity, but won't generate any code.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE))
+           || typecode == COMPLEX_TYPE
+           || typecode == VECTOR_TYPE))
        {
          error ("wrong type argument to unary plus");
          return error_mark_node;
@@ -2261,7 +2449,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          error ("wrong type argument to unary exclamation mark");
          return error_mark_node;
        }
-      arg = c_common_truthvalue_conversion (arg);
+      arg = lang_hooks.truthvalue_conversion (arg);
       return invert_truthvalue (arg);
 
     case NOP_EXPR:
@@ -2287,12 +2475,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-
-      val = unary_complex_lvalue (code, arg, 0);
-      if (val != 0)
-       return val;
 
       /* Increment or decrement the real part of the value,
         and don't change the imaginary part.  */
@@ -2306,8 +2488,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          arg = stabilize_reference (arg);
          real = build_unary_op (REALPART_EXPR, arg, 1);
          imag = build_unary_op (IMAGPART_EXPR, arg, 1);
-         return build (COMPLEX_EXPR, TREE_TYPE (arg),
-                       build_unary_op (code, real, 1), imag);
+         return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+                        build_unary_op (code, real, 1), imag);
        }
 
       /* Report invalid types.  */
@@ -2360,57 +2542,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        inc = convert (argtype, inc);
 
-       /* Handle incrementing a cast-expression.  */
-
-       while (1)
-         switch (TREE_CODE (arg))
-           {
-           case NOP_EXPR:
-           case CONVERT_EXPR:
-           case FLOAT_EXPR:
-           case FIX_TRUNC_EXPR:
-           case FIX_FLOOR_EXPR:
-           case FIX_ROUND_EXPR:
-           case FIX_CEIL_EXPR:
-             pedantic_lvalue_warning (CONVERT_EXPR);
-             /* If the real type has the same machine representation
-                as the type it is cast to, we can make better output
-                by adding directly to the inside of the cast.  */
-             if ((TREE_CODE (TREE_TYPE (arg))
-                  == TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))))
-                 && (TYPE_MODE (TREE_TYPE (arg))
-                     == TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0)))))
-               arg = TREE_OPERAND (arg, 0);
-             else
-               {
-                 tree incremented, modify, value;
-                 if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-                   value = boolean_increment (code, arg);
-                 else
-                   {
-                     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;
-               }
-             break;
-
-           default:
-             goto give_up;
-           }
-      give_up:
-
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
@@ -2420,19 +2551,19 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        /* Report a read-only lvalue.  */
        if (TREE_READONLY (arg))
-         readonly_warning (arg,
-                           ((code == PREINCREMENT_EXPR
-                             || code == POSTINCREMENT_EXPR)
-                            ? "increment" : "decrement"));
+         readonly_error (arg,
+                         ((code == PREINCREMENT_EXPR
+                           || code == POSTINCREMENT_EXPR)
+                          ? "increment" : "decrement"));
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
        else
-         val = build (code, TREE_TYPE (arg), arg, inc);
+         val = build2 (code, TREE_TYPE (arg), arg, inc);
        TREE_SIDE_EFFECTS (val) = 1;
        val = convert (result_type, val);
        if (TREE_CODE (val) != code)
-         TREE_NO_UNUSED_WARNING (val) = 1;
+         TREE_NO_WARNING (val) = 1;
        return val;
       }
 
@@ -2457,12 +2588,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
                                  TREE_OPERAND (arg, 1), 1);
        }
 
-      /* Handle complex lvalues (when permitted)
-        by reduction to simpler cases.  */
-      val = unary_complex_lvalue (code, arg, flag);
-      if (val != 0)
-       return val;
-
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
@@ -2482,42 +2607,24 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
                                          TREE_READONLY (arg),
                                          TREE_THIS_VOLATILE (arg));
 
-      argtype = build_pointer_type (argtype);
-
       if (!c_mark_addressable (arg))
        return error_mark_node;
 
-      {
-       tree addr;
-
-       if (TREE_CODE (arg) == COMPONENT_REF)
-         {
-           tree field = TREE_OPERAND (arg, 1);
+      if (TREE_CODE (arg) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+       {
+         error ("attempt to take address of bit-field structure member `%D'",
+                TREE_OPERAND (arg, 1));
+         return error_mark_node;
+       }
 
-           addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag);
+      argtype = build_pointer_type (argtype);
+      val = build1 (ADDR_EXPR, argtype, arg);
 
-           if (DECL_C_BIT_FIELD (field))
-             {
-               error ("attempt to take address of bit-field structure member `%s'",
-                      IDENTIFIER_POINTER (DECL_NAME (field)));
-               return error_mark_node;
-             }
+      if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
+       TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
 
-           addr = fold (build (PLUS_EXPR, argtype,
-                               convert (argtype, addr),
-                               convert (argtype, byte_position (field))));
-         }
-       else
-         addr = build1 (code, argtype, arg);
-
-       /* Address of a static or external variable or
-          file-scope function counts as a constant.  */
-       if (staticp (arg)
-           && ! (TREE_CODE (arg) == FUNCTION_DECL
-                 && !DECL_FILE_SCOPE_P (arg)))
-         TREE_CONSTANT (addr) = 1;
-       return addr;
-      }
+      return val;
 
     default:
       break;
@@ -2525,12 +2632,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
   if (argtype == 0)
     argtype = TREE_TYPE (arg);
-  return fold (build1 (code, argtype, arg));
+  val = build1 (code, argtype, arg);
+  return require_constant_value ? fold_initializer (val) : fold (val);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language.
    Lvalues can be assigned, unless their type has TYPE_READONLY.
-   Lvalues can have their address taken, unless they have DECL_REGISTER.  */
+   Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
 int
 lvalue_p (tree ref)
@@ -2558,7 +2666,6 @@ lvalue_p (tree ref)
              && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
 
     case BIND_EXPR:
-    case RTL_EXPR:
       return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
 
     default:
@@ -2569,7 +2676,7 @@ lvalue_p (tree ref)
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  */
 
-int
+static int
 lvalue_or_else (tree ref, const char *msgid)
 {
   int win = lvalue_p (ref);
@@ -2580,86 +2687,25 @@ lvalue_or_else (tree ref, const char *msgid)
   return win;
 }
 
-/* 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.  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 (enum tree_code code, tree arg, int flag)
-{
-  /* Handle (a, b) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COMPOUND_EXPR)
-    {
-      tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
-
-      /* 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 && !flag)
-       pedantic_lvalue_warning (COMPOUND_EXPR);
-
-      return build (COMPOUND_EXPR, TREE_TYPE (real_result),
-                   TREE_OPERAND (arg, 0), real_result);
-    }
-
-  /* Handle (a ? b : c) used as an "lvalue".  */
-  if (TREE_CODE (arg) == COND_EXPR)
-    {
-      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), flag),
-              build_unary_op (code, TREE_OPERAND (arg, 2), flag)));
-    }
-
-  return 0;
-}
-
-/* If pedantic, warn about improper lvalue.   CODE is either COND_EXPR
-   COMPOUND_EXPR, or CONVERT_EXPR (for casts).  */
-
-static void
-pedantic_lvalue_warning (enum tree_code code)
-{
-  switch (code)
-    {
-    case COND_EXPR:
-      pedwarn ("use of conditional expressions as lvalues is deprecated");
-      break;
-    case COMPOUND_EXPR:
-      pedwarn ("use of compound expressions as lvalues is deprecated");
-      break;
-    default:
-      pedwarn ("use of cast expressions as lvalues is deprecated");
-      break;
-    }
-}
 \f
 /* Warn about storing in something that is `const'.  */
 
 void
-readonly_warning (tree arg, const char *msgid)
+readonly_error (tree arg, const char *msgid)
 {
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_warning (TREE_OPERAND (arg, 0), msgid);
+       readonly_error (TREE_OPERAND (arg, 0), msgid);
       else
-       pedwarn ("%s of read-only member `%s'", _(msgid),
-                IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
+       error ("%s of read-only member `%s'", _(msgid),
+              IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    pedwarn ("%s of read-only variable `%s'", _(msgid),
-            IDENTIFIER_POINTER (DECL_NAME (arg)));
+    error ("%s of read-only variable `%s'", _(msgid),
+          IDENTIFIER_POINTER (DECL_NAME (arg)));
   else
-    pedwarn ("%s of read-only location", _(msgid));
+    error ("%s of read-only location", _(msgid));
 }
 \f
 /* Mark EXP saying that we need to be able to take the
@@ -2700,10 +2746,10 @@ c_mark_addressable (tree exp)
       case CONST_DECL:
       case PARM_DECL:
       case RESULT_DECL:
-       if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+       if (C_DECL_REGISTER (x)
            && DECL_NONLOCAL (x))
          {
-           if (TREE_PUBLIC (x))
+           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
                error ("global register variable `%s' used in nested function",
                       IDENTIFIER_POINTER (DECL_NAME (x)));
@@ -2712,30 +2758,18 @@ c_mark_addressable (tree exp)
            pedwarn ("register variable `%s' used in nested function",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
-       else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
+       else if (C_DECL_REGISTER (x))
          {
-           if (TREE_PUBLIC (x))
+           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
              {
                error ("address of global register variable `%s' requested",
                       IDENTIFIER_POINTER (DECL_NAME (x)));
                return false;
              }
 
-           /* If we are making this addressable due to its having
-              volatile components, give a different error message.  Also
-              handle the case of an unnamed parameter by not trying
-              to give the name.  */
-
-           else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
-             {
-               error ("cannot put object with volatile field into register");
-               return false;
-             }
-
            pedwarn ("address of register variable `%s' requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
-       put_var_into_stack (x, /*rescan=*/true);
 
        /* drops in */
       case FUNCTION_DECL:
@@ -2758,7 +2792,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   tree result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
 
-  ifexp = c_common_truthvalue_conversion (default_conversion (ifexp));
+  ifexp = lang_hooks.truthvalue_conversion (default_conversion (ifexp));
 
   /* Promote both alternatives.  */
 
@@ -2777,6 +2811,14 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   type2 = TREE_TYPE (op2);
   code2 = TREE_CODE (type2);
 
+  /* C90 does not permit non-lvalue arrays in conditional expressions.
+     In C99 they will be pointers by now.  */
+  if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
+    {
+      error ("non-lvalue array in conditional expression");
+      return error_mark_node;
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -2800,21 +2842,21 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
         will be considered, but default promotions won't.  */
       if (warn_sign_compare && !skip_evaluation)
        {
-         int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1));
-         int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2));
+         int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
+         int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
 
          if (unsigned_op1 ^ unsigned_op2)
            {
              /* Do not warn if the result type is signed, since the
                 signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
-             if (! TREE_UNSIGNED (result_type))
+             if (! TYPE_UNSIGNED (result_type))
                /* OK */;
              /* Do not warn if the signed quantity is an unsuffixed
                 integer literal (or some static constant expression
                 involving such literals) and it is non-negative.  */
-             else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1))
-                      || (unsigned_op1 && c_tree_expr_nonnegative_p (op2)))
+             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");
@@ -2830,7 +2872,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
       if (comp_target_types (type1, type2, 1))
-       result_type = common_type (type1, type2);
+       result_type = common_pointer_type (type1, type2);
       else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
               && TREE_CODE (orig_op1) != NOP_EXPR)
        result_type = qualify_type (type2, type1);
@@ -2901,49 +2943,32 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     op2 = convert_and_check (result_type, op2);
 
   if (TREE_CODE (ifexp) == INTEGER_CST)
-    return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
+    return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
 
-  return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
+  return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2));
 }
 \f
-/* Given a list of expressions, return a compound expression
-   that performs them all and returns the value of the last of them.  */
+/* Return a compound expression that performs two expressions and
+   returns the value of the second of them.  */
 
 tree
-build_compound_expr (tree list)
-{
-  return internal_build_compound_expr (list, TRUE);
-}
-
-static tree
-internal_build_compound_expr (tree list, int first_p)
+build_compound_expr (tree expr1, tree expr2)
 {
-  tree rest;
+  /* Convert arrays and functions to pointers.  */
+  expr2 = default_function_array_conversion (expr2);
 
-  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));
-
-      /* Don't let (0, 0) be null pointer constant.  */
-      if (!first_p && integer_zerop (TREE_VALUE (list)))
-       return non_lvalue (TREE_VALUE (list));
-      return TREE_VALUE (list);
-    }
+  /* Don't let (0, 0) be null pointer constant.  */
+  if (integer_zerop (expr2))
+    expr2 = non_lvalue (expr2);
 
-  rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
-
-  if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
+  if (! TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
          statement: with -Wextra or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
       if (warn_unused_value
-           && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
-                && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
+           && ! (TREE_CODE (expr1) == CONVERT_EXPR
+                && VOID_TYPE_P (TREE_TYPE (expr1))))
         warning ("left-hand operand of comma expression has no effect");
     }
 
@@ -2952,9 +2977,9 @@ internal_build_compound_expr (tree list, int first_p)
      `foo() + bar(), baz()' the result of the `+' operator is not used,
      so we should issue a warning.  */
   else if (warn_unused_value)
-    warn_if_unused_value (TREE_VALUE (list));
+    warn_if_unused_value (expr1, input_location);
 
-  return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
+  return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
 }
 
 /* Build an expression representing a cast to type TYPE of expression EXPR.  */
@@ -2970,8 +2995,10 @@ build_c_cast (tree type, tree expr)
   /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
      only in <protocol> qualifications.  But when constructing cast expressions,
      the protocols do matter and must be kept around.  */
-  if (!c_dialect_objc () || !objc_is_object_ptr (type))
-    type = TYPE_MAIN_VARIANT (type);
+  if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
+    return build1 (NOP_EXPR, type, expr);
+
+  type = TYPE_MAIN_VARIANT (type);
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
@@ -3001,7 +3028,7 @@ build_c_cast (tree type, tree expr)
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-                      TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT))
+                      TYPE_MAIN_VARIANT (TREE_TYPE (value))))
          break;
 
       if (field)
@@ -3013,8 +3040,9 @@ build_c_cast (tree type, tree expr)
          t = digest_init (type,
                           build_constructor (type,
                                              build_tree_list (field, value)),
-                          0);
+                          true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
+         TREE_INVARIANT (t) = TREE_INVARIANT (value);
          return t;
        }
       error ("cast to union type from type not present in union");
@@ -3119,10 +3147,17 @@ build_c_cast (tree type, tree expr)
             if the cast breaks type based aliasing.  */
          if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
            warning ("type-punning to incomplete type might break strict-aliasing rules");
-         else if (!alias_sets_conflict_p
-                  (get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))),
-                   get_alias_set (TREE_TYPE (type))))
-           warning ("dereferencing type-punned pointer will break strict-aliasing rules");
+         else
+           {
+             HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+             HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+
+             if (!alias_sets_conflict_p (set1, set2))
+               warning ("dereferencing type-punned pointer will break strict-aliasing rules");
+             else if (warn_strict_aliasing > 1
+                      && !alias_sets_might_conflict_p (set1, set2))
+               warning ("dereferencing type-punned pointer might break strict-aliasing rules");
+           }
        }
 
       /* If pedantic, warn for conversions between function and object
@@ -3153,19 +3188,28 @@ build_c_cast (tree type, tree expr)
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-         TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+         if (EXPR_P (ovalue))
+           /* If OVALUE had overflow set, then so will VALUE, so it
+              is safe to overwrite.  */
+           TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+         else
+           TREE_OVERFLOW (value) = 0;
+         
+         if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+           /* Similarly, constant_overflow cannot have become
+              cleared.  */
+           TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
 
-  /* Pedantically, don't let (void *) (FOO *) 0 be a null pointer constant.  */
-  if (pedantic && TREE_CODE (value) == INTEGER_CST
+  /* Don't let (void *) (FOO *) 0 be a null pointer constant.  */
+  if (TREE_CODE (value) == INTEGER_CST
       && TREE_CODE (expr) == INTEGER_CST
       && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
     value = non_lvalue (value);
 
-  /* If pedantic, don't let a cast be an lvalue.  */
-  if (value == expr && pedantic)
+  /* Don't let a cast be an lvalue.  */
+  if (value == expr)
     value = non_lvalue (value);
 
   return value;
@@ -3173,15 +3217,16 @@ build_c_cast (tree type, tree expr)
 
 /* Interpret a cast of expression EXPR to type TYPE.  */
 tree
-c_cast_expr (tree type, tree expr)
+c_cast_expr (struct c_type_name *type_name, tree expr)
 {
+  tree type;
   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);
+  type = groktypename (type_name);
   warn_strict_prototypes = saved_wsp;
 
   return build_c_cast (type, expr);
@@ -3210,50 +3255,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   /* Do not use STRIP_NOPS here.  We do not want an enumerator
-     whose value is 0 to count as a null pointer constant.  */
-  if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
-    rhs = TREE_OPERAND (rhs, 0);
-
-  newrhs = rhs;
-
-  /* Handle control structure constructs used as "lvalues".  */
-
-  switch (TREE_CODE (lhs))
-    {
-      /* Handle (a, b) used as an "lvalue".  */
-    case COMPOUND_EXPR:
-      pedantic_lvalue_warning (COMPOUND_EXPR);
-      newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs);
-      if (TREE_CODE (newrhs) == ERROR_MARK)
-       return error_mark_node;
-      return build (COMPOUND_EXPR, lhstype,
-                   TREE_OPERAND (lhs, 0), newrhs);
+     whose value is 0 to count as a null pointer constant.  */
+  if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
+    rhs = TREE_OPERAND (rhs, 0);
 
-      /* Handle (a ? b : c) used as an "lvalue".  */
-    case COND_EXPR:
-      pedantic_lvalue_warning (COND_EXPR);
-      rhs = save_expr (rhs);
-      {
-       /* Produce (a ? (b = rhs) : (c = rhs))
-          except that the RHS goes through a save-expr
-          so the code to compute it is only emitted once.  */
-       tree cond
-         = build_conditional_expr (TREE_OPERAND (lhs, 0),
-                                   build_modify_expr (TREE_OPERAND (lhs, 1),
-                                                      modifycode, rhs),
-                                   build_modify_expr (TREE_OPERAND (lhs, 2),
-                                                      modifycode, rhs));
-       if (TREE_CODE (cond) == ERROR_MARK)
-         return cond;
-       /* Make sure the code to compute the rhs comes out
-          before the split.  */
-       return build (COMPOUND_EXPR, TREE_TYPE (lhs),
-                     /* But cast it to void to avoid an "unused" error.  */
-                     convert (void_type_node, rhs), cond);
-      }
-    default:
-      break;
-    }
+  newrhs = rhs;
 
   /* If a binary op has been requested, combine the old LHS value with the RHS
      producing the value we should actually store into the LHS.  */
@@ -3264,42 +3270,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  /* Handle a cast used as an "lvalue".
-     We have already performed any binary operator using the value as cast.
-     Now convert the result to the cast type of the lhs,
-     and then true type of the lhs and store it there;
-     then convert result back to the cast type to be the value
-     of the assignment.  */
-
-  switch (TREE_CODE (lhs))
-    {
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case FLOAT_EXPR:
-    case FIX_TRUNC_EXPR:
-    case FIX_FLOOR_EXPR:
-    case FIX_ROUND_EXPR:
-    case FIX_CEIL_EXPR:
-      newrhs = default_function_array_conversion (newrhs);
-      {
-       tree inner_lhs = TREE_OPERAND (lhs, 0);
-       tree result;
-       result = build_modify_expr (inner_lhs, NOP_EXPR,
-                                   convert (TREE_TYPE (inner_lhs),
-                                            convert (lhstype, newrhs)));
-       if (TREE_CODE (result) == ERROR_MARK)
-         return result;
-       pedantic_lvalue_warning (CONVERT_EXPR);
-       return convert (TREE_TYPE (lhs), result);
-      }
-
-    default:
-      break;
-    }
-
-  /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
-     Reject anything strange now.  */
-
   if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
     return error_mark_node;
 
@@ -3309,7 +3279,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
-    readonly_warning (lhs, "assignment");
+    readonly_error (lhs, "assignment");
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -3341,7 +3311,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   /* Scan operands */
 
-  result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
+  result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
 
   /* If we got the LHS in a different type for storing in,
@@ -3414,7 +3384,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
      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), COMPARE_STRICT) == 1)
+      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
     {
       if (!lvalue_p (rhs))
        {
@@ -3437,9 +3407,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       return rhs;
     }
   /* Some types can interconvert without explicit casts.  */
-  else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
-          && ((*targetm.vector_opaque_p) (type)
-              || (*targetm.vector_opaque_p) (rhstype)))
+  else if (codel == VECTOR_TYPE
+           && vector_types_convertible_p (type, TREE_TYPE (rhs)))
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
@@ -3463,7 +3432,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
          tree memb_type = TREE_TYPE (memb_types);
 
          if (comptypes (TYPE_MAIN_VARIANT (memb_type),
-                        TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT))
+                        TYPE_MAIN_VARIANT (rhstype)))
            break;
 
          if (TREE_CODE (memb_type) != POINTER_TYPE)
@@ -3553,8 +3522,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
 
       /* Opaque pointers are treated like void pointers.  */
-      is_opaque_pointer = ((*targetm.vector_opaque_p) (type)
-                           || (*targetm.vector_opaque_p) (rhstype))
+      is_opaque_pointer = (targetm.vector_opaque_p (type)
+                           || targetm.vector_opaque_p (rhstype))
         && TREE_CODE (ttl) == VECTOR_TYPE
         && TREE_CODE (ttr) == VECTOR_TYPE;
 
@@ -3591,7 +3560,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
                       || target_cmp)
                ;
              /* If there is a mismatch, do warn.  */
-             else if (pedantic)
+             else
                warn_for_assignment ("pointer targets in %s differ in signedness",
                                     errtype, funname, parmnum);
            }
@@ -3717,7 +3686,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
            {
              /* Function name is known; supply it.  */
              const char *const argstring = _("passing arg of `%s'");
-             new_opname = alloca (IDENTIFIER_LENGTH (function)
+             new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                                   + strlen (argstring) + 1 + 1);
              sprintf (new_opname, argstring,
                       IDENTIFIER_POINTER (function));
@@ -3726,7 +3695,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
            {
              /* Function name unknown (call through ptr).  */
              const char *const argnofun = _("passing arg of pointer to function");
-             new_opname = alloca (strlen (argnofun) + 1 + 1);
+             new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
              sprintf (new_opname, argnofun);
            }
        }
@@ -3734,7 +3703,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
        {
          /* Function name is known; supply it.  */
          const char *const argstring = _("passing arg %d of `%s'");
-         new_opname = alloca (IDENTIFIER_LENGTH (function)
+         new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
                               + strlen (argstring) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argstring, argnum,
                   IDENTIFIER_POINTER (function));
@@ -3743,7 +3712,7 @@ warn_for_assignment (const char *msgid, const char *opname, tree function,
        {
          /* Function name unknown (call through ptr); just give arg number.  */
          const char *const argnofun = _("passing arg %d of pointer to function");
-         new_opname = alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
+         new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
          sprintf (new_opname, argnofun, argnum);
        }
       opname = new_opname;
@@ -3793,7 +3762,7 @@ store_init_value (tree decl, tree init)
 
   /* Digest the specified initializer into an expression.  */
 
-  value = digest_init (type, init, TREE_STATIC (decl));
+  value = digest_init (type, init, true, TREE_STATIC (decl));
 
   /* Store the expression if valid; else report error.  */
 
@@ -3874,11 +3843,8 @@ static int spelling_size;                /* Size of the spelling stack.  */
   if (depth >= spelling_size)                                          \
     {                                                                  \
       spelling_size += 10;                                             \
-      if (spelling_base == 0)                                          \
-       spelling_base = xmalloc (spelling_size * sizeof (struct spelling)); \
-      else                                                             \
-        spelling_base = xrealloc (spelling_base,               \
-                                 spelling_size * sizeof (struct spelling)); \
+      spelling_base = XRESIZEVEC (struct spelling, spelling_base,      \
+                                 spelling_size);                       \
       RESTORE_SPELLING_DEPTH (depth);                                  \
     }                                                                  \
                                                                        \
@@ -3968,7 +3934,7 @@ error_init (const char *msgid)
   char *ofwhat;
 
   error ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for `%s')", ofwhat);
 }
@@ -3983,7 +3949,7 @@ pedwarn_init (const char *msgid)
   char *ofwhat;
 
   pedwarn ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     pedwarn ("(near initialization for `%s')", ofwhat);
 }
@@ -3998,19 +3964,37 @@ warning_init (const char *msgid)
   char *ofwhat;
 
   warning ("%s", _(msgid));
-  ofwhat = print_spelling (alloca (spelling_length () + 1));
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning ("(near initialization for `%s')", ofwhat);
 }
 \f
+/* If TYPE is an array type and EXPR is a parenthesized string
+   constant, warn if pedantic that EXPR is being used to initialize an
+   object of type TYPE.  */
+
+void
+maybe_warn_string_init (tree type, struct c_expr expr)
+{
+  if (pedantic
+      && TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (expr.value) == STRING_CST
+      && expr.original_code != STRING_CST)
+    pedwarn_init ("array initialized from parenthesized string constant");
+}
+
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
 
+   If INIT is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of INIT, STRICT_STRING is not used.
+
    REQUIRE_CONSTANT requests an error if non-constant initializers or
    elements are seen.  */
 
 static tree
-digest_init (tree type, tree init, int require_constant)
+digest_init (tree type, tree init, bool strict_string, int require_constant)
 {
   enum tree_code code = TREE_CODE (type);
   tree inside_init = init;
@@ -4031,32 +4015,41 @@ digest_init (tree type, tree init, int require_constant)
   /* Initialization of an array of chars from a string constant
      optionally enclosed in braces.  */
 
-  if (code == ARRAY_TYPE)
+  if (code == ARRAY_TYPE && inside_init
+      && TREE_CODE (inside_init) == STRING_CST)
     {
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if ((typ1 == char_type_node
-          || typ1 == signed_char_type_node
-          || typ1 == unsigned_char_type_node
-          || typ1 == unsigned_wchar_type_node
-          || typ1 == signed_wchar_type_node)
-         && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
+      /* Note that an array could be both an array of character type
+        and an array of wchar_t if wchar_t is signed char or unsigned
+        char.  */
+      bool char_array = (typ1 == char_type_node
+                        || typ1 == signed_char_type_node
+                        || typ1 == unsigned_char_type_node);
+      bool wchar_array = !!comptypes (typ1, wchar_type_node);
+      if (char_array || wchar_array)
        {
+         struct c_expr expr;
+         bool char_string;
+         expr.value = inside_init;
+         expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
+         maybe_warn_string_init (type, expr);
+
+         char_string
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
+              == char_type_node);
+
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                        TYPE_MAIN_VARIANT (type), COMPARE_STRICT))
+                        TYPE_MAIN_VARIANT (type)))
            return inside_init;
 
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              != char_type_node)
-             && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
+         if (!wchar_array && !char_string)
            {
              error_init ("char-array initialized from wide string");
              return error_mark_node;
            }
-         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              == char_type_node)
-             && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
+         if (char_string && !char_array)
            {
-             error_init ("int-array initialized from non-wide string");
+             error_init ("wchar_t-array initialized from non-wide string");
              return error_mark_node;
            }
 
@@ -4078,19 +4071,24 @@ digest_init (tree type, tree init, int require_constant)
 
          return inside_init;
        }
+      else if (INTEGRAL_TYPE_P (typ1))
+       {
+         error_init ("array of inappropriate type initialized "
+                     "from string constant");
+         return error_mark_node;
+       }
     }
 
   /* Build a VECTOR_CST from a *constant* vector constructor.  If the
      vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
      below and handle as a constructor.  */
     if (code == VECTOR_TYPE
-        && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)
+        && vector_types_convertible_p (TREE_TYPE (inside_init), type)
         && TREE_CONSTANT (inside_init))
       {
        if (TREE_CODE (inside_init) == VECTOR_CST
-           && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                         TYPE_MAIN_VARIANT (type),
-                         COMPARE_STRICT))
+            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+                         TYPE_MAIN_VARIANT (type)))
          return inside_init;
        else
          return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
@@ -4101,19 +4099,19 @@ digest_init (tree type, tree init, int require_constant)
 
   if (inside_init && TREE_TYPE (inside_init) != 0
       && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                    TYPE_MAIN_VARIANT (type), COMPARE_STRICT)
+                    TYPE_MAIN_VARIANT (type))
          || (code == ARRAY_TYPE
-             && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
+             && comptypes (TREE_TYPE (inside_init), type))
          || (code == VECTOR_TYPE
-             && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
+             && comptypes (TREE_TYPE (inside_init), type))
          || (code == POINTER_TYPE
              && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-                           TREE_TYPE (type), COMPARE_STRICT))
+                           TREE_TYPE (type)))
          || (code == POINTER_TYPE
              && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
              && comptypes (TREE_TYPE (inside_init),
-                           TREE_TYPE (type), COMPARE_STRICT))))
+                           TREE_TYPE (type)))))
     {
       if (code == POINTER_TYPE)
        {
@@ -4189,7 +4187,8 @@ digest_init (tree type, tree init, int require_constant)
   /* Handle scalar types, including conversions.  */
 
   if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
-      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE)
+      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
+      || code == VECTOR_TYPE)
     {
       /* Note that convert_for_assignment calls default_conversion
         for arrays and functions.  We must not call it in the
@@ -4296,14 +4295,14 @@ static int constructor_depth;
 /* 0 if implicitly pushing constructor levels is allowed.  */
 int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages.  */
 
-static int require_constant_value;
-static int require_constant_elements;
-
 /* 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 const char *constructor_asmspec;
+
 /* Nonzero if this is an initializer for a top-level decl.  */
 static int constructor_top_level;
 
@@ -4337,9 +4336,9 @@ struct constructor_stack
   struct init_node *pending_elts;
   int offset;
   int depth;
-  /* If nonzero, this value should replace the entire
+  /* If value nonzero, this value should replace the entire
      constructor at this level.  */
-  tree replacement_value;
+  struct c_expr replacement_value;
   struct constructor_range_stack *range_stack;
   char constant;
   char simple;
@@ -4375,6 +4374,7 @@ struct initializer_stack
 {
   struct initializer_stack *next;
   tree decl;
+  const char *asmspec;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
   tree elements;
@@ -4391,12 +4391,17 @@ struct initializer_stack *initializer_stack;
 /* Prepare to parse and output the initializer for variable DECL.  */
 
 void
-start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
+start_init (tree decl, tree asmspec_tree, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+  struct initializer_stack *p = XNEW (struct initializer_stack);
+  const char *asmspec = 0;
+
+  if (asmspec_tree)
+    asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   p->decl = constructor_decl;
+  p->asmspec = constructor_asmspec;
   p->require_constant_value = require_constant_value;
   p->require_constant_elements = require_constant_elements;
   p->constructor_stack = constructor_stack;
@@ -4410,6 +4415,7 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
   initializer_stack = p;
 
   constructor_decl = decl;
+  constructor_asmspec = asmspec;
   constructor_designated = 0;
   constructor_top_level = top_level;
 
@@ -4459,13 +4465,13 @@ finish_init (void)
       free (q);
     }
 
-  if (constructor_range_stack)
-    abort ();
+  gcc_assert (!constructor_range_stack);
 
   /* Pop back to the data of the outer initializer (if any).  */
   free (spelling_base);
-  
+
   constructor_decl = p->decl;
+  constructor_asmspec = p->asmspec;
   require_constant_value = p->require_constant_value;
   require_constant_elements = p->require_constant_elements;
   constructor_stack = p->constructor_stack;
@@ -4489,12 +4495,12 @@ finish_init (void)
 void
 really_start_incremental_init (tree type)
 {
-  struct constructor_stack *p = xmalloc (sizeof (struct constructor_stack));
+  struct constructor_stack *p = XNEW (struct constructor_stack);
 
   if (type == 0)
     type = TREE_TYPE (constructor_decl);
 
-  if ((*targetm.vector_opaque_p) (type))
+  if (targetm.vector_opaque_p (type))
     error ("opaque vector types cannot be initialized");
 
   p->type = constructor_type;
@@ -4510,7 +4516,8 @@ really_start_incremental_init (tree type)
   p->erroneous = constructor_erroneous;
   p->pending_elts = constructor_pending_elts;
   p->depth = constructor_depth;
-  p->replacement_value = 0;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
   p->implicit = 0;
   p->range_stack = 0;
   p->outer = 0;
@@ -4552,14 +4559,14 @@ really_start_incremental_init (tree 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_max_index = build_int_cst (NULL_TREE, -1);
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_2 (-1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4574,7 +4581,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = convert (bitsizetype, bitsize_zero_node);
       constructor_unfilled_index = constructor_index;
     }
@@ -4625,7 +4632,7 @@ push_init_level (int implicit)
        value = find_init_member (constructor_index);
     }
 
-  p = xmalloc (sizeof (struct constructor_stack));
+  p = XNEW (struct constructor_stack);
   p->type = constructor_type;
   p->fields = constructor_fields;
   p->index = constructor_index;
@@ -4639,7 +4646,8 @@ push_init_level (int implicit)
   p->erroneous = constructor_erroneous;
   p->pending_elts = constructor_pending_elts;
   p->depth = constructor_depth;
-  p->replacement_value = 0;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
   p->implicit = implicit;
   p->outer = 0;
   p->incremental = constructor_incremental;
@@ -4728,7 +4736,7 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = convert (bitsizetype, integer_zero_node);
       constructor_unfilled_index = constructor_index;
     }
@@ -4742,14 +4750,14 @@ push_init_level (int implicit)
          /* 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_max_index = build_int_cst (NULL_TREE, -1);
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_2 (-1, -1);
+           constructor_max_index = build_int_cst (NULL_TREE, -1);
 
          constructor_index
            = convert (bitsizetype,
@@ -4776,18 +4784,23 @@ push_init_level (int implicit)
 }
 
 /* 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
+   finish up that level of constructor.  If a single expression
+   with redundant braces initialized that level, return the
+   c_expr structure for that expression.  Otherwise, the original_code
+   element is set to ERROR_MARK.
+   If we were outputting the elements as they are read, return 0 as the value
    from inner levels (process_init_element ignores that),
-   but return error_mark_node from the outermost level
+   but return error_mark_node as the value from the outermost level
    (that's what we want to put in DECL_INITIAL).
-   Otherwise, return a CONSTRUCTOR expression.  */
+   Otherwise, return a CONSTRUCTOR expression as the value.  */
 
-tree
+struct c_expr
 pop_init_level (int implicit)
 {
   struct constructor_stack *p;
-  tree constructor = 0;
+  struct c_expr ret;
+  ret.value = 0;
+  ret.original_code = ERROR_MARK;
 
   if (implicit == 0)
     {
@@ -4796,10 +4809,13 @@ pop_init_level (int implicit)
       while (constructor_stack->implicit)
        process_init_element (pop_init_level (1));
 
-      if (constructor_range_stack)
-       abort ();
+      gcc_assert (!constructor_range_stack);
     }
 
+  /* Now output all pending elements.  */
+  constructor_incremental = 1;
+  output_pending_init_elements (1);
+
   p = constructor_stack;
 
   /* Error for initializing a flexible array member, or a zero-length
@@ -4813,8 +4829,10 @@ pop_init_level (int implicit)
         already have pedwarned for empty brackets.  */
       if (integer_zerop (constructor_unfilled_index))
        constructor_type = NULL_TREE;
-      else if (! TYPE_SIZE (constructor_type))
+      else
        {
+         gcc_assert (!TYPE_SIZE (constructor_type));
+         
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
          else if (pedantic)
@@ -4826,14 +4844,10 @@ pop_init_level (int implicit)
          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
+  if (warn_missing_field_initializers
       && constructor_type
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
@@ -4854,15 +4868,11 @@ pop_init_level (int implicit)
          }
     }
 
-  /* Now output all pending elements.  */
-  constructor_incremental = 1;
-  output_pending_init_elements (1);
-
   /* Pad out the end of the structure.  */
-  if (p->replacement_value)
+  if (p->replacement_value.value)
     /* If this closes a superfluous brace pair,
        just pass out the element between them.  */
-    constructor = p->replacement_value;
+    ret = p->replacement_value;
   else if (constructor_type == 0)
     ;
   else if (TREE_CODE (constructor_type) != RECORD_TYPE
@@ -4876,28 +4886,28 @@ pop_init_level (int implicit)
        {
          if (!constructor_erroneous)
            error_init ("empty scalar initializer");
-         constructor = error_mark_node;
+         ret.value = error_mark_node;
        }
       else if (TREE_CHAIN (constructor_elements) != 0)
        {
          error_init ("extra elements in scalar initializer");
-         constructor = TREE_VALUE (constructor_elements);
+         ret.value = TREE_VALUE (constructor_elements);
        }
       else
-       constructor = TREE_VALUE (constructor_elements);
+       ret.value = TREE_VALUE (constructor_elements);
     }
   else
     {
       if (constructor_erroneous)
-       constructor = error_mark_node;
+       ret.value = error_mark_node;
       else
        {
-         constructor = build_constructor (constructor_type,
-                                          nreverse (constructor_elements));
+         ret.value = build_constructor (constructor_type,
+                                        nreverse (constructor_elements));
          if (constructor_constant)
-           TREE_CONSTANT (constructor) = 1;
+           TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
-           TREE_STATIC (constructor) = 1;
+           TREE_STATIC (ret.value) = 1;
        }
     }
 
@@ -4923,13 +4933,16 @@ pop_init_level (int implicit)
   constructor_stack = p->next;
   free (p);
 
-  if (constructor == 0)
+  if (ret.value == 0)
     {
       if (constructor_stack == 0)
-       return error_mark_node;
-      return NULL_TREE;
+       {
+         ret.value = error_mark_node;
+         return ret;
+       }
+      return ret;
     }
-  return constructor;
+  return ret;
 }
 
 /* Common handling for both array range and field name designators.
@@ -4946,14 +4959,14 @@ set_designator (int array)
   if (constructor_type == 0)
     return 1;
 
-  /* If there were errors in this designator list already, bail out silently.  */
+  /* 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 ();
+      gcc_assert (!constructor_range_stack);
 
       /* Designator list starts at the level of closest explicit
         braces.  */
@@ -4969,19 +4982,20 @@ set_designator (int array)
       return 1;
     }
 
-  if (TREE_CODE (constructor_type) == RECORD_TYPE
-      || TREE_CODE (constructor_type) == UNION_TYPE)
+  switch (TREE_CODE (constructor_type))
     {
+    case  RECORD_TYPE:
+    case  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)
-    {
+      break;
+    case ARRAY_TYPE:
       subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+      break;
+    default:
+      gcc_unreachable ();
     }
-  else
-    abort ();
 
   subcode = TREE_CODE (subtype);
   if (array && subcode != ARRAY_TYPE)
@@ -5009,7 +5023,7 @@ push_range_stack (tree range_end)
 {
   struct constructor_range_stack *p;
 
-  p = ggc_alloc (sizeof (struct constructor_range_stack));
+  p = GGC_NEW (struct constructor_range_stack);
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -5034,6 +5048,13 @@ set_init_index (tree first, tree last)
 
   designator_errorneous = 1;
 
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
+      || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
+    {
+      error_init ("array index in initializer not of integer type");
+      return;
+    }
+
   while ((TREE_CODE (first) == NOP_EXPR
          || TREE_CODE (first) == CONVERT_EXPR
          || TREE_CODE (first) == NON_LVALUE_EXPR)
@@ -5183,7 +5204,7 @@ add_pending_init (tree purpose, tree value)
        }
     }
 
-  r = ggc_alloc (sizeof (struct init_node));
+  r = GGC_NEW (struct init_node);
   r->purpose = purpose;
   r->value = value;
 
@@ -5394,18 +5415,17 @@ set_nonincremental_init_from_string (tree str)
   const char *p, *end;
   int byte, wchar_bytes, charwidth, bitpos;
 
-  if (TREE_CODE (constructor_type) != ARRAY_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
 
   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 ();
-
+    {
+      gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
+                 == TYPE_PRECISION (wchar_type_node));
+      wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+    }
   charwidth = TYPE_PRECISION (char_type_node);
   type = TREE_TYPE (constructor_type);
   p = TREE_STRING_POINTER (str);
@@ -5436,7 +5456,7 @@ set_nonincremental_init_from_string (tree str)
            }
        }
 
-      if (!TREE_UNSIGNED (type))
+      if (!TYPE_UNSIGNED (type))
        {
          bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
          if (bitpos < HOST_BITS_PER_WIDE_INT)
@@ -5458,8 +5478,7 @@ set_nonincremental_init_from_string (tree str)
                      << (bitpos - HOST_BITS_PER_WIDE_INT);
        }
 
-      value = build_int_2 (val[1], val[0]);
-      TREE_TYPE (value) = type;
+      value = build_int_cst_wide (type, val[1], val[0]);
       add_pending_init (purpose, value);
     }
 
@@ -5526,13 +5545,17 @@ find_init_member (tree field)
    Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
    TYPE is the data type that the containing data type wants here.
    FIELD is the field (a FIELD_DECL) or the index that this element fills.
+   If VALUE is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of VALUE, STRICT_STRING is not used.
 
    PENDING if non-nil means output pending elements that belong
    right after this element.  (PENDING is normally 1;
    it is 0 while outputting pending elements, to avoid recursion.)  */
 
 static void
-output_init_element (tree value, tree type, tree field, int pending)
+output_init_element (tree value, bool strict_string, tree type, tree field,
+                    int pending)
 {
   if (type == error_mark_node)
     {
@@ -5543,9 +5566,9 @@ output_init_element (tree value, tree type, tree field, int pending)
       || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
          && !(TREE_CODE (value) == STRING_CST
               && TREE_CODE (type) == ARRAY_TYPE
-              && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+              && INTEGRAL_TYPE_P (TREE_TYPE (type)))
          && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-                        TYPE_MAIN_VARIANT (type), COMPARE_STRICT)))
+                        TYPE_MAIN_VARIANT (type))))
     value = default_conversion (value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
@@ -5588,7 +5611,7 @@ output_init_element (tree value, tree type, tree field, int pending)
                  || TREE_CHAIN (field)))))
     return;
 
-  value = digest_init (type, value, require_constant_value);
+  value = digest_init (type, value, strict_string, require_constant_value);
   if (value == error_mark_node)
     {
       constructor_erroneous = 1;
@@ -5708,7 +5731,7 @@ output_pending_init_elements (int all)
        {
          if (tree_int_cst_equal (elt->purpose,
                                  constructor_unfilled_index))
-           output_init_element (elt->value,
+           output_init_element (elt->value, true,
                                 TREE_TYPE (constructor_type),
                                 constructor_unfilled_index, 0);
          else if (tree_int_cst_lt (constructor_unfilled_index,
@@ -5762,7 +5785,7 @@ output_pending_init_elements (int all)
          if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
            {
              constructor_unfilled_fields = elt->purpose;
-             output_init_element (elt->value, TREE_TYPE (elt->purpose),
+             output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
                                   elt->purpose, 0);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
@@ -5829,10 +5852,11 @@ output_pending_init_elements (int all)
    it calls output_init_element.  */
 
 void
-process_init_element (tree value)
+process_init_element (struct c_expr value)
 {
-  tree orig_value = value;
-  int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
+  tree orig_value = value.value;
+  int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
+  bool strict_string = value.original_code == STRING_CST;
 
   designator_depth = 0;
   designator_errorneous = 0;
@@ -5842,16 +5866,16 @@ process_init_element (tree value)
   if (string_flag
       && constructor_type
       && TREE_CODE (constructor_type) == ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
+      && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
       && integer_zerop (constructor_unfilled_index))
     {
-      if (constructor_stack->replacement_value)
+      if (constructor_stack->replacement_value.value)
         error_init ("excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
 
-  if (constructor_stack->replacement_value != 0)
+  if (constructor_stack->replacement_value.value != 0)
     {
       error_init ("excess elements in struct initializer");
       return;
@@ -5884,10 +5908,10 @@ process_init_element (tree value)
     {
       /* If value is a compound literal and we'll be just using its
         content, don't put it into a SAVE_EXPR.  */
-      if (TREE_CODE (value) != COMPOUND_LITERAL_EXPR
+      if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR
          || !require_constant_value
          || flag_isoc99)
-       value = save_expr (value);
+       value.value = save_expr (value.value);
     }
 
   while (1)
@@ -5919,16 +5943,16 @@ process_init_element (tree value)
            }
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
            {
@@ -5936,10 +5960,11 @@ process_init_element (tree value)
              continue;
            }
 
-         if (value)
+         if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value, fieldtype, constructor_fields, 1);
+             output_init_element (value.value, strict_string,
+                                  fieldtype, constructor_fields, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -6001,20 +6026,21 @@ process_init_element (tree value)
             __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))))
+             && !(value.value && (integer_zerop (value.value)
+                                  || real_zerop (value.value))))
            warning ("traditional C rejects initialization of unions");
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && fieldcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE))
            {
@@ -6022,10 +6048,11 @@ process_init_element (tree value)
              continue;
            }
 
-         if (value)
+         if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value, fieldtype, constructor_fields, 1);
+             output_init_element (value.value, strict_string,
+                                  fieldtype, constructor_fields, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -6044,16 +6071,16 @@ process_init_element (tree value)
          enum tree_code eltcode = TREE_CODE (elttype);
 
          /* Accept a string constant to initialize a subarray.  */
-         if (value != 0
+         if (value.value != 0
              && eltcode == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (elttype))
              && string_flag)
-           value = orig_value;
+           value.value = orig_value;
          /* Otherwise, if we have come to a subaggregate,
             and we don't have an element of its type, push into it.  */
-         else if (value != 0 && !constructor_no_implicit
-                  && value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
+         else if (value.value != 0 && !constructor_no_implicit
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE))
            {
@@ -6070,17 +6097,18 @@ process_init_element (tree value)
            }
 
          /* Now output the actual element.  */
-         if (value)
+         if (value.value)
            {
              push_array_bounds (tree_low_cst (constructor_index, 0));
-             output_init_element (value, elttype, constructor_index, 1);
+             output_init_element (value.value, strict_string,
+                                  elttype, constructor_index, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-         if (! value)
+         if (!value.value)
            /* If we are doing the bookkeeping for an element that was
               directly output as a constructor, we must update
               constructor_unfilled_index.  */
@@ -6099,13 +6127,14 @@ process_init_element (tree value)
            }
 
          /* Now output the actual element.  */
-         if (value)
-           output_init_element (value, elttype, constructor_index, 1);
+         if (value.value)
+           output_init_element (value.value, strict_string,
+                                elttype, constructor_index, 1);
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
 
-         if (! value)
+         if (!value.value)
            /* If we are doing the bookkeeping for an element that was
               directly output as a constructor, we must update
               constructor_unfilled_index.  */
@@ -6121,8 +6150,9 @@ process_init_element (tree value)
        }
       else
        {
-         if (value)
-           output_init_element (value, constructor_type, NULL_TREE, 1);
+         if (value.value)
+           output_init_element (value.value, strict_string,
+                                constructor_type, NULL_TREE, 1);
          constructor_fields = 0;
        }
 
@@ -6137,16 +6167,14 @@ process_init_element (tree value)
          constructor_range_stack = 0;
          while (constructor_stack != range_stack->stack)
            {
-             if (!constructor_stack->implicit)
-               abort ();
+             gcc_assert (constructor_stack->implicit);
              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 ();
+             gcc_assert (constructor_stack->implicit);
              process_init_element (pop_init_level (1));
            }
 
@@ -6183,82 +6211,64 @@ process_init_element (tree value)
   constructor_range_stack = 0;
 }
 \f
-/* Build a simple asm-statement, from one string literal.  */
+/* Build a complete asm-statement, whose components are a CV_QUALIFIER
+   (guaranteed to be 'volatile' or null) and ARGS (represented using
+   an ASM_EXPR node).  */
 tree
-simple_asm_stmt (tree expr)
+build_asm_stmt (tree cv_qualifier, tree args)
 {
-  STRIP_NOPS (expr);
-
-  if (TREE_CODE (expr) == ADDR_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-
-  if (TREE_CODE (expr) == STRING_CST)
-    {
-      tree stmt;
-
-      /* Simple asm statements are treated as volatile.  */
-      stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE],
-                                  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;
+  if (!ASM_VOLATILE_P (args) && cv_qualifier)
+    ASM_VOLATILE_P (args) = 1;
+  return add_stmt (args);
 }
 
-/* Build an asm-statement, whose components are a CV_QUALIFIER, a
-   STRING, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
-
+/* Build an asm-expr, whose components are a STRING, some OUTPUTS,
+   some INPUTS, and some CLOBBERS.  The latter three may be NULL.
+   SIMPLE indicates whether there was anything at all after the
+   string in the asm expression -- asm("blah") and asm("blah" : )
+   are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
-build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs,
-               tree clobbers)
+build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
+               bool simple)
 {
   tree tail;
+  tree args;
+  int i;
+  const char *constraint;
+  bool allows_mem, allows_reg, is_inout;
+  int ninputs;
+  int noutputs;
 
-  if (TREE_CODE (string) != STRING_CST)
-    {
-      error ("asm template is not a string constant");
-      return NULL_TREE;
-    }
-
-  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;
-    }
+  ninputs = list_length (inputs);
+  noutputs = list_length (outputs);
 
-  /* We can remove output conversions that change the type,
-     but not the mode.  */
-  for (tail = outputs; tail; tail = TREE_CHAIN (tail))
+  /* Remove output conversions that change the type but not the mode.  */
+  for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree output = TREE_VALUE (tail);
-
       STRIP_NOPS (output);
       TREE_VALUE (tail) = output;
+      lvalue_or_else (output, "invalid lvalue in asm statement");
 
-      /* Allow conversions as LHS here.  build_modify_expr as called below
-        will do the right thing with them.  */
-      while (TREE_CODE (output) == NOP_EXPR
-            || TREE_CODE (output) == CONVERT_EXPR
-            || TREE_CODE (output) == FLOAT_EXPR
-            || TREE_CODE (output) == FIX_TRUNC_EXPR
-            || TREE_CODE (output) == FIX_FLOOR_EXPR
-            || TREE_CODE (output) == FIX_ROUND_EXPR
-            || TREE_CODE (output) == FIX_CEIL_EXPR)
-       output = TREE_OPERAND (output, 0);
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
 
-      lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement");
-    }
+      if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
+                                    &allows_mem, &allows_reg, &is_inout))
+        {
+          /* By marking this operand as erroneous, we will not try
+          to process this operand again in expand_asm_operands.  */
+          TREE_VALUE (tail) = error_mark_node;
+          continue;
+        }
 
-  /* 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;
+      /* If the operand is a DECL that is going to end up in
+        memory, assume it is addressable.  This is a bit more
+        conservative than it would ideally be; the exact test is
+        buried deep in expand_asm_operands and depends on the
+        DECL_RTL for the OPERAND -- which we don't have at this
+        point.  */
+      if (!allows_reg && DECL_P (output))
+        c_mark_addressable (output);
     }
 
   /* Perform default conversions on array and function inputs.
@@ -6267,75 +6277,46 @@ build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs,
   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.  */
-
-void
-c_expand_asm_operands (tree string, tree outputs, tree inputs,
-                      tree clobbers, int vol, location_t locus)
-{
-  int noutputs = list_length (outputs);
-  int i;
-  /* o[I] is the place that output number I should be written.  */
-  tree *o = alloca (noutputs * sizeof (tree));
-  tree tail;
+  args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
 
-  /* Record the contents of OUTPUTS before it is modified.  */
-  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+  /* Simple asm statements are treated as volatile.  */
+  if (simple)
     {
-      o[i] = TREE_VALUE (tail);
-      if (o[i] == error_mark_node)
-       return;
+      ASM_VOLATILE_P (args) = 1;
+      ASM_INPUT_P (args) = 1;
     }
+  return args;
+}
+\f
+/* Generate a goto statement to LABEL.  */
 
-  /* 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, locus);
+tree
+c_finish_goto_label (tree label)
+{
+  tree decl = lookup_label (label);
+  if (!decl)
+    return NULL_TREE;
 
-  /* Copy all the intermediate outputs into the specified outputs.  */
-  for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
-    {
-      if (o[i] != TREE_VALUE (tail))
-       {
-         expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
-                      NULL_RTX, VOIDmode, EXPAND_NORMAL);
-         free_temp_slots ();
+  TREE_USED (decl) = 1;
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, decl));
+}
 
-         /* 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.)  */
-      else
-       {
-         tree type = TREE_TYPE (o[i]);
-         if (TREE_READONLY (o[i])
-             || TYPE_READONLY (type)
-             || ((TREE_CODE (type) == RECORD_TYPE
-                  || TREE_CODE (type) == UNION_TYPE)
-                 && C_TYPE_FIELDS_READONLY (type)))
-           readonly_warning (o[i], "modification by `asm'");
-       }
-    }
+/* Generate a computed goto statement to EXPR.  */
 
-  /* Those MODIFY_EXPRs could do autoincrements.  */
-  emit_queue ();
+tree
+c_finish_goto_ptr (tree expr)
+{
+  if (pedantic)
+    pedwarn ("ISO C forbids `goto *expr;'");
+  expr = convert (ptr_type_node, expr);
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
 }
-\f
-/* Expand a C `return' statement.
-   RETVAL is the expression for what to return,
-   or a null pointer for `return;' with no value.  */
+
+/* Generate a C `return' statement.  RETVAL is the expression for what
+   to return, or a null pointer for `return;' with no value.  */
 
 tree
-c_expand_return (tree retval)
+c_finish_return (tree retval)
 {
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
 
@@ -6402,10 +6383,11 @@ c_expand_return (tree retval)
            case ADDR_EXPR:
              inner = TREE_OPERAND (inner, 0);
 
-             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
+             while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r'
+                    && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
-             if (TREE_CODE (inner) == VAR_DECL
+             if (DECL_P (inner)
                  && ! DECL_EXTERNAL (inner)
                  && ! TREE_STATIC (inner)
                  && DECL_CONTEXT (inner) == current_function_decl)
@@ -6419,21 +6401,27 @@ c_expand_return (tree retval)
          break;
        }
 
-      retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
+      retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
     }
 
return add_stmt (build_return_stmt (retval));
 return add_stmt (build_stmt (RETURN_EXPR, retval));
 }
 \f
 struct c_switch {
   /* The SWITCH_STMT being built.  */
   tree switch_stmt;
+
+  /* The original type of the testing expression, ie. before the
+     default conversion is applied.  */
+  tree orig_type;
+
   /* 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;
 };
@@ -6444,7 +6432,7 @@ struct c_switch {
    during the processing of the body of a function, and we never
    collect at that point.  */
 
-static struct c_switch *switch_stack;
+struct c_switch *c_switch_stack;
 
 /* Start a C switch statement, testing expression EXP.  Return the new
    SWITCH_STMT.  */
@@ -6482,13 +6470,15 @@ c_start_case (tree exp)
     }
 
   /* Add this new SWITCH_STMT to the stack.  */
-  cs = xmalloc (sizeof (*cs));
-  cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type);
+  cs = XNEW (struct c_switch);
+  cs->switch_stmt = build_stmt ((enum tree_code) SWITCH_STMT, exp, NULL_TREE,
+                               orig_type);
+  cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
-  cs->next = switch_stack;
-  switch_stack = cs;
+  cs->next = c_switch_stack;
+  c_switch_stack = cs;
 
-  return add_stmt (switch_stack->switch_stmt);
+  return add_stmt (cs->switch_stmt);
 }
 
 /* Process a case label.  */
@@ -6498,21 +6488,14 @@ do_case (tree low_value, tree high_value)
 {
   tree label = NULL_TREE;
 
-  if (switch_stack)
+  if (c_switch_stack)
     {
-      bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE);
-
-      label = c_add_case_label (switch_stack->cases,
-                               SWITCH_COND (switch_stack->switch_stmt),
+      label = c_add_case_label (c_switch_stack->cases,
+                               SWITCH_COND (c_switch_stack->switch_stmt),
+                               c_switch_stack->orig_type,
                                low_value, high_value);
       if (label == error_mark_node)
        label = NULL_TREE;
-      else if (switch_was_empty_p)
-       {
-         /* Attach the first case label to the SWITCH_BODY.  */
-         SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt);
-         TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE;
-       }
     }
   else if (low_value)
     error ("case label not within a switch statement");
@@ -6525,19 +6508,409 @@ do_case (tree low_value, tree high_value)
 /* Finish the switch statement.  */
 
 void
-c_finish_case (void)
+c_finish_case (tree body)
 {
-  struct c_switch *cs = switch_stack;
+  struct c_switch *cs = c_switch_stack;
+
+  SWITCH_BODY (cs->switch_stmt) = body;
 
-  /* Rechain the next statements to the SWITCH_STMT.  */
-  last_tree = cs->switch_stmt;
+  /* Emit warnings as needed.  */
+  c_do_switch_warnings (cs->cases, cs->switch_stmt);
 
   /* Pop the stack.  */
-  switch_stack = switch_stack->next;
+  c_switch_stack = cs->next;
   splay_tree_delete (cs->cases);
-  free (cs);
+  XDELETE (cs);
+}
+\f
+/* Emit an if statement.  IF_LOCUS is the location of the 'if'.  COND,
+   THEN_BLOCK and ELSE_BLOCK are expressions to be used; ELSE_BLOCK
+   may be null.  NESTED_IF is true if THEN_BLOCK contains another IF
+   statement, and was not surrounded with parenthesis.  */
+
+void
+c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
+                 tree else_block, bool nested_if)
+{
+  tree stmt;
+
+  /* Diagnose an ambiguous else if if-then-else is nested inside if-then.  */
+  if (warn_parentheses && nested_if && else_block == NULL)
+    {
+      tree inner_if = then_block;
+
+      /* We know from the grammar productions that there is an IF nested
+        within THEN_BLOCK.  Due to labels and c99 conditional declarations,
+        it might not be exactly THEN_BLOCK, but should be the last
+        non-container statement within.  */
+      while (1)
+       switch (TREE_CODE (inner_if))
+         {
+         case COND_EXPR:
+           goto found;
+         case BIND_EXPR:
+           inner_if = BIND_EXPR_BODY (inner_if);
+           break;
+         case STATEMENT_LIST:
+           inner_if = expr_last (then_block);
+           break;
+         case TRY_FINALLY_EXPR:
+         case TRY_CATCH_EXPR:
+           inner_if = TREE_OPERAND (inner_if, 0);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+    found:
+
+      if (COND_EXPR_ELSE (inner_if))
+        warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
+                 &if_locus);
+    }
+
+  /* Diagnose ";" via the special empty statement node that we create.  */
+  if (extra_warnings)
+    {
+      if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block))
+       {
+         if (!else_block)
+           warning ("%Hempty body in an if-statement",
+                    EXPR_LOCUS (then_block));
+         then_block = alloc_stmt_list ();
+       }
+      if (else_block
+         && TREE_CODE (else_block) == NOP_EXPR
+         && !TREE_TYPE (else_block))
+       {
+         warning ("%Hempty body in an else-statement",
+                  EXPR_LOCUS (else_block));
+         else_block = alloc_stmt_list ();
+       }
+    }
+
+  stmt = build3 (COND_EXPR, NULL_TREE, cond, then_block, else_block);
+  SET_EXPR_LOCATION (stmt, if_locus);
+  add_stmt (stmt);
+}
+
+/* Emit a general-purpose loop construct.  START_LOCUS is the location of
+   the beginning of the loop.  COND is the loop condition.  COND_IS_FIRST
+   is false for DO loops.  INCR is the FOR increment expression.  BODY is
+   the statement controlled by the loop.  BLAB is the break label.  CLAB is
+   the continue label.  Everything is allowed to be NULL.  */
+
+void
+c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
+              tree blab, tree clab, bool cond_is_first)
+{
+  tree entry = NULL, exit = NULL, t;
+
+  /* Detect do { ... } while (0) and don't generate loop construct.  */
+  if (cond && !cond_is_first && integer_zerop (cond))
+    cond = NULL;
+  if (cond_is_first || cond)
+    {
+      tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+      /* If we have an exit condition, then we build an IF with gotos either
+         out of the loop, or to the top of it.  If there's no exit condition,
+         then we just build a jump back to the top.  */
+      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+      if (cond)
+        {
+          /* Canonicalize the loop condition to the end.  This means
+             generating a branch to the loop condition.  Reuse the
+             continue label, if possible.  */
+          if (cond_is_first)
+            {
+              if (incr || !clab)
+                {
+                  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+                  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+                }
+              else
+                t = build1 (GOTO_EXPR, void_type_node, clab);
+             SET_EXPR_LOCATION (t, start_locus);
+              add_stmt (t);
+            }
+         t = build_and_jump (&blab);
+          exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
+          exit = fold (exit);
+         if (cond_is_first)
+            SET_EXPR_LOCATION (exit, start_locus);
+         else
+            SET_EXPR_LOCATION (exit, input_location);
+        }
+      add_stmt (top);
+    }
+  if (body)
+    add_stmt (body);
+  if (clab)
+    add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
+  if (incr)
+    add_stmt (incr);
+  if (entry)
+    add_stmt (entry);
+  if (exit)
+    add_stmt (exit);
+  if (blab)
+    add_stmt (build1 (LABEL_EXPR, void_type_node, blab));
+}
+
+tree
+c_finish_bc_stmt (tree *label_p, bool is_break)
+{
+  tree label = *label_p;
+
+  if (!label)
+    *label_p = label = create_artificial_label ();
+  else if (TREE_CODE (label) != LABEL_DECL)
+    {
+      if (is_break)
+       error ("break statement not within loop or switch");
+      else
+        error ("continue statement not within a loop");
+      return NULL_TREE;
+    }
+
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
+}
+
+/* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
+
+static void
+emit_side_effect_warnings (tree expr)
+{
+  if (expr == error_mark_node)
+    ;
+  else if (!TREE_SIDE_EFFECTS (expr))
+    {
+      if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
+       warning ("%Hstatement with no effect",
+                EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
+    }
+  else if (warn_unused_value)
+    warn_if_unused_value (expr, input_location);
+}
+
+/* Process an expression as if it were a complete statement.  Emit
+   diagnostics, but do not call ADD_STMT.  */
+
+tree
+c_process_expr_stmt (tree expr)
+{
+  if (!expr)
+    return NULL_TREE;
+
+  /* Do default conversion if safe and possibly important,
+     in case within ({...}).  */
+  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+       && (flag_isoc99 || lvalue_p (expr)))
+      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
+    expr = default_conversion (expr);
+
+  if (warn_sequence_point)
+    verify_sequence_points (expr);
+
+  if (TREE_TYPE (expr) != error_mark_node
+      && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
+      && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
+    error ("expression statement has incomplete type");
+
+  /* If we're not processing a statement expression, warn about unused values.
+     Warnings for statement expressions will be emitted later, once we figure
+     out which is the result.  */
+  if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
+      && (extra_warnings || warn_unused_value))
+    emit_side_effect_warnings (expr);
+
+  /* If the expression is not of a type to which we cannot assign a line
+     number, wrap the thing in a no-op NOP_EXPR.  */
+  if (DECL_P (expr) || TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
+    expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
+
+  if (EXPR_P (expr))
+    SET_EXPR_LOCATION (expr, input_location);
+
+  return expr;
+}
+
+/* Emit an expression as a statement.  */
+
+tree
+c_finish_expr_stmt (tree expr)
+{
+  if (expr)
+    return add_stmt (c_process_expr_stmt (expr));
+  else
+    return NULL;
+}
+
+/* Do the opposite and emit a statement as an expression.  To begin,
+   create a new binding level and return it.  */
+
+tree
+c_begin_stmt_expr (void)
+{
+  tree ret;
+
+  /* We must force a BLOCK for this level so that, if it is not expanded
+     later, there is a way to turn off the entire subtree of blocks that
+     are contained in it.  */
+  keep_next_level ();
+  ret = c_begin_compound_stmt (true);
+
+  /* Mark the current statement list as belonging to a statement list.  */
+  STATEMENT_LIST_STMT_EXPR (ret) = 1;
+
+  return ret;
+}
+
+tree
+c_finish_stmt_expr (tree body)
+{
+  tree last, type, tmp, val;
+  tree *last_p;
+
+  body = c_end_compound_stmt (body, true);
+
+  /* Locate the last statement in BODY.  See c_end_compound_stmt
+     about always returning a BIND_EXPR.  */
+  last_p = &BIND_EXPR_BODY (body);
+  last = BIND_EXPR_BODY (body);
+
+ continue_searching:
+  if (TREE_CODE (last) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator i;
+
+      /* This can happen with degenerate cases like ({ }).  No value.  */
+      if (!TREE_SIDE_EFFECTS (last))
+       return body;
+
+      /* If we're supposed to generate side effects warnings, process
+        all of the statements except the last.  */
+      if (extra_warnings || warn_unused_value)
+       {
+         for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
+           emit_side_effect_warnings (tsi_stmt (i));
+       }
+      else
+       i = tsi_last (last);
+      last_p = tsi_stmt_ptr (i);
+      last = *last_p;
+    }
+
+  /* If the end of the list is exception related, then the list was split
+     by a call to push_cleanup.  Continue searching.  */
+  if (TREE_CODE (last) == TRY_FINALLY_EXPR
+      || TREE_CODE (last) == TRY_CATCH_EXPR)
+    {
+      last_p = &TREE_OPERAND (last, 0);
+      last = *last_p;
+      goto continue_searching;
+    }
+
+  /* In the case that the BIND_EXPR is not necessary, return the
+     expression out from inside it.  */
+  if (last == error_mark_node
+      || (last == BIND_EXPR_BODY (body)
+         && BIND_EXPR_VARS (body) == NULL))
+    return last;
+
+  /* Extract the type of said expression.  */
+  type = TREE_TYPE (last);
+
+  /* If we're not returning a value at all, then the BIND_EXPR that
+     we already have is a fine expression to return.  */
+  if (!type || VOID_TYPE_P (type))
+    return body;
+
+  /* Now that we've located the expression containing the value, it seems
+     silly to make voidify_wrapper_expr repeat the process.  Create a
+     temporary of the appropriate type and stick it in a TARGET_EXPR.  */
+  tmp = create_tmp_var_raw (type, NULL);
+
+  /* Unwrap a no-op NOP_EXPR as added by c_finish_expr_stmt.  This avoids
+     tree_expr_nonnegative_p giving up immediately.  */
+  val = last;
+  if (TREE_CODE (val) == NOP_EXPR
+      && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
+    val = TREE_OPERAND (val, 0);
+
+  *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
+  SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
+
+  return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
+}
+\f
+/* Begin and end compound statements.  This is as simple as pushing
+   and popping new statement lists from the tree.  */
+
+tree
+c_begin_compound_stmt (bool do_scope)
+{
+  tree stmt = push_stmt_list ();
+  if (do_scope)
+    push_scope ();
+  return stmt;
+}
+
+tree
+c_end_compound_stmt (tree stmt, bool do_scope)
+{
+  tree block = NULL;
+
+  if (do_scope)
+    {
+      if (c_dialect_objc ())
+       objc_clear_super_receiver ();
+      block = pop_scope ();
+    }
+
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (block, stmt);
+
+  /* If this compound statement is nested immediately inside a statement
+     expression, then force a BIND_EXPR to be created.  Otherwise we'll
+     do the wrong thing for ({ { 1; } }) or ({ 1; { } }).  In particular,
+     STATEMENT_LISTs merge, and thus we can lose track of what statement
+     was really last.  */
+  if (cur_stmt_list
+      && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
+      && TREE_CODE (stmt) != BIND_EXPR)
+    {
+      stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
+      TREE_SIDE_EFFECTS (stmt) = 1;
+    }
+
+  return stmt;
 }
 
+/* Queue a cleanup.  CLEANUP is an expression/statement to be executed
+   when the current scope is exited.  EH_ONLY is true when this is not
+   meant to apply to normal control flow transfer.  */
+
+void
+push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
+{
+  enum tree_code code;
+  tree stmt, list;
+  bool stmt_expr;
+
+  code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
+  stmt = build_stmt (code, NULL, cleanup);
+  add_stmt (stmt);
+  stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
+  list = push_stmt_list ();
+  TREE_OPERAND (stmt, 0) = list;
+  STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
+}
+\f
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    This function differs from `build' in several ways:
@@ -6676,6 +7049,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
+         if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+           code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+         if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+           code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
          if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
@@ -6684,7 +7062,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
               undefined if the quotient can't be represented in the
               computation mode.  We shorten only if unsigned or if
               dividing by something we know != -1.  */
-           shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
+           shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                       || (TREE_CODE (op1) == INTEGER_CST
                           && ! integer_all_onesp (op1)));
          common = 1;
@@ -6711,7 +7089,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             on some targets, since the modulo instruction is undefined if the
             quotient can't be represented in the computation mode.  We shorten
             only if unsigned or if dividing by something we know != -1.  */
-         shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
+         shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
                     || (TREE_CODE (op1) == INTEGER_CST
                         && ! integer_all_onesp (op1)));
          common = 1;
@@ -6732,8 +7110,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             but that does not mean the operands should be
             converted to ints!  */
          result_type = integer_type_node;
-         op0 = c_common_truthvalue_conversion (op0);
-         op1 = c_common_truthvalue_conversion (op1);
+         op0 = lang_hooks.truthvalue_conversion (op0);
+         op1 = lang_hooks.truthvalue_conversion (op1);
          converted = 1;
        }
       break;
@@ -6824,11 +7202,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         but don't convert the args to int!  */
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == COMPLEX_TYPE
-          || code0 == VECTOR_TYPE)
+          || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == COMPLEX_TYPE
-             || code1 == VECTOR_TYPE))
+             || code1 == COMPLEX_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -6838,7 +7214,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          if (comp_target_types (type0, type1, 1))
-           result_type = common_type (type0, type1);
+           result_type = common_pointer_type (type0, type1);
          else if (VOID_TYPE_P (tt0))
            {
              /* op0 != orig_op0 detects the case of something
@@ -6886,7 +7262,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        {
          if (comp_target_types (type0, type1, 1))
            {
-             result_type = common_type (type0, type1);
+             result_type = common_pointer_type (type0, type1);
              if (pedantic
                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
@@ -6911,7 +7287,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        {
          if (comp_target_types (type0, type1, 1))
            {
-             result_type = common_type (type0, type1);
+             result_type = common_pointer_type (type0, type1);
              if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
                  != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
                pedwarn ("comparison of complete and incomplete pointers");
@@ -6958,6 +7334,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case UNGT_EXPR:
     case UNGE_EXPR:
     case UNEQ_EXPR:
+    case LTGT_EXPR:
       build_type = integer_type_node;
       if (code0 != REAL_TYPE || code1 != REAL_TYPE)
        {
@@ -6971,6 +7348,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
     }
 
+  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
+    return error_mark_node;
+
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
        || code0 == VECTOR_TYPE)
       &&
@@ -6999,7 +7379,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          tree arg0 = get_narrower (op0, &unsigned0);
          tree arg1 = get_narrower (op1, &unsigned1);
          /* UNS is 1 if the operation to be done is an unsigned one.  */
-         int uns = TREE_UNSIGNED (result_type);
+         int uns = TYPE_UNSIGNED (result_type);
          tree type;
 
          final_type = result_type;
@@ -7010,11 +7390,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if ((TYPE_PRECISION (TREE_TYPE (op0))
               == TYPE_PRECISION (TREE_TYPE (arg0)))
              && TREE_TYPE (op0) != final_type)
-           unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));
+           unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
          if ((TYPE_PRECISION (TREE_TYPE (op1))
               == TYPE_PRECISION (TREE_TYPE (arg1)))
              && TREE_TYPE (op1) != final_type)
-           unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));
+           unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
 
          /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */
 
@@ -7069,14 +7449,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          final_type = result_type;
 
          if (arg0 == op0 && final_type == TREE_TYPE (op0))
-           unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
+           unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
 
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
              /* We cannot drop an unsigned shift after sign-extension.  */
-             && (!TREE_UNSIGNED (final_type) || unsigned_arg))
+             && (!TYPE_UNSIGNED (final_type) || unsigned_arg))
            {
              /* Do an unsigned shift if the operand was zero-extended.  */
              result_type
@@ -7112,8 +7492,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
          if (warn_sign_compare && skip_evaluation == 0)
            {
-             int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
-             int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
+             int op0_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+             int op1_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op1));
              int unsignedp0, unsignedp1;
              tree primop0 = get_narrower (op0, &unsignedp0);
              tree primop1 = get_narrower (op1, &unsignedp1);
@@ -7132,7 +7512,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 Do not warn if the comparison is being done in a signed type,
                 since the signed type will only be chosen if it can represent
                 all the values of the unsigned type.  */
-             if (! TREE_UNSIGNED (result_type))
+             if (! TYPE_UNSIGNED (result_type))
                /* OK */;
               /* Do not warn if both operands are the same signedness.  */
               else if (op0_signed == op1_signed)
@@ -7151,7 +7531,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                     constant expression involving such literals or a
                     conditional expression involving such literals)
                     and it is non-negative.  */
-                 if (c_tree_expr_nonnegative_p (sop))
+                 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
@@ -7249,23 +7629,25 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        op0 = convert (result_type, op0);
       if (TREE_TYPE (op1) != result_type)
        op1 = convert (result_type, op1);
+
+      /* This can happen if one operand has a vector type, and the other
+        has a different type.  */
+      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+       return error_mark_node;
     }
 
   if (build_type == NULL_TREE)
     build_type = result_type;
 
   {
-    tree result = build (resultcode, build_type, op0, op1);
-    tree folded;
+    tree result = build2 (resultcode, build_type, op0, op1);
 
     /* Treat expressions in initializers specially as they can't trap.  */
-    folded = initializer_stack ? fold_initializer (result)
-                              : fold (result);
-    if (folded == result)
-      TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+    result = require_constant_value ? fold_initializer (result)
+                                   : fold (result);
+
     if (final_type != 0)
-      return convert (final_type, folded);
-    return folded;
+      result = convert (final_type, result);
+    return result;
   }
 }
-