On Thu, 2018-06-28 at 02:28 +0200, Paolo Carlini wrote:
> Hi,
> 
> On 28/06/2018 01:31, Jason Merrill wrote:
> > 
> > > +/* Returns the smallest location.  */
> > 
> > This should probably say "...that is not UNKNOWN_LOCATION."
> 
> I agree.
> > Actually, the places you use min_location would seem to work fine
> > with
> > max_location as well.  What are your criteria for choosing one or
> > the
> > other?
> 
> I should have explained that in better detail. I see two different 
> circumstances: either we have error messages where we say something
> like 
> "cannot be both":
> 
> -       error ("member %qD cannot be declared both %<virtual%> "
> -              "and %<static%>", dname);
> +       error_at (max_location (declspecs->locations[ds_virtual],
> +                               declspecs-
> >locations[ds_storage_class]),
> +                 "member %qD cannot be declared both %<virtual%>
> "
> +                 "and %<static%>", dname);
> 
> where, in my opinion, we want to point to the max_location, we want
> to point to where the contradiction shows up in the code. Or, we have
> errors like:
> 
> -       error ("storage class specified for template parameter
> %qs", name);
> +       error_at (min_location (declspecs->locations[ds_thread],
> +                               declspecs-
> >locations[ds_storage_class]),
> +                 "storage class specified for template parameter
> %qs",
> +                 name);
> 
> where ill-formed code has either one or two such specifiers (that is
> __thread and/or static) but even one would wrong, thus we want to
> point to the first one, thus min_location (this is in fact a variant
> of the reasoning behind smallest_type_quals_location).
> 
> Did I explain myself clearly enough? If we are going for something
> simple, I would suggest uniformly using min_location, not
> max_location.

If I'm following you right, the idea is that gcc should complain
because two different things in the user's source code contradict each
other.

In such circumstances, I think we ought to try to print *both*
locations, so that we're showing, rather than just telling.

So the user experience might be something like:

test.cc:42:1: error: member 'bar::foo' cannot be declared both 'virtual' and 
'static'
 static virtual foo ();
 ^~~~~~ ~~~~~~~

It's possible to send two locations through one diagnostic using
rich_location, via e.g.:

   gcc_rich_location richloc (primary_location);
   richloc.add_range (secondary_location, false);
   error_at (&richloc, "member %qD etc etc"", .../* etc*/);

For this case, I don't think it matters which one is primary and which
is secondary (it merely determines the file:line:column in the
preliminary message of the diagnostic).

Another approach would be to use two diagnostics, for something like:

test.cc:42:8: error: member 'foo' cannot be declared both 'virtual'...
 static virtual foo ();
        ^~~~~~~
test.cc:42:1: note: ...and 'static'
 static virtual foo ();
 ^~~~~~
 
but given that in this case the two things are likely to be close
together in the user's source, I prefer the "two locations in one
diagnostic" approach.

Hope this is constructive
Dave

> By the way, I think I found examples of locations following both the
> patterns above in clang and icc too.
> 
> Thanks,
> Paolo.
> 

Reply via email to