OSDN Git Service

PR c/38957
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 60b0b02..4b9b2b3 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -42,14 +42,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "target.h"
 #include "tree-iterator.h"
-#include "tree-gimple.h"
+#include "gimple.h"
 #include "tree-flow.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
 enum impl_conv {
   ic_argpass,
-  ic_argpass_nonproto,
   ic_assign,
   ic_init,
   ic_return
@@ -91,13 +90,13 @@ static void push_string (const char *);
 static void push_member_name (tree);
 static int spelling_length (void);
 static char *print_spelling (char *);
-static void warning_init (const char *);
+static void warning_init (int, const char *);
 static tree digest_init (tree, tree, bool, int);
-static void output_init_element (tree, bool, tree, tree, int);
+static void output_init_element (tree, bool, tree, tree, int, bool);
 static void output_pending_init_elements (int);
 static int set_designator (int);
 static void push_range_stack (tree);
-static void add_pending_init (tree, tree);
+static void add_pending_init (tree, tree, bool);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
@@ -470,8 +469,8 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p2));
-                       if (pedantic)
-                         pedwarn ("function types not truly compatible in ISO C");
+                       pedwarn (input_location, OPT_pedantic, 
+                                "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
                  }
@@ -495,8 +494,8 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p1));
-                       if (pedantic)
-                         pedwarn ("function types not truly compatible in ISO C");
+                       pedwarn (input_location, OPT_pedantic, 
+                                "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
                  }
@@ -722,7 +721,7 @@ c_common_type (tree t1, tree t2)
             signed type.  */
          if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
            {
-             unsigned char mclass = 0;
+             enum mode_class mclass = (enum mode_class) 0;
              if (GET_MODE_CLASS (m1) == MODE_UFRACT)
                mclass = MODE_FRACT;
              else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
@@ -733,7 +732,7 @@ c_common_type (tree t1, tree t2)
            }
          if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
            {
-             unsigned char mclass = 0;
+             enum mode_class mclass = (enum mode_class) 0;
              if (GET_MODE_CLASS (m2) == MODE_UFRACT)
                mclass = MODE_FRACT;
              else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
@@ -1039,8 +1038,8 @@ comp_target_types (tree ttl, tree ttr)
     mvr = TYPE_MAIN_VARIANT (mvr);
   val = comptypes (mvl, mvr);
 
-  if (val == 2 && pedantic)
-    pedwarn ("types are not quite compatible");
+  if (val == 2)
+    pedwarn (input_location, OPT_pedantic, "types are not quite compatible");
   return val;
 }
 \f
@@ -1363,7 +1362,7 @@ function_types_compatible_p (const_tree f1, const_tree f2)
   /* 'volatile' qualifiers on a function's return type used to mean
      the function is noreturn.  */
   if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
-    pedwarn ("function return types not compatible due to %<volatile%>");
+    pedwarn (input_location, 0, "function return types not compatible due to %<volatile%>");
   if (TYPE_VOLATILE (ret1))
     ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
                                 TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
@@ -1618,7 +1617,7 @@ array_to_pointer_conversion (tree 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);
+  adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1);
   return convert (ptrtype, adr);
 }
 
@@ -1635,7 +1634,7 @@ function_to_pointer_conversion (tree exp)
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  return build_unary_op (ADDR_EXPR, exp, 0);
+  return build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 0);
 }
 
 /* Perform the default conversion of arrays and functions to pointers.
@@ -1657,8 +1656,7 @@ default_function_array_conversion (struct c_expr exp)
        bool lvalue_array_p;
 
        while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
-               || TREE_CODE (exp.value) == NOP_EXPR
-               || TREE_CODE (exp.value) == CONVERT_EXPR)
+               || CONVERT_EXPR_P (exp.value))
               && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
          {
            if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
@@ -1968,18 +1966,20 @@ build_component_ref (tree datum, tree component)
 \f
 /* Given an expression PTR for a pointer, return an expression
    for the value pointed to.
-   ERRORSTRING is the name of the operator to appear in error messages.  */
+   ERRORSTRING is the name of the operator to appear in error messages.
+
+   LOC is the location to use for the generated tree.  */
 
 tree
-build_indirect_ref (tree ptr, const char *errorstring)
+build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
+  tree ref;
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
-      if (TREE_CODE (pointer) == CONVERT_EXPR
-          || TREE_CODE (pointer) == NOP_EXPR
+      if (CONVERT_EXPR_P (pointer)
           || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
        {
          /* If a warning is issued, mark it to avoid duplicates from
@@ -1994,21 +1994,24 @@ build_indirect_ref (tree ptr, const char *errorstring)
       if (TREE_CODE (pointer) == ADDR_EXPR
          && (TREE_TYPE (TREE_OPERAND (pointer, 0))
              == TREE_TYPE (type)))
-       return TREE_OPERAND (pointer, 0);
+       {
+         ref = TREE_OPERAND (pointer, 0);
+         protected_set_expr_location (ref, loc);
+         return ref;
+       }
       else
        {
          tree t = TREE_TYPE (type);
-         tree ref;
 
          ref = build1 (INDIRECT_REF, t, pointer);
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
-             error ("dereferencing pointer to incomplete type");
+             error_at (loc, "dereferencing pointer to incomplete type");
              return error_mark_node;
            }
          if (VOID_TYPE_P (t) && skip_evaluation == 0)
-           warning (0, "dereferencing %<void *%> pointer");
+           warning_at (loc, 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
@@ -2021,11 +2024,13 @@ build_indirect_ref (tree ptr, const char *errorstring)
          TREE_SIDE_EFFECTS (ref)
            = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
          TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
+         protected_set_expr_location (ref, loc);
          return ref;
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error ("invalid type argument of %qs (have %qT)", errorstring, type);
+    error_at (loc,
+             "invalid type argument of %qs (have %qT)", errorstring, type);
   return error_mark_node;
 }
 
@@ -2036,11 +2041,14 @@ build_indirect_ref (tree ptr, const char *errorstring)
    If A is a variable or a member, we generate a primitive ARRAY_REF.
    This avoids forcing the array out of registers, and can work on
    arrays that are not lvalues (for example, members of structures returned
-   by functions).  */
+   by functions).
+
+   LOC is the location to use for the returned expression.  */
 
 tree
-build_array_ref (tree array, tree index)
+build_array_ref (tree array, tree index, location_t loc)
 {
+  tree ret;
   bool swapped = false;
   if (TREE_TYPE (array) == error_mark_node
       || TREE_TYPE (index) == error_mark_node)
@@ -2053,7 +2061,7 @@ build_array_ref (tree array, tree index)
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-         error ("subscripted value is neither array nor pointer");
+         error_at (loc, "subscripted value is neither array nor pointer");
          return error_mark_node;
        }
       temp = array;
@@ -2064,13 +2072,13 @@ build_array_ref (tree array, tree index)
 
   if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
     {
-      error ("array subscript is not an integer");
+      error_at (loc, "array subscript is not an integer");
       return error_mark_node;
     }
 
   if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
     {
-      error ("subscripted value is pointer to function");
+      error_at (loc, "subscripted value is pointer to function");
       return error_mark_node;
     }
 
@@ -2117,9 +2125,11 @@ build_array_ref (tree array, tree index)
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
-           pedwarn ("ISO C forbids subscripting %<register%> array");
+           pedwarn (loc, OPT_pedantic, 
+                    "ISO C forbids subscripting %<register%> array");
          else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn ("ISO C90 forbids subscripting non-lvalue array");
+           pedwarn (loc, OPT_pedantic, 
+                    "ISO C90 forbids subscripting non-lvalue array");
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
@@ -2139,7 +2149,9 @@ build_array_ref (tree array, tree index)
               in an inline function.
               Hope it doesn't break something else.  */
            | TREE_THIS_VOLATILE (array));
-      return require_complete_type (fold (rval));
+      ret = require_complete_type (fold (rval));
+      protected_set_expr_location (ret, loc);
+      return ret;
     }
   else
     {
@@ -2151,8 +2163,9 @@ build_array_ref (tree array, tree index)
       gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
       gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
 
-      return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
-                                "array indexing");
+      return build_indirect_ref
+       (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
+        "array indexing");
     }
 }
 \f
@@ -2193,8 +2206,6 @@ build_external_ref (tree id, int fun, location_t loc)
   /* Recursive call does not count as usage.  */
   if (ref != current_function_decl) 
     {
-      if (!skip_evaluation)
-       assemble_external (ref);
       TREE_USED (ref) = 1;
     }
 
@@ -2213,7 +2224,6 @@ build_external_ref (tree id, int fun, location_t loc)
       used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
-      TREE_INVARIANT (ref) = 1;
     }
   else if (current_function_decl != 0
           && !DECL_FILE_SCOPE_P (current_function_decl)
@@ -2236,8 +2246,8 @@ build_external_ref (tree id, int fun, location_t loc)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
           && ! TREE_PUBLIC (ref)
           && DECL_CONTEXT (ref) != current_function_decl)
-    pedwarn ("%H%qD is static but used in inline function %qD "
-            "which is not static", &loc, ref, current_function_decl);
+    pedwarn (loc, 0, "%qD is static but used in inline function %qD "
+            "which is not static", ref, current_function_decl);
 
   return ref;
 }
@@ -2399,8 +2409,7 @@ build_function_call (tree function, tree params)
      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.  */
-  if ((TREE_CODE (function) == NOP_EXPR
-       || TREE_CODE (function) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (function)
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && !comptypes (fntype, TREE_TYPE (tem)))
@@ -2412,11 +2421,10 @@ 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 (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.  */
-      inform ("if this code is reached, the program will abort");
+      if (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.  */
+       inform (input_location, "if this code is reached, the program will abort");
 
       if (VOID_TYPE_P (return_type))
        return trap;
@@ -2444,8 +2452,14 @@ build_function_call (tree function, tree params)
   if (nargs < 0)
     return error_mark_node;
 
-  /* Check that the arguments to the function are valid.  */
+  /* Check that arguments to builtin functions match the expectations.  */
+  if (fundecl
+      && DECL_BUILT_IN (fundecl)
+      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+      && !check_builtin_function_arguments (fundecl, nargs, argarray))
+    return error_mark_node;
 
+  /* Check that the arguments to the function are valid.  */
   check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
                            TYPE_ARG_TYPES (fntype));
 
@@ -2456,7 +2470,7 @@ build_function_call (tree function, tree params)
       if (TREE_CONSTANT (result)
          && (name == NULL_TREE
              || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
-       pedwarn_init ("initializer element is not constant");
+       pedwarn_init (input_location, 0, "initializer element is not constant");
     }
   else
     result = fold_build_call_array (TREE_TYPE (fntype),
@@ -2723,15 +2737,18 @@ convert_arguments (int nargs, tree *argarray,
 /* 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.  */
+   CONVERT_EXPR for code.
+
+   LOC is the location to use for the tree generated.
+*/
 
 struct c_expr
-parser_build_unary_op (enum tree_code code, struct c_expr arg)
+parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc)
 {
   struct c_expr result;
 
-  result.original_code = ERROR_MARK;
-  result.value = build_unary_op (code, arg.value, 0);
+  result.value = build_unary_op (loc, code, arg.value, 0);
+  result.original_code = code;
   
   if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
     overflow_warning (result.value);
@@ -2743,29 +2760,35 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg)
    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.  */
+   operators in a way that is likely to confuse the user.
+
+   LOCATION is the location of the binary operator.  */
 
 struct c_expr
-parser_build_binary_op (enum tree_code code, struct c_expr arg1,
-                       struct c_expr arg2)
+parser_build_binary_op (location_t location, enum tree_code code,
+                       struct c_expr arg1, struct c_expr arg2)
 {
   struct c_expr result;
 
   enum tree_code code1 = arg1.original_code;
   enum tree_code code2 = arg2.original_code;
 
-  result.value = build_binary_op (code, arg1.value, arg2.value, 1);
+  result.value = build_binary_op (location, code,
+                                 arg1.value, arg2.value, 1);
   result.original_code = code;
 
   if (TREE_CODE (result.value) == ERROR_MARK)
     return result;
 
+  if (location != UNKNOWN_LOCATION)
+    protected_set_expr_location (result.value, location);
+
   /* Check for cases such as x+y<<z which users are likely
      to misinterpret.  */
   if (warn_parentheses)
-    warn_about_parentheses (code, code1, code2);
+    warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
 
-  if (code1 != tcc_comparison)
+  if (TREE_CODE_CLASS (code1) != tcc_comparison)
     warn_logical_operator (code, arg1.value, arg2.value);
 
   /* Warn about comparisons against string literals, with the exception
@@ -2800,13 +2823,12 @@ pointer_diff (tree op0, tree op1)
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
-  if (pedantic || warn_pointer_arith)
-    {
-      if (TREE_CODE (target_type) == VOID_TYPE)
-       pedwarn ("pointer of type %<void *%> used in subtraction");
-      if (TREE_CODE (target_type) == FUNCTION_TYPE)
-       pedwarn ("pointer to a function used in subtraction");
-    }
+  if (TREE_CODE (target_type) == VOID_TYPE)
+    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+            "pointer of type %<void *%> used in subtraction");
+  if (TREE_CODE (target_type) == FUNCTION_TYPE)
+    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+            "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
      converting a partial to an integral mode, we get a convert_expression
@@ -2816,13 +2838,13 @@ pointer_diff (tree op0, tree op1)
      different mode in place.)
      So first try to find a common term here 'by hand'; we want to cover
      at least the cases that occur in legal static initializers.  */
-  if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (op0)
       && (TYPE_PRECISION (TREE_TYPE (op0))
          == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
     con0 = TREE_OPERAND (op0, 0);
   else
     con0 = op0;
-  if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (op1)
       && (TYPE_PRECISION (TREE_TYPE (op1))
          == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
     con1 = TREE_OPERAND (op1, 0);
@@ -2857,7 +2879,8 @@ pointer_diff (tree op0, tree op1)
      Do not do default conversions on the minus operator
      in case restype is a short type.  */
 
-  op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
+  op0 = build_binary_op (input_location,
+                        MINUS_EXPR, convert (restype, op0),
                         convert (restype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
@@ -2877,16 +2900,20 @@ pointer_diff (tree op0, tree op1)
    the default promotions (such as from short to int).
    For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
    allows non-lvalues; this is only used to handle conversion of non-lvalue
-   arrays to pointers in C99.  */
+   arrays to pointers in C99.
+
+   LOCATION is the location of the operator.  */
 
 tree
-build_unary_op (enum tree_code code, tree xarg, int flag)
+build_unary_op (location_t location,
+               enum tree_code code, tree xarg, int flag)
 {
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
   tree arg = xarg;
   tree argtype = 0;
   enum tree_code typecode;
   tree val;
+  tree ret = error_mark_node;
   int noconvert = flag;
   const char *invalid_op_diag;
 
@@ -2902,7 +2929,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
   if ((invalid_op_diag
        = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
     {
-      error (invalid_op_diag);
+      error_at (location, invalid_op_diag);
       return error_mark_node;
     }
 
@@ -2916,7 +2943,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
-         error ("wrong type argument to unary plus");
+         error_at (location, "wrong type argument to unary plus");
          return error_mark_node;
        }
       else if (!noconvert)
@@ -2929,7 +2956,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
            || typecode == VECTOR_TYPE))
        {
-         error ("wrong type argument to unary minus");
+         error_at (location, "wrong type argument to unary minus");
          return error_mark_node;
        }
       else if (!noconvert)
@@ -2948,14 +2975,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
-         if (pedantic)
-           pedwarn ("ISO C does not support %<~%> for complex conjugation");
+         pedwarn (location, OPT_pedantic, 
+                  "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
        }
       else
        {
-         error ("wrong type argument to bit-complement");
+         error_at (location, "wrong type argument to bit-complement");
          return error_mark_node;
        }
       break;
@@ -2963,7 +2990,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
     case ABS_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
        {
-         error ("wrong type argument to abs");
+         error_at (location, "wrong type argument to abs");
          return error_mark_node;
        }
       else if (!noconvert)
@@ -2975,7 +3002,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
            || typecode == COMPLEX_TYPE))
        {
-         error ("wrong type argument to conjugation");
+         error_at (location, "wrong type argument to conjugation");
          return error_mark_node;
        }
       else if (!noconvert)
@@ -2987,27 +3014,31 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          && typecode != REAL_TYPE && typecode != POINTER_TYPE
          && typecode != COMPLEX_TYPE)
        {
-         error ("wrong type argument to unary exclamation mark");
+         error_at (location,
+                   "wrong type argument to unary exclamation mark");
          return error_mark_node;
        }
-      arg = c_objc_common_truthvalue_conversion (arg);
-      return invert_truthvalue (arg);
+      arg = c_objc_common_truthvalue_conversion (location, arg);
+      ret = invert_truthvalue (arg);
+      goto return_build_unary_op;
 
     case REALPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
-       return TREE_REALPART (arg);
+       ret = TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
-       return arg;
+       ret = arg;
+      goto return_build_unary_op;
 
     case IMAGPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
-       return TREE_IMAGPART (arg);
+       ret = TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
-       return convert (TREE_TYPE (arg), integer_zero_node);
+       ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+      goto return_build_unary_op;
 
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -3020,18 +3051,18 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        {
          tree real, imag;
 
-         if (pedantic)
-           pedwarn ("ISO C does not support %<++%> and %<--%>"
-                    " on complex types");
+         pedwarn (location, OPT_pedantic, 
+                  "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
-         real = build_unary_op (REALPART_EXPR, arg, 1);
-         imag = build_unary_op (IMAGPART_EXPR, arg, 1);
-         real = build_unary_op (code, real, 1);
+         real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
+         imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
+         real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
          if (real == error_mark_node || imag == error_mark_node)
            return error_mark_node;
-         return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
-                        real, imag);
+         ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+                       real, imag);
+         goto return_build_unary_op;
        }
 
       /* Report invalid types.  */
@@ -3040,18 +3071,16 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-           error ("wrong type argument to increment");
+           error_at (location, "wrong type argument to increment");
          else
-           error ("wrong type argument to decrement");
+           error_at (location, "wrong type argument to decrement");
 
          return error_mark_node;
        }
 
       {
        tree inc;
-       tree result_type = TREE_TYPE (arg);
 
-       arg = get_unwidened (arg, 0);
        argtype = TREE_TYPE (arg);
 
        /* Compute the increment.  */
@@ -3060,27 +3089,30 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          {
            /* If pointer target is an undefined struct,
               we just cannot know how to do the arithmetic.  */
-           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
+           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 error ("increment of pointer to unknown structure");
+                 error_at (location,
+                           "increment of pointer to unknown structure");
                else
-                 error ("decrement of pointer to unknown structure");
+                 error_at (location,
+                           "decrement of pointer to unknown structure");
              }
-           else if ((pedantic || warn_pointer_arith)
-                    && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
-                        || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
+           else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
+                    || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 pedwarn ("wrong type argument to increment");
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                          "wrong type argument to increment");
                else
-                 pedwarn ("wrong type argument to decrement");
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                          "wrong type argument to decrement");
              }
 
-           inc = c_size_in_bytes (TREE_TYPE (result_type));
+           inc = c_size_in_bytes (TREE_TYPE (argtype));
            inc = fold_convert (sizetype, inc);
          }
-       else if (FRACT_MODE_P (TYPE_MODE (result_type)))
+       else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
            /* For signed fract types, we invert ++ to -- or
               -- to ++, and change inc from 1 to -1, because
@@ -3127,10 +3159,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
        else
          val = build2 (code, TREE_TYPE (arg), arg, inc);
        TREE_SIDE_EFFECTS (val) = 1;
-       val = convert (result_type, val);
        if (TREE_CODE (val) != code)
          TREE_NO_WARNING (val) = 1;
-       return val;
+       ret = val;
+       goto return_build_unary_op;
       }
 
     case ADDR_EXPR:
@@ -3142,7 +3174,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          /* Don't let this be an lvalue.  */
          if (lvalue_p (TREE_OPERAND (arg, 0)))
            return non_lvalue (TREE_OPERAND (arg, 0));
-         return TREE_OPERAND (arg, 0);
+         ret = TREE_OPERAND (arg, 0);
+         goto return_build_unary_op;
        }
 
       /* For &x[y], return x+y */
@@ -3151,7 +3184,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          tree op0 = TREE_OPERAND (arg, 0);
          if (!c_mark_addressable (op0))
            return error_mark_node;
-         return build_binary_op (PLUS_EXPR,
+         return build_binary_op (location, PLUS_EXPR,
                                  (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
                                   ? array_to_pointer_conversion (op0)
                                   : op0),
@@ -3194,12 +3227,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
 
          op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         goto return_build_unary_op;
        }
 
       val = build1 (ADDR_EXPR, argtype, arg);
 
-      return val;
+      ret = val;
+      goto return_build_unary_op;
 
     default:
       gcc_unreachable ();
@@ -3207,8 +3242,12 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
   if (argtype == 0)
     argtype = TREE_TYPE (arg);
-  return require_constant_value ? fold_build1_initializer (code, argtype, arg)
-                               : fold_build1 (code, argtype, arg);
+  ret = require_constant_value ? fold_build1_initializer (code, argtype, arg)
+                              : fold_build1 (code, argtype, arg);
+ return_build_unary_op:
+  gcc_assert (ret != error_mark_node);
+  protected_set_expr_location (ret, location);
+  return ret;
 }
 
 /* Return nonzero if REF is an lvalue valid for this language.
@@ -3349,7 +3388,7 @@ c_mark_addressable (tree exp)
                  ("global register variable %qD used in nested function", x);
                return false;
              }
-           pedwarn ("register variable %qD used in nested function", x);
+           pedwarn (input_location, 0, "register variable %qD used in nested function", x);
          }
        else if (C_DECL_REGISTER (x))
          {
@@ -3456,8 +3495,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
     {
-      if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
-       pedwarn ("ISO C forbids conditional expr with only one void side");
+      if (code1 != VOID_TYPE || code2 != VOID_TYPE)
+       pedwarn (input_location, OPT_pedantic, 
+                "ISO C forbids conditional expr with only one void side");
       result_type = void_type_node;
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
@@ -3470,30 +3510,34 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
        result_type = qualify_type (type1, type2);
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
-         if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
-           pedwarn ("ISO C forbids conditional expr between "
+         if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
+           pedwarn (input_location, OPT_pedantic, 
+                    "ISO C forbids conditional expr between "
                     "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
                                                          TREE_TYPE (type2)));
        }
       else if (VOID_TYPE_P (TREE_TYPE (type2)))
        {
-         if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
-           pedwarn ("ISO C forbids conditional expr between "
+         if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
+           pedwarn (input_location, OPT_pedantic, 
+                    "ISO C forbids conditional expr between "
                     "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
                                                          TREE_TYPE (type1)));
        }
       else
        {
-         pedwarn ("pointer type mismatch in conditional expression");
+         pedwarn (input_location, 0, 
+                  "pointer type mismatch in conditional expression");
          result_type = build_pointer_type (void_type_node);
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
       if (!null_pointer_constant_p (orig_op2))
-       pedwarn ("pointer/integer type mismatch in conditional expression");
+       pedwarn (input_location, 0, 
+                "pointer/integer type mismatch in conditional expression");
       else
        {
          op2 = null_pointer_node;
@@ -3503,7 +3547,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
     {
       if (!null_pointer_constant_p (orig_op1))
-       pedwarn ("pointer/integer type mismatch in conditional expression");
+       pedwarn (input_location, 0, 
+                "pointer/integer type mismatch in conditional expression");
       else
        {
          op1 = null_pointer_node;
@@ -3550,13 +3595,11 @@ build_compound_expr (tree expr1, tree expr2)
       if (warn_unused_value)
        {
          if (VOID_TYPE_P (TREE_TYPE (expr1))
-             && (TREE_CODE (expr1) == NOP_EXPR
-                 || TREE_CODE (expr1) == CONVERT_EXPR))
+             && CONVERT_EXPR_P (expr1))
            ; /* (void) a, b */
          else if (VOID_TYPE_P (TREE_TYPE (expr1))
                   && TREE_CODE (expr1) == COMPOUND_EXPR
-                  && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
-                      || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
+                  && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
            warning (OPT_Wunused_value, 
@@ -3616,33 +3659,31 @@ build_c_cast (tree type, tree expr)
 
   if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
-      if (pedantic)
-       {
-         if (TREE_CODE (type) == RECORD_TYPE
-             || TREE_CODE (type) == UNION_TYPE)
-           pedwarn ("ISO C forbids casting nonscalar to the same type");
-       }
+      if (TREE_CODE (type) == RECORD_TYPE
+         || TREE_CODE (type) == UNION_TYPE)
+       pedwarn (input_location, OPT_pedantic, 
+                "ISO C forbids casting nonscalar to the same type");
     }
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-       if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-                      TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+       if (TREE_TYPE (field) != error_mark_node
+           && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+                         TYPE_MAIN_VARIANT (TREE_TYPE (value))))
          break;
 
       if (field)
        {
          tree t;
 
-         if (pedantic)
-           pedwarn ("ISO C forbids casts to union type");
+         pedwarn (input_location, OPT_pedantic,
+                  "ISO C forbids casts to union type");
          t = digest_init (type,
                           build_constructor_single (type, field, value),
                           true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
-         TREE_INVARIANT (t) = TREE_INVARIANT (value);
          return t;
        }
       error ("cast to union type from type not present in union");
@@ -3749,7 +3790,8 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
-       pedwarn ("ISO C forbids conversion of function pointer to object pointer type");
+       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+                "conversion of function pointer to object pointer type");
 
       if (pedantic
          && TREE_CODE (type) == POINTER_TYPE
@@ -3757,7 +3799,8 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
          && !null_pointer_constant_p (value))
-       pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
+       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+                "conversion of object pointer to function pointer type");
 
       ovalue = value;
       value = convert (type, value);
@@ -3809,10 +3852,13 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
    to combine the old value of LHS with RHS to get the new value.
-   Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.  */
+   Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
+
+   LOCATION is the location of the MODIFYCODE operator.  */
 
 tree
-build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
+build_modify_expr (location_t location,
+                  tree lhs, enum tree_code modifycode, tree rhs)
 {
   tree result;
   tree newrhs;
@@ -3839,7 +3885,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (modifycode != NOP_EXPR)
     {
       lhs = stabilize_reference (lhs);
-      newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+      newrhs = build_binary_op (location,
+                               modifycode, lhs, rhs, 1);
     }
 
   /* Give an error for storing in something that is 'const'.  */
@@ -3886,13 +3933,17 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
     {
       result = objc_generate_write_barrier (lhs, modifycode, newrhs);
       if (result)
-       return result;
+       {
+         protected_set_expr_location (result, location);
+         return result;
+       }
     }
 
   /* Scan operands.  */
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
+  protected_set_expr_location (result, location);
 
   /* If we got the LHS in a different type for storing in,
      convert the result back to the nominal type of LHS
@@ -3901,8 +3952,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  return convert_for_assignment (olhstype, result, ic_assign,
-                                NULL_TREE, NULL_TREE, 0);
+
+  result = convert_for_assignment (olhstype, result, ic_assign,
+                                  NULL_TREE, NULL_TREE, 0);
+  protected_set_expr_location (result, location);
+  return result;
 }
 \f
 /* Convert value RHS to type TYPE as preparation for an assignment
@@ -3926,7 +3980,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
-  if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
+  if (errtype == ic_argpass)
     {
       tree selector;
       /* Change pointer to function to the function itself for
@@ -3948,28 +4002,29 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
      compile time.  */
-#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE)    \
-  do {                                         \
-    switch (errtype)                           \
-      {                                                \
-      case ic_argpass:                         \
-       pedwarn (AR, parmnum, rname);           \
-       break;                                  \
-      case ic_argpass_nonproto:                        \
-       warning (0, AR, parmnum, rname);                \
-       break;                                  \
-      case ic_assign:                          \
-       pedwarn (AS);                           \
-       break;                                  \
-      case ic_init:                            \
-       pedwarn (IN);                           \
-       break;                                  \
-      case ic_return:                          \
-       pedwarn (RE);                           \
-       break;                                  \
-      default:                                 \
-       gcc_unreachable ();                     \
-      }                                                \
+#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)               \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        pedwarn (LOCATION, OPT, AS);                                     \
+        break;                                                           \
+      case ic_init:                                                      \
+        pedwarn (LOCATION, OPT, IN);                                     \
+        break;                                                           \
+      case ic_return:                                                    \
+        pedwarn (LOCATION, OPT, RE);                                     \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
   } while (0)
 
   STRIP_TYPE_NOPS (rhs);
@@ -4076,7 +4131,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   /* Conversion to a transparent union from its member types.
      This applies only to function arguments.  */
   if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
-      && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
+      && errtype == ic_argpass)
     {
       tree memb, marginal_memb = NULL_TREE;
 
@@ -4147,7 +4202,8 @@ 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 (G_("passing argument %d of %qE "
+                   WARN_FOR_ASSIGNMENT (input_location, 0,
+                                        G_("passing argument %d of %qE "
                                            "makes qualified function "
                                            "pointer from unqualified"),
                                         G_("assignment makes qualified "
@@ -4160,7 +4216,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                                            "pointer from unqualified"));
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
+               WARN_FOR_ASSIGNMENT (input_location, 0,
+                                    G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
                                     G_("assignment discards qualifiers "
                                        "from pointer target type"),
@@ -4172,8 +4229,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
              memb = marginal_memb;
            }
 
-         if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
-           pedwarn ("ISO C prohibits argument conversion to union type");
+         if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
+           pedwarn (input_location, OPT_pedantic, 
+                    "ISO C prohibits argument conversion to union type");
 
          rhs = fold_convert (TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
@@ -4196,10 +4254,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       if (TREE_CODE (mvr) != ARRAY_TYPE)
        mvr = TYPE_MAIN_VARIANT (mvr);
       /* Opaque pointers are treated like void pointers.  */
-      is_opaque_pointer = (targetm.vector_opaque_p (type)
-                          || targetm.vector_opaque_p (rhstype))
-       && TREE_CODE (ttl) == VECTOR_TYPE
-       && TREE_CODE (ttr) == VECTOR_TYPE;
+      is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
 
       /* C++ does not allow the implicit conversion void* -> T*.  However,
         for the purpose of reducing the number of false positives, we
@@ -4220,7 +4275,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
          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",
@@ -4261,7 +4315,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                  (VOID_TYPE_P (ttr)
                   && !null_pointer_constant_p (rhs)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
+           WARN_FOR_ASSIGNMENT (input_location, OPT_pedantic,
+                                G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                                    "and %<void *%>"),
                                 G_("ISO C forbids assignment between "
@@ -4281,7 +4336,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                     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 "
+                   WARN_FOR_ASSIGNMENT (input_location, 0,
+                                        G_("passing argument %d of %qE discards "
                                            "qualifiers from pointer target type"),
                                         G_("assignment discards qualifiers "
                                            "from pointer target type"),
@@ -4297,7 +4353,8 @@ 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 (G_("pointer targets in passing argument "
+               WARN_FOR_ASSIGNMENT (input_location, OPT_Wpointer_sign,
+                                    G_("pointer targets in passing argument "
                                        "%d of %qE differ in signedness"),
                                     G_("pointer targets in assignment "
                                        "differ in signedness"),
@@ -4314,7 +4371,8 @@ 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 (G_("passing argument %d of %qE makes "
+               WARN_FOR_ASSIGNMENT (input_location, 0,
+                                    G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
                                        "from unqualified"),
                                     G_("assignment makes qualified function "
@@ -4328,7 +4386,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       else
        /* Avoid warning about the volatile ObjC EH puts on decls.  */
        if (!objc_ok)
-         WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from "
+         WARN_FOR_ASSIGNMENT (input_location, 0,
+                              G_("passing argument %d of %qE from "
                                  "incompatible pointer type"),
                               G_("assignment from incompatible pointer type"),
                               G_("initialization from incompatible "
@@ -4350,7 +4409,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       if (!null_pointer_constant_p (rhs))
-       WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
+       WARN_FOR_ASSIGNMENT (input_location, 0,
+                            G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
                             G_("assignment makes pointer from integer "
                                "without a cast"),
@@ -4363,7 +4423,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer "
+      WARN_FOR_ASSIGNMENT (input_location, 0,
+                          G_("passing argument %d of %qE makes integer "
                              "from pointer without a cast"),
                           G_("assignment makes integer from pointer "
                              "without a cast"),
@@ -4379,19 +4440,22 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   switch (errtype)
     {
     case ic_argpass:
-    case ic_argpass_nonproto:
-      /* ??? This should not be an error when inlining calls to
-        unprototyped functions.  */
       error ("incompatible type for argument %d of %qE", parmnum, rname);
+      inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
+             ? DECL_SOURCE_LOCATION (fundecl) : input_location,
+             "expected %qT but argument is of type %qT", type, rhstype);
       break;
     case ic_assign:
-      error ("incompatible types in assignment");
+      error ("incompatible types when assigning to type %qT from type %qT",
+            type, rhstype);
       break;
     case ic_init:
-      error ("incompatible types in initialization");
+      error ("incompatible types when initializing type %qT using type %qT",
+            type, rhstype);
       break;
     case ic_return:
-      error ("incompatible types in return");
+      error ("incompatible types when returning type %qT but %qT was expected",
+            rhstype, type);
       break;
     default:
       gcc_unreachable ();
@@ -4621,34 +4685,37 @@ error_init (const char *msgid)
     error ("(near initialization for %qs)", ofwhat);
 }
 
-/* Issue a pedantic warning for a bad initializer component.
-   MSGID identifies the message.
-   The component name is taken from the spelling stack.  */
+/* Issue a pedantic warning for a bad initializer component.  OPT is
+   the option OPT_* (from options.h) controlling this warning or 0 if
+   it is unconditionally given.  MSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
 
 void
-pedwarn_init (const char *msgid)
+pedwarn_init (location_t location, int opt, const char *msgid)
 {
   char *ofwhat;
 
-  pedwarn ("%s", _(msgid));
+  pedwarn (location, opt, "%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    pedwarn ("(near initialization for %qs)", ofwhat);
+    pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
 }
 
-/* Issue a warning for a bad initializer component.
-   MSGID identifies the message.
-   The component name is taken from the spelling stack.  */
+/* Issue a warning for a bad initializer component.  
+
+   OPT is the OPT_W* value corresponding to the warning option that
+   controls this warning.  MSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
 
 static void
-warning_init (const char *msgid)
+warning_init (int opt, const char *msgid)
 {
   char *ofwhat;
 
-  warning (0, "%s", _(msgid));
+  warning (opt, "%s", _(msgid));
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
-    warning (0, "(near initialization for %qs)", ofwhat);
+    warning (opt, "(near initialization for %qs)", ofwhat);
 }
 \f
 /* If TYPE is an array type and EXPR is a parenthesized string
@@ -4662,7 +4729,8 @@ maybe_warn_string_init (tree type, struct c_expr expr)
       && TREE_CODE (type) == ARRAY_TYPE
       && TREE_CODE (expr.value) == STRING_CST
       && expr.original_code != STRING_CST)
-    pedwarn_init ("array initialized from parenthesized string constant");
+    pedwarn_init (input_location, OPT_pedantic, 
+                 "array initialized from parenthesized string constant");
 }
 
 /* Digest the parser output INIT as an initializer for type TYPE.
@@ -4705,48 +4773,58 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
                         || typ1 == signed_char_type_node
                         || typ1 == unsigned_char_type_node);
       bool wchar_array = !!comptypes (typ1, wchar_type_node);
-      if (char_array || wchar_array)
+      bool char16_array = !!comptypes (typ1, char16_type_node);
+      bool char32_array = !!comptypes (typ1, char32_type_node);
+
+      if (char_array || wchar_array || char16_array || char32_array)
        {
          struct c_expr expr;
-         bool char_string;
+         tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
          expr.value = inside_init;
          expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
          maybe_warn_string_init (type, expr);
 
-         char_string
-           = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
-              == char_type_node);
-
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                         TYPE_MAIN_VARIANT (type)))
            return inside_init;
 
-         if (!wchar_array && !char_string)
+         if (char_array)
            {
-             error_init ("char-array initialized from wide string");
-             return error_mark_node;
+             if (typ2 != char_type_node)
+               {
+                 error_init ("char-array initialized from wide string");
+                 return error_mark_node;
+               }
            }
-         if (char_string && !char_array)
+         else
            {
-             error_init ("wchar_t-array initialized from non-wide string");
-             return error_mark_node;
+             if (typ2 == char_type_node)
+               {
+                 error_init ("wide character array initialized from non-wide "
+                             "string");
+                 return error_mark_node;
+               }
+             else if (!comptypes(typ1, typ2))
+               {
+                 error_init ("wide character array initialized from "
+                             "incompatible wide string");
+                 return error_mark_node;
+               }
            }
 
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
              && TYPE_SIZE (type) != 0
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
-             /* Subtract 1 (or sizeof (wchar_t))
+             /* Subtract the size of a single (possibly wide) character
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
              && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
                                       TREE_STRING_LENGTH (inside_init)
-                                      - ((TYPE_PRECISION (typ1)
-                                          != TYPE_PRECISION (char_type_node))
-                                         ? (TYPE_PRECISION (wchar_type_node)
-                                            / BITS_PER_UNIT)
-                                         : 1)))
-           pedwarn_init ("initializer-string for array of chars is too long");
+                                      - (TYPE_PRECISION (typ1)
+                                         / BITS_PER_UNIT)))
+           pedwarn_init (input_location, 0, 
+                         "initializer-string for array of chars is too long");
 
          return inside_init;
        }
@@ -4792,6 +4870,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
        }
     }
 
+  if (warn_sequence_point)
+    verify_sequence_points (inside_init);
+
   /* Any type can be initialized
      from an expression of the same type, optionally with braces.  */
 
@@ -4861,7 +4942,8 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
          if (inside_init == error_mark_node)
            error_init ("initializer element is not constant");
          else
-           pedwarn_init ("initializer element is not constant");
+           pedwarn_init (input_location, OPT_pedantic,
+                         "initializer element is not constant");
          if (flag_pedantic_errors)
            inside_init = error_mark_node;
        }
@@ -5307,12 +5389,12 @@ push_init_level (int implicit)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
-           process_init_element (pop_init_level (1));
+           process_init_element (pop_init_level (1), true);
          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));
+           process_init_element (pop_init_level (1), true);
          else
            break;
        }
@@ -5415,7 +5497,7 @@ push_init_level (int implicit)
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
     {
       missing_braces_mentioned = 1;
-      warning_init ("missing braces around initializer");
+      warning_init (OPT_Wmissing_braces, "missing braces around initializer");
     }
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5476,7 +5558,7 @@ push_init_level (int implicit)
   else
     {
       if (constructor_type != error_mark_node)
-       warning_init ("braces around scalar initializer");
+       warning_init (0, "braces around scalar initializer");
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -5506,7 +5588,7 @@ pop_init_level (int implicit)
       /* When we come to an explicit close brace,
         pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1));
+       process_init_element (pop_init_level (1), true);
 
       gcc_assert (!constructor_range_stack);
     }
@@ -5534,8 +5616,9 @@ pop_init_level (int implicit)
 
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
-         else if (pedantic)
-           pedwarn_init ("initialization of a flexible array member");
+         else
+           pedwarn_init (input_location, OPT_pedantic,
+                         "initialization of a flexible array member");
 
          /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
@@ -5562,7 +5645,8 @@ pop_init_level (int implicit)
        if (constructor_unfilled_fields && !constructor_designated)
          {
            push_member_name (constructor_unfilled_fields);
-           warning_init ("missing initializer");
+           warning_init (OPT_Wmissing_field_initializers,
+                          "missing initializer");
            RESTORE_SPELLING_DEPTH (constructor_depth);
          }
     }
@@ -5604,7 +5688,7 @@ pop_init_level (int implicit)
          ret.value = build_constructor (constructor_type,
                                         constructor_elements);
          if (constructor_constant)
-           TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+           TREE_CONSTANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
            TREE_STATIC (ret.value) = 1;
        }
@@ -5663,7 +5747,7 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1));
+       process_init_element (pop_init_level (1), true);
       constructor_designated = 1;
       return 0;
     }
@@ -5824,10 +5908,15 @@ set_init_label (tree fieldname)
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
    identifies the initializer, either array index or field in a structure.
-   VALUE is the value of that index or field.  */
+   VALUE is the value of that index or field.
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value)
+add_pending_init (tree purpose, tree value, bool implicit)
 {
   struct init_node *p, **q, *r;
 
@@ -5845,10 +5934,13 @@ add_pending_init (tree purpose, tree value)
            q = &p->right;
          else
            {
-             if (TREE_SIDE_EFFECTS (p->value))
-               warning_init ("initialized field with side-effects overwritten");
-             else if (warn_override_init)
-               warning_init ("initialized field overwritten");
+             if (!implicit)
+               {
+                 if (TREE_SIDE_EFFECTS (p->value))
+                   warning_init (0, "initialized field with side-effects overwritten");
+                 else if (warn_override_init)
+                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+               }
              p->value = value;
              return;
            }
@@ -5868,10 +5960,13 @@ add_pending_init (tree purpose, tree value)
            q = &p->right;
          else
            {
-             if (TREE_SIDE_EFFECTS (p->value))
-               warning_init ("initialized field with side-effects overwritten");
-             else if (warn_override_init)
-               warning_init ("initialized field overwritten");
+             if (!implicit)
+               {
+                 if (TREE_SIDE_EFFECTS (p->value))
+                   warning_init (0, "initialized field with side-effects overwritten");
+                 else if (warn_override_init)
+                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+               }
              p->value = value;
              return;
            }
@@ -6056,7 +6151,7 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value);
+    add_pending_init (index, value, false);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -6092,15 +6187,7 @@ set_nonincremental_init_from_string (tree str)
 
   gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
 
-  if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
-      == TYPE_PRECISION (char_type_node))
-    wchar_bytes = 1;
-  else
-    {
-      gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
-                 == TYPE_PRECISION (wchar_type_node));
-      wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
-    }
+  wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT;
   charwidth = TYPE_PRECISION (char_type_node);
   type = TREE_TYPE (constructor_type);
   p = TREE_STRING_POINTER (str);
@@ -6154,7 +6241,7 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value);
+      add_pending_init (purpose, value, false);
     }
 
   constructor_incremental = 0;
@@ -6227,11 +6314,16 @@ find_init_member (tree field)
 
    PENDING if non-nil means output pending elements that belong
    right after this element.  (PENDING is normally 1;
-   it is 0 while outputting pending elements, to avoid recursion.)  */
+   it is 0 while outputting pending elements, to avoid recursion.)
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
 
 static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
-                    int pending)
+                    int pending, bool implicit)
 {
   constructor_elt *celt;
 
@@ -6279,7 +6371,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
          value = error_mark_node;
        }
       else if (require_constant_elements)
-       pedwarn ("initializer element is not computable at load time");
+       pedwarn (input_location, 0,
+                "initializer element is not computable at load time");
     }
 
   /* If this field is empty (and not at the end of structure),
@@ -6309,7 +6402,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
          && tree_int_cst_lt (field, constructor_unfilled_index))
        set_nonincremental_init ();
 
-      add_pending_init (field, value);
+      add_pending_init (field, value, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -6335,17 +6428,21 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
            }
        }
 
-      add_pending_init (field, value);
+      add_pending_init (field, value, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
           && !VEC_empty (constructor_elt, constructor_elements))
     {
-      if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
-                                      constructor_elements)->value))
-       warning_init ("initialized field with side-effects overwritten");
-      else if (warn_override_init)
-       warning_init ("initialized field overwritten");
+      if (!implicit)
+       {
+         if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+                                          constructor_elements)->value))
+           warning_init (0,
+                         "initialized field with side-effects overwritten");
+         else if (warn_override_init)
+           warning_init (OPT_Woverride_init, "initialized field overwritten");
+       }
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
@@ -6416,7 +6513,7 @@ output_pending_init_elements (int all)
                                  constructor_unfilled_index))
            output_init_element (elt->value, true,
                                 TREE_TYPE (constructor_type),
-                                constructor_unfilled_index, 0);
+                                constructor_unfilled_index, 0, false);
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
@@ -6469,7 +6566,7 @@ output_pending_init_elements (int all)
            {
              constructor_unfilled_fields = elt->purpose;
              output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
-                                  elt->purpose, 0);
+                                  elt->purpose, 0, false);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
@@ -6532,10 +6629,15 @@ output_pending_init_elements (int all)
    to handle a partly-braced initializer.
 
    Once this has found the correct level for the new element,
-   it calls output_init_element.  */
+   it calls output_init_element.
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
 
 void
-process_init_element (struct c_expr value)
+process_init_element (struct c_expr value, bool implicit)
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -6576,12 +6678,12 @@ process_init_element (struct c_expr value)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
-       process_init_element (pop_init_level (1));
+       process_init_element (pop_init_level (1), true);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
-       process_init_element (pop_init_level (1));
+       process_init_element (pop_init_level (1), true);
       else
        break;
     }
@@ -6606,7 +6708,8 @@ process_init_element (struct c_expr value)
 
          if (constructor_fields == 0)
            {
-             pedwarn_init ("excess elements in struct initializer");
+             pedwarn_init (input_location, 0,
+                           "excess elements in struct initializer");
              break;
            }
 
@@ -6647,7 +6750,7 @@ process_init_element (struct c_expr value)
            {
              push_member_name (constructor_fields);
              output_init_element (value.value, strict_string,
-                                  fieldtype, constructor_fields, 1);
+                                  fieldtype, constructor_fields, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -6689,7 +6792,8 @@ process_init_element (struct c_expr value)
 
          if (constructor_fields == 0)
            {
-             pedwarn_init ("excess elements in union initializer");
+             pedwarn_init (input_location, 0,
+                           "excess elements in union initializer");
              break;
            }
 
@@ -6736,7 +6840,7 @@ process_init_element (struct c_expr value)
            {
              push_member_name (constructor_fields);
              output_init_element (value.value, strict_string,
-                                  fieldtype, constructor_fields, 1);
+                                  fieldtype, constructor_fields, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -6776,7 +6880,8 @@ process_init_element (struct c_expr value)
              && (tree_int_cst_lt (constructor_max_index, constructor_index)
                  || integer_all_onesp (constructor_max_index)))
            {
-             pedwarn_init ("excess elements in array initializer");
+             pedwarn_init (input_location, 0,
+                           "excess elements in array initializer");
              break;
            }
 
@@ -6785,7 +6890,7 @@ process_init_element (struct c_expr value)
            {
              push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, strict_string,
-                                  elttype, constructor_index, 1);
+                                  elttype, constructor_index, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
@@ -6806,14 +6911,15 @@ process_init_element (struct c_expr value)
            always have a fixed size derived from their type.  */
          if (tree_int_cst_lt (constructor_max_index, constructor_index))
            {
-             pedwarn_init ("excess elements in vector initializer");
+             pedwarn_init (input_location, 0,
+                           "excess elements in vector initializer");
              break;
            }
 
          /* Now output the actual element.  */
          if (value.value)
            output_init_element (value.value, strict_string,
-                                elttype, constructor_index, 1);
+                                elttype, constructor_index, 1, implicit);
 
          constructor_index
            = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
@@ -6830,14 +6936,15 @@ process_init_element (struct c_expr value)
       else if (constructor_type != error_mark_node
               && constructor_fields == 0)
        {
-         pedwarn_init ("excess elements in scalar initializer");
+         pedwarn_init (input_location, 0,
+                       "excess elements in scalar initializer");
          break;
        }
       else
        {
          if (value.value)
            output_init_element (value.value, strict_string,
-                                constructor_type, NULL_TREE, 1);
+                                constructor_type, NULL_TREE, 1, implicit);
          constructor_fields = 0;
        }
 
@@ -6853,14 +6960,14 @@ process_init_element (struct c_expr value)
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1));
+             process_init_element (pop_init_level (1), true);
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1));
+             process_init_element (pop_init_level (1), true);
            }
 
          p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
@@ -7061,8 +7168,7 @@ c_finish_goto_label (tree label)
 tree
 c_finish_goto_ptr (tree expr)
 {
-  if (pedantic)
-    pedwarn ("ISO C forbids %<goto *expr;%>");
+  pedwarn (input_location, OPT_pedantic, "ISO C forbids %<goto *expr;%>");
   expr = convert (ptr_type_node, expr);
   return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
 }
@@ -7085,7 +7191,8 @@ c_finish_return (tree retval)
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
-         pedwarn_c99 ("%<return%> with no value, in "
+         pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wreturn_type, 
+                      "%<return%> with no value, in "
                       "function returning non-void");
          no_warning = true;
        }
@@ -7094,9 +7201,11 @@ c_finish_return (tree retval)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn ("%<return%> with a value, in function returning void");
-      else if (pedantic)
-       pedwarn ("ISO C forbids %<return%> with expression, in function returning void");
+       pedwarn (input_location, 0, 
+                "%<return%> with a value, in function returning void");
+      else 
+       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+                "%<return%> with expression, in function returning void");
     }
   else
     {
@@ -7117,8 +7226,10 @@ c_finish_return (tree retval)
        {
          switch (TREE_CODE (inner))
            {
-           case NOP_EXPR:   case NON_LVALUE_EXPR:  case CONVERT_EXPR:
+           CASE_CONVERT:
+           case NON_LVALUE_EXPR:
            case PLUS_EXPR:
+           case POINTER_PLUS_EXPR:
              inner = TREE_OPERAND (inner, 0);
              continue;
 
@@ -7130,9 +7241,8 @@ c_finish_return (tree retval)
                tree op1 = TREE_OPERAND (inner, 1);
 
                while (!POINTER_TYPE_P (TREE_TYPE (op1))
-                      && (TREE_CODE (op1) == NOP_EXPR
-                          || TREE_CODE (op1) == NON_LVALUE_EXPR
-                          || TREE_CODE (op1) == CONVERT_EXPR))
+                      && (CONVERT_EXPR_P (op1)
+                          || TREE_CODE (op1) == NON_LVALUE_EXPR))
                  op1 = TREE_OPERAND (op1, 0);
 
                if (POINTER_TYPE_P (TREE_TYPE (op1)))
@@ -7164,6 +7274,9 @@ c_finish_return (tree retval)
        }
 
       retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
+
+      if (warn_sequence_point)
+       verify_sequence_points (retval);
     }
 
   ret_stmt = build_stmt (RETURN_EXPR, retval);
@@ -7241,6 +7354,9 @@ c_start_case (tree exp)
                     "converted to %<int%> in ISO C");
 
          exp = default_conversion (exp);
+
+         if (warn_sequence_point)
+           verify_sequence_points (exp);
        }
     }
 
@@ -7376,8 +7492,6 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
                  &if_locus);
     }
 
-  empty_if_body_warning (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);
@@ -7500,6 +7614,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
   if (skip)
     return NULL_TREE;
 
+  if (!is_break)
+    add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
+
   return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
 }
 
@@ -7856,6 +7973,7 @@ push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
 \f
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
+   LOCATION is the operator's location.
    This function differs from `build' in several ways:
    the data type of the result is computed and recorded in it,
    warnings are generated if arg data types are invalid,
@@ -7870,12 +7988,13 @@ push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
    the arithmetic is to be done.  */
 
 tree
-build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
-                int convert_p)
+build_binary_op (location_t location, enum tree_code code,
+                tree orig_op0, tree orig_op1, int convert_p)
 {
   tree type0, type1;
   enum tree_code code0, code1;
   tree op0, op1;
+  tree ret = error_mark_node;
   const char *invalid_op_diag;
 
   /* Expression code to give to the expression when it is built.
@@ -7923,6 +8042,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   /* True means types are compatible as far as ObjC is concerned.  */
   bool objc_ok;
 
+  if (location == UNKNOWN_LOCATION)
+    location = input_location;
+
   if (convert_p)
     {
       op0 = default_conversion (orig_op0);
@@ -7955,7 +8077,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if ((invalid_op_diag
        = targetm.invalid_binary_op (code, type0, type1)))
     {
-      error (invalid_op_diag);
+      error_at (location, invalid_op_diag);
       return error_mark_node;
     }
 
@@ -7966,9 +8088,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case PLUS_EXPR:
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       return pointer_int_sum (PLUS_EXPR, op0, op1);
+       {
+         ret = pointer_int_sum (PLUS_EXPR, op0, op1);
+         goto return_build_binary_op;
+       }
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
-       return pointer_int_sum (PLUS_EXPR, op1, op0);
+       {
+         ret = pointer_int_sum (PLUS_EXPR, op1, op0);
+         goto return_build_binary_op;
+       }
       else
        common = 1;
       break;
@@ -7978,10 +8106,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
          && comp_target_types (type0, type1))
-       return pointer_diff (op0, op1);
+       {
+         ret = pointer_diff (op0, op1);
+         goto return_build_binary_op;
+       }
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       return pointer_int_sum (MINUS_EXPR, op0, op1);
+       {
+         ret = pointer_int_sum (MINUS_EXPR, op0, op1);
+         goto return_build_binary_op;
+       }
       else
        common = 1;
       break;
@@ -7995,7 +8129,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
-      warn_for_div_by_zero (op1);
+      warn_for_div_by_zero (location, op1);
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == FIXED_POINT_TYPE
@@ -8042,7 +8176,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
-      warn_for_div_by_zero (op1);
+      warn_for_div_by_zero (location, op1);
 
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -8073,8 +8207,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
             but that does not mean the operands should be
             converted to ints!  */
          result_type = integer_type_node;
-         op0 = c_common_truthvalue_conversion (op0);
-         op1 = c_common_truthvalue_conversion (op1);
+         op0 = c_common_truthvalue_conversion (location, op0);
+         op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
        }
       break;
@@ -8138,9 +8272,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case EQ_EXPR:
     case NE_EXPR:
-      if (code0 == REAL_TYPE || code1 == REAL_TYPE)
-       warning (OPT_Wfloat_equal,
-                "comparing floating point with == or != is unsafe");
+      if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
+       warning_at (location,
+                   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;
@@ -8164,20 +8299,21 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 whose value is 0 but which isn't a valid null ptr const.  */
              if (pedantic && !null_pointer_constant_p (orig_op0)
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids comparison of %<void *%>"
-                        " with function pointer");
+               pedwarn (location, OPT_pedantic, "ISO C forbids "
+                        "comparison of %<void *%> with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
              if (pedantic && !null_pointer_constant_p (orig_op1)
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids comparison of %<void *%>"
-                        " with function pointer");
+               pedwarn (location, OPT_pedantic, "ISO C forbids "
+                        "comparison of %<void *%> with function pointer");
            }
          else
            /* Avoid warning about the volatile ObjC EH puts on decls.  */
            if (!objc_ok)
-             pedwarn ("comparison of distinct pointer types lacks a cast");
+             pedwarn (location, 0,
+                      "comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
            result_type = ptr_type_node;
@@ -8186,27 +8322,29 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        {
          if (TREE_CODE (op0) == ADDR_EXPR
              && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
-           warning (OPT_Waddress, "the address of %qD will never be NULL",
-                    TREE_OPERAND (op0, 0));
+           warning_at (location,
+                       OPT_Waddress, "the address of %qD will never be NULL",
+                       TREE_OPERAND (op0, 0));
          result_type = type0;
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          if (TREE_CODE (op1) == ADDR_EXPR
              && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
-           warning (OPT_Waddress, "the address of %qD will never be NULL",
-                    TREE_OPERAND (op1, 0));
+           warning_at (location,
+                       OPT_Waddress, "the address of %qD will never be NULL",
+                       TREE_OPERAND (op1, 0));
          result_type = type1;
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
-         pedwarn ("comparison between pointer and integer");
+         pedwarn (location, 0, "comparison between pointer and integer");
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
          result_type = type1;
-         pedwarn ("comparison between pointer and integer");
+         pedwarn (location, 0, "comparison between pointer and integer");
        }
       break;
 
@@ -8227,38 +8365,44 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
              result_type = common_pointer_type (type0, type1);
              if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
                  != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
-               pedwarn ("comparison of complete and incomplete pointers");
-             else if (pedantic
-                      && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-               pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
+               pedwarn (location, 0,
+                        "comparison of complete and incomplete pointers");
+             else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
+               pedwarn (location, OPT_pedantic, "ISO C forbids "
+                        "ordered comparisons of pointers to functions");
            }
          else
            {
              result_type = ptr_type_node;
-             pedwarn ("comparison of distinct pointer types lacks a cast");
+             pedwarn (location, 0,
+                      "comparison of distinct pointer types lacks a cast");
            }
        }
       else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
          result_type = type0;
-         if (pedantic || extra_warnings)
-           pedwarn ("ordered comparison of pointer with integer zero");
+         if (pedantic)
+           pedwarn (location, OPT_pedantic, 
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                    "ordered comparison of pointer with integer zero");
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         if (pedantic)
-           pedwarn ("ordered comparison of pointer with integer zero");
+         pedwarn (location, OPT_pedantic, 
+                  "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
-         pedwarn ("comparison between pointer and integer");
+         pedwarn (location, 0, "comparison between pointer and integer");
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
          result_type = type1;
-         pedwarn ("comparison between pointer and integer");
+         pedwarn (location, 0, "comparison between pointer and integer");
        }
       break;
 
@@ -8274,7 +8418,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
                                                    TREE_TYPE (type1))))
     {
-      binary_op_error (code, type0, type1);
+      binary_op_error (location, code, type0, type1);
       return error_mark_node;
     }
 
@@ -8306,93 +8450,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
       if (shorten && none_complex)
        {
-         int unsigned0, unsigned1;
-         tree arg0, arg1;
-         int uns;
-         tree type;
-
-         /* Cast OP0 and OP1 to RESULT_TYPE.  Doing so prevents
-            excessive narrowing when we call get_narrower below.  For
-            example, suppose that OP0 is of unsigned int extended
-            from signed char and that RESULT_TYPE is long long int.
-            If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
-            like
-
-              (long long int) (unsigned int) signed_char
-
-            which get_narrower would narrow down to
-
-              (unsigned int) signed char
-
-            If we do not cast OP0 first, get_narrower would return
-            signed_char, which is inconsistent with the case of the
-            explicit cast.  */
-         op0 = convert (result_type, op0);
-         op1 = convert (result_type, op1);
-
-         arg0 = get_narrower (op0, &unsigned0);
-         arg1 = get_narrower (op1, &unsigned1);
-
-         /* UNS is 1 if the operation to be done is an unsigned one.  */
-         uns = TYPE_UNSIGNED (result_type);
-
          final_type = result_type;
-
-         /* Handle the case that OP0 (or OP1) does not *contain* a conversion
-            but it *requires* conversion to FINAL_TYPE.  */
-
-         if ((TYPE_PRECISION (TREE_TYPE (op0))
-              == TYPE_PRECISION (TREE_TYPE (arg0)))
-             && TREE_TYPE (op0) != final_type)
-           unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
-         if ((TYPE_PRECISION (TREE_TYPE (op1))
-              == TYPE_PRECISION (TREE_TYPE (arg1)))
-             && TREE_TYPE (op1) != final_type)
-           unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
-
-         /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */
-
-         /* For bitwise operations, signedness of nominal type
-            does not matter.  Consider only how operands were extended.  */
-         if (shorten == -1)
-           uns = unsigned0;
-
-         /* Note that in all three cases below we refrain from optimizing
-            an unsigned operation on sign-extended args.
-            That would not be valid.  */
-
-         /* Both args variable: if both extended in same way
-            from same width, do it in that width.
-            Do it unsigned if args were zero-extended.  */
-         if ((TYPE_PRECISION (TREE_TYPE (arg0))
-              < TYPE_PRECISION (result_type))
-             && (TYPE_PRECISION (TREE_TYPE (arg1))
-                 == TYPE_PRECISION (TREE_TYPE (arg0)))
-             && unsigned0 == unsigned1
-             && (unsigned0 || !uns))
-           result_type
-             = c_common_signed_or_unsigned_type
-             (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
-         else if (TREE_CODE (arg0) == INTEGER_CST
-                  && (unsigned1 || !uns)
-                  && (TYPE_PRECISION (TREE_TYPE (arg1))
-                      < TYPE_PRECISION (result_type))
-                  && (type
-                      = c_common_signed_or_unsigned_type (unsigned1,
-                                                          TREE_TYPE (arg1)))
-                  && !POINTER_TYPE_P (type)
-                  && int_fits_type_p (arg0, type))
-           result_type = type;
-         else if (TREE_CODE (arg1) == INTEGER_CST
-                  && (unsigned0 || !uns)
-                  && (TYPE_PRECISION (TREE_TYPE (arg0))
-                      < TYPE_PRECISION (result_type))
-                  && (type
-                      = c_common_signed_or_unsigned_type (unsigned0,
-                                                          TREE_TYPE (arg0)))
-                  && !POINTER_TYPE_P (type)
-                  && int_fits_type_p (arg1, type))
-           result_type = type;
+         result_type = shorten_binary_op (result_type, op0, op1, 
+                                          shorten == -1);
        }
 
       /* Shifts can be shortened if shifting right.  */
@@ -8440,130 +8500,19 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
            = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
 
          if (val != 0)
-           return val;
+           {
+             ret = val;
+             goto return_build_binary_op;
+           }
 
          op0 = xop0, op1 = xop1;
          converted = 1;
          resultcode = xresultcode;
 
-         if (warn_sign_compare && skip_evaluation == 0)
-           {
-             int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
-             int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
-             int unsignedp0, unsignedp1;
-             tree primop0 = get_narrower (op0, &unsignedp0);
-             tree primop1 = get_narrower (op1, &unsignedp1);
-
-             xop0 = orig_op0;
-             xop1 = orig_op1;
-             STRIP_TYPE_NOPS (xop0);
-             STRIP_TYPE_NOPS (xop1);
-
-             /* Give warnings for comparisons between signed and unsigned
-                quantities that may fail.
-
-                Do the checking based on the original operand trees, so that
-                casts will be considered, but default promotions won't be.
-
-                Do not warn if the comparison is being done in a signed type,
-                since the signed type will only be chosen if it can represent
-                all the values of the unsigned type.  */
-             if (!TYPE_UNSIGNED (result_type))
-               /* OK */;
-             /* Do not warn if both operands are the same signedness.  */
-             else if (op0_signed == op1_signed)
-               /* OK */;
-             else
-               {
-                 tree sop, uop;
-                 bool ovf;
-
-                 if (op0_signed)
-                   sop = xop0, uop = xop1;
-                 else
-                   sop = xop1, uop = xop0;
-
-                 /* Do not warn if the signed quantity is an
-                    unsuffixed integer literal (or some static
-                    constant expression involving such literals or a
-                    conditional expression involving such literals)
-                    and it is non-negative.  */
-                 if (tree_expr_nonnegative_warnv_p (sop, &ovf))
-                   /* OK */;
-                 /* Do not warn if the comparison is an equality operation,
-                    the unsigned quantity is an integral constant, and it
-                    would fit in the result if the result were signed.  */
-                 else if (TREE_CODE (uop) == INTEGER_CST
-                          && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
-                          && int_fits_type_p
-                          (uop, c_common_signed_type (result_type)))
-                   /* OK */;
-                 /* Do not warn if the unsigned quantity is an enumeration
-                    constant and its maximum value would fit in the result
-                    if the result were signed.  */
-                 else if (TREE_CODE (uop) == INTEGER_CST
-                          && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
-                          && int_fits_type_p
-                          (TYPE_MAX_VALUE (TREE_TYPE (uop)),
-                           c_common_signed_type (result_type)))
-                   /* OK */;
-                 else
-                   warning (OPT_Wsign_compare, "comparison between signed and unsigned");
-               }
-
-             /* Warn if two unsigned values are being compared in a size
-                larger than their original size, and one (and only one) is the
-                result of a `~' operator.  This comparison will always fail.
-
-                Also warn if one operand is a constant, and the constant
-                does not have all bits set that are set in the ~ operand
-                when it is extended.  */
-
-             if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
-                 != (TREE_CODE (primop1) == BIT_NOT_EXPR))
-               {
-                 if (TREE_CODE (primop0) == BIT_NOT_EXPR)
-                   primop0 = get_narrower (TREE_OPERAND (primop0, 0),
-                                           &unsignedp0);
-                 else
-                   primop1 = get_narrower (TREE_OPERAND (primop1, 0),
-                                           &unsignedp1);
-
-                 if (host_integerp (primop0, 0) || host_integerp (primop1, 0))
-                   {
-                     tree primop;
-                     HOST_WIDE_INT constant, mask;
-                     int unsignedp, bits;
-
-                     if (host_integerp (primop0, 0))
-                       {
-                         primop = primop1;
-                         unsignedp = unsignedp1;
-                         constant = tree_low_cst (primop0, 0);
-                       }
-                     else
-                       {
-                         primop = primop0;
-                         unsignedp = unsignedp0;
-                         constant = tree_low_cst (primop1, 0);
-                       }
-
-                     bits = TYPE_PRECISION (TREE_TYPE (primop));
-                     if (bits < TYPE_PRECISION (result_type)
-                         && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
-                       {
-                         mask = (~(HOST_WIDE_INT) 0) << bits;
-                         if ((mask & constant) != mask)
-                           warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant");
-                       }
-                   }
-                 else if (unsignedp0 && unsignedp1
-                          && (TYPE_PRECISION (TREE_TYPE (primop0))
-                              < TYPE_PRECISION (result_type))
-                          && (TYPE_PRECISION (TREE_TYPE (primop1))
-                              < TYPE_PRECISION (result_type)))
-                   warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned");
-               }
+         if (warn_sign_compare && !skip_evaluation)
+            {
+              warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, 
+                                     result_type, resultcode);
            }
        }
     }
@@ -8576,7 +8525,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
   if (!result_type)
     {
-      binary_op_error (code, TREE_TYPE (op0), TREE_TYPE (op1));
+      binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
       return error_mark_node;
     }
 
@@ -8596,39 +8545,40 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (build_type == NULL_TREE)
     build_type = result_type;
 
-  {
-    /* Treat expressions in initializers specially as they can't trap.  */
-    tree result = require_constant_value ? fold_build2_initializer (resultcode,
-                                                                   build_type,
-                                                                   op0, op1)
-                                        : fold_build2 (resultcode, build_type,
-                                                       op0, op1);
-
-    if (final_type != 0)
-      result = convert (final_type, result);
-    return result;
-  }
+  /* Treat expressions in initializers specially as they can't trap.  */
+  ret = require_constant_value ? fold_build2_initializer (resultcode,
+                                                         build_type,
+                                                         op0, op1)
+                              : fold_build2 (resultcode, build_type,
+                                             op0, op1);
+  if (final_type != 0)
+    ret = convert (final_type, ret);
+
+ return_build_binary_op:
+  gcc_assert (ret != error_mark_node);
+  protected_set_expr_location (ret, location);
+  return ret;
 }
 
 
 /* Convert EXPR to be a truth-value, validating its type for this
-   purpose.  */
+   purpose.  LOCATION is the source location for the expression.  */
 
 tree
-c_objc_common_truthvalue_conversion (tree expr)
+c_objc_common_truthvalue_conversion (location_t location, tree expr)
 {
   switch (TREE_CODE (TREE_TYPE (expr)))
     {
     case ARRAY_TYPE:
-      error ("used array that cannot be converted to pointer where scalar is required");
+      error_at (location, "used array that cannot be converted to pointer where scalar is required");
       return error_mark_node;
 
     case RECORD_TYPE:
-      error ("used struct type value where scalar is required");
+      error_at (location, "used struct type value where scalar is required");
       return error_mark_node;
 
     case UNION_TYPE:
-      error ("used union type value where scalar is required");
+      error_at (location, "used union type value where scalar is required");
       return error_mark_node;
 
     case FUNCTION_TYPE:
@@ -8640,7 +8590,7 @@ c_objc_common_truthvalue_conversion (tree expr)
 
   /* ??? Should we also give an error for void and vectors rather than
      leaving those to give errors later?  */
-  return c_common_truthvalue_conversion (expr);
+  return c_common_truthvalue_conversion (location, expr);
 }
 \f
 
@@ -8648,8 +8598,7 @@ c_objc_common_truthvalue_conversion (tree expr)
    required.  */
 
 tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
-               bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
 {
   if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
     {
@@ -8677,6 +8626,8 @@ c_begin_omp_parallel (void)
   return block;
 }
 
+/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound statement.  */
+
 tree
 c_finish_omp_parallel (tree clauses, tree block)
 {
@@ -8692,6 +8643,36 @@ c_finish_omp_parallel (tree clauses, tree block)
   return add_stmt (stmt);
 }
 
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_task (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound statement.  */
+
+tree
+c_finish_omp_task (tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (block, true);
+
+  stmt = make_node (OMP_TASK);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TASK_CLAUSES (stmt) = clauses;
+  OMP_TASK_BODY (stmt) = block;
+
+  return add_stmt (stmt);
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -8852,6 +8833,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
+       case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_COLLAPSE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;