OSDN Git Service

PR c/38957
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 121feba..4b9b2b3 100644 (file)
@@ -1,13 +1,13 @@
 /* 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
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file is part of the C front end.
@@ -43,14 +42,13 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #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
@@ -75,12 +73,12 @@ static int missing_braces_mentioned;
 static int require_constant_value;
 static int require_constant_elements;
 
-static bool null_pointer_constant_p (tree);
+static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (tree, tree);
+static int tagged_types_tu_compatible_p (const_tree, const_tree);
 static int comp_target_types (tree, tree);
-static int function_types_compatible_p (tree, tree);
-static int type_lists_compatible_p (tree, tree);
+static int function_types_compatible_p (const_tree, const_tree);
+static int type_lists_compatible_p (const_tree, const_tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
 static int convert_arguments (int, tree *, tree, tree, tree, tree);
@@ -92,26 +90,26 @@ 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);
 static void readonly_error (tree, enum lvalue_use);
-static int lvalue_or_else (tree, enum lvalue_use);
-static int lvalue_p (tree);
+static int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (tree, tree);
+static int comptypes_internal (const_tree, const_tree);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
 static bool
-null_pointer_constant_p (tree expr)
+null_pointer_constant_p (const_tree expr)
 {
   /* This should really operate on c_expr structures, but they aren't
      yet available everywhere required.  */
@@ -128,8 +126,8 @@ null_pointer_constant_p (tree expr)
 
 struct tagged_tu_seen_cache {
   const struct tagged_tu_seen_cache * next;
-  tree t1;
-  tree t2;
+  const_tree t1;
+  const_tree t2;
   /* The return value of tagged_types_tu_compatible_p if we had seen
      these two types already.  */
   int val;
@@ -162,7 +160,7 @@ require_complete_type (tree value)
    and TYPE is the type that was invalid.  */
 
 void
-c_incomplete_type_error (tree value, tree type)
+c_incomplete_type_error (const_tree value, const_tree type)
 {
   const char *type_code_string;
 
@@ -257,7 +255,7 @@ qualify_type (tree type, tree like)
 /* Return true iff the given tree T is a variable length array.  */
 
 bool
-c_vla_type_p (tree t)
+c_vla_type_p (const_tree t)
 {
   if (TREE_CODE (t) == ARRAY_TYPE
       && C_TYPE_VARIABLE_SIZE (t))
@@ -471,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;
                      }
                  }
@@ -496,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;
                      }
                  }
@@ -531,6 +529,7 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_1, mv1;
   tree pointed_to_2, mv2;
   tree target;
+  unsigned target_quals;
 
   /* Save time if the two types are the same.  */
 
@@ -558,10 +557,15 @@ common_pointer_type (tree t1, tree t2)
   if (TREE_CODE (mv2) != ARRAY_TYPE)
     mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
   target = composite_type (mv1, mv2);
-  t1 = build_pointer_type (c_build_qualified_type
-                          (target,
-                           TYPE_QUALS (pointed_to_1) |
-                           TYPE_QUALS (pointed_to_2)));
+
+  /* For function types do not merge const qualifiers, but drop them
+     if used inconsistently.  The middle-end uses these to mark const
+     and noreturn functions.  */
+  if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
+    target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+  else
+    target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+  t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
 
@@ -605,9 +609,11 @@ c_common_type (tree t1, tree t2)
   code2 = TREE_CODE (t2);
 
   gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
-             || code1 == REAL_TYPE || code1 == INTEGER_TYPE);
+             || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
+             || code1 == INTEGER_TYPE);
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
-             || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
+             || code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
+             || code2 == INTEGER_TYPE);
 
   /* When one operand is a decimal float type, the other operand cannot be
      a generic float type or a complex type.  We also disallow vector types
@@ -682,6 +688,91 @@ c_common_type (tree t1, tree t2)
        return dfloat32_type_node;
     }
 
+  /* Deal with fixed-point types.  */
+  if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
+    {
+      unsigned int unsignedp = 0, satp = 0;
+      enum machine_mode m1, m2;
+      unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
+
+      m1 = TYPE_MODE (t1);
+      m2 = TYPE_MODE (t2);
+
+      /* If one input type is saturating, the result type is saturating.  */
+      if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
+       satp = 1;
+
+      /* If both fixed-point types are unsigned, the result type is unsigned.
+        When mixing fixed-point and integer types, follow the sign of the
+        fixed-point type.
+        Otherwise, the result type is signed.  */
+      if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
+          && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
+         || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t1))
+         || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t2)))
+       unsignedp = 1;
+
+      /* The result type is signed.  */
+      if (unsignedp == 0)
+       {
+         /* If the input type is unsigned, we need to convert to the
+            signed type.  */
+         if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
+           {
+             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)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
+           }
+         if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
+           {
+             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)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
+           }
+       }
+
+      if (code1 == FIXED_POINT_TYPE)
+       {
+         fbit1 = GET_MODE_FBIT (m1);
+         ibit1 = GET_MODE_IBIT (m1);
+       }
+      else
+       {
+         fbit1 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
+       }
+
+      if (code2 == FIXED_POINT_TYPE)
+       {
+         fbit2 = GET_MODE_FBIT (m2);
+         ibit2 = GET_MODE_IBIT (m2);
+       }
+      else
+       {
+         fbit2 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
+       }
+
+      max_ibit = ibit1 >= ibit2 ?  ibit1 : ibit2;
+      max_fbit = fbit1 >= fbit2 ?  fbit1 : fbit2;
+      return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
+                                                satp);
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -783,10 +874,10 @@ comptypes (tree type1, tree type2)
    differs from comptypes, in that we don't free the seen types.  */
 
 static int
-comptypes_internal (tree type1, tree type2)
+comptypes_internal (const_tree type1, const_tree type2)
 {
-  tree t1 = type1;
-  tree t2 = type2;
+  const_tree t1 = type1;
+  const_tree t2 = type2;
   int attrval, val;
 
   /* Suppress errors caused by previously reported errors.  */
@@ -947,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
@@ -959,7 +1050,7 @@ comp_target_types (tree ttl, tree ttr)
    being parsed, so if two trees have context chains ending in null,
    they're in the same translation unit.  */
 int
-same_translation_unit_p (tree t1, tree t2)
+same_translation_unit_p (const_tree t1, const_tree t2)
 {
   while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
     switch (TREE_CODE_CLASS (TREE_CODE (t1)))
@@ -991,7 +1082,7 @@ same_translation_unit_p (tree t1, tree t2)
 /* Allocate the seen two types, assuming that they are compatible. */
 
 static struct tagged_tu_seen_cache *
-alloc_tagged_tu_seen_cache (tree t1, tree t2)
+alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
 {
   struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
   tu->next = tagged_tu_seen_base;
@@ -1024,9 +1115,10 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
   const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
   while (tu != tu_til)
     {
-      struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu;
+      const struct tagged_tu_seen_cache *const tu1
+       = (const struct tagged_tu_seen_cache *) tu;
       tu = tu1->next;
-      free (tu1);
+      free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
     }
   tagged_tu_seen_base = tu_til;
 }
@@ -1038,7 +1130,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
    rules.  */
 
 static int
-tagged_types_tu_compatible_p (tree t1, tree t2)
+tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1146,11 +1238,12 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
          {
            int result;
 
-
-           if (DECL_NAME (s1) == NULL
-               || DECL_NAME (s1) != DECL_NAME (s2))
+           if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+
+           if (result != 1 && !DECL_NAME (s1))
+             break;
            if (result == 0)
              {
                tu->val = 0;
@@ -1177,28 +1270,31 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
          {
            bool ok = false;
 
-           if (DECL_NAME (s1) != NULL)
-             for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
-               if (DECL_NAME (s1) == DECL_NAME (s2))
-                 {
-                   int result;
-                   result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
-                   if (result == 0)
-                     {
-                       tu->val = 0;
-                       return 0;
-                     }
-                   if (result == 2)
-                     needs_warning = true;
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+             if (DECL_NAME (s1) == DECL_NAME (s2))
+               {
+                 int result;
 
-                   if (TREE_CODE (s1) == FIELD_DECL
-                       && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
-                                            DECL_FIELD_BIT_OFFSET (s2)) != 1)
-                     break;
+                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+
+                 if (result != 1 && !DECL_NAME (s1))
+                   continue;
+                 if (result == 0)
+                   {
+                     tu->val = 0;
+                     return 0;
+                   }
+                 if (result == 2)
+                   needs_warning = true;
 
-                   ok = true;
+                 if (TREE_CODE (s1) == FIELD_DECL
+                     && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                          DECL_FIELD_BIT_OFFSET (s2)) != 1)
                    break;
-                 }
+
+                 ok = true;
+                 break;
+               }
            if (!ok)
              {
                tu->val = 0;
@@ -1252,7 +1348,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
    Otherwise, the argument types must match.  */
 
 static int
-function_types_compatible_p (tree f1, tree f2)
+function_types_compatible_p (const_tree f1, const_tree f2)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1266,7 +1362,7 @@ function_types_compatible_p (tree f1, 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);
@@ -1315,7 +1411,7 @@ function_types_compatible_p (tree f1, tree f2)
    or 2 for compatible with warning.  */
 
 static int
-type_lists_compatible_p (tree args1, tree args2)
+type_lists_compatible_p (const_tree args1, const_tree args2)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1416,7 +1512,7 @@ type_lists_compatible_p (tree args1, tree args2)
 /* Compute the size to increment a pointer by.  */
 
 static tree
-c_size_in_bytes (tree type)
+c_size_in_bytes (const_tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
@@ -1521,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);
 }
 
@@ -1538,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.
@@ -1560,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)
@@ -1683,14 +1778,19 @@ default_conversion (tree exp)
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  if (INTEGRAL_TYPE_P (type))
-    return perform_integral_promotions (exp);
-
   if (code == VOID_TYPE)
     {
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+
+  exp = require_complete_type (exp);
+  if (exp == error_mark_node)
+    return error_mark_node;
+
+  if (INTEGRAL_TYPE_P (type))
+    return perform_integral_promotions (exp);
+
   return exp;
 }
 \f
@@ -1866,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
@@ -1892,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
@@ -1919,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;
 }
 
@@ -1934,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)
@@ -1951,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;
@@ -1962,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;
     }
 
@@ -2015,14 +2125,14 @@ 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));
-      if (TREE_CODE (type) != ARRAY_TYPE)
-       type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
         or if the array is.  */
@@ -2039,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
     {
@@ -2051,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
@@ -2090,9 +2203,11 @@ build_external_ref (tree id, int fun, location_t loc)
   if (TREE_DEPRECATED (ref))
     warn_deprecated_use (ref);
 
-  if (!skip_evaluation)
-    assemble_external (ref);
-  TREE_USED (ref) = 1;
+  /* Recursive call does not count as usage.  */
+  if (ref != current_function_decl) 
+    {
+      TREE_USED (ref) = 1;
+    }
 
   if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
     {
@@ -2109,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)
@@ -2130,9 +2244,10 @@ build_external_ref (tree id, int fun, location_t loc)
           && DECL_EXTERNAL (current_function_decl)
           && VAR_OR_FUNCTION_DECL_P (ref)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
-          && ! TREE_PUBLIC (ref))
-    pedwarn ("%H%qD is static but used in inline function %qD "
-            "which is not static", &loc, ref, current_function_decl);
+          && ! TREE_PUBLIC (ref)
+          && DECL_CONTEXT (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;
 }
@@ -2294,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)))
@@ -2307,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;
@@ -2339,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));
 
@@ -2351,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),
@@ -2390,6 +2509,8 @@ convert_arguments (int nargs, tree *argarray,
 {
   tree typetail, valtail;
   int parmnum;
+  const bool type_generic = fundecl
+    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   tree selector;
 
   /* Change pointer to function to the function itself for
@@ -2581,8 +2702,13 @@ convert_arguments (int nargs, tree *argarray,
               && (TYPE_PRECISION (TREE_TYPE (val))
                   < TYPE_PRECISION (double_type_node))
               && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
-       /* Convert `float' to `double'.  */
-       argarray[parmnum] = convert (double_type_node, val);
+        {
+         if (type_generic)
+           argarray[parmnum] = val;
+         else
+           /* Convert `float' to `double'.  */
+           argarray[parmnum] = convert (double_type_node, val);
+       }
       else if ((invalid_func_diag =
                targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
        {
@@ -2611,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);
@@ -2631,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
@@ -2688,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
@@ -2704,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);
@@ -2745,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))))
@@ -2765,19 +2900,27 @@ 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_CODE (TREE_TYPE (arg));
+  enum tree_code typecode;
   tree val;
+  tree ret = error_mark_node;
   int noconvert = flag;
   const char *invalid_op_diag;
 
+  if (code != ADDR_EXPR)
+    arg = require_complete_type (arg);
+
+  typecode = TREE_CODE (TREE_TYPE (arg));
   if (typecode == ERROR_MARK)
     return error_mark_node;
   if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
@@ -2786,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;
     }
 
@@ -2797,10 +2940,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         is enough to prevent anybody from looking inside for
         associativity, but won't generate any code.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || typecode == 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)
@@ -2810,10 +2953,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
     case NEGATE_EXPR:
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE
+           || 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)
@@ -2821,7 +2964,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case BIT_NOT_EXPR:
-      if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE)
+      /* ~ works on integer types and non float vectors. */
+      if (typecode == INTEGER_TYPE
+         || (typecode == VECTOR_TYPE
+             && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
        {
          if (!noconvert)
            arg = default_conversion (arg);
@@ -2829,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;
@@ -2844,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)
@@ -2856,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)
@@ -2864,31 +3010,35 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case TRUTH_NOT_EXPR:
-      if (typecode != INTEGER_TYPE
+      if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
          && 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:
@@ -2901,38 +3051,36 @@ 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.  */
 
-      if (typecode != POINTER_TYPE
+      if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
          && 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.  */
@@ -2941,29 +3089,53 @@ 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 (argtype)))
+         {
+           /* For signed fract types, we invert ++ to -- or
+              -- to ++, and change inc from 1 to -1, because
+              it is not possible to represent 1 in signed fract constants.
+              For unsigned fract types, the result always overflows and
+              we get an undefined (original) or the maximum value.  */
+           if (code == PREINCREMENT_EXPR)
+             code = PREDECREMENT_EXPR;
+           else if (code == PREDECREMENT_EXPR)
+             code = PREINCREMENT_EXPR;
+           else if (code == POSTINCREMENT_EXPR)
+             code = POSTDECREMENT_EXPR;
+           else /* code == POSTDECREMENT_EXPR  */
+             code = POSTINCREMENT_EXPR;
+
+           inc = integer_minus_one_node;
+           inc = convert (argtype, inc);
          }
        else
-         inc = integer_one_node;
-
-       inc = convert (argtype, inc);
+         {
+           inc = integer_one_node;
+           inc = convert (argtype, inc);
+         }
 
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
@@ -2987,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:
@@ -3002,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 */
@@ -3011,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),
@@ -3051,15 +3224,17 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
+         tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
 
          op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         return fold_build2 (PLUS_EXPR, argtype, op0, op1);
+         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 ();
@@ -3067,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.
@@ -3076,9 +3255,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
 static int
-lvalue_p (tree ref)
+lvalue_p (const_tree ref)
 {
-  enum tree_code code = TREE_CODE (ref);
+  const enum tree_code code = TREE_CODE (ref);
 
   switch (code)
     {
@@ -3139,10 +3318,11 @@ readonly_error (tree arg, enum lvalue_use use)
                         G_("read-only variable %qD used as %<asm%> output")),
           arg);
   else
-    error (READONLY_MSG (G_("assignment of read-only location"),
-                        G_("increment of read-only location"),
-                        G_("decrement of read-only location"),
-                        G_("read-only location used as %<asm%> output")));
+    error (READONLY_MSG (G_("assignment of read-only location %qE"),
+                        G_("increment of read-only location %qE"),
+                        G_("decrement of read-only location %qE"),
+                        G_("read-only location %qE used as %<asm%> output")),
+          arg);
 }
 
 
@@ -3151,7 +3331,7 @@ readonly_error (tree arg, enum lvalue_use use)
    how the lvalue is being used and so selects the error message.  */
 
 static int
-lvalue_or_else (tree ref, enum lvalue_use use)
+lvalue_or_else (const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
@@ -3208,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))
          {
@@ -3309,14 +3489,15 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
                           && tree_expr_nonnegative_warnv_p (op2, &ovf)))
                /* OK */;
              else
-               warning (0, "signed and unsigned type in conditional expression");
+               warning (OPT_Wsign_compare, "signed and unsigned type in conditional expression");
            }
        }
     }
   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)
@@ -3329,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;
@@ -3362,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;
@@ -3404,18 +3590,16 @@ build_compound_expr (tree expr1, tree expr2)
   if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
-        statement: with -Wextra or -Wunused, we should warn if it doesn't have
+        statement: with -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
       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, 
@@ -3466,35 +3650,40 @@ build_c_cast (tree type, tree expr)
       return error_mark_node;
     }
 
+  if (!VOID_TYPE_P (type))
+    {
+      value = require_complete_type (value);
+      if (value == error_mark_node)
+       return error_mark_node;
+    }
+
   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");
@@ -3543,12 +3732,12 @@ build_c_cast (tree type, tree expr)
                 && TREE_CODE (in_otype) == POINTER_TYPE);
 
          if (added)
-           warning (0, "cast adds new qualifiers to function type");
+           warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
 
          if (discarded)
            /* There are qualifiers present in IN_OTYPE that are not
               present in IN_TYPE.  */
-           warning (0, "cast discards qualifiers from pointer target type");
+           warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
        }
 
       /* Warn about possible alignment problems.  */
@@ -3601,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
@@ -3609,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);
@@ -3661,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;
@@ -3691,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'.  */
@@ -3738,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
@@ -3753,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
@@ -3778,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
@@ -3800,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);
@@ -3875,6 +4078,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+  rhs = require_complete_type (rhs);
+  if (rhs == error_mark_node)
+    return error_mark_node;
   /* A type converts to a reference to it.
      This code doesn't fully support references, it's just for the
      special case of va_start and va_copy.  */
@@ -3907,9 +4113,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
+           || codel == FIXED_POINT_TYPE
            || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
            || codel == BOOLEAN_TYPE)
           && (coder == INTEGER_TYPE || coder == REAL_TYPE
+              || coder == FIXED_POINT_TYPE
               || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
               || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
@@ -3923,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;
 
@@ -3994,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 "
@@ -4007,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"),
@@ -4019,9 +4229,11 @@ 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);
        }
     }
@@ -4042,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
@@ -4066,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",
@@ -4098,8 +4306,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
          || (target_cmp = comp_target_types (type, rhstype))
          || is_opaque_pointer
-         || (unsigned_type_for (mvl)
-             == unsigned_type_for (mvr)))
+         || (c_common_unsigned_type (mvl)
+             == c_common_unsigned_type (mvr)))
        {
          if (pedantic
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -4107,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 "
@@ -4127,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"),
@@ -4143,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"),
@@ -4160,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 "
@@ -4174,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 "
@@ -4196,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"),
@@ -4209,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"),
@@ -4225,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 ();
@@ -4245,37 +4463,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
   return error_mark_node;
 }
-
-/* Convert VALUE for assignment into inlined parameter PARM.  ARGNUM
-   is used for error and warning reporting and indicates which argument
-   is being processed.  */
-
-tree
-c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
-{
-  tree ret, type;
-
-  /* If FN was prototyped at the call site, the value has been converted
-     already in convert_arguments.
-     However, we might see a prototype now that was not in place when
-     the function call was seen, so check that the VALUE actually matches
-     PARM before taking an early exit.  */
-  if (!value
-      || (TYPE_ARG_TYPES (TREE_TYPE (fn))
-         && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
-             == TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
-    return value;
-
-  type = TREE_TYPE (parm);
-  ret = convert_for_assignment (type, value,
-                               ic_argpass_nonproto, fn,
-                               fn, argnum);
-  if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
-      && INTEGRAL_TYPE_P (type)
-      && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-    ret = default_conversion (ret);
-  return ret;
-}
 \f
 /* If VALUE is a compound expr all of whose expressions are constant, then
    return its value.  Otherwise, return error_mark_node.
@@ -4498,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
@@ -4539,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.
@@ -4582,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;
        }
@@ -4669,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.  */
 
@@ -4738,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;
        }
@@ -4759,9 +4964,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
   /* Handle scalar types, including conversions.  */
 
-  if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
-      || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
-      || code == VECTOR_TYPE)
+  if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
+      || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
+      || code == COMPLEX_TYPE || code == VECTOR_TYPE)
     {
       if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
          && (TREE_CODE (init) == STRING_CST
@@ -5184,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;
        }
@@ -5292,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
@@ -5353,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;
     }
@@ -5383,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);
     }
@@ -5411,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.
@@ -5439,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);
          }
     }
@@ -5481,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;
        }
@@ -5540,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;
     }
@@ -5701,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;
 
@@ -5722,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;
            }
@@ -5745,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;
            }
@@ -5933,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)
     {
@@ -5969,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);
@@ -6031,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;
@@ -6104,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;
 
@@ -6156,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),
@@ -6186,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
@@ -6212,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;
@@ -6293,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))
            {
@@ -6346,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))
            {
@@ -6409,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;
@@ -6453,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;
     }
@@ -6483,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;
            }
 
@@ -6524,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
@@ -6566,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;
            }
 
@@ -6613,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
@@ -6653,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;
            }
 
@@ -6662,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);
            }
 
@@ -6683,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);
@@ -6707,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;
        }
 
@@ -6730,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);
@@ -6938,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));
 }
@@ -6962,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;
        }
@@ -6971,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
     {
@@ -6994,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;
 
@@ -7007,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)))
@@ -7041,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);
@@ -7118,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);
        }
     }
 
@@ -7253,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);
@@ -7377,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));
 }
 
@@ -7733,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,
@@ -7747,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.
@@ -7800,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);
@@ -7832,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;
     }
 
@@ -7843,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;
@@ -7855,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;
@@ -7872,11 +8129,13 @@ 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
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
          enum tree_code tcode0 = code0, tcode1 = code1;
@@ -7886,7 +8145,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
            tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
 
-         if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
+         if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
+             || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
            resultcode = RDIV_EXPR;
          else
            /* Although it would be tempting to shorten always here, that
@@ -7906,13 +8166,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case BIT_XOR_EXPR:
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        shorten = -1;
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+      /* Allow vector types which are not floating point types.   */
+      else if (code0 == VECTOR_TYPE
+              && code1 == VECTOR_TYPE
+              && !VECTOR_FLOAT_TYPE_P (type0)
+              && !VECTOR_FLOAT_TYPE_P (type1))
        common = 1;
       break;
 
     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)
        {
@@ -7933,16 +8197,18 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
-          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+          || code0 == FIXED_POINT_TYPE)
          && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
-             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+             || code1 == FIXED_POINT_TYPE))
        {
          /* Result of these operations is always an int,
             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;
@@ -7952,7 +8218,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -7980,7 +8247,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
            {
@@ -8004,16 +8272,17 @@ 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;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == COMPLEX_TYPE)
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == COMPLEX_TYPE))
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8030,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;
@@ -8052,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;
 
@@ -8081,8 +8353,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case LT_EXPR:
     case GT_EXPR:
       build_type = integer_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE))
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
@@ -8091,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;
 
@@ -8138,15 +8418,15 @@ 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;
     }
 
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-       || code0 == VECTOR_TYPE)
+       || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
       &&
       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
-       || code1 == VECTOR_TYPE))
+       || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
     {
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
@@ -8170,91 +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)),
-                      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)),
-                      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.  */
@@ -8302,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 (0, "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 (0, "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 (0, "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);
            }
        }
     }
@@ -8438,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;
     }
 
@@ -8458,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:
@@ -8502,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
 
@@ -8510,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)
     {
@@ -8539,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)
 {
@@ -8554,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.  */
 
@@ -8714,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;
 
@@ -8769,3 +8890,68 @@ c_finish_omp_clauses (tree clauses)
   bitmap_obstack_release (NULL);
   return clauses;
 }
+
+/* Make a variant type in the proper way for C/C++, propagating qualifiers
+   down to the element type of an array.  */
+
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+  if (type == error_mark_node)
+    return type;
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree t;
+      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+                                                 type_quals);
+
+      /* See if we already have an identically qualified type.  */
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         if (TYPE_QUALS (strip_array_types (t)) == type_quals
+             && TYPE_NAME (t) == TYPE_NAME (type)
+             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+             && attribute_list_equal (TYPE_ATTRIBUTES (t),
+                                      TYPE_ATTRIBUTES (type)))
+           break;
+       }
+      if (!t)
+       {
+          tree domain = TYPE_DOMAIN (type);
+
+         t = build_variant_type_copy (type);
+         TREE_TYPE (t) = element_type;
+
+          if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
+              || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
+            SET_TYPE_STRUCTURAL_EQUALITY (t);
+          else if (TYPE_CANONICAL (element_type) != element_type
+                   || (domain && TYPE_CANONICAL (domain) != domain))
+            {
+              tree unqualified_canon 
+                = build_array_type (TYPE_CANONICAL (element_type),
+                                    domain? TYPE_CANONICAL (domain) 
+                                          : NULL_TREE);
+              TYPE_CANONICAL (t) 
+                = c_build_qualified_type (unqualified_canon, type_quals);
+            }
+          else
+            TYPE_CANONICAL (t) = t;
+       }
+      return t;
+    }
+
+  /* A restrict-qualified pointer type must be a pointer to object or
+     incomplete type.  Note that the use of POINTER_TYPE_P also allows
+     REFERENCE_TYPEs, which is appropriate for C++.  */
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && (!POINTER_TYPE_P (type)
+         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+    {
+      error ("invalid use of %<restrict%>");
+      type_quals &= ~TYPE_QUAL_RESTRICT;
+    }
+
+  return build_qualified_type (type, type_quals);
+}