OSDN Git Service

2005-07-20 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 663dd7f..4839591 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 /* This file is part of the C front end.
@@ -64,7 +64,8 @@ int in_sizeof;
 /* The level of nesting inside "typeof".  */
 int in_typeof;
 
-struct c_label_context *label_context_stack;
+struct c_label_context_se *label_context_stack_se;
+struct c_label_context_vm *label_context_stack_vm;
 
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
@@ -75,11 +76,10 @@ static int require_constant_elements;
 
 static tree qualify_type (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree);
-static int comp_target_types (tree, tree, int);
+static int comp_target_types (tree, tree);
 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);
@@ -343,7 +343,7 @@ composite_type (tree t1, tree t2)
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
        /* Tell global_bindings_p to return false so that variable_size
-          doesn't abort on VLAs in parameter types.  */
+          doesn't die on VLAs in parameter types.  */
        c_override_global_bindings_to_false = true;
 
        len = list_length (p1);
@@ -617,7 +617,9 @@ c_common_type (tree t1, tree t2)
 }
 \f
 /* Wrapper around c_common_type that is used by c-common.c.  ENUMERAL_TYPEs
-   are allowed here and are converted to their compatible integer types.  */
+   are allowed here and are converted to their compatible integer types.
+   BOOLEAN_TYPEs are allowed here and return either boolean_type_node or
+   preferably a non-Boolean type as the common type.  */
 tree
 common_type (tree t1, tree t2)
 {
@@ -625,6 +627,18 @@ common_type (tree t1, tree t2)
     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);
+
+  /* If both types are BOOLEAN_TYPE, then return boolean_type_node.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE
+      && TREE_CODE (t2) == BOOLEAN_TYPE)
+    return boolean_type_node;
+
+  /* If either type is BOOLEAN_TYPE, then return the other.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE)
+    return t2;
+  if (TREE_CODE (t2) == BOOLEAN_TYPE)
+    return t1;
+
   return c_common_type (t1, t2);
 }
 \f
@@ -696,10 +710,6 @@ comptypes (tree type1, tree type2)
   switch (TREE_CODE (t1))
     {
     case POINTER_TYPE:
-      /* We must give ObjC the first crack at comparing pointers, since
-          protocol qualifiers may be involved.  */
-      if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
-       break;
       /* Do not remove mode or aliasing information.  */
       if (TYPE_MODE (t1) != TYPE_MODE (t2)
          || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
@@ -751,13 +761,8 @@ comptypes (tree type1, tree type2)
         break;
       }
 
-    case RECORD_TYPE:
-      /* We are dealing with two distinct structs.  In assorted Objective-C
-        corner cases, however, these can still be deemed equivalent.  */
-      if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
-       val = 1;
-
     case ENUMERAL_TYPE:
+    case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
        val = tagged_types_tu_compatible_p (t1, t2);
@@ -775,22 +780,14 @@ comptypes (tree type1, tree type2)
 }
 
 /* Return 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  REFLEXIVE is only used by ObjC - set it
-   to 1 or 0 depending if the check of the pointer types is meant to
-   be reflexive or not (typically, assignments are not reflexive,
-   while comparisons are reflexive).
-*/
+   ignoring their qualifiers.  */
 
 static int
-comp_target_types (tree ttl, tree ttr, int reflexive)
+comp_target_types (tree ttl, tree ttr)
 {
   int val;
   tree mvl, mvr;
 
-  /* Give objc_comptypes a crack at letting these types through.  */
-  if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
-    return val;
-
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
   mvl = TREE_TYPE (ttl);
@@ -1248,109 +1245,130 @@ decl_constant_value (tree decl)
 static tree
 decl_constant_value_for_broken_optimization (tree decl)
 {
+  tree ret;
+
   if (pedantic || DECL_MODE (decl) == BLKmode)
     return decl;
-  else
-    return decl_constant_value (decl);
-}
-
 
-/* Perform the default conversion of arrays and functions to pointers.
-   Return the result of converting EXP.  For any other expression, just
-   return EXP.  */
+  ret = decl_constant_value (decl);
+  /* Avoid unwanted tree sharing between the initializer and current
+     function's body where the tree can be modified e.g. by the
+     gimplifier.  */
+  if (ret != decl && TREE_STATIC (decl))
+    ret = unshare_expr (ret);
+  return ret;
+}
 
+/* Convert the array expression EXP to a pointer.  */
 static tree
-default_function_array_conversion (tree exp)
+array_to_pointer_conversion (tree exp)
 {
-  tree orig_exp;
+  tree orig_exp = exp;
   tree type = TREE_TYPE (exp);
-  enum tree_code code = TREE_CODE (type);
-  int not_lvalue = 0;
+  tree adr;
+  tree restype = TREE_TYPE (type);
+  tree ptrtype;
 
-  /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
-     an lvalue.
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
 
-     Do not use STRIP_NOPS here!  It will remove conversions from pointer
-     to integer and cause infinite recursion.  */
-  orig_exp = exp;
-  while (TREE_CODE (exp) == NON_LVALUE_EXPR
-        || (TREE_CODE (exp) == NOP_EXPR
-            && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
-    {
-      if (TREE_CODE (exp) == NON_LVALUE_EXPR)
-       not_lvalue = 1;
-      exp = TREE_OPERAND (exp, 0);
-    }
+  STRIP_TYPE_NOPS (exp);
 
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  if (code == FUNCTION_TYPE)
+  ptrtype = build_pointer_type (restype);
+
+  if (TREE_CODE (exp) == INDIRECT_REF)
+    return convert (ptrtype, TREE_OPERAND (exp, 0));
+
+  if (TREE_CODE (exp) == VAR_DECL)
     {
-      return build_unary_op (ADDR_EXPR, exp, 0);
+      /* 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_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
+      return adr;
     }
-  if (code == ARRAY_TYPE)
-    {
-      tree adr;
-      tree restype = TREE_TYPE (type);
-      tree ptrtype;
-      int constp = 0;
-      int volatilep = 0;
-      int lvalue_array_p;
 
-      if (REFERENCE_CLASS_P (exp) || DECL_P (exp))
-       {
-         constp = TREE_READONLY (exp);
-         volatilep = TREE_THIS_VOLATILE (exp);
-       }
+  /* This way is better for a COMPONENT_REF since it can
+     simplify the offset for a component.  */
+  adr = build_unary_op (ADDR_EXPR, exp, 1);
+  return convert (ptrtype, adr);
+}
 
-      if (TYPE_QUALS (type) || constp || volatilep)
-       restype
-         = c_build_qualified_type (restype,
-                                   TYPE_QUALS (type)
-                                   | (constp * TYPE_QUAL_CONST)
-                                   | (volatilep * TYPE_QUAL_VOLATILE));
+/* Convert the function expression EXP to a pointer.  */
+static tree
+function_to_pointer_conversion (tree exp)
+{
+  tree orig_exp = exp;
 
-      if (TREE_CODE (exp) == INDIRECT_REF)
-       return convert (build_pointer_type (restype),
-                       TREE_OPERAND (exp, 0));
+  gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
 
-      if (TREE_CODE (exp) == COMPOUND_EXPR)
-       {
-         tree op1 = default_conversion (TREE_OPERAND (exp, 1));
-         return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
-                        TREE_OPERAND (exp, 0), op1);
-       }
+  STRIP_TYPE_NOPS (exp);
 
-      lvalue_array_p = !not_lvalue && lvalue_p (exp);
-      if (!flag_isoc99 && !lvalue_array_p)
-       {
-         /* Before C99, non-lvalue arrays do not decay to pointers.
-            Normally, using such an array would be invalid; but it can
-            be used correctly inside sizeof or as a statement expression.
-            Thus, do not give an error here; an error will result later.  */
-         return exp;
-       }
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
 
-      ptrtype = build_pointer_type (restype);
+  return build_unary_op (ADDR_EXPR, exp, 0);
+}
 
-      if (TREE_CODE (exp) == VAR_DECL)
-       {
-         /* 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_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
-         return adr;
-       }
-      /* This way is better for a COMPONENT_REF since it can
-        simplify the offset for a component.  */
-      adr = build_unary_op (ADDR_EXPR, exp, 1);
-      return convert (ptrtype, adr);
+/* Perform the default conversion of arrays and functions to pointers.
+   Return the result of converting EXP.  For any other expression, just
+   return EXP after removing NOPs.  */
+
+struct c_expr
+default_function_array_conversion (struct c_expr exp)
+{
+  tree orig_exp = exp.value;
+  tree type = TREE_TYPE (exp.value);
+  enum tree_code code = TREE_CODE (type);
+
+  switch (code)
+    {
+    case ARRAY_TYPE:
+      {
+       bool not_lvalue = false;
+       bool lvalue_array_p;
+
+       while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
+               || TREE_CODE (exp.value) == NOP_EXPR)
+              && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
+         {
+           if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
+             not_lvalue = true;
+           exp.value = TREE_OPERAND (exp.value, 0);
+         }
+
+       if (TREE_NO_WARNING (orig_exp))
+         TREE_NO_WARNING (exp.value) = 1;
+
+       lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
+       if (!flag_isoc99 && !lvalue_array_p)
+         {
+           /* Before C99, non-lvalue arrays do not decay to pointers.
+              Normally, using such an array would be invalid; but it can
+              be used correctly inside sizeof or as a statement expression.
+              Thus, do not give an error here; an error will result later.  */
+           return exp;
+         }
+
+       exp.value = array_to_pointer_conversion (exp.value);
+      }
+      break;
+    case FUNCTION_TYPE:
+      exp.value = function_to_pointer_conversion (exp.value);
+      break;
+    default:
+      STRIP_TYPE_NOPS (exp.value);
+      if (TREE_NO_WARNING (orig_exp))
+       TREE_NO_WARNING (exp.value) = 1;
+      break;
     }
+
   return exp;
 }
 
@@ -1404,8 +1422,7 @@ perform_integral_promotions (tree exp)
 
 
 /* Perform default promotions for C data used in expressions.
-   Arrays and functions are converted to pointers;
-   enumeral types or short or char, to int.
+   Enumeral types or short or char are converted to int.
    In addition, manifest constants symbols are replaced by their values.  */
 
 tree
@@ -1415,8 +1432,10 @@ default_conversion (tree exp)
   tree type = TREE_TYPE (exp);
   enum tree_code code = TREE_CODE (type);
 
-  if (code == FUNCTION_TYPE || code == ARRAY_TYPE)
-    return default_function_array_conversion (exp);
+  /* Functions and arrays have been converted during parsing.  */
+  gcc_assert (code != FUNCTION_TYPE);
+  if (code == ARRAY_TYPE)
+    return exp;
 
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
@@ -1632,12 +1651,9 @@ build_indirect_ref (tree ptr, const char *errorstring)
       else
        {
          tree t = TREE_TYPE (type);
-         tree mvt = t;
          tree ref;
 
-         if (TREE_CODE (mvt) != ARRAY_TYPE)
-           mvt = TYPE_MAIN_VARIANT (mvt);
-         ref = build1 (INDIRECT_REF, mvt, pointer);
+         ref = build1 (INDIRECT_REF, t, pointer);
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
@@ -1645,7 +1661,7 @@ build_indirect_ref (tree ptr, const char *errorstring)
              return error_mark_node;
            }
          if (VOID_TYPE_P (t) && skip_evaluation == 0)
-           warning ("dereferencing %<void *%> pointer");
+           warning (0, "dereferencing %<void *%> pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
             so that we get the proper error message if the result is used
@@ -1718,9 +1734,9 @@ build_array_ref (tree array, tree index)
      deliberately.  ??? Existing practice has also been to warn only
      when the char index is syntactically the index, not for
      char[array].  */
-  if (warn_char_subscripts && !swapped
+  if (!swapped
       && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-    warning ("array subscript has type %<char%>");
+    warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
 
   /* Apply default promotions *after* noticing character types.  */
   index = default_conversion (index);
@@ -1978,19 +1994,23 @@ build_function_call (tree function, tree params)
   /* Convert anything with function type to a pointer-to-function.  */
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      name = DECL_NAME (function);
+      /* Implement type-directed function overloading for builtins.
+        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+        handle all the type checking.  The result is a complete expression
+        that implements this function call.  */
+      tem = resolve_overloaded_builtin (function, params);
+      if (tem)
+       return tem;
 
-      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
-        (because calling an inline function does not mean the function
-        needs to be separately compiled).  */
-      fntype = build_type_variant (TREE_TYPE (function),
-                                  TREE_READONLY (function),
-                                  TREE_THIS_VOLATILE (function));
+      name = DECL_NAME (function);
       fundecl = function;
-      function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
     }
-  else
-    function = default_conversion (function);
+  if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
+    function = function_to_pointer_conversion (function);
+
+  /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
+     expressions, like those used for ObjC messenger dispatches.  */
+  function = objc_rewrite_function_call (function, params);
 
   fntype = TREE_TYPE (function);
 
@@ -2014,13 +2034,8 @@ build_function_call (tree function, tree params)
      If it is not, replace the call by a trap, wrapped up in a compound
      expression if necessary.  This has the nice side-effect to prevent
      the tree-inliner from generating invalid assignment trees which may
-     blow up in the RTL expander later.
-
-     ??? This doesn't work for Objective-C because objc_comptypes
-     refuses to compare function prototypes, yet the compiler appears
-     to build calls that are flagged as invalid by C's comptypes.  */
-  if (!c_dialect_objc ()
-      && TREE_CODE (function) == NOP_EXPR
+     blow up in the RTL expander later.  */
+  if (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)))
@@ -2032,7 +2047,7 @@ build_function_call (tree function, tree params)
       /* This situation leads to run-time undefined behavior.  We can't,
         therefore, simply error unless we can prove that all possible
         executions of the program must execute the code.  */
-      warning ("function called through a non-compatible type");
+      warning (0, "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.  */
@@ -2046,10 +2061,9 @@ build_function_call (tree function, tree params)
 
          if (AGGREGATE_TYPE_P (return_type))
            rhs = build_compound_literal (return_type,
-                                         build_constructor (return_type,
-                                                            NULL_TREE));
+                                         build_constructor (return_type, 0));
          else
-           rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node));
+           rhs = fold_build1 (NOP_EXPR, return_type, integer_zero_node);
 
          return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
@@ -2066,7 +2080,8 @@ build_function_call (tree function, tree params)
 
   /* Check that the arguments to the function are valid.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+                           TYPE_ARG_TYPES (fntype));
 
   result = build3 (CALL_EXPR, TREE_TYPE (fntype),
                   function, coerced_params, NULL_TREE);
@@ -2153,8 +2168,6 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
 
       STRIP_TYPE_NOPS (val);
 
-      val = default_function_array_conversion (val);
-
       val = require_complete_type (val);
 
       if (type != 0)
@@ -2177,32 +2190,32 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-                   warning ("passing argument %d of %qE as integer "
+                   warning (0, "passing argument %d of %qE as integer "
                             "rather than floating due to prototype",
                             argnum, rname);
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-                   warning ("passing argument %d of %qE as integer "
+                   warning (0, "passing argument %d of %qE as integer "
                             "rather than complex due to prototype",
                             argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
-                   warning ("passing argument %d of %qE as complex "
+                   warning (0, "passing argument %d of %qE as complex "
                             "rather than floating due to prototype",
                             argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-                   warning ("passing argument %d of %qE as floating "
+                   warning (0, "passing argument %d of %qE as floating "
                             "rather than integer due to prototype",
                             argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && INTEGRAL_TYPE_P (TREE_TYPE (val)))
-                   warning ("passing argument %d of %qE as complex "
+                   warning (0, "passing argument %d of %qE as complex "
                             "rather than integer due to prototype",
                             argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
-                   warning ("passing argument %d of %qE as floating "
+                   warning (0, "passing argument %d of %qE as floating "
                             "rather than complex due to prototype",
                             argnum, rname);
                  /* ??? At some point, messages should be written about
@@ -2214,7 +2227,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
                      if (formal_prec == TYPE_PRECISION (float_type_node))
-                       warning ("passing argument %d of %qE as %<float%> "
+                       warning (0, "passing argument %d of %qE as %<float%> "
                                 "rather than %<double%> due to prototype",
                                 argnum, rname);
                    }
@@ -2234,8 +2247,9 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warning ("passing argument %d of %qE with different "
-                                "width due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "with different width due to prototype",
+                                argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
@@ -2256,11 +2270,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warning ("passing argument %d of %qE as unsigned "
-                                "due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "as unsigned due to prototype",
+                                argnum, rname);
                      else
-                       warning ("passing argument %d of %qE as signed "
-                                "due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "as signed due to prototype", argnum, rname);
                    }
                }
 
@@ -2303,11 +2318,27 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
   return nreverse (result);
 }
 \f
-/* This is the entry point used by the parser
-   for binary operators in the input.
-   In addition to constructing the expression,
-   we check for operands that were written with other binary operators
-   in a way that is likely to confuse the user.  */
+/* This is the entry point used by the parser to build unary operators
+   in the input.  CODE, a tree_code, specifies the unary operator, and
+   ARG is the operand.  For unary plus, the C parser currently uses
+   CONVERT_EXPR for code.  */
+
+struct c_expr
+parser_build_unary_op (enum tree_code code, struct c_expr arg)
+{
+  struct c_expr result;
+
+  result.original_code = ERROR_MARK;
+  result.value = build_unary_op (code, arg.value, 0);
+  overflow_warning (result.value);
+  return result;
+}
+
+/* This is the entry point used by the parser to build binary operators
+   in the input.  CODE, a tree_code, specifies the binary operator, and
+   ARG1 and ARG2 are the operands.  In addition to constructing the
+   expression, we check for operands that were written with other binary
+   operators in a way that is likely to confuse the user.  */
 
 struct c_expr
 parser_build_binary_op (enum tree_code code, struct c_expr arg1,
@@ -2332,14 +2363,14 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
        {
          if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning ("suggest parentheses around + or - inside shift");
+           warning (0, "suggest parentheses around + or - inside shift");
        }
 
       if (code == TRUTH_ORIF_EXPR)
        {
          if (code1 == TRUTH_ANDIF_EXPR
              || code2 == TRUTH_ANDIF_EXPR)
-           warning ("suggest parentheses around && within ||");
+           warning (0, "suggest parentheses around && within ||");
        }
 
       if (code == BIT_IOR_EXPR)
@@ -2348,11 +2379,11 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning ("suggest parentheses around arithmetic in operand of |");
+           warning (0, "suggest parentheses around arithmetic in operand of |");
          /* Check cases like x|y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning ("suggest parentheses around comparison in operand of |");
+           warning (0, "suggest parentheses around comparison in operand of |");
        }
 
       if (code == BIT_XOR_EXPR)
@@ -2361,28 +2392,28 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == BIT_AND_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning ("suggest parentheses around arithmetic in operand of ^");
+           warning (0, "suggest parentheses around arithmetic in operand of ^");
          /* Check cases like x^y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning ("suggest parentheses around comparison in operand of ^");
+           warning (0, "suggest parentheses around comparison in operand of ^");
        }
 
       if (code == BIT_AND_EXPR)
        {
          if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning ("suggest parentheses around + or - in operand of &");
+           warning (0, "suggest parentheses around + or - in operand of &");
          /* Check cases like x&y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning ("suggest parentheses around comparison in operand of &");
+           warning (0, "suggest parentheses around comparison in operand of &");
        }
       /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
       if (TREE_CODE_CLASS (code) == tcc_comparison
          && (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison))
-       warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
+       warning (0, "comparisons like X<=Y<=Z do not have their mathematical meaning");
 
     }
 
@@ -2462,7 +2493,7 @@ pointer_diff (tree op0, tree op1)
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)));
+  return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -2483,12 +2514,20 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
   enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
   tree val;
   int noconvert = flag;
+  const char *invalid_op_diag;
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
   if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
     typecode = INTEGER_TYPE;
 
+  if ((invalid_op_diag
+       = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
+    {
+      error (invalid_op_diag);
+      return error_mark_node;
+    }
+
   switch (code)
     {
     case CONVERT_EXPR:
@@ -2563,13 +2602,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case TRUTH_NOT_EXPR:
-      /* ??? Why do most validation here but that for non-lvalue arrays
-        in c_objc_common_truthvalue_conversion?  */
       if (typecode != INTEGER_TYPE
          && typecode != REAL_TYPE && typecode != POINTER_TYPE
-         && typecode != COMPLEX_TYPE
-         /* These will convert to a pointer.  */
-         && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
+         && typecode != COMPLEX_TYPE)
        {
          error ("wrong type argument to unary exclamation mark");
          return error_mark_node;
@@ -2584,7 +2619,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        return arg;
 
@@ -2592,7 +2627,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        return convert (TREE_TYPE (arg), integer_zero_node);
 
@@ -2708,9 +2743,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       /* For &x[y], return x+y */
       if (TREE_CODE (arg) == ARRAY_REF)
        {
-         if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
+         tree op0 = TREE_OPERAND (arg, 0);
+         if (!c_mark_addressable (op0))
            return error_mark_node;
-         return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
+         return build_binary_op (PLUS_EXPR,
+                                 (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
+                                  ? array_to_pointer_conversion (op0)
+                                  : op0),
                                  TREE_OPERAND (arg, 1), 1);
        }
 
@@ -2750,9 +2789,6 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
       val = build1 (ADDR_EXPR, argtype, arg);
 
-      if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
-       TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
-
       return val;
 
     default:
@@ -2819,20 +2855,20 @@ readonly_error (tree arg, enum lvalue_use use)
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
        readonly_error (TREE_OPERAND (arg, 0), use);
       else
-       error (READONLY_MSG (N_("assignment of read-only member %qD"),
-                            N_("increment of read-only member %qD"),
-                            N_("decrement of read-only member %qD")),
+       error (READONLY_MSG (G_("assignment of read-only member %qD"),
+                            G_("increment of read-only member %qD"),
+                            G_("decrement of read-only member %qD")),
               TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (N_("assignment of read-only variable %qD"),
-                        N_("increment of read-only variable %qD"),
-                        N_("decrement of read-only variable %qD")),
+    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
+                        G_("increment of read-only variable %qD"),
+                        G_("decrement of read-only variable %qD")),
           arg);
   else
-    error (READONLY_MSG (N_("assignment of read-only location"),
-                        N_("increment of read-only location"),
-                        N_("decrement of read-only location")));
+    error (READONLY_MSG (G_("assignment of read-only location"),
+                        G_("increment of read-only location"),
+                        G_("decrement of read-only location")));
 }
 
 
@@ -2995,7 +3031,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
                       || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
                /* OK */;
              else
-               warning ("signed and unsigned type in conditional expression");
+               warning (0, "signed and unsigned type in conditional expression");
            }
        }
     }
@@ -3007,7 +3043,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))
+      if (comp_target_types (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)
@@ -3080,10 +3116,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   if (result_type != TREE_TYPE (op2))
     op2 = convert_and_check (result_type, op2);
 
-  if (TREE_CODE (ifexp) == INTEGER_CST)
-    return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
-
-  return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2));
+  return fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
 }
 \f
 /* Return a compound expression that performs two expressions and
@@ -3092,18 +3125,23 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
 tree
 build_compound_expr (tree expr1, tree expr2)
 {
-  /* Convert arrays and functions to pointers.  */
-  expr2 = default_function_array_conversion (expr2);
-
   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 (expr1) == CONVERT_EXPR
-                && VOID_TYPE_P (TREE_TYPE (expr1))))
-        warning ("left-hand operand of comma expression has no effect");
+      if (warn_unused_value)
+       {
+         if (VOID_TYPE_P (TREE_TYPE (expr1))
+             && TREE_CODE (expr1) == CONVERT_EXPR)
+           ; /* (void) a, b */
+         else if (VOID_TYPE_P (TREE_TYPE (expr1))
+                  && TREE_CODE (expr1) == COMPOUND_EXPR
+                  && TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR)
+           ; /* (void) a, (void) b, c */
+         else
+           warning (0, "left-hand operand of comma expression has no effect");
+       }
     }
 
   /* With -Wunused, we should also warn if the left-hand operand does have
@@ -3158,7 +3196,6 @@ build_c_cast (tree type, tree expr)
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
-      value = default_function_array_conversion (value);
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
@@ -3172,8 +3209,7 @@ build_c_cast (tree type, tree expr)
          if (pedantic)
            pedwarn ("ISO C forbids casts to union type");
          t = digest_init (type,
-                          build_constructor (type,
-                                             build_tree_list (field, value)),
+                          build_constructor_single (type, field, value),
                           true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          TREE_INVARIANT (t) = TREE_INVARIANT (value);
@@ -3186,14 +3222,9 @@ build_c_cast (tree type, tree expr)
     {
       tree otype, ovalue;
 
-      /* If casting to void, avoid the error that would come
-        from default_conversion in the case of a non-lvalue array.  */
       if (type == void_type_node)
        return build1 (CONVERT_EXPR, type, value);
 
-      /* Convert functions and arrays to pointers,
-        but don't convert any other types.  */
-      value = default_function_array_conversion (value);
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
@@ -3230,16 +3261,16 @@ build_c_cast (tree type, tree expr)
                 && TREE_CODE (in_otype) == POINTER_TYPE);
 
          if (added)
-           warning ("cast adds new qualifiers to function type");
+           warning (0, "cast adds new qualifiers to function type");
 
          if (discarded)
            /* There are qualifiers present in IN_OTYPE that are not
               present in IN_TYPE.  */
-           warning ("cast discards qualifiers from pointer target type");
+           warning (0, "cast discards qualifiers from pointer target type");
        }
 
       /* Warn about possible alignment problems.  */
-      if (STRICT_ALIGNMENT && warn_cast_align
+      if (STRICT_ALIGNMENT
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
@@ -3250,48 +3281,54 @@ build_c_cast (tree type, tree expr)
                || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
               && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
          && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
-       warning ("cast increases required alignment of target type");
+       warning (OPT_Wcast_align,
+                "cast increases required alignment of target type");
 
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
          && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
          && !TREE_CONSTANT (value))
-       warning ("cast from pointer to integer of different size");
+       warning (OPT_Wpointer_to_int_cast,
+                "cast from pointer to integer of different size");
 
-      if (warn_bad_function_cast
-         && TREE_CODE (value) == CALL_EXPR
+      if (TREE_CODE (value) == CALL_EXPR
          && TREE_CODE (type) != TREE_CODE (otype))
-       warning ("cast from function call of type %qT to non-matching "
-                "type %qT", otype, type);
+       warning (OPT_Wbad_function_cast, "cast from function call of type %qT "
+                "to non-matching type %qT", otype, type);
 
       if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
          && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
          /* Don't warn about converting any constant.  */
          && !TREE_CONSTANT (value))
-       warning ("cast to pointer from integer of different size");
+       warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
+                "of different size");
 
-      if (TREE_CODE (type) == POINTER_TYPE
+      if (flag_strict_aliasing && warn_strict_aliasing
+         && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (expr) == ADDR_EXPR
-         && DECL_P (TREE_OPERAND (expr, 0))
-         && flag_strict_aliasing && warn_strict_aliasing
+         && (DECL_P (TREE_OPERAND (expr, 0))
+             || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
          && !VOID_TYPE_P (TREE_TYPE (type)))
        {
-         /* Casting the address of a decl to non void pointer. Warn
+         /* Casting the address of an object to non void pointer. Warn
             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");
+           warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+                    "might 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");
+               warning (OPT_Wstrict_aliasing, "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");
+               warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+                        "pointer might break strict-aliasing rules");
            }
        }
 
@@ -3320,17 +3357,16 @@ build_c_cast (tree type, tree expr)
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         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);
+         /* If OVALUE had overflow set, then so will VALUE, so it
+            is safe to overwrite.  */
+         if (CONSTANT_CLASS_P (ovalue))
+           {
+             TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+             /* Similarly, constant_overflow cannot have become cleared.  */
+             TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+           }
          else
            TREE_OVERFLOW (value) = 0;
-         
-         if (CONSTANT_CLASS_P (ovalue))
-           /* Similarly, constant_overflow cannot have become
-              cleared.  */
-           TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
        }
     }
 
@@ -3431,6 +3467,14 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
+  /* Emit ObjC write barrier, if necessary.  */
+  if (c_dialect_objc () && flag_objc_gc)
+    {
+      result = objc_generate_write_barrier (lhs, modifycode, newrhs);
+      if (result)
+       return result;
+    }
+
   /* Scan operands.  */
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
@@ -3466,6 +3510,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   tree rhstype;
   enum tree_code coder;
   tree rname = NULL_TREE;
+  bool objc_ok = false;
 
   if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
     {
@@ -3497,7 +3542,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
        pedwarn (AR, parmnum, rname);           \
        break;                                  \
       case ic_argpass_nonproto:                        \
-       warning (AR, parmnum, rname);           \
+       warning (0, AR, parmnum, rname);                \
        break;                                  \
       case ic_assign:                          \
        pedwarn (AS);                           \
@@ -3515,10 +3560,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
   STRIP_TYPE_NOPS (rhs);
 
-  if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
-      || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
-    rhs = default_conversion (rhs);
-  else if (optimize && TREE_CODE (rhs) == VAR_DECL)
+  if (optimize && TREE_CODE (rhs) == VAR_DECL
+          && TREE_CODE (TREE_TYPE (rhs)) != ARRAY_TYPE)
     rhs = decl_constant_value_for_broken_optimization (rhs);
 
   rhstype = TREE_TYPE (rhs);
@@ -3527,14 +3570,35 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   if (coder == ERROR_MARK)
     return error_mark_node;
 
+  if (c_dialect_objc ())
+    {
+      int parmno;
+
+      switch (errtype)
+       {
+       case ic_return:
+         parmno = 0;
+         break;
+
+       case ic_assign:
+         parmno = -1;
+         break;
+
+       case ic_init:
+         parmno = -2;
+         break;
+
+       default:
+         parmno = parmnum;
+         break;
+       }
+
+      objc_ok = objc_compare_types (type, rhstype, parmno, rname);
+    }
+
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     {
       overflow_warning (rhs);
-      /* Check for Objective-C protocols.  This will automatically
-        issue a warning if there are protocol violations.  No need to
-        use the return value.  */
-      if (c_dialect_objc ())
-       objc_comptypes (type, rhstype, 0);
       return rhs;
     }
 
@@ -3617,7 +3681,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                 Meanwhile, the lhs target must have all the qualifiers of
                 the rhs.  */
              if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-                 || comp_target_types (memb_type, rhstype, 0))
+                 || comp_target_types (memb_type, rhstype))
                {
                  /* If this type won't generate any warnings, use it.  */
                  if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
@@ -3665,26 +3729,26 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-                   WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE "
+                   WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE "
                                            "makes qualified function "
                                            "pointer from unqualified"),
-                                        N_("assignment makes qualified "
+                                        G_("assignment makes qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        N_("initialization makes qualified "
+                                        G_("initialization makes qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        N_("return makes qualified function "
+                                        G_("return makes qualified function "
                                            "pointer from unqualified"));
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+               WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
-                                    N_("assignment discards qualifiers "
+                                    G_("assignment discards qualifiers "
                                        "from pointer target type"),
-                                    N_("initialization discards qualifiers "
+                                    G_("initialization discards qualifiers "
                                        "from pointer target type"),
-                                    N_("return discards qualifiers from "
+                                    G_("return discards qualifiers from "
                                        "pointer target type"));
            }
 
@@ -3715,12 +3779,72 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                            || targetm.vector_opaque_p (rhstype))
         && TREE_CODE (ttl) == VECTOR_TYPE
         && TREE_CODE (ttr) == VECTOR_TYPE;
+      
+      /* C++ does not allow the implicit conversion void* -> T*.  However,
+         for the purpose of reducing the number of false positives, we
+         tolerate the special case of
+
+                int *p = NULL;
+
+         where NULL is typically defined in C to be '(void *) 0'.  */
+      if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
+        warning (OPT_Wc___compat, "request for implicit conversion from "
+                 "%qT to %qT not permitted in C++", rhstype, type);
 
+      /* Check if the right-hand side has a format attribute but the
+        left-hand side doesn't.  */
+      if (warn_missing_format_attribute)
+        {
+         tree rattrs = TYPE_ATTRIBUTES (ttr), ra;
+         for (ra = rattrs; ra; ra = TREE_CHAIN (ra))
+           {
+             if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+               break;
+           }
+         if (ra)
+           {
+             tree lattrs = TYPE_ATTRIBUTES (ttl), la;
+             for (la = lattrs; la; la = TREE_CHAIN (la))
+             {
+               if (is_attribute_p ("format", TREE_PURPOSE (la)))
+                 break;
+             }
+             if (!la)
+               switch (errtype)
+                 {
+                 case ic_argpass:
+                 case ic_argpass_nonproto:
+                   warning (OPT_Wmissing_format_attribute,
+                            "argument %d of %qE might be "
+                            "a candidate for a format attribute",
+                            parmnum, rname);
+                   break;
+                 case ic_assign:
+                   warning (OPT_Wmissing_format_attribute,
+                            "assignment left-hand side might be "
+                            "a candidate for a format attribute");
+                   break;
+                 case ic_init:
+                   warning (OPT_Wmissing_format_attribute,
+                            "initialization left-hand side might be "
+                            "a candidate for a format attribute");
+                   break;
+                 case ic_return:
+                   warning (OPT_Wmissing_format_attribute,
+                            "return type might be "
+                            "a candidate for a format attribute");
+                   break;
+                 default:
+                   gcc_unreachable ();
+                 }
+           }
+       }
+      
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-         || (target_cmp = comp_target_types (type, rhstype, 0))
+         || (target_cmp = comp_target_types (type, rhstype))
          || is_opaque_pointer
          || (c_common_unsigned_type (mvl)
              == c_common_unsigned_type (mvr)))
@@ -3733,14 +3857,14 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                      which are not ANSI null ptr constants.  */
                   && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of "
+           WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                                    "and %<void *%>"),
-                                N_("ISO C forbids assignment between "
+                                G_("ISO C forbids assignment between "
                                    "function pointer and %<void *%>"),
-                                N_("ISO C forbids initialization between "
+                                G_("ISO C forbids initialization between "
                                    "function pointer and %<void *%>"),
-                                N_("ISO C forbids return between function "
+                                G_("ISO C forbids return between function "
                                    "pointer and %<void *%>"));
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
@@ -3748,14 +3872,20 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
-                                       "qualifiers from pointer target type"),
-                                    N_("assignment discards qualifiers "
-                                       "from pointer target type"),
-                                    N_("initialization discards qualifiers "
-                                       "from pointer target type"),
-                                    N_("return discards qualifiers from "
-                                       "pointer target type"));
+               {
+                 /* Types differing only by the presence of the 'volatile'
+                    qualifier are acceptable if the 'volatile' has been added
+                    in by the Objective-C EH machinery.  */
+                 if (!objc_type_quals_match (ttl, ttr))
+                   WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
+                                           "qualifiers from pointer target type"),
+                                        G_("assignment discards qualifiers "
+                                           "from pointer target type"),
+                                        G_("initialization discards qualifiers "
+                                           "from pointer target type"),
+                                        G_("return discards qualifiers from "
+                                           "pointer target type"));
+               }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
@@ -3763,13 +3893,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                ;
              /* If there is a mismatch, do warn.  */
              else if (warn_pointer_sign)
-               WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument "
+               WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument "
                                        "%d of %qE differ in signedness"),
-                                    N_("pointer targets in assignment "
+                                    G_("pointer targets in assignment "
                                        "differ in signedness"),
-                                    N_("pointer targets in initialization "
+                                    G_("pointer targets in initialization "
                                        "differ in signedness"),
-                                    N_("pointer targets in return differ "
+                                    G_("pointer targets in return differ "
                                        "in signedness"));
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
@@ -3780,24 +3910,27 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+               WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
                                        "from unqualified"),
-                                    N_("assignment makes qualified function "
+                                    G_("assignment makes qualified function "
                                        "pointer from unqualified"),
-                                    N_("initialization makes qualified "
+                                    G_("initialization makes qualified "
                                        "function pointer from unqualified"),
-                                    N_("return makes qualified function "
+                                    G_("return makes qualified function "
                                        "pointer from unqualified"));
            }
        }
       else
-       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from "
-                               "incompatible pointer type"),
-                            N_("assignment from incompatible pointer type"),
-                            N_("initialization from incompatible "
-                               "pointer type"),
-                            N_("return from incompatible pointer type"));
+       /* Avoid warning about the volatile ObjC EH puts on decls.  */
+       if (!objc_ok)
+         WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from "
+                                 "incompatible pointer type"),
+                              G_("assignment from incompatible pointer type"),
+                              G_("initialization from incompatible "
+                                 "pointer type"),
+                              G_("return from incompatible pointer type"));
+
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
@@ -3818,26 +3951,26 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
            && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
            && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
            && integer_zerop (TREE_OPERAND (rhs, 0))))
-       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+       WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
-                            N_("assignment makes pointer from integer "
+                            G_("assignment makes pointer from integer "
                                "without a cast"),
-                            N_("initialization makes pointer from "
+                            G_("initialization makes pointer from "
                                "integer without a cast"),
-                            N_("return makes pointer from integer "
+                            G_("return makes pointer from integer "
                                "without a cast"));
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer "
+      WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer "
                              "from pointer without a cast"),
-                          N_("assignment makes integer from pointer "
+                          G_("assignment makes integer from pointer "
                              "without a cast"),
-                          N_("initialization makes integer from pointer "
+                          G_("initialization makes integer from pointer "
                              "without a cast"),
-                          N_("return makes integer from pointer "
+                          G_("return makes integer from pointer "
                              "without a cast"));
       return convert (type, rhs);
     }
@@ -3938,9 +4071,10 @@ store_init_value (tree decl, tree init)
 
   /* Store the expression if valid; else report error.  */
 
-  if (warn_traditional && !in_system_header
+  if (!in_system_header
       && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
-    warning ("traditional C rejects automatic aggregate initialization");
+    warning (OPT_Wtraditional, "traditional C rejects automatic "
+            "aggregate initialization");
 
   DECL_INITIAL (decl) = value;
 
@@ -4134,10 +4268,10 @@ warning_init (const char *msgid)
 {
   char *ofwhat;
 
-  warning ("%s", _(msgid));
+  warning (0, "%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    warning ("(near initialization for %qs)", ofwhat);
+    warning (0, "(near initialization for %qs)", ofwhat);
 }
 \f
 /* If TYPE is an array type and EXPR is a parenthesized string
@@ -4261,18 +4395,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
       if (TREE_CODE (inside_init) == CONSTRUCTOR)
        {
-         tree link;
+         unsigned HOST_WIDE_INT ix;
+         tree value;
+         bool constant_p = true;
 
          /* Iterate through elements and check if all constructor
             elements are *_CSTs.  */
-         for (link = CONSTRUCTOR_ELTS (inside_init);
-              link;
-              link = TREE_CHAIN (link))
-           if (! CONSTANT_CLASS_P (TREE_VALUE (link)))
-             break;
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
+           if (!CONSTANT_CLASS_P (value))
+             {
+               constant_p = false;
+               break;
+             }
 
-         if (link == NULL)
-           return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+         if (constant_p)
+           return build_vector_from_ctor (type,
+                                          CONSTRUCTOR_ELTS (inside_init));
        }
     }
 
@@ -4289,22 +4427,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
          || (code == POINTER_TYPE
              && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-                           TREE_TYPE (type)))
-         || (code == POINTER_TYPE
-             && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
-             && comptypes (TREE_TYPE (inside_init),
                            TREE_TYPE (type)))))
     {
       if (code == POINTER_TYPE)
        {
-         inside_init = default_function_array_conversion (inside_init);
-
          if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
            {
-             error_init ("invalid use of non-lvalue array");
-             return error_mark_node;
+             if (TREE_CODE (inside_init) == STRING_CST
+                 || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+               inside_init = array_to_pointer_conversion (inside_init);
+             else
+               {
+                 error_init ("invalid use of non-lvalue array");
+                 return error_mark_node;
+               }
            }
-        }
+       }
 
       if (code == VECTOR_TYPE)
        /* Although the types are compatible, we may require a
@@ -4355,6 +4493,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
          inside_init = error_mark_node;
        }
 
+      /* Added to enable additional -Wmissing-format-attribute warnings.  */
+      if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
+       inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE,
+                                             NULL_TREE, 0);
       return inside_init;
     }
 
@@ -4364,9 +4506,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
       || 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
-        case where inside_init is a null pointer constant.  */
+      if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
+         && (TREE_CODE (init) == STRING_CST
+             || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
+       init = array_to_pointer_conversion (init);
       inside_init
        = convert_for_assignment (type, init, ic_init,
                                  NULL_TREE, NULL_TREE, 0);
@@ -4433,7 +4576,7 @@ static tree constructor_bit_index;
 /* If we are saving up the elements rather than allocating them,
    this is the list of elements so far (in reverse order,
    most recent first).  */
-static tree constructor_elements;
+static VEC(constructor_elt,gc) *constructor_elements;
 
 /* 1 if constructor should be incrementally stored into a constructor chain,
    0 if all the elements should be kept in AVL tree.  */
@@ -4504,7 +4647,7 @@ struct constructor_stack
   tree unfilled_index;
   tree unfilled_fields;
   tree bit_index;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct init_node *pending_elts;
   int offset;
   int depth;
@@ -4548,7 +4691,7 @@ struct initializer_stack
   tree decl;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct spelling *spelling;
   struct spelling *spelling_base;
   int spelling_size;
@@ -4772,19 +4915,27 @@ push_init_level (int implicit)
   tree value = NULL_TREE;
 
   /* If we've exhausted any levels that didn't have braces,
-     pop them now.  */
-  while (constructor_stack->implicit)
+     pop them now.  If implicit == 1, this will have been done in
+     process_init_element; do not repeat it here because in the case
+     of excess initializers for an empty aggregate this leads to an
+     infinite cycle of popping a level and immediately recreating
+     it.  */
+  if (implicit != 1)
     {
-      if ((TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-         && constructor_fields == 0)
-       process_init_element (pop_init_level (1));
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE
-              && constructor_max_index
-              && tree_int_cst_lt (constructor_max_index, constructor_index))
-       process_init_element (pop_init_level (1));
-      else
-       break;
+      while (constructor_stack->implicit)
+       {
+         if ((TREE_CODE (constructor_type) == RECORD_TYPE
+              || TREE_CODE (constructor_type) == UNION_TYPE)
+             && constructor_fields == 0)
+           process_init_element (pop_init_level (1));
+         else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+                  && constructor_max_index
+                  && tree_int_cst_lt (constructor_max_index,
+                                      constructor_index))
+           process_init_element (pop_init_level (1));
+         else
+           break;
+       }
     }
 
   /* Unless this is an explicit brace, we need to preserve previous
@@ -4875,7 +5026,7 @@ push_init_level (int implicit)
       constructor_constant = TREE_CONSTANT (value);
       constructor_simple = TREE_STATIC (value);
       constructor_elements = CONSTRUCTOR_ELTS (value);
-      if (constructor_elements
+      if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
        set_nonincremental_init ();
@@ -5008,7 +5159,7 @@ pop_init_level (int implicit)
 
          /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
-            Discard the initializer so that we do not abort later.  */
+            Discard the initializer so that we do not die later.  */
          if (TREE_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
@@ -5050,19 +5201,19 @@ pop_init_level (int implicit)
     {
       /* A nonincremental scalar initializer--just return
         the element, after verifying there is just one.  */
-      if (constructor_elements == 0)
+      if (VEC_empty (constructor_elt,constructor_elements))
        {
          if (!constructor_erroneous)
            error_init ("empty scalar initializer");
          ret.value = error_mark_node;
        }
-      else if (TREE_CHAIN (constructor_elements) != 0)
+      else if (VEC_length (constructor_elt,constructor_elements) != 1)
        {
          error_init ("extra elements in scalar initializer");
-         ret.value = TREE_VALUE (constructor_elements);
+         ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
        }
       else
-       ret.value = TREE_VALUE (constructor_elements);
+       ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
     }
   else
     {
@@ -5071,7 +5222,7 @@ pop_init_level (int implicit)
       else
        {
          ret.value = build_constructor (constructor_type,
-                                        nreverse (constructor_elements));
+                                        constructor_elements);
          if (constructor_constant)
            TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
@@ -5520,14 +5671,15 @@ add_pending_init (tree purpose, tree value)
 static void
 set_nonincremental_init (void)
 {
-  tree chain;
+  unsigned HOST_WIDE_INT ix;
+  tree index, value;
 
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != ARRAY_TYPE)
     return;
 
-  for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
-    add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+  FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
+    add_pending_init (index, value);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -5679,9 +5831,10 @@ find_init_member (tree field)
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     {
-      if (constructor_elements
-         && TREE_PURPOSE (constructor_elements) == field)
-       return TREE_VALUE (constructor_elements);
+      if (!VEC_empty (constructor_elt, constructor_elements)
+         && (VEC_last (constructor_elt, constructor_elements)->index
+             == field))
+       return VEC_last (constructor_elt, constructor_elements)->value;
     }
   return 0;
 }
@@ -5703,19 +5856,22 @@ static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
                     int pending)
 {
+  constructor_elt *celt;
+
   if (type == error_mark_node || value == error_mark_node)
     {
       constructor_erroneous = 1;
       return;
     }
-  if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
-      || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
-         && !(TREE_CODE (value) == STRING_CST
-              && TREE_CODE (type) == ARRAY_TYPE
-              && INTEGRAL_TYPE_P (TREE_TYPE (type)))
-         && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-                        TYPE_MAIN_VARIANT (type))))
-    value = default_conversion (value);
+  if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+      && (TREE_CODE (value) == STRING_CST
+         || TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
+      && !(TREE_CODE (value) == STRING_CST
+          && TREE_CODE (type) == ARRAY_TYPE
+          && INTEGRAL_TYPE_P (TREE_TYPE (type)))
+      && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
+                    TYPE_MAIN_VARIANT (type)))
+    value = array_to_pointer_conversion (value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
       && require_constant_value && !flag_isoc99 && pending)
@@ -5806,9 +5962,10 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
-          && constructor_elements)
+          && !VEC_empty (constructor_elt, constructor_elements))
     {
-      if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+      if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+                                      constructor_elements)->value))
        warning_init ("initialized field with side-effects overwritten");
 
       /* We can have just one union field set.  */
@@ -5818,10 +5975,9 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
   /* Otherwise, output this element either to
      constructor_elements or to the assembler file.  */
 
-  if (field && TREE_CODE (field) == INTEGER_CST)
-    field = copy_node (field);
-  constructor_elements
-    = tree_cons (field, value, constructor_elements);
+  celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
+  celt->index = field;
+  celt->value = value;
 
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6173,10 +6329,11 @@ process_init_element (struct c_expr value)
             again on the assumption that this must be conditional on
             __STDC__ anyway (and we've already complained about the
             member-designator already).  */
-         if (warn_traditional && !in_system_header && !constructor_designated
+         if (!in_system_header && !constructor_designated
              && !(value.value && (integer_zerop (value.value)
                                   || real_zerop (value.value))))
-           warning ("traditional C rejects initialization of unions");
+           warning (OPT_Wtraditional, "traditional C rejects initialization "
+                    "of unions");
 
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
@@ -6427,9 +6584,6 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       TREE_VALUE (tail) = output;
     }
 
-  /* Perform default conversions on array and function inputs.
-     Don't do this for other types as it would screw up operands
-     expected to be in memory.  */
   for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree input;
@@ -6437,8 +6591,6 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       input = TREE_VALUE (tail);
 
-      input = default_function_array_conversion (input);
-
       if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
                                  oconstraints, &allows_mem, &allows_reg))
        {
@@ -6486,15 +6638,33 @@ c_finish_goto_label (tree label)
       return NULL_TREE;
     }
 
+  if (C_DECL_UNJUMPABLE_VM (decl))
+    {
+      error ("jump into scope of identifier with variably modified type");
+      return NULL_TREE;
+    }
+
   if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl))
     {
       /* No jump from outside this statement expression context, so
         record that there is a jump from within this context.  */
       struct c_label_list *nlist;
       nlist = XOBNEW (&parser_obstack, struct c_label_list);
-      nlist->next = label_context_stack->labels_used;
+      nlist->next = label_context_stack_se->labels_used;
+      nlist->label = decl;
+      label_context_stack_se->labels_used = nlist;
+    }
+
+  if (!C_DECL_UNDEFINABLE_VM (decl))
+    {
+      /* No jump from outside this context context of identifiers with
+        variably modified type, so record that there is a jump from
+        within this context.  */
+      struct c_label_list *nlist;
+      nlist = XOBNEW (&parser_obstack, struct c_label_list);
+      nlist->next = label_context_stack_vm->labels_used;
       nlist->label = decl;
-      label_context_stack->labels_used = nlist;
+      label_context_stack_vm->labels_used = nlist;
     }
 
   TREE_USED (decl) = 1;
@@ -6521,7 +6691,7 @@ c_finish_return (tree retval)
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
 
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning ("function declared %<noreturn%> has a %<return%> statement");
+    warning (0, "function declared %<noreturn%> has a %<return%> statement");
 
   if (!retval)
     {
@@ -6592,7 +6762,7 @@ c_finish_return (tree retval)
                  && !DECL_EXTERNAL (inner)
                  && !TREE_STATIC (inner)
                  && DECL_CONTEXT (inner) == current_function_decl)
-               warning ("function returns address of local variable");
+               warning (0, "function returns address of local variable");
              break;
 
            default:
@@ -6628,6 +6798,11 @@ struct c_switch {
      appear.  */
   unsigned int blocked_stmt_expr;
 
+  /* Scope of outermost declarations of identifiers with variably
+     modified type within this switch statement; if nonzero, case and
+     default labels may not appear.  */
+  unsigned int blocked_vm;
+
   /* The next node on the stack.  */
   struct c_switch *next;
 };
@@ -6666,11 +6841,11 @@ c_start_case (tree exp)
        {
          type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
 
-         if (warn_traditional && !in_system_header
+         if (!in_system_header
              && (type == long_integer_type_node
                  || type == long_unsigned_type_node))
-           warning ("%<long%> switch expression not converted to "
-                    "%<int%> in ISO C");
+           warning (OPT_Wtraditional, "%<long%> switch expression not "
+                    "converted to %<int%> in ISO C");
 
          exp = default_conversion (exp);
          type = TREE_TYPE (exp);
@@ -6683,6 +6858,7 @@ c_start_case (tree exp)
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
   cs->blocked_stmt_expr = 0;
+  cs->blocked_vm = 0;
   cs->next = c_switch_stack;
   c_switch_stack = cs;
 
@@ -6696,7 +6872,8 @@ do_case (tree low_value, tree high_value)
 {
   tree label = NULL_TREE;
 
-  if (c_switch_stack && !c_switch_stack->blocked_stmt_expr)
+  if (c_switch_stack && !c_switch_stack->blocked_stmt_expr
+      && !c_switch_stack->blocked_vm)
     {
       label = c_add_case_label (c_switch_stack->cases,
                                SWITCH_COND (c_switch_stack->switch_expr),
@@ -6714,6 +6891,15 @@ do_case (tree low_value, tree high_value)
        error ("%<default%> label in statement expression not containing "
               "enclosing switch statement");
     }
+  else if (c_switch_stack && c_switch_stack->blocked_vm)
+    {
+      if (low_value)
+       error ("case label in scope of identifier with variably modified "
+              "type not containing enclosing switch statement");
+      else
+       error ("%<default%> label in scope of identifier with variably "
+              "modified type not containing enclosing switch statement");
+    }
   else if (low_value)
     error ("case label not within a switch statement");
   else
@@ -6728,13 +6914,23 @@ void
 c_finish_case (tree body)
 {
   struct c_switch *cs = c_switch_stack;
+  location_t switch_location;
 
   SWITCH_BODY (cs->switch_expr) = body;
 
+  /* We must not be within a statement expression nested in the switch
+     at this point; we might, however, be within the scope of an
+     identifier with variably modified type nested in the switch.  */
   gcc_assert (!cs->blocked_stmt_expr);
 
   /* Emit warnings as needed.  */
-  c_do_switch_expr_warnings (cs->cases, cs->switch_expr);
+  if (EXPR_HAS_LOCATION (cs->switch_expr))
+    switch_location = EXPR_LOCATION (cs->switch_expr);
+  else
+    switch_location = input_location;
+  c_do_switch_warnings (cs->cases, switch_location,
+                       TREE_TYPE (cs->switch_expr),
+                       SWITCH_COND (cs->switch_expr));
 
   /* Pop the stack.  */
   c_switch_stack = cs->next;
@@ -6783,7 +6979,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning ("%Hsuggest explicit braces to avoid ambiguous %<else%>",
+        warning (0, "%Hsuggest explicit braces to avoid ambiguous %<else%>",
                  &if_locus);
     }
 
@@ -6793,7 +6989,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
       if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block))
        {
          if (!else_block)
-           warning ("%Hempty body in an if-statement",
+           warning (0, "%Hempty body in an if-statement",
                     EXPR_LOCUS (then_block));
          then_block = alloc_stmt_list ();
        }
@@ -6801,13 +6997,13 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
          && TREE_CODE (else_block) == NOP_EXPR
          && !TREE_TYPE (else_block))
        {
-         warning ("%Hempty body in an else-statement",
+         warning (0, "%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);
+  stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
   SET_EXPR_LOCATION (stmt, if_locus);
   add_stmt (stmt);
 }
@@ -6932,7 +7128,7 @@ emit_side_effect_warnings (tree expr)
   else if (!TREE_SIDE_EFFECTS (expr))
     {
       if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
-       warning ("%Hstatement with no effect",
+       warning (0, "%Hstatement with no effect",
                 EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
     }
   else if (warn_unused_value)
@@ -6948,13 +7144,6 @@ 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);
 
@@ -6999,7 +7188,7 @@ tree
 c_begin_stmt_expr (void)
 {
   tree ret;
-  struct c_label_context *nstack;
+  struct c_label_context_se *nstack;
   struct c_label_list *glist;
 
   /* We must force a BLOCK for this level so that, if it is not expanded
@@ -7012,17 +7201,17 @@ c_begin_stmt_expr (void)
       c_switch_stack->blocked_stmt_expr++;
       gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
     }
-  for (glist = label_context_stack->labels_used;
+  for (glist = label_context_stack_se->labels_used;
        glist != NULL;
        glist = glist->next)
     {
       C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1;
     }
-  nstack = XOBNEW (&parser_obstack, struct c_label_context);
+  nstack = XOBNEW (&parser_obstack, struct c_label_context_se);
   nstack->labels_def = NULL;
   nstack->labels_used = NULL;
-  nstack->next = label_context_stack;
-  label_context_stack = nstack;
+  nstack->next = label_context_stack_se;
+  label_context_stack_se = nstack;
 
   /* Mark the current statement list as belonging to a statement list.  */
   STATEMENT_LIST_STMT_EXPR (ret) = 1;
@@ -7045,7 +7234,7 @@ c_finish_stmt_expr (tree body)
     }
   /* It is no longer possible to jump to labels defined within this
      statement expression.  */
-  for (dlist = label_context_stack->labels_def;
+  for (dlist = label_context_stack_se->labels_def;
        dlist != NULL;
        dlist = dlist->next)
     {
@@ -7053,7 +7242,7 @@ c_finish_stmt_expr (tree body)
     }
   /* It is again possible to define labels with a goto just outside
      this statement expression.  */
-  for (glist = label_context_stack->next->labels_used;
+  for (glist = label_context_stack_se->next->labels_used;
        glist != NULL;
        glist = glist->next)
     {
@@ -7061,10 +7250,11 @@ c_finish_stmt_expr (tree body)
       glist_prev = glist;
     }
   if (glist_prev != NULL)
-    glist_prev->next = label_context_stack->labels_used;
+    glist_prev->next = label_context_stack_se->labels_used;
   else
-    label_context_stack->next->labels_used = label_context_stack->labels_used;
-  label_context_stack = label_context_stack->next;
+    label_context_stack_se->next->labels_used
+      = label_context_stack_se->labels_used;
+  label_context_stack_se = label_context_stack_se->next;
 
   /* Locate the last statement in BODY.  See c_end_compound_stmt
      about always returning a BIND_EXPR.  */
@@ -7135,6 +7325,75 @@ c_finish_stmt_expr (tree body)
 
   return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
 }
+
+/* Begin the scope of an identifier of variably modified type, scope
+   number SCOPE.  Jumping from outside this scope to inside it is not
+   permitted.  */
+
+void
+c_begin_vm_scope (unsigned int scope)
+{
+  struct c_label_context_vm *nstack;
+  struct c_label_list *glist;
+
+  gcc_assert (scope > 0);
+  if (c_switch_stack && !c_switch_stack->blocked_vm)
+    c_switch_stack->blocked_vm = scope;
+  for (glist = label_context_stack_vm->labels_used;
+       glist != NULL;
+       glist = glist->next)
+    {
+      C_DECL_UNDEFINABLE_VM (glist->label) = 1;
+    }
+  nstack = XOBNEW (&parser_obstack, struct c_label_context_vm);
+  nstack->labels_def = NULL;
+  nstack->labels_used = NULL;
+  nstack->scope = scope;
+  nstack->next = label_context_stack_vm;
+  label_context_stack_vm = nstack;
+}
+
+/* End a scope which may contain identifiers of variably modified
+   type, scope number SCOPE.  */
+
+void
+c_end_vm_scope (unsigned int scope)
+{
+  if (label_context_stack_vm == NULL)
+    return;
+  if (c_switch_stack && c_switch_stack->blocked_vm == scope)
+    c_switch_stack->blocked_vm = 0;
+  /* We may have a number of nested scopes of identifiers with
+     variably modified type, all at this depth.  Pop each in turn.  */
+  while (label_context_stack_vm->scope == scope)
+    {
+      struct c_label_list *dlist, *glist, *glist_prev = NULL;
+
+      /* It is no longer possible to jump to labels defined within this
+        scope.  */
+      for (dlist = label_context_stack_vm->labels_def;
+          dlist != NULL;
+          dlist = dlist->next)
+       {
+         C_DECL_UNJUMPABLE_VM (dlist->label) = 1;
+       }
+      /* It is again possible to define labels with a goto just outside
+        this scope.  */
+      for (glist = label_context_stack_vm->next->labels_used;
+          glist != NULL;
+          glist = glist->next)
+       {
+         C_DECL_UNDEFINABLE_VM (glist->label) = 0;
+         glist_prev = glist;
+       }
+      if (glist_prev != NULL)
+       glist_prev->next = label_context_stack_vm->labels_used;
+      else
+       label_context_stack_vm->next->labels_used
+         = label_context_stack_vm->labels_used;
+      label_context_stack_vm = label_context_stack_vm->next;
+    }
+}
 \f
 /* Begin and end compound statements.  This is as simple as pushing
    and popping new statement lists from the tree.  */
@@ -7221,6 +7480,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   tree type0, type1;
   enum tree_code code0, code1;
   tree op0, op1;
+  const char *invalid_op_diag;
 
   /* Expression code to give to the expression when it is built.
      Normally this is CODE, which is what the caller asked for,
@@ -7264,6 +7524,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   /* Nonzero means set RESULT_TYPE to the common type of the args.  */
   int common = 0;
 
+  /* True means types are compatible as far as ObjC is concerned.  */
+  bool objc_ok;
+
   if (convert_p)
     {
       op0 = default_conversion (orig_op0);
@@ -7293,6 +7556,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
+  if ((invalid_op_diag
+       = targetm.invalid_binary_op (code, type0, type1)))
+    {
+      error (invalid_op_diag);
+      return error_mark_node;
+    }
+
+  objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -7309,7 +7581,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       /* Subtraction of two similar pointers.
         We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
-         && comp_target_types (type0, type1, 1))
+         && comp_target_types (type0, type1))
        return pointer_diff (op0, op1);
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -7329,20 +7601,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case EXACT_DIV_EXPR:
       /* Floating point division by zero is a legitimate way to obtain
         infinities and NaNs.  */
-      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
-       warning ("division by zero");
+      if (skip_evaluation == 0 && integer_zerop (op1))
+       warning (OPT_Wdiv_by_zero, "division by zero");
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
+         enum tree_code tcode0 = code0, tcode1 = code1;
+
          if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
-           code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+           tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
          if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
-           code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+           tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
 
-         if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
+         if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
            /* Although it would be tempting to shorten always here, that
@@ -7368,8 +7642,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
-      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
-       warning ("division by zero");
+      if (skip_evaluation == 0 && integer_zerop (op1))
+       warning (OPT_Wdiv_by_zero, "division by zero");
 
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -7414,14 +7688,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
              if (tree_int_cst_sgn (op1) < 0)
-               warning ("right shift count is negative");
+               warning (0, "right shift count is negative");
              else
                {
                  if (!integer_zerop (op1))
                    short_shift = 1;
 
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-                   warning ("right shift count >= width of type");
+                   warning (0, "right shift count >= width of type");
                }
            }
 
@@ -7442,10 +7716,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
              if (tree_int_cst_sgn (op1) < 0)
-               warning ("left shift count is negative");
+               warning (0, "left shift count is negative");
 
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-               warning ("left shift count >= width of type");
+               warning (0, "left shift count >= width of type");
            }
 
          /* Use the type of the value to be shifted.  */
@@ -7461,8 +7735,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case EQ_EXPR:
     case NE_EXPR:
-      if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
-       warning ("comparing floating point with == or != is unsafe");
+      if (code0 == REAL_TYPE || code1 == REAL_TYPE)
+       warning (OPT_Wfloat_equal,
+                "comparing floating point with == or != is unsafe");
       /* Result of comparison is always int,
         but don't convert the args to int!  */
       build_type = integer_type_node;
@@ -7478,7 +7753,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
-         if (comp_target_types (type0, type1, 1))
+         if (comp_target_types (type0, type1))
            result_type = common_pointer_type (type0, type1);
          else if (VOID_TYPE_P (tt0))
            {
@@ -7497,7 +7772,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                         " with function pointer");
            }
          else
-           pedwarn ("comparison of distinct pointer types lacks a cast");
+           /* Avoid warning about the volatile ObjC EH puts on decls.  */
+           if (!objc_ok)
+             pedwarn ("comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
            result_type = ptr_type_node;
@@ -7530,7 +7807,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (comp_target_types (type0, type1, 1))
+         if (comp_target_types (type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
              if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
@@ -7579,6 +7856,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
+  if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+      && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
+         || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
+                                                   TREE_TYPE (type1))))
+    {
+      binary_op_error (code);
+      return error_mark_node;
+    }
+
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
        || code0 == VECTOR_TYPE)
       &&
@@ -7779,7 +8065,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                            c_common_signed_type (result_type)))
                    /* OK */;
                  else
-                   warning ("comparison between signed and unsigned");
+                   warning (0, "comparison between signed and unsigned");
                }
 
              /* Warn if two unsigned values are being compared in a size
@@ -7825,7 +8111,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                        {
                          mask = (~(HOST_WIDE_INT) 0) << bits;
                          if ((mask & constant) != mask)
-                           warning ("comparison of promoted ~unsigned with constant");
+                           warning (0, "comparison of promoted ~unsigned with constant");
                        }
                    }
                  else if (unsignedp0 && unsignedp1
@@ -7833,7 +8119,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                               < TYPE_PRECISION (result_type))
                           && (TYPE_PRECISION (TREE_TYPE (primop1))
                               < TYPE_PRECISION (result_type)))
-                   warning ("comparison of promoted ~unsigned with unsigned");
+                   warning (0, "comparison of promoted ~unsigned with unsigned");
                }
            }
        }
@@ -7882,12 +8168,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
 
 /* Convert EXPR to be a truth-value, validating its type for this
-   purpose.  Passes EXPR to default_function_array_conversion.  */
+   purpose.  */
 
 tree
 c_objc_common_truthvalue_conversion (tree expr)
 {
-  expr = default_function_array_conversion (expr);
   switch (TREE_CODE (TREE_TYPE (expr)))
     {
     case ARRAY_TYPE:
@@ -7902,6 +8187,9 @@ c_objc_common_truthvalue_conversion (tree expr)
       error ("used union type value where scalar is required");
       return error_mark_node;
 
+    case FUNCTION_TYPE:
+      gcc_unreachable ();
+
     default:
       break;
     }
@@ -7910,3 +8198,24 @@ c_objc_common_truthvalue_conversion (tree expr)
      leaving those to give errors later?  */
   return c_common_truthvalue_conversion (expr);
 }
+\f
+
+/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as
+   required.  */
+
+tree
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
+               bool *ti ATTRIBUTE_UNUSED, bool *se)
+{
+  if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
+    {
+      tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
+      /* Executing a compound literal inside a function reinitializes
+        it.  */
+      if (!TREE_STATIC (decl))
+       *se = true;
+      return decl;
+    }
+  else
+    return expr;
+}