]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/c/c-typeck.c
re PR c/51849 (-Wc99-compat would be considered useful)
[gcc.git] / gcc / c / c-typeck.c
index 7cb717a9749b013b0df3a1e42d5b15b2cede92e4..0ed92c699f753feb5a6968a3dda6c051b3fc01f0 100644 (file)
@@ -40,7 +40,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "tree-iterator.h"
 #include "bitmap.h"
-#include "pointer-set.h"
 #include "basic-block.h"
 #include "gimple-expr.h"
 #include "gimplify.h"
@@ -50,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "c-family/c-ubsan.h"
 #include "cilk.h"
+#include "wide-int.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -73,9 +73,9 @@ int in_typeof;
    if expr.original_code == SIZEOF_EXPR.  */
 tree c_last_sizeof_arg;
 
-/* Nonzero if we've already printed a "missing braces around initializer"
-   message within this initializer.  */
-static int missing_braces_mentioned;
+/* Nonzero if we might need to print a "missing braces around
+   initializer" message within this initializer.  */
+static int found_missing_braces;
 
 static int require_constant_value;
 static int require_constant_elements;
@@ -89,24 +89,26 @@ static int function_types_compatible_p (const_tree, const_tree, bool *,
                                        bool *);
 static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
 static tree lookup_field (tree, tree);
-static int convert_arguments (tree, vec<tree, va_gc> *, vec<tree, va_gc> *,
-                             tree, tree);
+static int convert_arguments (location_t, vec<location_t>, tree,
+                             vec<tree, va_gc> *, vec<tree, va_gc> *, tree,
+                             tree);
 static tree pointer_diff (location_t, tree, tree);
-static tree convert_for_assignment (location_t, tree, tree, tree,
+static tree convert_for_assignment (location_t, location_t, tree, tree, tree,
                                    enum impl_conv, bool, tree, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
 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 (int, const char *);
+static void warning_init (location_t, int, const char *);
 static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool,
-                                struct obstack *);
+static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
+                                bool, struct obstack *);
 static void output_pending_init_elements (int, struct obstack *);
-static int set_designator (int, struct obstack *);
+static int set_designator (location_t, int, struct obstack *);
 static void push_range_stack (tree, struct obstack *);
-static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void add_pending_init (location_t, tree, tree, tree, bool,
+                             struct obstack *);
 static void set_nonincremental_init (struct obstack *);
 static void set_nonincremental_init_from_string (tree, struct obstack *);
 static tree find_init_member (tree, struct obstack *);
@@ -1752,22 +1754,20 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
     }
 }
 \f
-/* Compute the size to increment a pointer by.  */
+/* Compute the size to increment a pointer by.  When a function type or void
+   type or incomplete type is passed, size_one_node is returned.
+   This function does not emit any diagnostics; the caller is responsible
+   for that.  */
 
 static tree
 c_size_in_bytes (const_tree type)
 {
   enum tree_code code = TREE_CODE (type);
 
-  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK
+      || !COMPLETE_TYPE_P (type))
     return size_one_node;
 
-  if (!COMPLETE_OR_VOID_TYPE_P (type))
-    {
-      error ("arithmetic on pointer to an incomplete type");
-      return size_one_node;
-    }
-
   /* Convert in case a char is more than one unit.  */
   return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
                         size_int (TYPE_PRECISION (char_type_node)
@@ -2008,13 +2008,17 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
       tmp = create_tmp_var (nonatomic_type, NULL);
       tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
       TREE_ADDRESSABLE (tmp) = 1;
+      TREE_NO_WARNING (tmp) = 1;
 
       /* Issue __atomic_load (&expr, &tmp, SEQ_CST);  */
       fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
       params->quick_push (expr_addr);
       params->quick_push (tmp_addr);
       params->quick_push (seq_cst);
-      func_call = build_function_call_vec (loc, fndecl, params, NULL);
+      func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+
+      /* EXPR is always read.  */
+      mark_exp_read (exp.value);
 
       /* Return tmp which contains the value loaded.  */
       exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp);
@@ -2102,7 +2106,8 @@ default_conversion (tree exp)
 
   if (code == VOID_TYPE)
     {
-      error ("void value not ignored as it ought to be");
+      error_at (EXPR_LOC_OR_LOC (exp, input_location),
+               "void value not ignored as it ought to be");
       return error_mark_node;
     }
 
@@ -2423,7 +2428,7 @@ build_array_ref (location_t loc, tree array, tree index)
       || TREE_TYPE (index) == error_mark_node)
     return error_mark_node;
 
-  if (flag_enable_cilkplus && contains_array_notation_expr (index))
+  if (flag_cilkplus && contains_array_notation_expr (index))
     {
       size_t rank = 0;
       if (!find_rank (loc, index, index, true, &rank))
@@ -2505,7 +2510,7 @@ build_array_ref (location_t loc, tree array, tree index)
            return error_mark_node;
        }
 
-      if (pedantic)
+      if (pedantic || warn_c90_c99_compat)
        {
          tree foo = array;
          while (TREE_CODE (foo) == COMPONENT_REF)
@@ -2513,9 +2518,10 @@ build_array_ref (location_t loc, tree array, tree index)
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
            pedwarn (loc, OPT_Wpedantic,
                     "ISO C forbids subscripting %<register%> array");
-         else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn (loc, OPT_Wpedantic,
-                    "ISO C90 forbids subscripting non-lvalue array");
+         else if (!lvalue_p (foo))
+           pedwarn_c90 (loc, OPT_Wpedantic,
+                        "ISO C90 forbids subscripting non-lvalue "
+                        "array");
        }
 
       type = TREE_TYPE (TREE_TYPE (array));
@@ -2725,6 +2731,16 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
   else
     {
       bool expr_const_operands = true;
+
+      if (TREE_CODE (expr.value) == PARM_DECL
+         && C_ARRAY_PARAMETER (expr.value))
+       {
+         if (warning_at (loc, OPT_Wsizeof_array_argument,
+                         "%<sizeof%> on array function parameter %qE will "
+                         "return size of %qT", expr.value,
+                         expr.original_type))
+           inform (DECL_SOURCE_LOCATION (expr.value), "declared here");
+       }
       tree folded_expr = c_fully_fold (expr.value, require_constant_value,
                                       &expr_const_operands);
       ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
@@ -2796,7 +2812,7 @@ build_function_call (location_t loc, tree function, tree params)
   vec_alloc (v, list_length (params));
   for (; params; params = TREE_CHAIN (params))
     v->quick_push (TREE_VALUE (params));
-  ret = build_function_call_vec (loc, function, v, NULL);
+  ret = c_build_function_call_vec (loc, vNULL, function, v, NULL);
   vec_free (v);
   return ret;
 }
@@ -2818,8 +2834,8 @@ static void inform_declaration (tree decl)
    PARAMS.  */
 
 tree
-build_function_call_vec (location_t loc, tree function,
-                        vec<tree, va_gc> *params,
+build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+                        tree function, vec<tree, va_gc> *params,
                         vec<tree, va_gc> *origtypes)
 {
   tree fntype, fundecl = 0;
@@ -2835,14 +2851,6 @@ build_function_call_vec (location_t loc, tree function,
   /* Convert anything with function type to a pointer-to-function.  */
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      /* Implement type-directed function overloading for builtins.
-        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
-        handle all the type checking.  The result is a complete expression
-        that implements this function call.  */
-      tem = resolve_overloaded_builtin (loc, function, params);
-      if (tem)
-       return tem;
-
       name = DECL_NAME (function);
 
       if (flag_tm)
@@ -2853,7 +2861,7 @@ build_function_call_vec (location_t loc, tree function,
       if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
         origtypes = NULL;
 
-      if (flag_enable_cilkplus
+      if (flag_cilkplus
          && is_cilkplus_reduce_builtin (function))
        origtypes = NULL;
     }
@@ -2901,62 +2909,30 @@ build_function_call_vec (location_t loc, tree function,
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
-                            function, fundecl);
+  nargs = convert_arguments (loc, arg_loc, TYPE_ARG_TYPES (fntype), params,
+                            origtypes, function, fundecl);
   if (nargs < 0)
     return error_mark_node;
 
   /* Check that the function is called through a compatible prototype.
-     If it is not, replace the call by a trap, wrapped up in a compound
-     expression if necessary.  This has the nice side-effect to prevent
-     the tree-inliner from generating invalid assignment trees which may
-     blow up in the RTL expander later.  */
+     If it is not, warn.  */
   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)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc,
-                                      builtin_decl_explicit (BUILT_IN_TRAP),
-                                      NULL_TREE);
-      int i;
 
       /* 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.  */
-      if (warning_at (loc, 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 (loc, "if this code is reached, the program will abort");
-      /* Before the abort, allow the function arguments to exit or
-        call longjmp.  */
-      for (i = 0; i < nargs; i++)
-       trap = build2 (COMPOUND_EXPR, void_type_node, (*params)[i], trap);
-
-      if (VOID_TYPE_P (return_type))
-       {
-         if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
-           pedwarn (loc, 0,
-                    "function with qualified void return type called");
-         return trap;
-       }
-      else
-       {
-         tree rhs;
+      warning_at (loc, 0, "function called through a non-compatible type");
 
-         if (AGGREGATE_TYPE_P (return_type))
-           rhs = build_compound_literal (loc, return_type,
-                                         build_constructor (return_type,
-                                           NULL),
-                                         false);
-         else
-           rhs = build_zero_cst (return_type);
-
-         return require_complete_type (build2 (COMPOUND_EXPR, return_type,
-                                               trap, rhs));
-       }
-    }
+      if (VOID_TYPE_P (return_type)
+         && TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
+       pedwarn (loc, 0,
+                "function with qualified void return type called");
+     }
 
   argarray = vec_safe_address (params);
 
@@ -2997,6 +2973,30 @@ build_function_call_vec (location_t loc, tree function,
     }
   return require_complete_type (result);
 }
+
+/* Like build_function_call_vec, but call also resolve_overloaded_builtin.  */
+
+tree
+c_build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+                          tree function, vec<tree, va_gc> *params,
+                          vec<tree, va_gc> *origtypes)
+{
+  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
+  STRIP_TYPE_NOPS (function);
+
+  /* Convert anything with function type to a pointer-to-function.  */
+  if (TREE_CODE (function) == FUNCTION_DECL)
+    {
+      /* Implement type-directed function overloading for builtins.
+        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+        handle all the type checking.  The result is a complete expression
+        that implements this function call.  */
+      tree tem = resolve_overloaded_builtin (loc, function, params);
+      if (tem)
+       return tem;
+    }
+  return build_function_call_vec (loc, arg_loc, function, params, origtypes);
+}
 \f
 /* Convert the argument expressions in the vector VALUES
    to the types in the list TYPELIST.
@@ -3013,19 +3013,22 @@ build_function_call_vec (location_t loc, tree function,
 
    This is also where warnings about wrong number of args are generated.
 
+   ARG_LOC are locations of function arguments (if any).
+
    Returns the actual number of arguments processed (which may be less
    than the length of VALUES in some error situations), or -1 on
    failure.  */
 
 static int
-convert_arguments (tree typelist, vec<tree, va_gc> *values,
-                  vec<tree, va_gc> *origtypes, tree function, tree fundecl)
+convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
+                  vec<tree, va_gc> *values, vec<tree, va_gc> *origtypes,
+                  tree function, tree fundecl)
 {
   tree typetail, val;
   unsigned int parmnum;
   bool error_args = false;
   const bool type_generic = fundecl
-    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
+    && lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
   tree selector;
 
@@ -3061,7 +3064,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
          break;
        }
     }
-  if (flag_enable_cilkplus && fundecl && is_cilkplus_reduce_builtin (fundecl))
+  if (flag_cilkplus && fundecl && is_cilkplus_reduce_builtin (fundecl))
     return vec_safe_length (values);
 
   /* Scan the given expressions and types, producing individual
@@ -3079,15 +3082,19 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
       bool excess_precision = false;
       bool npc;
       tree parmval;
+      /* Some __atomic_* builtins have additional hidden argument at
+        position 0.  */
+      location_t ploc
+       = !arg_loc.is_empty () && values->length () == arg_loc.length ()
+         ? expansion_point_location_if_in_system_header (arg_loc[parmnum])
+         : input_location;
 
       if (type == void_type_node)
        {
          if (selector)
-           error_at (input_location,
-                     "too many arguments to method %qE", selector);
+           error_at (loc, "too many arguments to method %qE", selector);
          else
-           error_at (input_location,
-                     "too many arguments to function %qE", function);
+           error_at (loc, "too many arguments to function %qE", function);
          inform_declaration (fundecl);
          return parmnum;
        }
@@ -3123,7 +3130,8 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
 
          if (type == error_mark_node || !COMPLETE_TYPE_P (type))
            {
-             error ("type of formal parameter %d is incomplete", parmnum + 1);
+             error_at (ploc, "type of formal parameter %d is incomplete",
+                       parmnum + 1);
              parmval = val;
            }
          else
@@ -3138,34 +3146,40 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
 
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (valtype) == REAL_TYPE)
-                   warning (0, "passing argument %d of %qE as integer "
-                            "rather than floating due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as integer rather "
+                               "than floating due to prototype",
+                               argnum, rname);
                  if (INTEGRAL_TYPE_P (type)
                      && TREE_CODE (valtype) == COMPLEX_TYPE)
-                   warning (0, "passing argument %d of %qE as integer "
-                            "rather than complex due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as integer rather "
+                               "than complex due to prototype",
+                               argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && TREE_CODE (valtype) == REAL_TYPE)
-                   warning (0, "passing argument %d of %qE as complex "
-                            "rather than floating due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as complex rather "
+                               "than floating due to prototype",
+                               argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && INTEGRAL_TYPE_P (valtype))
-                   warning (0, "passing argument %d of %qE as floating "
-                            "rather than integer due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as floating rather "
+                               "than integer due to prototype",
+                               argnum, rname);
                  else if (TREE_CODE (type) == COMPLEX_TYPE
                           && INTEGRAL_TYPE_P (valtype))
-                   warning (0, "passing argument %d of %qE as complex "
-                            "rather than integer due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as complex rather "
+                               "than integer due to prototype",
+                               argnum, rname);
                  else if (TREE_CODE (type) == REAL_TYPE
                           && TREE_CODE (valtype) == COMPLEX_TYPE)
-                   warning (0, "passing argument %d of %qE as floating "
-                            "rather than complex due to prototype",
-                            argnum, rname);
+                   warning_at (ploc, OPT_Wtraditional_conversion,
+                               "passing argument %d of %qE as floating rather "
+                               "than complex due to prototype",
+                               argnum, rname);
                  /* ??? At some point, messages should be written about
                     conversions between complex types, but that's too messy
                     to do now.  */
@@ -3176,9 +3190,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
                         since without a prototype it would be `double'.  */
                      if (formal_prec == TYPE_PRECISION (float_type_node)
                          && type != dfloat32_type_node)
-                       warning (0, "passing argument %d of %qE as %<float%> "
-                                "rather than %<double%> due to prototype",
-                                argnum, rname);
+                       warning_at (ploc, 0,
+                                   "passing argument %d of %qE as %<float%> "
+                                   "rather than %<double%> due to prototype",
+                                   argnum, rname);
 
                      /* Warn if mismatch between argument and prototype
                         for decimal float types.  Warn of conversions with
@@ -3201,9 +3216,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
                                   || (type == dfloat64_type_node
                                       && (valtype
                                           != dfloat32_type_node))))
-                       warning (0, "passing argument %d of %qE as %qT "
-                                "rather than %qT due to prototype",
-                                argnum, rname, type, valtype);
+                       warning_at (ploc, 0,
+                                   "passing argument %d of %qE as %qT "
+                                   "rather than %qT due to prototype",
+                                   argnum, rname, type, valtype);
 
                    }
                  /* Detect integer changing in width or signedness.
@@ -3222,10 +3238,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "with different width due to prototype",
-                                argnum, rname);
+                       warning_at (ploc, OPT_Wtraditional_conversion,
+                                   "passing argument %d of %qE "
+                                   "with different width due to prototype",
+                                   argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
@@ -3246,14 +3262,15 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
                               && TYPE_UNSIGNED (valtype))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "as unsigned due to prototype",
-                                argnum, rname);
+                       warning_at (ploc, OPT_Wtraditional_conversion,
+                                   "passing argument %d of %qE "
+                                   "as unsigned due to prototype",
+                                   argnum, rname);
                      else
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "as signed due to prototype", argnum, rname);
+                       warning_at (ploc, OPT_Wtraditional_conversion,
+                                   "passing argument %d of %qE "
+                                   "as signed due to prototype",
+                                   argnum, rname);
                    }
                }
 
@@ -3262,9 +3279,9 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
              if (excess_precision)
                val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
              origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
-             parmval = convert_for_assignment (input_location, type, val,
-                                               origtype, ic_argpass, npc,
-                                               fundecl, function,
+             parmval = convert_for_assignment (loc, ploc, type,
+                                               val, origtype, ic_argpass,
+                                               npc, fundecl, function,
                                                parmnum + 1);
 
              if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
@@ -3286,10 +3303,10 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
            {
              /* Convert `float' to `double'.  */
              if (warn_double_promotion && !c_inhibit_evaluation_warnings)
-               warning (OPT_Wdouble_promotion,
-                        "implicit conversion from %qT to %qT when passing "
-                        "argument to function",
-                        valtype, double_type_node);
+               warning_at (ploc, OPT_Wdouble_promotion,
+                           "implicit conversion from %qT to %qT when passing "
+                           "argument to function",
+                           valtype, double_type_node);
              parmval = convert (double_type_node, val);
            }
        }
@@ -3319,8 +3336,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error_at (input_location,
-               "too few arguments to function %qE", function);
+      error_at (loc, "too few arguments to function %qE", function);
       inform_declaration (fundecl);
       return -1;
     }
@@ -3388,13 +3404,18 @@ parser_build_binary_op (location_t location, enum tree_code code,
   /* Check for cases such as x+y<<z which users are likely
      to misinterpret.  */
   if (warn_parentheses)
-    warn_about_parentheses (input_location, code,
-                           code1, arg1.value, code2, arg2.value);
+    warn_about_parentheses (location, code, code1, arg1.value, code2,
+                           arg2.value);
 
   if (warn_logical_op)
-    warn_logical_operator (input_location, code, TREE_TYPE (result.value),
+    warn_logical_operator (location, code, TREE_TYPE (result.value),
                           code1, arg1.value, code2, arg2.value);
 
+  if (warn_logical_not_paren
+      && code1 == TRUTH_NOT_EXPR
+      && code2 != TRUTH_NOT_EXPR)
+    warn_logical_not_parentheses (location, code, arg1.value, arg2.value);
+
   /* Warn about comparisons against string literals, with the exception
      of testing for equality or inequality of a string literal with NULL.  */
   if (code == EQ_EXPR || code == NE_EXPR)
@@ -3439,7 +3460,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
   addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
   addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
-  tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
   /* If the operands point into different address spaces, we need to
@@ -3469,7 +3489,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
   else
     inttype = restype;
 
-
   if (TREE_CODE (target_type) == VOID_TYPE)
     pedwarn (loc, OPT_Wpointer_arith,
             "pointer of type %<void *%> used in subtraction");
@@ -3477,50 +3496,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
     pedwarn (loc, 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
-     that is in the way to do any simplifications.
-     (fold-const.c doesn't know that the extra bits won't be needed.
-     split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
-     different mode in place.)
-     So first try to find a common term here 'by hand'; we want to cover
-     at least the cases that occur in legal static initializers.  */
-  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 (CONVERT_EXPR_P (op1)
-      && (TYPE_PRECISION (TREE_TYPE (op1))
-         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
-    con1 = TREE_OPERAND (op1, 0);
-  else
-    con1 = op1;
-
-  if (TREE_CODE (con0) == POINTER_PLUS_EXPR)
-    {
-      lit0 = TREE_OPERAND (con0, 1);
-      con0 = TREE_OPERAND (con0, 0);
-    }
-  else
-    lit0 = integer_zero_node;
-
-  if (TREE_CODE (con1) == POINTER_PLUS_EXPR)
-    {
-      lit1 = TREE_OPERAND (con1, 1);
-      con1 = TREE_OPERAND (con1, 0);
-    }
-  else
-    lit1 = integer_zero_node;
-
-  if (operand_equal_p (con0, con1, 0))
-    {
-      op0 = lit0;
-      op1 = lit1;
-    }
-
-
   /* First do the subtraction as integers;
      then drop through to build the divide operator.
      Do not do default conversions on the minus operator
@@ -3533,9 +3508,11 @@ pointer_diff (location_t loc, tree op0, tree op1)
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
     error_at (loc, "arithmetic on pointer to an incomplete type");
 
-  /* This generates an error if op0 is pointer to incomplete type.  */
   op1 = c_size_in_bytes (target_type);
 
+  if (pointer_to_zero_sized_aggr_p (TREE_TYPE (orig_op1)))
+    error_at (loc, "arithmetic on pointer to an empty aggregate");
+
   /* Divide by the size, in easiest possible way.  */
   result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
                            op0, convert (inttype, op1));
@@ -3637,6 +3614,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
   nonatomic_rhs_type = build_qualified_type (rhs_type, TYPE_UNQUALIFIED);
   val = create_tmp_var (nonatomic_rhs_type, NULL);
   TREE_ADDRESSABLE (val) = 1;
+  TREE_NO_WARNING (val) = 1;
   rhs = build2 (MODIFY_EXPR, nonatomic_rhs_type, val, rhs);
   SET_EXPR_LOCATION (rhs, loc);
   add_stmt (rhs);
@@ -3651,7 +3629,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
       params->quick_push (lhs_addr);
       params->quick_push (rhs);
       params->quick_push (seq_cst);
-      func_call = build_function_call_vec (loc, fndecl, params, NULL);
+      func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
       add_stmt (func_call);
 
       /* Finish the compound statement.  */
@@ -3665,7 +3643,8 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
   /* Create the variables and labels required for the op= form.  */
   old = create_tmp_var (nonatomic_lhs_type, NULL);
   old_addr = build_unary_op (loc, ADDR_EXPR, old, 0);
-  TREE_ADDRESSABLE (val) = 1;
+  TREE_ADDRESSABLE (old) = 1;
+  TREE_NO_WARNING (old) = 1;
 
   newval = create_tmp_var (nonatomic_lhs_type, NULL);
   newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0);
@@ -3682,7 +3661,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
   params->quick_push (lhs_addr);
   params->quick_push (old_addr);
   params->quick_push (seq_cst);
-  func_call = build_function_call_vec (loc, fndecl, params, NULL);
+  func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
   add_stmt (func_call);
   params->truncate (0);
 
@@ -3702,8 +3681,8 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
 
   /* newval = old + val;  */
   rhs = build_binary_op (loc, modifycode, old, val, 1);
-  rhs = convert_for_assignment (loc, nonatomic_lhs_type, rhs, NULL_TREE,
-                               ic_assign, false, NULL_TREE,
+  rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type,
+                               rhs, NULL_TREE, ic_assign, false, NULL_TREE,
                                NULL_TREE, 0);
   if (rhs != error_mark_node)
     {
@@ -3721,7 +3700,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
   params->quick_push (integer_zero_node);
   params->quick_push (seq_cst);
   params->quick_push (seq_cst);
-  func_call = build_function_call_vec (loc, fndecl, params, NULL);
+  func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
 
   goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
   SET_EXPR_LOCATION (goto_stmt, loc);
@@ -4002,16 +3981,18 @@ build_unary_op (location_t location,
 
        if (typecode == POINTER_TYPE)
          {
-           /* If pointer target is an undefined struct,
+           /* If pointer target is an incomplete type,
               we just cannot know how to do the arithmetic.  */
            if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                  error_at (location,
-                           "increment of pointer to unknown structure");
+                           "increment of pointer to an incomplete type %qT",
+                           TREE_TYPE (argtype));
                else
                  error_at (location,
-                           "decrement of pointer to unknown structure");
+                           "decrement of pointer to an incomplete type %qT",
+                           TREE_TYPE (argtype));
              }
            else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
@@ -4380,20 +4361,21 @@ c_mark_addressable (tree exp)
    the usual ones because of excess precision.  */
 
 static tree
-ep_convert_and_check (tree type, tree expr, tree semantic_type)
+ep_convert_and_check (location_t loc, tree type, tree expr,
+                     tree semantic_type)
 {
   if (TREE_TYPE (expr) == type)
     return expr;
 
   if (!semantic_type)
-    return convert_and_check (type, expr);
+    return convert_and_check (loc, type, expr);
 
   if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
       && TREE_TYPE (expr) != semantic_type)
     {
       /* For integers, we need to check the real conversion, not
         the conversion to the excess precision type.  */
-      expr = convert_and_check (semantic_type, expr);
+      expr = convert_and_check (loc, semantic_type, expr);
     }
   /* Result type is the excess precision type, which should be
      large enough, so do not check.  */
@@ -4677,8 +4659,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                          TYPE_READONLY (type1) || TYPE_READONLY (type2),
                          TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
 
-  op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
-  op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
+  op1 = ep_convert_and_check (colon_loc, result_type, op1,
+                             semantic_result_type);
+  op2 = ep_convert_and_check (colon_loc, result_type, op2,
+                             semantic_result_type);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
     {
@@ -4736,7 +4720,7 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
   tree eptype = NULL_TREE;
   tree ret;
 
-  if (flag_enable_cilkplus
+  if (flag_cilkplus
       && (TREE_CODE (expr1) == CILK_SPAWN_STMT
          || TREE_CODE (expr2) == CILK_SPAWN_STMT))
     {
@@ -4778,6 +4762,23 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
                        "left-hand operand of comma expression has no effect");
        }
     }
+  else if (TREE_CODE (expr1) == COMPOUND_EXPR
+          && warn_unused_value)
+    {
+      tree r = expr1;
+      location_t cloc = loc;
+      while (TREE_CODE (r) == COMPOUND_EXPR)
+        {
+         if (EXPR_HAS_LOCATION (r))
+           cloc = EXPR_LOCATION (r);
+         r = TREE_OPERAND (r, 1);
+       }
+      if (!TREE_SIDE_EFFECTS (r)
+         && !VOID_TYPE_P (TREE_TYPE (r))
+         && !CONVERT_EXPR_P (r))
+       warning_at (cloc, OPT_Wunused_value,
+                   "right-hand operand of comma expression has no effect");
+    }
 
   /* With -Wunused, we should also warn if the left-hand operand does have
      side-effects, but computes a value which is not used.  For example, in
@@ -4851,7 +4852,7 @@ handle_warn_cast_qual (location_t loc, tree type, tree otype)
     /* There are qualifiers present in IN_OTYPE that are not present
        in IN_TYPE.  */
     warning_at (loc, OPT_Wcast_qual,
-               "cast discards %q#v qualifier from pointer target type",
+               "cast discards %qv qualifier from pointer target type",
                discarded);
 
   if (added || discarded)
@@ -5105,9 +5106,7 @@ build_c_cast (location_t loc, tree type, tree expr)
            }
          else if (TREE_OVERFLOW (value))
            /* Reset VALUE's overflow flags, ensuring constant sharing.  */
-           value = build_int_cst_wide (TREE_TYPE (value),
-                                       TREE_INT_CST_LOW (value),
-                                       TREE_INT_CST_HIGH (value));
+           value = wide_int_to_tree (TREE_TYPE (value), value);
        }
     }
 
@@ -5361,9 +5360,9 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       newrhs = c_fully_fold (newrhs, false, NULL);
       if (rhs_semantic_type)
        newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
-      newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
-                                      ic_assign, npc, NULL_TREE,
-                                      NULL_TREE, 0);
+      newrhs = convert_for_assignment (location, rhs_loc, lhstype, newrhs,
+                                      rhs_origtype, ic_assign, npc,
+                                      NULL_TREE, NULL_TREE, 0);
       if (TREE_CODE (newrhs) == ERROR_MARK)
        return error_mark_node;
     }
@@ -5398,8 +5397,9 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (olhstype == TREE_TYPE (result))
     goto return_result;
 
-  result = convert_for_assignment (location, olhstype, result, rhs_origtype,
-                                  ic_assign, false, NULL_TREE, NULL_TREE, 0);
+  result = convert_for_assignment (location, rhs_loc, olhstype, result,
+                                  rhs_origtype, ic_assign, false, NULL_TREE,
+                                  NULL_TREE, 0);
   protected_set_expr_location (result, location);
 
 return_result:
@@ -5519,6 +5519,74 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
   return ret;
 }
 
+/* Issue an error message for a bad initializer component.
+   GMSGID identifies the message.
+   The component name is taken from the spelling stack.  */
+
+static void
+error_init (location_t loc, const char *gmsgid)
+{
+  char *ofwhat;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  error_at (loc, gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat)
+    inform (loc, "(near initialization for %qs)", ofwhat);
+}
+
+/* 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.  GMSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
+
+static void
+pedwarn_init (location_t location, int opt, const char *gmsgid)
+{
+  char *ofwhat;
+  bool warned;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  warned = pedwarn (location, opt, gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat && warned)
+    inform (location, "(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a warning for a bad initializer component.
+
+   OPT is the OPT_W* value corresponding to the warning option that
+   controls this warning.  GMSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
+
+static void
+warning_init (location_t loc, int opt, const char *gmsgid)
+{
+  char *ofwhat;
+  bool warned;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  warned = warning_at (loc, opt, gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat && warned)
+    inform (loc, "(near initialization for %qs)", ofwhat);
+}
+\f
+/* If TYPE is an array type and EXPR is a parenthesized string
+   constant, warn if pedantic that EXPR is being used to initialize an
+   object of type TYPE.  */
+
+void
+maybe_warn_string_init (location_t loc, tree type, struct c_expr expr)
+{
+  if (pedantic
+      && TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (expr.value) == STRING_CST
+      && expr.original_code != STRING_CST)
+    pedwarn_init (loc, OPT_Wpedantic,
+                 "array initialized from parenthesized string constant");
+}
+
 /* Convert value RHS to type TYPE as preparation for an assignment to
    an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
    original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -5530,13 +5598,14 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
    ERRTYPE says whether it is argument passing, assignment,
    initialization or return.
 
-   LOCATION is the location of the RHS.
+   LOCATION is the location of the assignment, EXPR_LOC is the location of
+   the RHS or, for a function, location of an argument.
    FUNCTION is a tree for the function being called.
    PARMNUM is the number of the argument, for printing in error messages.  */
 
 static tree
-convert_for_assignment (location_t location, tree type, tree rhs,
-                       tree origtype, enum impl_conv errtype,
+convert_for_assignment (location_t location, location_t expr_loc, tree type,
+                       tree rhs, tree origtype, enum impl_conv errtype,
                        bool null_pointer_constant, tree fundecl,
                        tree function, int parmnum)
 {
@@ -5569,14 +5638,14 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   /* 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(LOCATION, OPT, AR, AS, IN, RE)                      \
+#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE)        \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
+        if (pedwarn (PLOC, OPT, AR, parmnum, rname))                    \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
-                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                 ? DECL_SOURCE_LOCATION (fundecl) : PLOC,               \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -5587,7 +5656,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         pedwarn_init (LOCATION, OPT, IN);                                \
         break;                                                           \
       case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE);                                    \
+        pedwarn (LOCATION, OPT, RE);                                    \
         break;                                                           \
       default:                                                           \
         gcc_unreachable ();                                              \
@@ -5599,25 +5668,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
      compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
      extra parameter to enumerate qualifiers.  */
 
-#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
+#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS)  \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
+        if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))             \
           inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
-                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                 ? DECL_SOURCE_LOCATION (fundecl) : PLOC,               \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
       case ic_assign:                                                    \
-        pedwarn (LOCATION, OPT, AS, QUALS);                          \
+        pedwarn (LOCATION, OPT, AS, QUALS);                             \
         break;                                                           \
       case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN, QUALS);                          \
+        pedwarn (LOCATION, OPT, IN, QUALS);                             \
         break;                                                           \
       case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE, QUALS);                             \
+        pedwarn (LOCATION, OPT, RE, QUALS);                             \
         break;                                                           \
       default:                                                           \
         gcc_unreachable ();                                              \
@@ -5666,7 +5735,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          && TREE_CODE (type) == ENUMERAL_TYPE
          && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
        {
-         WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+         WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
                               G_("enum conversion when passing argument "
                                  "%d of %qE is invalid in C++"),
                               G_("enum conversion in assignment is "
@@ -5708,9 +5777,11 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
       SET_EXPR_LOCATION (rhs, location);
 
-      rhs = convert_for_assignment (location, build_pointer_type (TREE_TYPE (type)),
-                                   rhs, origtype, errtype, null_pointer_constant,
-                                   fundecl, function, parmnum);
+      rhs = convert_for_assignment (location, expr_loc,
+                                   build_pointer_type (TREE_TYPE (type)),
+                                   rhs, origtype, errtype,
+                                   null_pointer_constant, fundecl, function,
+                                   parmnum);
       if (rhs == error_mark_node)
        return error_mark_node;
 
@@ -5736,7 +5807,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       bool save = in_late_binary_op;
       if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = true;
-      ret = convert_and_check (type, orig_rhs);
+      ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
+                              ? expr_loc : location, type, orig_rhs);
       if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = save;
       return ret;
@@ -5746,7 +5818,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   if ((codel == RECORD_TYPE || codel == UNION_TYPE)
       && codel == coder
       && comptypes (type, rhstype))
-    return convert_and_check (type, rhs);
+    return convert_and_check (expr_loc != UNKNOWN_LOCATION
+                             ? expr_loc : location, type, rhs);
 
   /* Conversion to a transparent union or record from its member types.
      This applies only to function arguments.  */
@@ -5825,7 +5898,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                     vice-versa.  */
                  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-                   WARN_FOR_QUALIFIERS (location, 0,
+                   WARN_FOR_QUALIFIERS (location, expr_loc,
+                                        OPT_Wdiscarded_qualifiers,
                                         G_("passing argument %d of %qE "
                                            "makes %q#v qualified function "
                                            "pointer from unqualified"),
@@ -5841,7 +5915,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                }
              else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-               WARN_FOR_QUALIFIERS (location, 0,
+               WARN_FOR_QUALIFIERS (location, expr_loc,
+                                    OPT_Wdiscarded_qualifiers,
                                     G_("passing argument %d of %qE discards "
                                        "%qv qualifier from pointer target type"),
                                     G_("assignment discards %qv qualifier "
@@ -5917,8 +5992,9 @@ convert_for_assignment (location_t location, tree type, tree rhs,
 
         where NULL is typically defined in C to be '(void *) 0'.  */
       if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
-       warning_at (location, OPT_Wc___compat,
-                   "request for implicit conversion "
+       warning_at (errtype == ic_argpass ? expr_loc : location,
+                   OPT_Wc___compat,
+                   "request for implicit conversion "
                    "from %qT to %qT not permitted in C++", rhstype, type);
 
       /* See if the pointers point to incompatible address spaces.  */
@@ -5930,7 +6006,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          switch (errtype)
            {
            case ic_argpass:
-             error_at (location, "passing argument %d of %qE from pointer to "
+             error_at (expr_loc, "passing argument %d of %qE from pointer to "
                        "non-enclosed address space", parmnum, rname);
              break;
            case ic_assign:
@@ -5959,7 +6035,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          switch (errtype)
          {
          case ic_argpass:
-           warning_at (location, OPT_Wsuggest_attribute_format,
+           warning_at (expr_loc, OPT_Wsuggest_attribute_format,
                        "argument %d of %qE might be "
                        "a candidate for a format attribute",
                        parmnum, rname);
@@ -6003,7 +6079,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                  (VOID_TYPE_P (ttr)
                   && !null_pointer_constant
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
+           WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
                                 G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                                    "and %<void *%>"),
@@ -6022,7 +6098,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
              if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
                  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
                {
-                 WARN_FOR_QUALIFIERS (location, 0,
+                 WARN_FOR_QUALIFIERS (location, expr_loc,
+                                      OPT_Wdiscarded_qualifiers,
                                       G_("passing argument %d of %qE discards "
                                          "%qv qualifier from pointer target type"),
                                       G_("assignment discards %qv qualifier "
@@ -6040,7 +6117,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                ;
              /* If there is a mismatch, do warn.  */
              else if (warn_pointer_sign)
-               WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
+               WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
                                     G_("pointer targets in passing argument "
                                        "%d of %qE differ in signedness"),
                                     G_("pointer targets in assignment "
@@ -6059,7 +6136,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-               WARN_FOR_QUALIFIERS (location, 0,
+               WARN_FOR_QUALIFIERS (location, expr_loc,
+                                    OPT_Wdiscarded_qualifiers,
                                     G_("passing argument %d of %qE makes "
                                        "%q#v qualified function pointer "
                                        "from unqualified"),
@@ -6075,7 +6153,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       else
        /* Avoid warning about the volatile ObjC EH puts on decls.  */
        if (!objc_ok)
-         WARN_FOR_ASSIGNMENT (location, 0,
+         WARN_FOR_ASSIGNMENT (location, expr_loc,
+                              OPT_Wincompatible_pointer_types,
                               G_("passing argument %d of %qE from "
                                  "incompatible pointer type"),
                               G_("assignment from incompatible pointer type"),
@@ -6098,7 +6177,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       if (!null_pointer_constant)
-       WARN_FOR_ASSIGNMENT (location, 0,
+       WARN_FOR_ASSIGNMENT (location, expr_loc,
+                            OPT_Wint_conversion,
                             G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
                             G_("assignment makes pointer from integer "
@@ -6112,7 +6192,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (location, 0,
+      WARN_FOR_ASSIGNMENT (location, expr_loc,
+                          OPT_Wint_conversion,
                           G_("passing argument %d of %qE makes integer "
                              "from pointer without a cast"),
                           G_("assignment makes integer from pointer "
@@ -6136,9 +6217,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   switch (errtype)
     {
     case ic_argpass:
-      error_at (location, "incompatible type for argument %d of %qE", parmnum, rname);
+      error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
+               rname);
       inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
-             ? DECL_SOURCE_LOCATION (fundecl) : input_location,
+             ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
              "expected %qT but argument is of type %qT", type, rhstype);
       break;
     case ic_assign:
@@ -6147,12 +6229,12 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       break;
     case ic_init:
       error_at (location,
-               "incompatible types when initializing type %qT using type %qT",
+               "incompatible types when initializing type %qT using type %qT",
                type, rhstype);
       break;
     case ic_return:
       error_at (location,
-               "incompatible types when returning type %qT but %qT was "
+               "incompatible types when returning type %qT but %qT was "
                "expected", rhstype, type);
       break;
     default:
@@ -6379,72 +6461,6 @@ print_spelling (char *buffer)
   return buffer;
 }
 
-/* Issue an error message for a bad initializer component.
-   GMSGID identifies the message.
-   The component name is taken from the spelling stack.  */
-
-void
-error_init (const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  error (gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    error ("(near initialization for %qs)", ofwhat);
-}
-
-/* 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.  GMSGID identifies the message.  The
-   component name is taken from the spelling stack.  */
-
-void
-pedwarn_init (location_t location, int opt, const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  pedwarn (location, opt, gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a warning for a bad initializer component.
-
-   OPT is the OPT_W* value corresponding to the warning option that
-   controls this warning.  GMSGID identifies the message.  The
-   component name is taken from the spelling stack.  */
-
-static void
-warning_init (int opt, const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  warning (opt, gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    warning (opt, "(near initialization for %qs)", ofwhat);
-}
-\f
-/* If TYPE is an array type and EXPR is a parenthesized string
-   constant, warn if pedantic that EXPR is being used to initialize an
-   object of type TYPE.  */
-
-void
-maybe_warn_string_init (tree type, struct c_expr expr)
-{
-  if (pedantic
-      && TREE_CODE (type) == ARRAY_TYPE
-      && TREE_CODE (expr.value) == STRING_CST
-      && expr.original_code != STRING_CST)
-    pedwarn_init (input_location, OPT_Wpedantic,
-                 "array initialized from parenthesized string constant");
-}
-
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
 
@@ -6515,7 +6531,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
          expr.value = inside_init;
          expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
          expr.original_type = NULL;
-         maybe_warn_string_init (type, expr);
+         maybe_warn_string_init (init_loc, type, expr);
 
          if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
            pedwarn_init (init_loc, OPT_Wpedantic,
@@ -6529,7 +6545,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
            {
              if (typ2 != char_type_node)
                {
-                 error_init ("char-array initialized from wide string");
+                 error_init (init_loc, "char-array initialized from wide "
+                             "string");
                  return error_mark_node;
                }
            }
@@ -6537,14 +6554,14 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
            {
              if (typ2 == char_type_node)
                {
-                 error_init ("wide character array initialized from non-wide "
-                             "string");
+                 error_init (init_loc, "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");
+                 error_init (init_loc, "wide character array initialized "
+                             "from incompatible wide string");
                  return error_mark_node;
                }
            }
@@ -6577,7 +6594,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
        }
       else if (INTEGRAL_TYPE_P (typ1))
        {
-         error_init ("array of inappropriate type initialized "
+         error_init (init_loc, "array of inappropriate type initialized "
                      "from string constant");
          return error_mark_node;
        }
@@ -6645,7 +6662,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
                  (init_loc, inside_init);
              else
                {
-                 error_init ("invalid use of non-lvalue array");
+                 error_init (init_loc, "invalid use of non-lvalue array");
                  return error_mark_node;
                }
            }
@@ -6671,7 +6688,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
       if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
          && TREE_CODE (inside_init) != CONSTRUCTOR)
        {
-         error_init ("array initialized from non-constant array expression");
+         error_init (init_loc, "array initialized from non-constant array "
+                     "expression");
          return error_mark_node;
        }
 
@@ -6685,7 +6703,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
            = valid_compound_expr_initializer (inside_init,
                                               TREE_TYPE (inside_init));
          if (inside_init == error_mark_node)
-           error_init ("initializer element is not constant");
+           error_init (init_loc, "initializer element is not constant");
          else
            pedwarn_init (init_loc, OPT_Wpedantic,
                          "initializer element is not constant");
@@ -6696,7 +6714,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
               && !initializer_constant_valid_p (inside_init,
                                                 TREE_TYPE (inside_init)))
        {
-         error_init ("initializer element is not constant");
+         error_init (init_loc, "initializer element is not constant");
          inside_init = error_mark_node;
        }
       else if (require_constant && !maybe_const)
@@ -6705,8 +6723,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
 
       /* Added to enable additional -Wsuggest-attribute=format warnings.  */
       if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
-       inside_init = convert_for_assignment (init_loc, type, inside_init,
-                                             origtype,
+       inside_init = convert_for_assignment (init_loc, UNKNOWN_LOCATION,
+                                             type, inside_init, origtype,
                                              ic_init, null_pointer_constant,
                                              NULL_TREE, NULL_TREE, 0);
       return inside_init;
@@ -6726,23 +6744,25 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
        inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
                              inside_init);
       inside_init
-       = convert_for_assignment (init_loc, type, inside_init, origtype,
-                                 ic_init, null_pointer_constant,
-                                 NULL_TREE, NULL_TREE, 0);
+       = convert_for_assignment (init_loc, UNKNOWN_LOCATION, type,
+                                 inside_init, origtype, ic_init,
+                                 null_pointer_constant, NULL_TREE, NULL_TREE,
+                                 0);
 
       /* Check to see if we have already given an error message.  */
       if (inside_init == error_mark_node)
        ;
       else if (require_constant && !TREE_CONSTANT (inside_init))
        {
-         error_init ("initializer element is not constant");
+         error_init (init_loc, "initializer element is not constant");
          inside_init = error_mark_node;
        }
       else if (require_constant
               && !initializer_constant_valid_p (inside_init,
                                                 TREE_TYPE (inside_init)))
        {
-         error_init ("initializer element is not computable at load time");
+         error_init (init_loc, "initializer element is not computable at "
+                     "load time");
          inside_init = error_mark_node;
        }
       else if (require_constant && !maybe_const)
@@ -6756,11 +6776,11 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
 
   if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
     {
-      error_init ("variable-sized object may not be initialized");
+      error_init (init_loc, "variable-sized object may not be initialized");
       return error_mark_node;
     }
 
-  error_init ("invalid initializer");
+  error_init (init_loc, "invalid initializer");
   return error_mark_node;
 }
 \f
@@ -6814,6 +6834,9 @@ static int constructor_nonconst;
 /* 1 if this constructor is erroneous so far.  */
 static int constructor_erroneous;
 
+/* 1 if this constructor is the universal zero initializer { 0 }.  */
+static int constructor_zeroinit;
+
 /* Structure for managing pending initializer elements, organized as an
    AVL tree.  */
 
@@ -6887,6 +6910,7 @@ struct constructor_stack
   char outer;
   char incremental;
   char designated;
+  int designator_depth;
 };
 
 static struct constructor_stack *constructor_stack;
@@ -6975,7 +6999,7 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
   constructor_stack = 0;
   constructor_range_stack = 0;
 
-  missing_braces_mentioned = 0;
+  found_missing_braces = 0;
 
   spelling_base = 0;
   spelling_size = 0;
@@ -7058,6 +7082,7 @@ really_start_incremental_init (tree type)
   p->outer = 0;
   p->incremental = constructor_incremental;
   p->designated = constructor_designated;
+  p->designator_depth = designator_depth;
   p->next = 0;
   constructor_stack = p;
 
@@ -7070,6 +7095,7 @@ really_start_incremental_init (tree type)
   constructor_type = type;
   constructor_incremental = 1;
   constructor_designated = 0;
+  constructor_zeroinit = 1;
   designator_depth = 0;
   designator_erroneous = 0;
 
@@ -7138,7 +7164,8 @@ really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
-push_init_level (int implicit, struct obstack * braced_init_obstack)
+push_init_level (location_t loc, int implicit,
+                struct obstack *braced_init_obstack)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -7156,13 +7183,15 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
-           process_init_element (pop_init_level (1, braced_init_obstack),
+           process_init_element (input_location,
+                                 pop_init_level (loc, 1, braced_init_obstack),
                                  true, braced_init_obstack);
          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, braced_init_obstack),
+           process_init_element (input_location,
+                                 pop_init_level (loc, 1, braced_init_obstack),
                                  true, braced_init_obstack);
          else
            break;
@@ -7203,6 +7232,7 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
   p->outer = 0;
   p->incremental = constructor_incremental;
   p->designated = constructor_designated;
+  p->designator_depth = designator_depth;
   p->next = constructor_stack;
   p->range_stack = 0;
   constructor_stack = p;
@@ -7239,6 +7269,9 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
          push_member_name (constructor_fields);
          constructor_depth++;
        }
+      /* If upper initializer is designated, then mark this as
+        designated too to prevent bogus warnings.  */
+      constructor_designated = p->designated;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
@@ -7249,7 +7282,7 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
 
   if (constructor_type == 0)
     {
-      error_init ("extra brace group at end of initializer");
+      error_init (loc, "extra brace group at end of initializer");
       constructor_fields = 0;
       constructor_unfilled_fields = 0;
       return;
@@ -7267,11 +7300,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
        set_nonincremental_init (braced_init_obstack);
     }
 
-  if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
-    {
-      missing_braces_mentioned = 1;
-      warning_init (OPT_Wmissing_braces, "missing braces around initializer");
-    }
+  if (implicit == 1)
+    found_missing_braces = 1;
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
@@ -7331,7 +7361,7 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
   else
     {
       if (constructor_type != error_mark_node)
-       warning_init (0, "braces around scalar initializer");
+       warning_init (input_location, 0, "braces around scalar initializer");
       constructor_fields = constructor_type;
       constructor_unfilled_fields = constructor_type;
     }
@@ -7349,7 +7379,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
-pop_init_level (int implicit, struct obstack * braced_init_obstack)
+pop_init_level (location_t loc, int implicit,
+               struct obstack *braced_init_obstack)
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -7362,10 +7393,9 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
       /* 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, braced_init_obstack),
-                               true, braced_init_obstack);
-       }
+       process_init_element (input_location,
+                             pop_init_level (loc, 1, braced_init_obstack),
+                             true, braced_init_obstack);
       gcc_assert (!constructor_range_stack);
     }
 
@@ -7391,9 +7421,9 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
          gcc_assert (!TYPE_SIZE (constructor_type));
 
          if (constructor_depth > 2)
-           error_init ("initialization of flexible array member in a nested context");
+           error_init (loc, "initialization of flexible array member in a nested context");
          else
-           pedwarn_init (input_location, OPT_Wpedantic,
+           pedwarn_init (loc, OPT_Wpedantic,
                          "initialization of a flexible array member");
 
          /* We have already issued an error message for the existence
@@ -7404,16 +7434,23 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
        }
     }
 
+  if (vec_safe_length (constructor_elements) != 1)
+    constructor_zeroinit = 0;
+
+  /* Warn when some structs are initialized with direct aggregation.  */
+  if (!implicit && found_missing_braces && warn_missing_braces
+      && !constructor_zeroinit)
+    {
+      warning_init (loc, OPT_Wmissing_braces,
+                   "missing braces around initializer");
+    }
+
   /* Warn when some struct elements are implicitly initialized to zero.  */
   if (warn_missing_field_initializers
       && constructor_type
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
-       bool constructor_zeroinit =
-        (vec_safe_length (constructor_elements) == 1
-         && integer_zerop ((*constructor_elements)[0].value));
-
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
@@ -7453,12 +7490,12 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
       if (vec_safe_is_empty (constructor_elements))
        {
          if (!constructor_erroneous)
-           error_init ("empty scalar initializer");
+           error_init (loc, "empty scalar initializer");
          ret.value = error_mark_node;
        }
       else if (vec_safe_length (constructor_elements) != 1)
        {
-         error_init ("extra elements in scalar initializer");
+         error_init (loc, "extra elements in scalar initializer");
          ret.value = (*constructor_elements)[0].value;
        }
       else
@@ -7503,6 +7540,7 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
   constructor_erroneous = p->erroneous;
   constructor_incremental = p->incremental;
   constructor_designated = p->designated;
+  designator_depth = p->designator_depth;
   constructor_pending_elts = p->pending_elts;
   constructor_depth = p->depth;
   if (!p->implicit)
@@ -7521,7 +7559,8 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
-set_designator (int array, struct obstack * braced_init_obstack)
+set_designator (location_t loc, int array,
+               struct obstack *braced_init_obstack)
 {
   tree subtype;
   enum tree_code subcode;
@@ -7543,10 +7582,9 @@ set_designator (int array, struct obstack * braced_init_obstack)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
-       {
-         process_init_element (pop_init_level (1, braced_init_obstack),
-                               true, braced_init_obstack);
-       }
+       process_init_element (input_location,
+                             pop_init_level (loc, 1, braced_init_obstack),
+                             true, braced_init_obstack);
       constructor_designated = 1;
       return 0;
     }
@@ -7569,17 +7607,17 @@ set_designator (int array, struct obstack * braced_init_obstack)
   subcode = TREE_CODE (subtype);
   if (array && subcode != ARRAY_TYPE)
     {
-      error_init ("array index in non-array initializer");
+      error_init (loc, "array index in non-array initializer");
       return 1;
     }
   else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
     {
-      error_init ("field name not in record or union initializer");
+      error_init (loc, "field name not in record or union initializer");
       return 1;
     }
 
   constructor_designated = 1;
-  push_init_level (2, braced_init_obstack);
+  push_init_level (loc, 2, braced_init_obstack);
   return 0;
 }
 
@@ -7612,10 +7650,10 @@ push_range_stack (tree range_end, struct obstack * braced_init_obstack)
    of indices, running from FIRST through LAST.  */
 
 void
-set_init_index (tree first, tree last,
-               struct obstack * braced_init_obstack)
+set_init_index (location_t loc, tree first, tree last,
+               struct obstack *braced_init_obstack)
 {
-  if (set_designator (1, braced_init_obstack))
+  if (set_designator (loc, 1, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -7623,7 +7661,7 @@ set_init_index (tree first, tree last,
   if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
       || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
     {
-      error_init ("array index in initializer not of integer type");
+      error_init (loc, "array index in initializer not of integer type");
       return;
     }
 
@@ -7631,7 +7669,7 @@ set_init_index (tree first, tree last,
     {
       first = c_fully_fold (first, false, NULL);
       if (TREE_CODE (first) == INTEGER_CST)
-       pedwarn_init (input_location, OPT_Wpedantic,
+       pedwarn_init (loc, OPT_Wpedantic,
                      "array index in initializer is not "
                      "an integer constant expression");
     }
@@ -7640,22 +7678,22 @@ set_init_index (tree first, tree last,
     {
       last = c_fully_fold (last, false, NULL);
       if (TREE_CODE (last) == INTEGER_CST)
-       pedwarn_init (input_location, OPT_Wpedantic,
+       pedwarn_init (loc, OPT_Wpedantic,
                      "array index in initializer is not "
                      "an integer constant expression");
     }
 
   if (TREE_CODE (first) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
+    error_init (loc, "nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
+    error_init (loc, "nonconstant array index in initializer");
   else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
-    error_init ("array index in non-array initializer");
+    error_init (loc, "array index in non-array initializer");
   else if (tree_int_cst_sgn (first) == -1)
-    error_init ("array index in initializer exceeds array bounds");
+    error_init (loc, "array index in initializer exceeds array bounds");
   else if (constructor_max_index
           && tree_int_cst_lt (constructor_max_index, first))
-    error_init ("array index in initializer exceeds array bounds");
+    error_init (loc, "array index in initializer exceeds array bounds");
   else
     {
       constant_expression_warning (first);
@@ -7674,7 +7712,7 @@ set_init_index (tree first, tree last,
            last = 0;
          else if (tree_int_cst_lt (last, first))
            {
-             error_init ("empty index range in initializer");
+             error_init (loc, "empty index range in initializer");
              last = 0;
            }
          else
@@ -7683,7 +7721,8 @@ set_init_index (tree first, tree last,
              if (constructor_max_index != 0
                  && tree_int_cst_lt (constructor_max_index, last))
                {
-                 error_init ("array index range in initializer exceeds array bounds");
+                 error_init (loc, "array index range in initializer exceeds "
+                             "array bounds");
                  last = 0;
                }
            }
@@ -7699,11 +7738,12 @@ set_init_index (tree first, tree last,
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
-set_init_label (tree fieldname, struct obstack * braced_init_obstack)
+set_init_label (location_t loc, tree fieldname,
+               struct obstack *braced_init_obstack)
 {
   tree field;
 
-  if (set_designator (0, braced_init_obstack))
+  if (set_designator (loc, 0, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -7711,7 +7751,7 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack)
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != UNION_TYPE)
     {
-      error_init ("field name not in record or union initializer");
+      error_init (loc, "field name not in record or union initializer");
       return;
     }
 
@@ -7730,7 +7770,7 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack)
        field = TREE_CHAIN (field);
        if (field)
          {
-           if (set_designator (0, braced_init_obstack))
+           if (set_designator (loc, 0, braced_init_obstack))
              return;
          }
       }
@@ -7748,8 +7788,8 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack)
    existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
-                 struct obstack * braced_init_obstack)
+add_pending_init (location_t loc, tree purpose, tree value, tree origtype,
+                 bool implicit, struct obstack *braced_init_obstack)
 {
   struct init_node *p, **q, *r;
 
@@ -7770,9 +7810,12 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
              if (!implicit)
                {
                  if (TREE_SIDE_EFFECTS (p->value))
-                   warning_init (0, "initialized field with side-effects overwritten");
+                   warning_init (loc, 0,
+                                 "initialized field with side-effects "
+                                 "overwritten");
                  else if (warn_override_init)
-                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+                   warning_init (loc, OPT_Woverride_init,
+                                 "initialized field overwritten");
                }
              p->value = value;
              p->origtype = origtype;
@@ -7797,9 +7840,12 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
              if (!implicit)
                {
                  if (TREE_SIDE_EFFECTS (p->value))
-                   warning_init (0, "initialized field with side-effects overwritten");
+                   warning_init (loc, 0,
+                                 "initialized field with side-effects "
+                                 "overwritten");
                  else if (warn_override_init)
-                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+                   warning_init (loc, OPT_Woverride_init,
+                                 "initialized field overwritten");
                }
              p->value = value;
              p->origtype = origtype;
@@ -7988,10 +8034,8 @@ set_nonincremental_init (struct obstack * braced_init_obstack)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    {
-      add_pending_init (index, value, NULL_TREE, true,
-                       braced_init_obstack);
-    }
+    add_pending_init (input_location, index, value, NULL_TREE, true,
+                     braced_init_obstack);
   constructor_elements = NULL;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -8042,20 +8086,20 @@ set_nonincremental_init_from_string (tree str,
     {
       if (wchar_bytes == 1)
        {
-         val[1] = (unsigned char) *p++;
-         val[0] = 0;
+         val[0] = (unsigned char) *p++;
+         val[1] = 0;
        }
       else
        {
-         val[0] = 0;
          val[1] = 0;
+         val[0] = 0;
          for (byte = 0; byte < wchar_bytes; byte++)
            {
              if (BYTES_BIG_ENDIAN)
                bitpos = (wchar_bytes - byte - 1) * charwidth;
              else
                bitpos = byte * charwidth;
-             val[bitpos < HOST_BITS_PER_WIDE_INT]
+             val[bitpos % HOST_BITS_PER_WIDE_INT]
                |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
                   << (bitpos % HOST_BITS_PER_WIDE_INT);
            }
@@ -8066,25 +8110,27 @@ set_nonincremental_init_from_string (tree str,
          bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
          if (bitpos < HOST_BITS_PER_WIDE_INT)
            {
-             if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+             if (val[0] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
                {
-                 val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
-                 val[0] = -1;
+                 val[0] |= ((HOST_WIDE_INT) -1) << bitpos;
+                 val[1] = -1;
                }
            }
          else if (bitpos == HOST_BITS_PER_WIDE_INT)
            {
-             if (val[1] < 0)
-               val[0] = -1;
+             if (val[0] < 0)
+               val[1] = -1;
            }
-         else if (val[0] & (((HOST_WIDE_INT) 1)
+         else if (val[1] & (((HOST_WIDE_INT) 1)
                             << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
-           val[0] |= ((HOST_WIDE_INT) -1)
+           val[1] |= ((HOST_WIDE_INT) -1)
                      << (bitpos - HOST_BITS_PER_WIDE_INT);
        }
 
-      value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, true,
+      value = wide_int_to_tree (type,
+                               wide_int::from_array (val, 2,
+                                                     HOST_BITS_PER_WIDE_INT * 2));
+      add_pending_init (input_location, purpose, value, NULL_TREE, true,
                         braced_init_obstack);
     }
 
@@ -8166,9 +8212,9 @@ find_init_member (tree field, struct obstack * braced_init_obstack)
    existing initializer.  */
 
 static void
-output_init_element (tree value, tree origtype, bool strict_string, tree type,
-                    tree field, int pending, bool implicit,
-                    struct obstack * braced_init_obstack)
+output_init_element (location_t loc, tree value, tree origtype,
+                    bool strict_string, tree type, tree field, int pending,
+                    bool implicit, struct obstack * braced_init_obstack)
 {
   tree semantic_type = NULL_TREE;
   bool maybe_const = true;
@@ -8224,16 +8270,16 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
     {
       if (require_constant_value)
        {
-         error_init ("initializer element is not constant");
+         error_init (loc, "initializer element is not constant");
          value = error_mark_node;
        }
       else if (require_constant_elements)
-       pedwarn (input_location, 0,
+       pedwarn (loc, OPT_Wpedantic,
                 "initializer element is not computable at load time");
     }
   else if (!maybe_const
           && (require_constant_value || require_constant_elements))
-    pedwarn_init (input_location, 0,
+    pedwarn_init (loc, OPT_Wpedantic,
                  "initializer element is not a constant expression");
 
   /* Issue -Wc++-compat warnings about initializing a bitfield with
@@ -8250,7 +8296,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (checktype != error_mark_node
          && (TYPE_MAIN_VARIANT (checktype)
              != TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
-       warning_init (OPT_Wc___compat,
+       warning_init (loc, OPT_Wc___compat,
                      "enum conversion in initialization is invalid in C++");
     }
 
@@ -8266,8 +8312,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
 
   if (semantic_type)
     value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
-  value = digest_init (input_location, type, value, origtype, npc,
-                      strict_string, require_constant_value);
+  value = digest_init (loc, type, value, origtype, npc, strict_string,
+                      require_constant_value);
   if (value == error_mark_node)
     {
       constructor_erroneous = 1;
@@ -8286,7 +8332,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
          && tree_int_cst_lt (field, constructor_unfilled_index))
        set_nonincremental_init (braced_init_obstack);
 
-      add_pending_init (field, value, origtype, implicit,
+      add_pending_init (loc, field, value, origtype, implicit,
                        braced_init_obstack);
       return;
     }
@@ -8313,7 +8359,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
            }
        }
 
-      add_pending_init (field, value, origtype, implicit,
+      add_pending_init (loc, field, value, origtype, implicit,
                        braced_init_obstack);
       return;
     }
@@ -8323,10 +8369,11 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (!implicit)
        {
          if (TREE_SIDE_EFFECTS (constructor_elements->last ().value))
-           warning_init (0,
+           warning_init (loc, 0,
                          "initialized field with side-effects overwritten");
          else if (warn_override_init)
-           warning_init (OPT_Woverride_init, "initialized field overwritten");
+           warning_init (loc, OPT_Woverride_init,
+                         "initialized field overwritten");
        }
 
       /* We can have just one union field set.  */
@@ -8394,8 +8441,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
        {
          if (tree_int_cst_equal (elt->purpose,
                                  constructor_unfilled_index))
-           output_init_element (elt->value, elt->origtype, true,
-                                TREE_TYPE (constructor_type),
+           output_init_element (input_location, elt->value, elt->origtype,
+                                true, TREE_TYPE (constructor_type),
                                 constructor_unfilled_index, 0, false,
                                 braced_init_obstack);
          else if (tree_int_cst_lt (constructor_unfilled_index,
@@ -8449,8 +8496,8 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
          if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
            {
              constructor_unfilled_fields = elt->purpose;
-             output_init_element (elt->value, elt->origtype, true,
-                                  TREE_TYPE (elt->purpose),
+             output_init_element (input_location, elt->value, elt->origtype,
+                                  true, TREE_TYPE (elt->purpose),
                                   elt->purpose, 0, false,
                                   braced_init_obstack);
            }
@@ -8523,7 +8570,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack)
    existing initializer.  */
 
 void
-process_init_element (struct c_expr value, bool implicit,
+process_init_element (location_t loc, struct c_expr value, bool implicit,
                      struct obstack * braced_init_obstack)
 {
   tree orig_value = value.value;
@@ -8534,6 +8581,9 @@ process_init_element (struct c_expr value, bool implicit,
   designator_depth = 0;
   designator_erroneous = 0;
 
+  if (!implicit && value.value && !integer_zerop (value.value))
+    constructor_zeroinit = 0;
+
   /* Handle superfluous braces around string cst as in
      char x[] = {"foo"}; */
   if (string_flag
@@ -8544,14 +8594,14 @@ process_init_element (struct c_expr value, bool implicit,
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
-       error_init ("excess elements in char array initializer");
+       error_init (loc, "excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
 
   if (constructor_stack->replacement_value.value != 0)
     {
-      error_init ("excess elements in struct initializer");
+      error_init (loc, "excess elements in struct initializer");
       return;
     }
 
@@ -8560,6 +8610,15 @@ process_init_element (struct c_expr value, bool implicit,
   if (constructor_type == 0)
     return;
 
+  if (!implicit && warn_designated_init && !was_designated
+      && TREE_CODE (constructor_type) == RECORD_TYPE
+      && lookup_attribute ("designated_init",
+                          TYPE_ATTRIBUTES (constructor_type)))
+    warning_init (loc,
+                 OPT_Wdesignated_init,
+                 "positional initialization of field "
+                 "in %<struct%> declared with %<designated_init%> attribute");
+
   /* If we've exhausted any levels that didn't have braces,
      pop them now.  */
   while (constructor_stack->implicit)
@@ -8567,14 +8626,16 @@ process_init_element (struct c_expr value, bool implicit,
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
-       process_init_element (pop_init_level (1, braced_init_obstack),
+       process_init_element (loc,
+                             pop_init_level (loc, 1, braced_init_obstack),
                              true, braced_init_obstack);
       else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
                || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && constructor_max_index
               && tree_int_cst_lt (constructor_max_index,
                                   constructor_index))
-       process_init_element (pop_init_level (1, braced_init_obstack),
+       process_init_element (loc,
+                             pop_init_level (loc, 1, braced_init_obstack),
                              true, braced_init_obstack);
       else
        break;
@@ -8611,8 +8672,7 @@ process_init_element (struct c_expr value, bool implicit,
 
          if (constructor_fields == 0)
            {
-             pedwarn_init (input_location, 0,
-                           "excess elements in struct initializer");
+             pedwarn_init (loc, 0, "excess elements in struct initializer");
              break;
            }
 
@@ -8627,7 +8687,8 @@ process_init_element (struct c_expr value, bool implicit,
              && TYPE_SIZE (fieldtype) == NULL_TREE
              && DECL_CHAIN (constructor_fields) == NULL_TREE)
            {
-             error_init ("non-static initialization of a flexible array member");
+             error_init (loc, "non-static initialization of a flexible "
+                         "array member");
              break;
            }
 
@@ -8645,14 +8706,14 @@ process_init_element (struct c_expr value, bool implicit,
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1, braced_init_obstack);
+             push_init_level (loc, 1, braced_init_obstack);
              continue;
            }
 
          if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value.value, value.original_type,
+             output_init_element (loc, value.value, value.original_type,
                                   strict_string, fieldtype,
                                   constructor_fields, 1, implicit,
                                   braced_init_obstack);
@@ -8697,7 +8758,7 @@ process_init_element (struct c_expr value, bool implicit,
 
          if (constructor_fields == 0)
            {
-             pedwarn_init (input_location, 0,
+             pedwarn_init (loc, 0,
                            "excess elements in union initializer");
              break;
            }
@@ -8737,14 +8798,14 @@ process_init_element (struct c_expr value, bool implicit,
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1, braced_init_obstack);
+             push_init_level (loc, 1, braced_init_obstack);
              continue;
            }
 
          if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value.value, value.original_type,
+             output_init_element (loc, value.value, value.original_type,
                                   strict_string, fieldtype,
                                   constructor_fields, 1, implicit,
                                   braced_init_obstack);
@@ -8779,7 +8840,7 @@ process_init_element (struct c_expr value, bool implicit,
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
-             push_init_level (1, braced_init_obstack);
+             push_init_level (loc, 1, braced_init_obstack);
              continue;
            }
 
@@ -8787,7 +8848,7 @@ process_init_element (struct c_expr value, bool implicit,
              && (tree_int_cst_lt (constructor_max_index, constructor_index)
                  || integer_all_onesp (constructor_max_index)))
            {
-             pedwarn_init (input_location, 0,
+             pedwarn_init (loc, 0,
                            "excess elements in array initializer");
              break;
            }
@@ -8796,7 +8857,7 @@ process_init_element (struct c_expr value, bool implicit,
          if (value.value)
            {
              push_array_bounds (tree_to_uhwi (constructor_index));
-             output_init_element (value.value, value.original_type,
+             output_init_element (loc, value.value, value.original_type,
                                   strict_string, elttype,
                                   constructor_index, 1, implicit,
                                   braced_init_obstack);
@@ -8821,7 +8882,7 @@ process_init_element (struct c_expr value, bool implicit,
            always have a fixed size derived from their type.  */
          if (tree_int_cst_lt (constructor_max_index, constructor_index))
            {
-             pedwarn_init (input_location, 0,
+             pedwarn_init (loc, 0,
                            "excess elements in vector initializer");
              break;
            }
@@ -8831,7 +8892,7 @@ process_init_element (struct c_expr value, bool implicit,
            {
              if (TREE_CODE (value.value) == VECTOR_CST)
                elttype = TYPE_MAIN_VARIANT (constructor_type);
-             output_init_element (value.value, value.original_type,
+             output_init_element (loc, value.value, value.original_type,
                                   strict_string, elttype,
                                   constructor_index, 1, implicit,
                                   braced_init_obstack);
@@ -8853,14 +8914,14 @@ process_init_element (struct c_expr value, bool implicit,
       else if (constructor_type != error_mark_node
               && constructor_fields == 0)
        {
-         pedwarn_init (input_location, 0,
+         pedwarn_init (loc, 0,
                        "excess elements in scalar initializer");
          break;
        }
       else
        {
          if (value.value)
-           output_init_element (value.value, value.original_type,
+           output_init_element (loc, value.value, value.original_type,
                                 strict_string, constructor_type,
                                 NULL_TREE, 1, implicit,
                                 braced_init_obstack);
@@ -8879,7 +8940,8 @@ process_init_element (struct c_expr value, bool implicit,
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1,
+             process_init_element (loc,
+                                   pop_init_level (loc, 1,
                                                    braced_init_obstack),
                                    true, braced_init_obstack);
            }
@@ -8888,7 +8950,9 @@ process_init_element (struct c_expr value, bool implicit,
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1, braced_init_obstack),
+             process_init_element (loc,
+                                   pop_init_level (loc, 1,
+                                                   braced_init_obstack),
                                    true, braced_init_obstack);
            }
 
@@ -8909,7 +8973,7 @@ process_init_element (struct c_expr value, bool implicit,
              p = p->next;
              if (!p)
                break;
-             push_init_level (2, braced_init_obstack);
+             push_init_level (loc, 2, braced_init_obstack);
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
@@ -9101,7 +9165,8 @@ c_finish_goto_ptr (location_t loc, tree expr)
 
 /* Generate a C `return' statement.  RETVAL is the expression for what
    to return, or a null pointer for `return;' with no value.  LOC is
-   the location of the return statement.  If ORIGTYPE is not NULL_TREE, it
+   the location of the return statement, or the location of the expression,
+   if the statement has any.  If ORIGTYPE is not NULL_TREE, it
    is the original type of RETVAL.  */
 
 tree
@@ -9116,7 +9181,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     warning_at (loc, 0,
                "function declared %<noreturn%> has a %<return%> statement");
 
-  if (flag_enable_cilkplus && contains_array_notation_expr (retval))
+  if (flag_cilkplus && contains_array_notation_expr (retval))
     {
       /* Array notations are allowed in a return statement if it is inside a
         built-in array notation reduction function.  */
@@ -9129,7 +9194,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
          return error_mark_node;
        }
     }
-  if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
+  if (flag_cilkplus && retval && contains_cilk_spawn_stmt (retval))
     {
       error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
                "allowed");
@@ -9173,8 +9238,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     }
   else
     {
-      tree t = convert_for_assignment (loc, valtype, retval, origtype,
-                                      ic_return,
+      tree t = convert_for_assignment (loc, UNKNOWN_LOCATION, valtype,
+                                      retval, origtype, ic_return,
                                       npc, NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
@@ -9234,9 +9299,18 @@ c_finish_return (location_t loc, tree retval, tree origtype)
                  && !DECL_EXTERNAL (inner)
                  && !TREE_STATIC (inner)
                  && DECL_CONTEXT (inner) == current_function_decl)
-               warning_at (loc,
-                           OPT_Wreturn_local_addr, "function returns address "
-                           "of local variable");
+               {
+                 if (TREE_CODE (inner) == LABEL_DECL)
+                   warning_at (loc, OPT_Wreturn_local_addr,
+                               "function returns address of label");
+                 else
+                   {
+                     warning_at (loc, OPT_Wreturn_local_addr,
+                                 "function returns address of local variable");
+                     tree zero = build_zero_cst (TREE_TYPE (res));
+                     t = build2 (COMPOUND_EXPR, TREE_TYPE (res), t, zero);
+                   }
+               }
              break;
 
            default:
@@ -9291,12 +9365,13 @@ struct c_switch *c_switch_stack;
 
 /* Start a C switch statement, testing expression EXP.  Return the new
    SWITCH_EXPR.  SWITCH_LOC is the location of the `switch'.
-   SWITCH_COND_LOC is the location of the switch's condition.  */
+   SWITCH_COND_LOC is the location of the switch's condition.
+   EXPLICIT_CAST_P is true if the expression EXP has explicit cast.  */
 
 tree
 c_start_case (location_t switch_loc,
              location_t switch_cond_loc,
-             tree exp)
+             tree exp, bool explicit_cast_p)
 {
   tree orig_type = error_mark_node;
   struct c_switch *cs;
@@ -9317,6 +9392,19 @@ c_start_case (location_t switch_loc,
       else
        {
          tree type = TYPE_MAIN_VARIANT (orig_type);
+         tree e = exp;
+
+         /* Warn if the condition has boolean value.  */
+         while (TREE_CODE (e) == COMPOUND_EXPR)
+           e = TREE_OPERAND (e, 1);
+
+         if ((TREE_CODE (type) == BOOLEAN_TYPE
+              || truth_value_p (TREE_CODE (e)))
+             /* Explicit cast to int suppresses this warning.  */
+             && !(TREE_CODE (type) == INTEGER_TYPE
+                  && explicit_cast_p))
+           warning_at (switch_cond_loc, OPT_Wswitch_bool,
+                       "switch condition has boolean value");
 
          if (!in_system_header_at (input_location)
              && (type == long_integer_type_node
@@ -9357,7 +9445,7 @@ do_case (location_t loc, tree low_value, tree high_value)
     {
       low_value = c_fully_fold (low_value, false, NULL);
       if (TREE_CODE (low_value) == INTEGER_CST)
-       pedwarn (input_location, OPT_Wpedantic,
+       pedwarn (loc, OPT_Wpedantic,
                 "case label is not an integer constant expression");
     }
 
@@ -9430,7 +9518,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
      else_block must be either 0 or be equal to the rank of the condition.  If
      the condition does not have array notations then break them up as it is
      broken up in a normal expression.  */
-  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+  if (flag_cilkplus && contains_array_notation_expr (cond))
     {
       size_t then_rank = 0, cond_rank = 0, else_rank = 0;
       if (!find_rank (if_locus, cond, cond, true, &cond_rank))
@@ -9505,7 +9593,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
 {
   tree entry = NULL, exit = NULL, t;
 
-  if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+  if (flag_cilkplus && contains_array_notation_expr (cond))
     {
       error_at (start_locus, "array notation expression cannot be used in a "
                "loop%'s condition");
@@ -9643,6 +9731,24 @@ emit_side_effect_warnings (location_t loc, tree expr)
       if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
        warning_at (loc, OPT_Wunused_value, "statement with no effect");
     }
+  else if (TREE_CODE (expr) == COMPOUND_EXPR)
+    {
+      tree r = expr;
+      location_t cloc = loc;
+      while (TREE_CODE (r) == COMPOUND_EXPR)
+       {
+         if (EXPR_HAS_LOCATION (r))
+           cloc = EXPR_LOCATION (r);
+         r = TREE_OPERAND (r, 1);
+       }
+      if (!TREE_SIDE_EFFECTS (r)
+         && !VOID_TYPE_P (TREE_TYPE (r))
+         && !CONVERT_EXPR_P (r)
+         && !TREE_NO_WARNING (r)
+         && !TREE_NO_WARNING (expr))
+       warning_at (cloc, OPT_Wunused_value,
+                   "right-hand operand of comma expression has no effect");
+    }
   else
     warn_if_unused_value (expr, loc);
 }
@@ -10037,12 +10143,12 @@ build_binary_op (location_t location, enum tree_code code,
   /* When Cilk Plus is enabled and there are array notations inside op0, then
      we check to see if there are builtin array notation functions.  If
      so, then we take on the type of the array notation inside it.  */
-  if (flag_enable_cilkplus && contains_array_notation_expr (op0)) 
+  if (flag_cilkplus && contains_array_notation_expr (op0)) 
     orig_type0 = type0 = find_correct_array_notation_type (op0);
   else
     orig_type0 = type0 = TREE_TYPE (op0);
 
-  if (flag_enable_cilkplus && contains_array_notation_expr (op1))
+  if (flag_cilkplus && contains_array_notation_expr (op1))
     orig_type1 = type1 = find_correct_array_notation_type (op1);
   else 
     orig_type1 = type1 = TREE_TYPE (op1);
@@ -10356,7 +10462,7 @@ build_binary_op (location_t location, enum tree_code code,
                {
                  int_const = false;
                  if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "right shift count is negative");
+                   warning_at (location, 0, "right shift count is negative");
                }
              else
                {
@@ -10367,7 +10473,8 @@ build_binary_op (location_t location, enum tree_code code,
                    {
                      int_const = false;
                      if (c_inhibit_evaluation_warnings == 0)
-                       warning (0, "right shift count >= width of type");
+                       warning_at (location, 0, "right shift count >= width "
+                                   "of type");
                    }
                }
            }
@@ -10409,14 +10516,15 @@ build_binary_op (location_t location, enum tree_code code,
                {
                  int_const = false;
                  if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "left shift count is negative");
+                   warning_at (location, 0, "left shift count is negative");
                }
 
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                {
                  int_const = false;
                  if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "left shift count >= width of type");
+                   warning_at (location, 0, "left shift count >= width of "
+                               "type");
                }
            }
 
@@ -10730,16 +10838,16 @@ build_binary_op (location_t location, enum tree_code code,
          if (first_complex)
            {
              if (TREE_TYPE (op0) != result_type)
-               op0 = convert_and_check (result_type, op0);
+               op0 = convert_and_check (location, result_type, op0);
              if (TREE_TYPE (op1) != real_type)
-               op1 = convert_and_check (real_type, op1);
+               op1 = convert_and_check (location, real_type, op1);
            }
          else
            {
              if (TREE_TYPE (op0) != real_type)
-               op0 = convert_and_check (real_type, op0);
+               op0 = convert_and_check (location, real_type, op0);
              if (TREE_TYPE (op1) != result_type)
-               op1 = convert_and_check (result_type, op1);
+               op1 = convert_and_check (location, result_type, op1);
            }
          if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
            return error_mark_node;
@@ -10854,7 +10962,8 @@ build_binary_op (location_t location, enum tree_code code,
          tree xop0 = op0, xop1 = op1, xresult_type = result_type;
          enum tree_code xresultcode = resultcode;
          tree val
-           = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
+           = shorten_compare (location, &xop0, &xop1, &xresult_type,
+                              &xresultcode);
 
          if (val != 0)
            {
@@ -10937,8 +11046,10 @@ build_binary_op (location_t location, enum tree_code code,
 
   if (!converted)
     {
-      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
-      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+      op0 = ep_convert_and_check (location, result_type, op0,
+                                 semantic_result_type);
+      op1 = ep_convert_and_check (location, result_type, op1,
+                                 semantic_result_type);
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -10946,7 +11057,8 @@ build_binary_op (location_t location, enum tree_code code,
        return error_mark_node;
     }
 
-  if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE))
+  if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE
+                       | SANITIZE_FLOAT_DIVIDE))
       && current_function_decl != 0
       && !lookup_attribute ("no_sanitize_undefined",
                            DECL_ATTRIBUTES (current_function_decl))
@@ -10957,7 +11069,8 @@ build_binary_op (location_t location, enum tree_code code,
       op1 = c_save_expr (op1);
       op0 = c_fully_fold (op0, false, NULL);
       op1 = c_fully_fold (op1, false, NULL);
-      if (doing_div_or_mod && (flag_sanitize & SANITIZE_DIVIDE))
+      if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE
+                                               | SANITIZE_FLOAT_DIVIDE)))
        instrument_expr = ubsan_instrument_division (location, op0, op1);
       else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT))
        instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
@@ -11641,15 +11754,15 @@ c_clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2,
                 tree decl, tree placeholder)
 {
   copy_body_data id;
-  struct pointer_map_t *decl_map = pointer_map_create ();
+  hash_map<tree, tree> decl_map;
 
-  *pointer_map_insert (decl_map, omp_decl1) = placeholder;
-  *pointer_map_insert (decl_map, omp_decl2) = decl;
+  decl_map.put (omp_decl1, placeholder);
+  decl_map.put (omp_decl2, decl);
   memset (&id, 0, sizeof (id));
   id.src_fn = DECL_CONTEXT (omp_decl1);
   id.dst_fn = current_function_decl;
   id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn);
-  id.decl_map = decl_map;
+  id.decl_map = &decl_map;
 
   id.copy_decl = copy_decl_no_change;
   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
@@ -11658,7 +11771,6 @@ c_clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2,
   id.transform_lang_insert_block = NULL;
   id.eh_lp_nr = 0;
   walk_tree (&stmt, copy_tree_body_r, &id, NULL);
-  pointer_map_destroy (decl_map);
   return stmt;
 }
 
@@ -11681,7 +11793,7 @@ c_finish_omp_clauses (tree clauses)
 {
   bitmap_head generic_head, firstprivate_head, lastprivate_head;
   bitmap_head aligned_head;
-  tree c, t, *pc = &clauses;
+  tree c, t, *pc;
   bool branch_seen = false;
   bool copyprivate_seen = false;
   tree *nowait_clause = NULL;
@@ -11713,7 +11825,8 @@ c_finish_omp_clauses (tree clauses)
          need_implicitly_determined = true;
          t = OMP_CLAUSE_DECL (c);
          if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
-             && FLOAT_TYPE_P (TREE_TYPE (t)))
+             && (FLOAT_TYPE_P (TREE_TYPE (t))
+                 || TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE))
            {
              enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
              const char *r_name = NULL;
@@ -11723,8 +11836,14 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+                 break;
                case MIN_EXPR:
+                 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
+                   r_name = "min";
+                 break;
                case MAX_EXPR:
+                 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
+                   r_name = "max";
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -11736,10 +11855,12 @@ c_finish_omp_clauses (tree clauses)
                  r_name = "|";
                  break;
                case TRUTH_ANDIF_EXPR:
-                 r_name = "&&";
+                 if (FLOAT_TYPE_P (TREE_TYPE (t)))
+                   r_name = "&&";
                  break;
                case TRUTH_ORIF_EXPR:
-                 r_name = "||";
+                 if (FLOAT_TYPE_P (TREE_TYPE (t)))
+                   r_name = "||";
                  break;
                default:
                  gcc_unreachable ();
@@ -11868,6 +11989,9 @@ c_finish_omp_clauses (tree clauses)
                s = size_one_node;
              OMP_CLAUSE_LINEAR_STEP (c) = s;
            }
+         else
+           OMP_CLAUSE_LINEAR_STEP (c)
+             = fold_convert (TREE_TYPE (t), OMP_CLAUSE_LINEAR_STEP (c));
          goto check_dup_generic;
 
        check_dup_generic:
@@ -11991,7 +12115,7 @@ c_finish_omp_clauses (tree clauses)
              else
                {
                  t = OMP_CLAUSE_DECL (c);
-                 if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
+                 if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
                    {
                      error_at (OMP_CLAUSE_LOCATION (c),
                                "array section does not have mappable type "
@@ -12020,9 +12144,9 @@ c_finish_omp_clauses (tree clauses)
            }
          else if (!c_mark_addressable (t))
            remove = true;
-         else if (!COMPLETE_TYPE_P (TREE_TYPE (t))
-                  && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
-                       && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER))
+         else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+                    && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
+                  && !lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%qD does not have a mappable type in %qs clause", t,
@@ -12288,8 +12412,7 @@ c_tree_equal (tree t1, tree t2)
   switch (code1)
     {
     case INTEGER_CST:
-      return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
-       && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+      return wi::eq_p (t1, t2);
 
     case REAL_CST:
       return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
This page took 0.187695 seconds and 5 git commands to generate.