Hi,
I'm looking into making more progress on those locations, for another
class of cases. Consider:
struct T { };
T foo();
void bar(int a, int b)
{
if (foo() && a < b)
;
}
thus, in this case, we have a class type T, instead of void. The error
message is:
a.cc: In function ‘void bar(int, int)’:
a.cc:7:20: error: no match for ‘operator&&’ (operand types are ‘T’ and
‘bool’)
if (foo() && a < b)
^
a.cc:7:20: note: candidate is:
a.cc:7:20: note: operator&&(bool, bool) <built-in>
if (foo() && a < b)
^
a.cc:7:20: note: no known conversion for argument 1 from ‘T’ to ‘bool’
in case my message ends up garbled, the carets do not point to &&
(column 13), two times point to b (column 20), which is obviously wrong.
In other terms, all the columns are 20, all wrong.
Now, a first step toward fixing this is improving on the work I did some
days ago on cp_parser_binary_expression: make sure that the location we
are eventually passing to build_x_binary_op is always, provably, the
location of the operator. It seems to me that In order to achieve that,
the right thing to do is always handling tree_type and loc (the location
of the operator) together, per the attached patch_parser (the
initialization of loc to input_location is just to prevent uninitialized
warnings)
Then, with patch_parser applied (it passes testing), we end up with a
correct first caret for the testcase above, that for "no match", but the
second one remains wrong. What happens is that the location is correct
up to the print_z_candidates call. It gets a correct location as
argument, and prints the "candidate is" message with the right column,
13. Then it calls print_z_candidate without passing a location, which,
in turn:
- Prints the <built-in> message with input_location as location,
which is 20, wrong.
- Then calls print_conversion_rejection passing location_of
(candidate->fn) which is again 20, again wrong.
Now, if I change print_z_candidate to get the location_t from
print_z_candidates and use it for both the last two outputs, I finally get:
a.cc: In function ‘void bar(int, int)’:
a.cc:7:13: error: no match for ‘operator&&’ (operand types are ‘T’ and
‘bool’)
if (foo() && a < b)
^
a.cc:7:13: note: candidate is:
a.cc:7:13: note: operator&&(bool, bool) <built-in>
a.cc:7:13: note: no known conversion for argument 1 from ‘T’ to ‘bool’
again, in case the text is garbled, all the locations seems finally
right to me, and, interestingly there is no caret at the end, which
seems Ok.
Now, what I suspect we are doing wrong here, is that we are not handling
separately, in terms of locations, the *builtin* overloads, which should
simply use always the location passed from upstream (as I did in my
quick experiment) from all the other overloads, for which the current
code seems fine. Seems right? The patch for this second half of the
issue seems now also rather simple to me.
Thanks,
Paolo.
///////////////////////
Index: parser.c
===================================================================
--- parser.c (revision 187362)
+++ parser.c (working copy)
@@ -1621,6 +1621,8 @@ typedef struct cp_parser_expression_stack_entry
enum tree_code tree_type;
/* Precedence of the binary operation we are parsing. */
enum cp_parser_prec prec;
+ /* Location of the binary operation we are parsing. */
+ location_t loc;
} cp_parser_expression_stack_entry;
/* The stack for storing partial expressions. We only need NUM_PREC_VALUES
@@ -7277,7 +7279,7 @@ cp_parser_binary_expression (cp_parser* parser, bo
cp_parser_expression_stack_entry *sp = &stack[0];
tree lhs, rhs;
cp_token *token;
- location_t loc;
+ location_t loc = input_location;
enum tree_code tree_type, lhs_type, rhs_type;
enum cp_parser_prec new_prec, lookahead_prec;
tree overload;
@@ -7290,7 +7292,6 @@ cp_parser_binary_expression (cp_parser* parser, bo
{
/* Get an operator token. */
token = cp_lexer_peek_token (parser->lexer);
- loc = token->location;
if (warn_cxx0x_compat
&& token->type == CPP_RSHIFT
@@ -7320,6 +7321,7 @@ cp_parser_binary_expression (cp_parser* parser, bo
get_rhs:
tree_type = binops_by_token[token->type].tree_type;
+ loc = token->location;
/* We used the operator token. */
cp_lexer_consume_token (parser->lexer);
@@ -7349,6 +7351,7 @@ cp_parser_binary_expression (cp_parser* parser, bo
stack overflows. */
sp->prec = prec;
sp->tree_type = tree_type;
+ sp->loc = loc;
sp->lhs = lhs;
sp->lhs_type = lhs_type;
sp++;
@@ -7370,6 +7373,7 @@ cp_parser_binary_expression (cp_parser* parser, bo
--sp;
prec = sp->prec;
tree_type = sp->tree_type;
+ loc = sp->loc;
rhs = lhs;
rhs_type = lhs_type;
lhs = sp->lhs;