This is the first patch in a series that strives to improve C++ location info.
The following is more like a base for another improvements, thus it contains
only one small test.  It adds a location_t parameter and a vector of location_t
of arguments to finish_call_expr - so functions such as build_over_call and
build_new_method_call can have this info as well.  Next patch will pass these
locations down to build_cxx_call/build_call_a/... functions - I hope we'll then
get rid of that pesky issue that the caret points to final ) of the function,
which is a pain in gdb if the function declarator spans multiple lines.

I'd prefer to do smaller (<1000 lines) incremental patches, where every patch
improves something concrete, rather than one huge megapatch.
Maybe you'll want to preapprove similar patches (add location_t to get better
diagnostics) in due course - up to you.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2014-08-01  Marek Polacek  <pola...@redhat.com>

        * call.c (convert_like, convert_like_with_context): Add location_t
        parameter.
        (build_user_type_conversion): Adjust convert_like call.
        (build_integral_nontype_arg_conv): Likewise.
        (build_new_function_call): Add location_t and vec<location_t>
        parameters.  Use them.
        (build_operator_new_call): Adjust build_over_call call.
        (build_op_call_1): Adjust build_over_call and
        convert_like_with_context calls.
        (build_new_op_1): Likewise.
        (build_conditional_expr_1): Adjust convert_like call.
        (convert_like_real): Add location_t parameter.  Use it.
        (build_over_call): Add location_t and vec<location_t> parameters.
        Use them.
        (build_special_member_call): Adjust build_new_method_call call.
        (build_new_method_call_1): Add location_t and vec<location_t>
        parameters.  Use them.
        (build_new_method_call): Likewise.
        (perform_implicit_conversion_flags): Adjust convert_like call.
        (perform_direct_initialization_if_possible): Adjust convert_like_real
        call.
        (initialize_reference): Adjust convert_like calls.
        * cp-array-notation.c (expand_sec_reduce_builtin): Adjust
        finish_call_expr call.
        * cp-tree.h: Adjust declarations.
        * init.c (build_new_1): Adjust build_new_method_call call.
        (build_dtor_call): Likewise.
        * method.c (locate_fn_flags): Likewise.
        * parser.c (cp_parser_userdef_char_literal): Adjust finish_call_expr
        call.
        (cp_parser_userdef_numeric_literal): Likewise.
        (cp_parser_userdef_string_literal): Likewise.
        (cp_parser_postfix_expression): New vector of locations.  Adjust
        cp_parser_parenthesized_expression_list call.  Make it fill the
        vector of locations of arguments.  Adjust build_new_method_call
        and finish_call_expr calls.  Release the vector of locations.
        (cp_parser_parenthesized_expression_list): Fill the vector of
        locations of arguments.
        (cp_parser_new_placement): Adjust
        cp_parser_parenthesized_expression_list call.
        (cp_parser_new_initializer): Likewise.
        (cp_parser_mem_initializer): Likewise.
        (cp_parser_initializer): Likewise.
        (cp_parser_gnu_attribute_list): Likewise.
        (cp_parser_std_attribute): Likewise.
        (cp_parser_functional_cast): Likewise.
        (cp_parser_omp_declare_reduction_exprs): Likewise.
        (cp_parser_perform_range_for_lookup): Adjust finish_call_expr calls.
        (cp_parser_range_for_member_function): Likewise.
        * pt.c (tsubst_copy_and_build): Adjust build_new_method_call and
        finish_call_expr calls.
        * semantics.c (finish_call_expr): Add location_t and vec<location_t>
        parameters.  Use them.
        (finish_omp_barrier): Update finish_call_expr call.
        (finish_omp_flush): Likewise.
        (finish_omp_taskwait): Likewise.
        (finish_omp_taskyield): Likewise.
        (finish_omp_cancel): Likewise.
        (finish_omp_cancellation_point): Likewise.

        * g++.dg/diagnostic/location-1.C: New test.

diff --git gcc/cp/call.c gcc/cp/call.c
index 4d37c65..b9db4b9 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -148,18 +148,19 @@ static int equal_functions (tree, tree);
 static int joust (struct z_candidate *, struct z_candidate *, bool,
                  tsubst_flags_t);
 static int compare_ics (conversion *, conversion *);
-static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
+static tree build_over_call (location_t, vec<location_t>,
+                            struct z_candidate *, int, tsubst_flags_t);
 static tree build_java_interface_fn_ref (tree, tree);
-#define convert_like(CONV, EXPR, COMPLAIN)                     \
-  convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0,          \
-                    /*issue_conversion_warnings=*/true,        \
-                    /*c_cast_p=*/false, (COMPLAIN))
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO, COMPLAIN )    \
-  convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0,                 \
+#define convert_like(LOC, CONV, EXPR, COMPLAIN)                                
\
+  convert_like_real ((LOC), (CONV), (EXPR), NULL_TREE, 0, 0,           \
                     /*issue_conversion_warnings=*/true,                \
                     /*c_cast_p=*/false, (COMPLAIN))
-static tree convert_like_real (conversion *, tree, tree, int, int, bool,
-                              bool, tsubst_flags_t);
+#define convert_like_with_context(LOC, CONV, EXPR, FN, ARGNO, COMPLAIN )      \
+  convert_like_real ((LOC), (CONV), (EXPR), (FN), (ARGNO), 0,                \
+                    /*issue_conversion_warnings=*/true,                      \
+                    /*c_cast_p=*/false, (COMPLAIN))
+static tree convert_like_real (location_t, conversion *, tree, tree, int, int,
+                              bool, bool, tsubst_flags_t);
 static void op_error (location_t, enum tree_code, enum tree_code, tree,
                      tree, tree, bool);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int,
@@ -3813,7 +3814,8 @@ build_user_type_conversion (tree totype, tree expr, int 
flags,
        ret = error_mark_node;
       else
         {
-          expr = convert_like (cand->second_conv, expr, complain);
+          expr = convert_like (input_location, cand->second_conv, expr,
+                              complain);
           ret = convert_from_reference (expr);
         }
     }
@@ -3885,7 +3887,7 @@ build_integral_nontype_arg_conv (tree type, tree expr, 
tsubst_flags_t complain)
       }
 
   if (conv)
-    expr = convert_like (conv, expr, complain);
+    expr = convert_like (loc, conv, expr, complain);
   else
     expr = error_mark_node;
 
@@ -4007,7 +4009,8 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc> 
*args,
    ARGS.  */
 
 tree
-build_new_function_call (tree fn, vec<tree, va_gc> **args, bool koenig_p, 
+build_new_function_call (location_t loc, tree fn, vec<location_t> arg_loc,
+                        vec<tree, va_gc> **args, bool koenig_p,
                         tsubst_flags_t complain)
 {
   struct z_candidate *candidates, *cand;
@@ -4069,7 +4072,7 @@ build_new_function_call (tree fn, vec<tree, va_gc> 
**args, bool koenig_p,
          about peculiar null pointer conversion.  */
       if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
         flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
-      result = build_over_call (cand, flags, complain);
+      result = build_over_call (loc, arg_loc, cand, flags, complain);
     }
 
   /* Free all the conversions we allocated.  */
@@ -4180,7 +4183,8 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> 
**args,
      *fn = cand->fn;
 
    /* Build the CALL_EXPR.  */
-   return build_over_call (cand, LOOKUP_NORMAL, complain);
+   return build_over_call (input_location, vNULL, cand, LOOKUP_NORMAL,
+                          complain);
 }
 
 /* Build a new call to operator().  This may change ARGS.  */
@@ -4300,11 +4304,12 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, 
tsubst_flags_t complain)
         DECL_NAME here.  */
       else if (TREE_CODE (cand->fn) == FUNCTION_DECL
               && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
-       result = build_over_call (cand, LOOKUP_NORMAL, complain);
+       result = build_over_call (input_location, vNULL, cand, LOOKUP_NORMAL,
+                                 complain);
       else
        {
-         obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
-                                          complain);
+         obj = convert_like_with_context (input_location, cand->convs[0],
+                                          obj, cand->fn, -1, complain);
          obj = convert_from_reference (obj);
          result = cp_build_function_call_vec (obj, args, complain);
        }
@@ -4806,15 +4811,15 @@ build_conditional_expr_1 (location_t loc, tree arg1, 
tree arg2, tree arg3,
              if (conv2 && !conv2->bad_p && conv3 && !conv3->bad_p)
                inform (loc, "  and each type can be converted to the other");
              else if (conv2 && conv2->kind == ck_ambig)
-               convert_like (conv2, arg2, complain);
+               convert_like (loc, conv2, arg2, complain);
              else
-               convert_like (conv3, arg3, complain);
+               convert_like (loc, conv3, arg3, complain);
            }
          result = error_mark_node;
        }
       else if (conv2 && !conv2->bad_p)
        {
-         arg2 = convert_like (conv2, arg2, complain);
+         arg2 = convert_like (loc, conv2, arg2, complain);
          arg2 = convert_from_reference (arg2);
          arg2_type = TREE_TYPE (arg2);
          /* Even if CONV2 is a valid conversion, the result of the
@@ -4828,7 +4833,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree 
arg2, tree arg3,
        }
       else if (conv3 && !conv3->bad_p)
        {
-         arg3 = convert_like (conv3, arg3, complain);
+         arg3 = convert_like (loc, conv3, arg3, complain);
          arg3 = convert_from_reference (arg3);
          arg3_type = TREE_TYPE (arg3);
          if (error_operand_p (arg3))
@@ -4938,12 +4943,12 @@ build_conditional_expr_1 (location_t loc, tree arg1, 
tree arg2, tree arg3,
         the converted operands are used in place of the original
         operands for the remainder of this section.  */
       conv = cand->convs[0];
-      arg1 = convert_like (conv, arg1, complain);
+      arg1 = convert_like (loc, conv, arg1, complain);
       conv = cand->convs[1];
-      arg2 = convert_like (conv, arg2, complain);
+      arg2 = convert_like (loc, conv, arg2, complain);
       arg2_type = TREE_TYPE (arg2);
       conv = cand->convs[2];
-      arg3 = convert_like (conv, arg3, complain);
+      arg3 = convert_like (loc, conv, arg3, complain);
       arg3_type = TREE_TYPE (arg3);
     }
 
@@ -5527,7 +5532,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int 
flags, tree arg1,
          if (resolve_args (arglist, complain) == NULL)
            result = error_mark_node;
          else
-           result = build_over_call (cand, LOOKUP_NORMAL, complain);
+           result = build_over_call (loc, vNULL, cand, LOOKUP_NORMAL,
+                                     complain);
        }
       else
        {
@@ -5570,7 +5576,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int 
flags, tree arg1,
          conv = cand->convs[0];
          if (conv->kind == ck_ref_bind)
            conv = next_conversion (conv);
-         arg1 = convert_like (conv, arg1, complain);
+         arg1 = convert_like (loc, conv, arg1, complain);
 
          if (arg2)
            {
@@ -5588,14 +5594,14 @@ build_new_op_1 (location_t loc, enum tree_code code, 
int flags, tree arg1,
                                       code_orig_arg1, arg1,
                                       code_orig_arg2, arg2);
 
-             arg2 = convert_like (conv, arg2, complain);
+             arg2 = convert_like (loc, conv, arg2, complain);
            }
          if (arg3)
            {
              conv = cand->convs[2];
              if (conv->kind == ck_ref_bind)
                conv = next_conversion (conv);
-             arg3 = convert_like (conv, arg3, complain);
+             arg3 = convert_like (loc, conv, arg3, complain);
            }
 
        }
@@ -6034,14 +6040,13 @@ maybe_print_user_conv_context (conversion *convs)
    conversions to inaccessible bases are permitted.  */
 
 static tree
-convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
-                  int inner, bool issue_conversion_warnings,
+convert_like_real (location_t loc, conversion *convs, tree expr, tree fn,
+                  int argnum, int inner, bool issue_conversion_warnings,
                   bool c_cast_p, tsubst_flags_t complain)
 {
   tree totype = convs->type;
   diagnostic_t diag_kind;
   int flags;
-  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
 
   if (convs->bad_p && !(complain & tf_error))
     return error_mark_node;
@@ -6089,7 +6094,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, 
int argnum,
                                      totype);
              if (complained)
                print_z_candidate (loc, "candidate is:", t->cand);
-             expr = convert_like_real (t, expr, fn, argnum, 1,
+             expr = convert_like_real (loc, t, expr, fn, argnum, 1,
                                        /*issue_conversion_warnings=*/false,
                                        /*c_cast_p=*/false,
                                        complain);
@@ -6106,14 +6111,14 @@ convert_like_real (conversion *convs, tree expr, tree 
fn, int argnum,
            }
          else if (t->kind == ck_user || !t->bad_p)
            {
-             expr = convert_like_real (t, expr, fn, argnum, 1,
+             expr = convert_like_real (loc, t, expr, fn, argnum, 1,
                                        /*issue_conversion_warnings=*/false,
                                        /*c_cast_p=*/false,
                                        complain);
              break;
            }
          else if (t->kind == ck_ambig)
-           return convert_like_real (t, expr, fn, argnum, 1,
+           return convert_like_real (loc, t, expr, fn, argnum, 1,
                                      /*issue_conversion_warnings=*/false,
                                      /*c_cast_p=*/false,
                                      complain);
@@ -6176,7 +6181,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, 
int argnum,
        for (i = 0; i < cand->num_convs; ++i)
          cand->convs[i]->user_conv_p = true;
 
-       expr = build_over_call (cand, LOOKUP_NORMAL, complain);
+       expr = build_over_call (loc, vNULL, cand, LOOKUP_NORMAL, complain);
 
        /* If this is a constructor or a function returning an aggr type,
           we need to build up a TARGET_EXPR.  */
@@ -6247,8 +6252,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, 
int argnum,
        /* Convert all the elements.  */
        FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
          {
-           tree sub = convert_like_real (convs->u.list[ix], val, fn, argnum,
-                                         1, false, false, complain);
+           tree sub = convert_like_real (loc, convs->u.list[ix], val, fn,
+                                         argnum, 1, false, false, complain);
            if (sub == error_mark_node)
              return sub;
            if (!BRACE_ENCLOSED_INITIALIZER_P (val))
@@ -6302,9 +6307,10 @@ convert_like_real (conversion *convs, tree expr, tree 
fn, int argnum,
       break;
     };
 
-  expr = convert_like_real (next_conversion (convs), expr, fn, argnum,
+  expr = convert_like_real (loc, next_conversion (convs), expr, fn, argnum,
                            convs->kind == ck_ref_bind ? -1 : 1,
-                           convs->kind == ck_ref_bind ? 
issue_conversion_warnings : false, 
+                           convs->kind == ck_ref_bind
+                           ? issue_conversion_warnings : false,
                            c_cast_p,
                            complain);
   if (expr == error_mark_node)
@@ -6870,11 +6876,12 @@ mark_versions_used (tree fn)
 
 /* Subroutine of the various build_*_call functions.  Overload resolution
    has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
-   ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
-   bitmask of various LOOKUP_* flags which apply to the call itself.  */
+   FLAGS is a bitmask of various LOOKUP_* flags which apply to the call
+   itself.  */
 
 static tree
-build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
+build_over_call (location_t loc, vec<location_t> arg_loc,
+                struct z_candidate *cand, int flags, tsubst_flags_t complain)
 {
   tree fn = cand->fn;
   const vec<tree, va_gc> *args = cand->args;
@@ -6924,7 +6931,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
       addr = build_addr_func (fn, complain);
       if (addr == error_mark_node)
        return error_mark_node;
-      expr = build_call_array_loc (input_location, return_type,
+      expr = build_call_array_loc (loc, return_type,
                                   addr, nargs, argarray);
       if (TREE_THIS_VOLATILE (fn) && cfun)
        current_function_returns_abnormally = 1;
@@ -7052,7 +7059,7 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
        {
          if (complain & tf_error)
            {
-             if (permerror (input_location, "passing %qT as %<this%> "
+             if (permerror (loc, "passing %qT as %<this%> "
                             "argument discards qualifiers",
                             TREE_TYPE (argtype)))
                inform (DECL_SOURCE_LOCATION (fn), "  in call to %qD", fn);
@@ -7085,9 +7092,9 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
                              BINFO_TYPE (cand->conversion_path), true))
        {
          if (complain & tf_error)
-           error ("%qT is not an accessible base of %qT",
-                  BINFO_TYPE (cand->conversion_path),
-                  TREE_TYPE (argtype));
+           error_at (loc, "%qT is not an accessible base of %qT",
+                     BINFO_TYPE (cand->conversion_path),
+                     TREE_TYPE (argtype));
          else
            return error_mark_node;
        }
@@ -7117,6 +7124,12 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
       tree type = TREE_VALUE (parm);
       tree arg = (*args)[arg_index];
       bool conversion_warning = true;
+      /* Some __atomic_* builtins have additional hidden argument at
+        position 0.  */
+      location_t ploc
+       = !arg_loc.is_empty () && args->length () == arg_loc.length ()
+         ? expansion_point_location_if_in_system_header (arg_loc[arg_index])
+         : input_location;
 
       conv = convs[i];
 
@@ -7167,15 +7180,16 @@ build_over_call (struct z_candidate *cand, int flags, 
tsubst_flags_t complain)
                  || (TREE_VEC_LENGTH (cand->explicit_targs)
                      <= TEMPLATE_TYPE_IDX (pattype))))
            {
-             pedwarn (input_location, 0, "deducing %qT as %qT",
+             pedwarn (loc, 0, "deducing %qT as %qT",
                       non_reference (TREE_TYPE (patparm)),
                       non_reference (type));
-             pedwarn (input_location, 0, "  in call to %q+D", cand->fn);
-             pedwarn (input_location, 0,
+             pedwarn (loc, 0, "  in call to %q+D", cand->fn);
+             pedwarn (loc, 0,
                       "  (you can disable this with -fno-deduce-init-list)");
            }
        }
-      val = convert_like_with_context (conv, arg, fn, i - is_method,
+      val = convert_like_with_context (ploc, conv, arg, fn,
+                                      i - is_method,
                                       conversion_warning
                                       ? complain
                                       : complain & (~tf_warning));
@@ -7678,7 +7692,7 @@ build_special_member_call (tree instance, tree name, 
vec<tree, va_gc> **args,
       vec_safe_insert (*args, 0, sub_vtt);
     }
 
-  ret = build_new_method_call (instance, fns, args,
+  ret = build_new_method_call (input_location, instance, fns, vNULL, args,
                               TYPE_BINFO (BINFO_TYPE (binfo)),
                               flags, /*fn=*/NULL,
                               complain);
@@ -7747,7 +7761,8 @@ name_as_c_string (tree name, tree type, bool *free_p)
    This may change ARGS.  */
 
 static tree
-build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
+build_new_method_call_1 (location_t loc, tree instance, tree fns,
+                        vec<location_t> arg_loc, vec<tree, va_gc> **args,
                         tree conversion_path, int flags,
                         tree *fn_p, tsubst_flags_t complain)
 {
@@ -8067,7 +8082,8 @@ build_new_method_call_1 (tree instance, tree fns, 
vec<tree, va_gc> **args,
              if (fn_p)
                *fn_p = fn;
              /* Build the actual CALL_EXPR.  */
-             call = build_over_call (cand, flags, complain);
+             call = build_over_call (loc, arg_loc, cand, flags,
+                                     complain);
              /* In an expression of the form `a->f()' where `f' turns
                 out to be a static member function, `a' is
                 none-the-less evaluated.  */
@@ -8130,13 +8146,15 @@ build_new_method_call_1 (tree instance, tree fns, 
vec<tree, va_gc> **args,
 /* Wrapper for above.  */
 
 tree
-build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args,
+build_new_method_call (location_t loc, tree instance, tree fns,
+                      vec<location_t> arg_loc, vec<tree, va_gc> **args,
                       tree conversion_path, int flags,
                       tree *fn_p, tsubst_flags_t complain)
 {
   tree ret;
   bool subtime = timevar_cond_start (TV_OVERLOAD);
-  ret = build_new_method_call_1 (instance, fns, args, conversion_path, flags,
+  ret = build_new_method_call_1 (loc, instance, fns, arg_loc, args,
+                                conversion_path, flags,
                                  fn_p, complain);
   timevar_cond_stop (TV_OVERLOAD, subtime);
   return ret;
@@ -9284,7 +9302,7 @@ perform_implicit_conversion_flags (tree type, tree expr,
        IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true;
     }
   else
-    expr = convert_like (conv, expr, complain);
+    expr = convert_like (loc, conv, expr, complain);
 
   /* Free all the conversions we allocated.  */
   obstack_free (&conversion_obstack, p);
@@ -9344,7 +9362,7 @@ perform_direct_initialization_if_possible (tree type,
   if (!conv || conv->bad_p)
     expr = NULL_TREE;
   else
-    expr = convert_like_real (conv, expr, NULL_TREE, 0, 0,
+    expr = convert_like_real (input_location, conv, expr, NULL_TREE, 0, 0,
                              /*issue_conversion_warnings=*/false,
                              c_cast_p,
                              complain);
@@ -9575,7 +9593,7 @@ initialize_reference (tree type, tree expr,
       if (complain & tf_error)
        {
          if (conv)
-           convert_like (conv, expr, complain);
+           convert_like (loc, conv, expr, complain);
          else if (!CP_TYPE_CONST_P (TREE_TYPE (type))
                   && !TYPE_REF_IS_RVALUE (type)
                   && !real_lvalue_p (expr))
@@ -9592,7 +9610,7 @@ initialize_reference (tree type, tree expr,
 
   if (conv->kind == ck_ref_bind)
     /* Perform the conversion.  */
-    expr = convert_like (conv, expr, complain);
+    expr = convert_like (loc, conv, expr, complain);
   else if (conv->kind == ck_ambig)
     /* We gave an error in build_user_type_conversion_1.  */
     expr = error_mark_node;
diff --git gcc/cp/cp-array-notation.c gcc/cp/cp-array-notation.c
index b45449b..44a3fbe 100644
--- gcc/cp/cp-array-notation.c
+++ gcc/cp/cp-array-notation.c
@@ -475,8 +475,8 @@ expand_sec_reduce_builtin (tree an_builtin_fn, tree 
*new_var)
        vec_safe_push (func_args, identity_value);
       vec_safe_push (func_args, func_parm);
 
-      new_expr = finish_call_expr (call_fn, &func_args, false, true,
-                                  tf_warning_or_error);
+      new_expr = finish_call_expr (location, call_fn, vNULL, &func_args,
+                                  false, true, tf_warning_or_error);
       if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
        new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr,
                                        tf_warning_or_error);
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index 0c0d804..a12f18e 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -5068,12 +5068,16 @@ extern bool sufficient_parms_p                  
(const_tree);
 extern tree type_decays_to                     (tree);
 extern tree build_user_type_conversion         (tree, tree, int,
                                                 tsubst_flags_t);
-extern tree build_new_function_call            (tree, vec<tree, va_gc> **, 
bool, 
+extern tree build_new_function_call            (location_t, tree,
+                                                vec<location_t>,
+                                                vec<tree, va_gc> **, bool,
                                                 tsubst_flags_t);
 extern tree build_operator_new_call            (tree, vec<tree, va_gc> **, 
tree *,
                                                 tree *, tree, tree *,
                                                 tsubst_flags_t);
-extern tree build_new_method_call              (tree, tree, vec<tree, va_gc> 
**,
+extern tree build_new_method_call              (location_t, tree, tree,
+                                                vec<location_t>,
+                                                vec<tree, va_gc> **,
                                                 tree, int, tree *,
                                                 tsubst_flags_t);
 extern tree build_special_member_call          (tree, tree, vec<tree, va_gc> 
**,
@@ -5832,7 +5836,9 @@ extern tree stmt_expr_value_expr          (tree);
 bool empty_expr_stmt_p                         (tree);
 extern tree perform_koenig_lookup              (tree, vec<tree, va_gc> *,
                                                 tsubst_flags_t);
-extern tree finish_call_expr                   (tree, vec<tree, va_gc> **, 
bool,
+extern tree finish_call_expr                   (location_t, tree,
+                                                vec<location_t>,
+                                                vec<tree, va_gc> **, bool,
                                                 bool, tsubst_flags_t);
 extern tree finish_increment_expr              (tree, enum tree_code);
 extern tree finish_this_expr                   (void);
diff --git gcc/cp/init.c gcc/cp/init.c
index f8cae28..4b702ea 100644
--- gcc/cp/init.c
+++ gcc/cp/init.c
@@ -2594,8 +2594,9 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, 
tree nelts,
                 }
              return error_mark_node;
            }
-         alloc_call = build_new_method_call (build_dummy_object (elt_type),
-                                             fns, placement,
+         alloc_call = build_new_method_call (input_location,
+                                             build_dummy_object (elt_type),
+                                             fns, vNULL, placement,
                                              /*conversion_path=*/NULL_TREE,
                                              LOOKUP_NORMAL,
                                              &alloc_fn,
@@ -3879,8 +3880,8 @@ build_dtor_call (tree exp, special_function_kind 
dtor_kind, int flags,
       gcc_unreachable ();
     }
   fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
-  return build_new_method_call (exp, fn,
-                               /*args=*/NULL,
+  return build_new_method_call (input_location, exp, fn,
+                               vNULL, /*args=*/NULL,
                                /*conversion_path=*/NULL_TREE,
                                flags,
                                /*fn_p=*/NULL,
diff --git gcc/cp/method.c gcc/cp/method.c
index f86a214..151c6a8 100644
--- gcc/cp/method.c
+++ gcc/cp/method.c
@@ -904,7 +904,8 @@ locate_fn_flags (tree type, tree name, tree argtype, int 
flags,
     }
 
   fns = lookup_fnfields (binfo, name, 0);
-  rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain);
+  rval = build_new_method_call (input_location, ob, fns, vNULL, &args, binfo,
+                               flags, &fn, complain);
 
   release_tree_vector (args);
   if (fn && rval == error_mark_node)
diff --git gcc/cp/parser.c gcc/cp/parser.c
index 32c7a3f..768bab6 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -1929,8 +1929,8 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
-  (cp_parser *, int, bool, bool, bool *, bool = false);
-/* Values for the second parameter of cp_parser_parenthesized_expression_list. 
 */
+  (cp_parser *, vec<location_t> *, int, bool, bool, bool *, bool = false);
+/* Values for the third parameter of cp_parser_parenthesized_expression_list.  
*/
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree, tree *, tree *);
@@ -3812,7 +3812,8 @@ cp_parser_userdef_char_literal (cp_parser *parser)
       release_tree_vector (args);
       return error_mark_node;
     }
-  result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
+  result = finish_call_expr (token->location, decl, vNULL, &args, false, true,
+                            tf_warning_or_error);
   release_tree_vector (args);
   if (result != error_mark_node)
     return result;
@@ -3907,7 +3908,8 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
-      result = finish_call_expr (decl, &args, false, true, tf_none);
+      result = finish_call_expr (token->location, decl, vNULL, &args, false,
+                                true, tf_none);
       if (result != error_mark_node)
        {
          if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && overflow > 0)
@@ -3938,7 +3940,8 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
-      result = finish_call_expr (decl, &args, false, true, tf_none);
+      result = finish_call_expr (token->location, decl, vNULL, &args, false,
+                                true, tf_none);
       if (result != error_mark_node)
        {
          release_tree_vector (args);
@@ -3956,7 +3959,8 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
     {
       tree tmpl_args = make_char_string_pack (num_string);
       decl = lookup_template_function (decl, tmpl_args);
-      result = finish_call_expr (decl, &args, false, true, tf_none);
+      result = finish_call_expr (token->location, decl, vNULL, &args, false,
+                                true, tf_none);
       if (result != error_mark_node)
        {
          release_tree_vector (args);
@@ -3996,7 +4000,8 @@ cp_parser_userdef_string_literal (tree literal)
     {
       tree tmpl_args = make_string_pack (value);
       decl = lookup_template_function (decl, tmpl_args);
-      result = finish_call_expr (decl, &args, false, true, tf_none);
+      result = finish_call_expr (input_location, decl, vNULL, &args, false,
+                                true, tf_none);
       if (result != error_mark_node)
        {
          release_tree_vector (args);
@@ -4017,7 +4022,8 @@ cp_parser_userdef_string_literal (tree literal)
       release_tree_vector (args);
       return error_mark_node;
     }
-  result = finish_call_expr (decl, &args, false, true, tf_none);
+  result = finish_call_expr (input_location, decl, vNULL, &args, false,
+                            true, tf_none);
   release_tree_vector (args);
   if (result != error_mark_node)
     return result;
@@ -5899,7 +5905,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
        tree p;
 
        cp_lexer_consume_token (parser->lexer);
-       vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+       vec = cp_parser_parenthesized_expression_list (parser, NULL, non_attr,
                    /*cast_p=*/false, /*allow_expansion_p=*/true,
                    /*non_constant_p=*/NULL);
        if (vec == NULL)
@@ -6064,6 +6070,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
            bool saved_non_integral_constant_expression_p = false;
            tsubst_flags_t complain = complain_flags (decltype_p);
            vec<tree, va_gc> *args;
+           location_t fn_loc = token->location;
+           vec<location_t> arg_loc = vNULL;
 
             is_member_access = false;
 
@@ -6080,7 +6088,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
                parser->integral_constant_expression_p = false;
              }
            args = (cp_parser_parenthesized_expression_list
-                   (parser, non_attr,
+                   (parser, &arg_loc, non_attr,
                     /*cast_p=*/false, /*allow_expansion_p=*/true,
                     /*non_constant_p=*/NULL,
                     /*want_literal_zero_p=*/warn_memset_transposed_args));
@@ -6197,7 +6205,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
                  {
                  postfix_expression
                    = (build_new_method_call
-                      (instance, fn, &args, NULL_TREE,
+                      (fn_loc, instance, fn, arg_loc, &args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
                         ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
                         : LOOKUP_NORMAL),
@@ -6206,7 +6214,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
                  }
                else
                  postfix_expression
-                   = finish_call_expr (postfix_expression, &args,
+                   = finish_call_expr (fn_loc, postfix_expression,
+                                       arg_loc, &args,
                                        /*disallow_virtual=*/false,
                                        /*koenig_p=*/false,
                                        complain);
@@ -6221,14 +6230,16 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
              /* A call to a static class member, or a namespace-scope
                 function.  */
              postfix_expression
-               = finish_call_expr (postfix_expression, &args,
+               = finish_call_expr (fn_loc, postfix_expression,
+                                   arg_loc, &args,
                                    /*disallow_virtual=*/true,
                                    koenig_p,
                                    complain);
            else
              /* All other function calls.  */
              postfix_expression
-               = finish_call_expr (postfix_expression, &args,
+               = finish_call_expr (fn_loc, postfix_expression,
+                                   arg_loc, &args,
                                    /*disallow_virtual=*/false,
                                    koenig_p,
                                    complain);
@@ -6237,6 +6248,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
            idk = CP_ID_KIND_NONE;
 
            release_tree_vector (args);
+           arg_loc.release ();
          }
          break;
 
@@ -6698,6 +6710,7 @@ static GTY(()) tree literal_zeros[itk_none];
 
 static vec<tree, va_gc> *
 cp_parser_parenthesized_expression_list (cp_parser* parser,
+                                        vec<location_t> *arg_loc,
                                         int is_attribute_list,
                                         bool cast_p,
                                          bool allow_expansion_p,
@@ -6730,6 +6743,10 @@ cp_parser_parenthesized_expression_list (cp_parser* 
parser,
       {
        tree expr;
 
+       /* Remember the location of the token.  */
+       if (arg_loc)
+         arg_loc->safe_push (cp_lexer_peek_token (parser->lexer)->location);
+
        /* At the beginning of attribute lists, check to see if the
           next token is an identifier.  */
        if (is_attribute_list == id_attr
@@ -7445,7 +7462,7 @@ cp_parser_new_placement (cp_parser* parser)
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, non_attr, /*cast_p=*/false,
+                    (parser, NULL, non_attr, /*cast_p=*/false,
                      /*allow_expansion_p=*/true,
                      /*non_constant_p=*/NULL));
 
@@ -7650,7 +7667,7 @@ cp_parser_new_initializer (cp_parser* parser)
     }
   else
     expression_list = (cp_parser_parenthesized_expression_list
-                      (parser, non_attr, /*cast_p=*/false,
+                      (parser, NULL, non_attr, /*cast_p=*/false,
                        /*allow_expansion_p=*/true,
                        /*non_constant_p=*/NULL));
 
@@ -10557,12 +10574,12 @@ cp_parser_perform_range_for_lookup (tree range, tree 
*begin, tree *end)
 
          member_begin = perform_koenig_lookup (id_begin, vec,
                                                tf_warning_or_error);
-         *begin = finish_call_expr (member_begin, &vec, false, true,
-                                    tf_warning_or_error);
+         *begin = finish_call_expr (input_location, member_begin, vNULL, &vec,
+                                    false, true, tf_warning_or_error);
          member_end = perform_koenig_lookup (id_end, vec,
                                              tf_warning_or_error);
-         *end = finish_call_expr (member_end, &vec, false, true,
-                                  tf_warning_or_error);
+         *end = finish_call_expr (input_location, member_end, vNULL, &vec,
+                                  false, true, tf_warning_or_error);
 
          release_tree_vector (vec);
        }
@@ -10608,7 +10625,7 @@ cp_parser_range_for_member_function (tree range, tree 
identifier)
     return error_mark_node;
 
   vec = make_tree_vector ();
-  res = finish_call_expr (member, &vec,
+  res = finish_call_expr (input_location, member, vNULL, &vec,
                          /*disallow_virtual=*/false,
                          /*koenig_p=*/false,
                          tf_warning_or_error);
@@ -12578,7 +12595,7 @@ cp_parser_mem_initializer (cp_parser* parser)
   else
     {
       vec<tree, va_gc> *vec;
-      vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+      vec = cp_parser_parenthesized_expression_list (parser, NULL, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
                                                     /*non_constant_p=*/NULL);
@@ -19044,7 +19061,7 @@ cp_parser_initializer (cp_parser* parser, bool* 
is_direct_init,
   else if (token->type == CPP_OPEN_PAREN)
     {
       vec<tree, va_gc> *vec;
-      vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+      vec = cp_parser_parenthesized_expression_list (parser, NULL, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
                                                     non_constant_p);
@@ -21977,7 +21994,7 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
                }
              else
                vec = cp_parser_parenthesized_expression_list 
-                 (parser, attr_flag, /*cast_p=*/false, 
+                 (parser, NULL, attr_flag, /*cast_p=*/false, 
                   /*allow_expansion_p=*/false, 
                   /*non_constant_p=*/NULL);
              if (vec == NULL)
@@ -22132,7 +22149,7 @@ cp_parser_std_attribute (cp_parser *parser)
       attr_flag = id_attr;
 
     vec = cp_parser_parenthesized_expression_list
-      (parser, attr_flag, /*cast_p=*/false,
+      (parser, NULL, attr_flag, /*cast_p=*/false,
        /*allow_expansion_p=*/true,
        /*non_constant_p=*/NULL);
     if (vec == NULL)
@@ -23560,7 +23577,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
     }
 
 
-  vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+  vec = cp_parser_parenthesized_expression_list (parser, NULL, non_attr,
                                                 /*cast_p=*/true,
                                                 /*allow_expansion_p=*/true,
                                                 /*non_constant_p=*/NULL);
@@ -30975,7 +30992,7 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, 
cp_parser *parser)
              || cp_parser_error_occurred (parser)
              || !cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
              || ((args = cp_parser_parenthesized_expression_list
-                               (parser, non_attr, /*cast_p=*/false,
+                               (parser, NULL, non_attr, /*cast_p=*/false,
                                 /*allow_expansion_p=*/true,
                                 /*non_constant_p=*/NULL)),
                  cp_parser_error_occurred (parser)))
diff --git gcc/cp/pt.c gcc/cp/pt.c
index baabcb1..54e6606 100644
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -14966,20 +14966,20 @@ tsubst_copy_and_build (tree t,
                    || any_type_dependent_arguments_p (call_args)))
              ret = build_nt_call_vec (function, call_args);
            else if (!BASELINK_P (fn))
-             ret = finish_call_expr (function, &call_args,
+             ret = finish_call_expr (loc, function, vNULL, &call_args,
                                       /*disallow_virtual=*/false,
                                       /*koenig_p=*/false,
                                       complain);
            else
              ret = (build_new_method_call
-                     (instance, fn,
+                     (loc, instance, fn, vNULL,
                       &call_args, NULL_TREE,
                       qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
                       /*fn_p=*/NULL,
                       complain));
          }
        else
-         ret = finish_call_expr (function, &call_args,
+         ret = finish_call_expr (loc, function, vNULL, &call_args,
                                  /*disallow_virtual=*/qualified_p,
                                  koenig_p,
                                  complain);
diff --git gcc/cp/semantics.c gcc/cp/semantics.c
index c87764d..5f4d2da 100644
--- gcc/cp/semantics.c
+++ gcc/cp/semantics.c
@@ -2194,7 +2194,8 @@ perform_koenig_lookup (tree fn, vec<tree, va_gc> *args,
    Returns code for the call.  */
 
 tree
-finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
+finish_call_expr (location_t loc, tree fn, vec<location_t> arg_loc,
+                 vec<tree, va_gc> **args, bool disallow_virtual,
                  bool koenig_p, tsubst_flags_t complain)
 {
   tree result;
@@ -2259,7 +2260,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool 
disallow_virtual,
       if (BASELINK_P (member))
        {
          tree object = TREE_OPERAND (fn, 0);
-         return build_new_method_call (object, member,
+         return build_new_method_call (loc, object, member,
+                                       arg_loc,
                                        args, NULL_TREE,
                                         (disallow_virtual
                                          ? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL
@@ -2315,7 +2317,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool 
disallow_virtual,
          object = build_non_dependent_expr (object);
        }
 
-      result = build_new_method_call (object, fn, args, NULL_TREE,
+      result = build_new_method_call (loc, object, fn, arg_loc, args,
+                                     NULL_TREE,
                                      (disallow_virtual
                                       ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
                                       : LOOKUP_NORMAL),
@@ -2362,7 +2365,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool 
disallow_virtual,
            }
 
          /* A call to a namespace-scope function.  */
-         result = build_new_function_call (fn, args, koenig_p, complain);
+         result = build_new_function_call (loc, fn, arg_loc, args, koenig_p,
+                                           complain);
        }
     }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
@@ -6628,7 +6632,8 @@ finish_omp_barrier (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
   vec<tree, va_gc> *vec = make_tree_vector ();
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
@@ -6638,7 +6643,8 @@ finish_omp_flush (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
   vec<tree, va_gc> *vec = make_tree_vector ();
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
@@ -6648,7 +6654,8 @@ finish_omp_taskwait (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
   vec<tree, va_gc> *vec = make_tree_vector ();
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
@@ -6658,7 +6665,8 @@ finish_omp_taskyield (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
   vec<tree, va_gc> *vec = make_tree_vector ();
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
@@ -6695,7 +6703,8 @@ finish_omp_cancel (tree clauses)
     ifc = boolean_true_node;
   vec->quick_push (build_int_cst (integer_type_node, mask));
   vec->quick_push (ifc);
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
@@ -6721,7 +6730,8 @@ finish_omp_cancellation_point (tree clauses)
     }
   vec<tree, va_gc> *vec
     = make_tree_vector_single (build_int_cst (integer_type_node, mask));
-  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  tree stmt = finish_call_expr (input_location, fn, vNULL, &vec, false, false,
+                               tf_warning_or_error);
   release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
diff --git gcc/testsuite/g++.dg/diagnostic/location-1.C 
gcc/testsuite/g++.dg/diagnostic/location-1.C
index e69de29..f9c3445 100644
--- gcc/testsuite/g++.dg/diagnostic/location-1.C
+++ gcc/testsuite/g++.dg/diagnostic/location-1.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+int foo (int *, int *, int *);
+
+void
+bar (void)
+{
+  foo (1, // { dg-error "8:invalid conversion" }
+         2, // { dg-error "10:invalid conversion" }
+           3); // { dg-error "12:invalid conversion" }
+}

        Marek

Reply via email to