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