From bb440aa08b3a570ef8e8cdcb7675eb814455fe5d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 1 Sep 2015 16:18:19 -0400 Subject: [PATCH 49/56] FIXME: C++ FE: various capture and use of tree ranges --- gcc/cp/call.c | 47 +++++++++++++++++++++++++++++++---------------- gcc/cp/cp-tree.h | 5 +++-- gcc/cp/error.c | 19 +++++++++++++++++++ gcc/cp/parser.c | 26 +++++++++++++++++++------- gcc/cp/typeck.c | 27 +++++++++++++++++++++------ 5 files changed, 93 insertions(+), 31 deletions(-) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 367d42b..c79aec1 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "cgraph.h" #include "internal-fn.h" +#include "gcc-rich-location.h" /* The various kinds of conversion. */ @@ -162,7 +163,7 @@ static tree build_java_interface_fn_ref (tree, tree); /*c_cast_p=*/false, (COMPLAIN)) static tree convert_like_real (conversion *, tree, tree, int, int, bool, bool, tsubst_flags_t); -static void op_error (location_t, enum tree_code, enum tree_code, tree, +static void op_error (range_or_loc, enum tree_code, enum tree_code, tree, tree, tree, bool); static struct z_candidate *build_user_type_conversion_1 (tree, tree, int, tsubst_flags_t); @@ -4031,16 +4032,19 @@ print_error_for_call_failure (tree fn, vec *args, struct z_candidate *candidates) { tree name = DECL_NAME (OVL_CURRENT (fn)); - location_t loc = location_of (name); + source_range range = range_of (name); + gcc_rich_location richloc (range); if (!any_strictly_viable (candidates)) - error_at (loc, "no matching function for call to %<%D(%A)%>", - name, build_tree_list_vec (args)); + error_at_rich_loc (&richloc, + "no matching function for call to %<%D(%A)%>", + name, build_tree_list_vec (args)); else - error_at (loc, "call of overloaded %<%D(%A)%> is ambiguous", - name, build_tree_list_vec (args)); + error_at_rich_loc (&richloc, + "call of overloaded %<%D(%A)%> is ambiguous", + name, build_tree_list_vec (args)); if (candidates) - print_z_candidates (loc, candidates); + print_z_candidates (location_of (name), candidates); } /* Return an expression for a call to FN (a namespace-scope function, @@ -4415,10 +4419,11 @@ op_error_string (const char *errmsg, int ntypes, bool match) } static void -op_error (location_t loc, enum tree_code code, enum tree_code code2, +op_error (range_or_loc src_range, enum tree_code code, enum tree_code code2, tree arg1, tree arg2, tree arg3, bool match) { const char *opname; + location_t loc = src_range.m_start; if (code == MODIFY_EXPR) opname = assignment_operator_name_info[code2].name; @@ -4472,9 +4477,17 @@ op_error (location_t loc, enum tree_code code, enum tree_code code2, default: if (arg2) - if (flag_diagnostics_show_caret) - error_at (loc, op_error_string (G_("%"), 2, match), - opname, TREE_TYPE (arg1), TREE_TYPE (arg2)); + if (flag_diagnostics_show_caret || flag_dump_location_details) + { + gcc_rich_location richloc (src_range); + richloc.add_expr_with_caption (arg1, global_dc, + G_("type %qT"), TREE_TYPE (arg1)); + richloc.add_expr_with_caption (arg2, global_dc, + G_("type %qT"), TREE_TYPE (arg2)); + error_at_rich_loc (&richloc, + op_error_string (G_("%"), 2, match), + opname, TREE_TYPE (arg1), TREE_TYPE (arg2)); + } else error_at (loc, op_error_string (G_("% in %<%E %s %E%>"), 2, match), @@ -5328,7 +5341,7 @@ add_candidates (tree fns, tree first_arg, const vec *args, } static tree -build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, +build_new_op_1 (source_range src_range, enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, tree *overload, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; @@ -5344,6 +5357,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, void *p; bool strict_p; bool any_viable_p; + location_t loc = src_range.m_start; if (error_operand_p (arg1) || error_operand_p (arg2) @@ -5559,7 +5573,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, code = PREINCREMENT_EXPR; else code = PREDECREMENT_EXPR; - result = build_new_op_1 (loc, code, flags, arg1, NULL_TREE, + result = build_new_op_1 (src_range, code, flags, arg1, NULL_TREE, NULL_TREE, overload, complain); break; @@ -5585,7 +5599,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, { /* ... Otherwise, report the more generic "no matching operator found" error */ - op_error (loc, code, code2, arg1, arg2, arg3, FALSE); + op_error (src_range, code, code2, arg1, arg2, arg3, FALSE); print_z_candidates (loc, candidates); } } @@ -5775,13 +5789,14 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, /* Wrapper for above. */ tree -build_new_op (location_t loc, enum tree_code code, int flags, +build_new_op (range_or_loc src_range, enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, tree *overload, tsubst_flags_t complain) { tree ret; bool subtime = timevar_cond_start (TV_OVERLOAD); - ret = build_new_op_1 (loc, code, flags, arg1, arg2, arg3, + //src_range.debug ("build_new_op (as source_range)"); + ret = build_new_op_1 (src_range, code, flags, arg1, arg2, arg3, overload, complain); timevar_cond_stop (TV_OVERLOAD, subtime); return ret; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 784a616..d8a3365 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5426,7 +5426,7 @@ extern tree build_new_method_call (tree, tree, vec **, tsubst_flags_t); extern tree build_special_member_call (tree, tree, vec **, tree, int, tsubst_flags_t); -extern tree build_new_op (location_t, enum tree_code, +extern tree build_new_op (range_or_loc, enum tree_code, int, tree, tree, tree, tree *, tsubst_flags_t); extern tree build_op_call (tree, vec **, @@ -5758,6 +5758,7 @@ extern void maybe_warn_variadic_templates (void); extern void maybe_warn_cpp0x (cpp0x_warn_str str); extern bool pedwarn_cxx98 (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); extern location_t location_of (tree); +extern source_range range_of (tree); extern void qualified_name_lookup_error (tree, tree, tree, location_t); @@ -6482,7 +6483,7 @@ extern tree cp_build_function_call_nary (tree, tsubst_flags_t, ...) ATTRIBUTE_SENTINEL; extern tree cp_build_function_call_vec (tree, vec **, tsubst_flags_t); -extern tree build_x_binary_op (location_t, +extern tree build_x_binary_op (range_or_loc, enum tree_code, tree, enum tree_code, tree, enum tree_code, tree *, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index cd4d71d..0a45122 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2930,6 +2930,25 @@ location_of (tree t) return EXPR_LOC_OR_LOC (t, input_location); } +/* Return the source range of a tree passed to %+ formats. */ + +source_range +range_of (tree t) +{ + if (TYPE_P (t)) + { + t = TYPE_MAIN_DECL (t); + if (t == NULL_TREE) + return source_range::from_location (input_location); + } + else if (TREE_CODE (t) == OVERLOAD) + t = OVL_FUNCTION (t); + + if (DECL_P (t)) + return DECL_LOCATION_RANGE (t); + return EXPR_RANGE_OR_LOC (t, input_location); +} + /* Now the interfaces from error et al to dump_type et al. Each takes an on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_ function. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 232a960..2f781fb 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6491,6 +6491,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, break; default: + set_source_range (&postfix_expression, loc, input_location); if (pidk_return != NULL) * pidk_return = idk; if (member_access_only_p) @@ -7489,6 +7490,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, non_constant_p)) expression = error_mark_node; + set_source_range (&expression, loc, input_location); + return expression; } @@ -8275,6 +8278,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, get_rhs: current.tree_type = binops_by_token[token->type].tree_type; current.loc = token->location; + current.range = token->range; /* We used the operator token. */ cp_lexer_consume_token (parser->lexer); @@ -8368,7 +8372,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, ? boolean_type_node : TREE_TYPE (current.lhs), current.lhs, rhs); else - current.lhs = build_x_binary_op (current.loc, current.tree_type, + current.lhs = build_x_binary_op (current.range, current.tree_type, current.lhs, current.lhs_type, rhs, rhs_type, &overload, complain_flags (decltype_p)); @@ -8643,8 +8647,10 @@ cp_parser_expression (cp_parser* parser, cp_id_kind * pidk, tree assignment_expression; /* Parse the next assignment-expression. */ + location_t startloc = cp_lexer_peek_token (parser->lexer)->location; assignment_expression = cp_parser_assignment_expression (parser, pidk, cast_p, decltype_p); + set_source_range (&assignment_expression, startloc, input_location); /* We don't create a temporary for a call that is the immediate operand of decltype or on the RHS of a comma. But when we see a comma, we @@ -26238,12 +26244,18 @@ cp_parser_check_class_key (enum tag_types class_key, tree type) return; if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type)) { - if (permerror (input_location, "%qs tag used in naming %q#T", - class_key == union_type ? "union" - : class_key == record_type ? "struct" : "class", - type)) - inform (DECL_SOURCE_LOCATION (TYPE_NAME (type)), - "%q#T was previously declared here", type); + rich_location rl_tag_reuse (input_source_range); + if (permerror_at_rich_loc (&rl_tag_reuse, + "%qs tag used in naming %q#T", + class_key == union_type ? "union" + : class_key == record_type ? "struct" : "class", + type)) + { + rich_location rl_prev_decl (DECL_LOCATION_RANGE (TYPE_NAME (type))); + inform_at_rich_loc (&rl_prev_decl, + "%q#T was previously declared here", + type); + } } } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index fa1176b..b06cbac 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-objc.h" #include "c-family/c-ubsan.h" #include "params.h" +#include "gcc-rich-location.h" static tree cp_build_addr_expr_strict (tree, tsubst_flags_t); static tree cp_build_function_call (tree, tree, tsubst_flags_t); @@ -3808,7 +3809,7 @@ convert_arguments (tree typelist, vec **values, tree fndecl, ARG2_CODE as ERROR_MARK. */ tree -build_x_binary_op (location_t loc, enum tree_code code, tree arg1, +build_x_binary_op (range_or_loc src_range, enum tree_code code, tree arg1, enum tree_code arg1_code, tree arg2, enum tree_code arg2_code, tree *overload, tsubst_flags_t complain) @@ -3816,6 +3817,7 @@ build_x_binary_op (location_t loc, enum tree_code code, tree arg1, tree orig_arg1; tree orig_arg2; tree expr; + location_t loc = src_range.m_start; orig_arg1 = arg1; orig_arg2 = arg2; @@ -3832,7 +3834,7 @@ build_x_binary_op (location_t loc, enum tree_code code, tree arg1, if (code == DOTSTAR_EXPR) expr = build_m_component_ref (arg1, arg2, complain); else - expr = build_new_op (loc, code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, + expr = build_new_op (src_range, code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, overload, complain); /* Check for cases such as x+y<