Patchwork [/,RFC] Improving more locations for binary expressions

login
register
mail settings
Submitter Paolo Carlini
Date May 10, 2012, 1:42 a.m.
Message ID <4FAB1D00.2060607@oracle.com>
Download mbox | patch
Permalink /patch/158104/
State New
Headers show

Comments

Paolo Carlini - May 10, 2012, 1:42 a.m.
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.

///////////////////////
Miles Bader - May 10, 2012, 5:55 a.m.
Paolo Carlini <paolo.carlini@oracle.com> writes:
> 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.

The new caret support does seem to have revealed a bunch of places
where the column info in error messages was pretty screwy... I guess
nobody paid much attention to it before... :]

Should these get reported as bugzilla bugs...?

-miles
Manuel López-Ibáñez - May 10, 2012, 8 a.m.
On 10 May 2012 07:55, Miles Bader <miles@gnu.org> wrote:
> Paolo Carlini <paolo.carlini@oracle.com> writes:
>> 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.
>
> The new caret support does seem to have revealed a bunch of places
> where the column info in error messages was pretty screwy... I guess
> nobody paid much attention to it before... :]
>
> Should these get reported as bugzilla bugs...?

In principle, yes. In practice, there are already so many known issues
that adding more would just waste contributors time doing bugzilla
administration.

So help would very much appreciated. In particular, the C FE and the
preprocessor are in much worse shape in terms of locations than the
C++ FE.

Some issues may be hard but many of them are a matter of setting a
breakpoint at the error, going up the frame, and figuring out where
the correct location could be got from. Then passing it down to the
error so it can use the correct location. If you can figure out that
but can't/won't write a patch, then please open a PR.

Cheers,

Manuel.
Jason Merrill - May 10, 2012, 2:28 p.m.
Looks good.

Jason

Patch

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;