This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] Improve location info [1/many]
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Sun, 10 Aug 2014 08:15:20 +0200
- Subject: Re: [C++ PATCH] Improve location info [1/many]
- Authentication-results: sourceware.org; auth=none
- References: <20140801115942 dot GG30336 at redhat dot com>
Ping.
On Fri, Aug 01, 2014 at 01:59:42PM +0200, Marek Polacek wrote:
> 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 <polacek@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
Marek