[PATCH] C++: fix fix-it hints for misspellings within explicit namespaces
David Malcolm
dmalcolm@redhat.com
Fri Jan 13 22:05:00 GMT 2017
On Wed, 2017-01-04 at 14:58 -0500, Jason Merrill wrote:
> On Tue, Jan 3, 2017 at 8:28 PM, David Malcolm <dmalcolm@redhat.com>
> wrote:
> > PR c++/77829 and PR c++/78656 identify an issue within the C++
> > frontend
> > where it issues nonsensical fix-it hints for misspelled name
> > lookups
> > within an explicitly given namespace: it finds the closest name
> > within
> > all namespaces, and uses the location of the namespace for the
> > replacement,
> > rather than the name.
> >
> > For example, for this error:
> >
> > #include <memory>
> > void* allocate(std::size_t n)
> > {
> > return std::alocator<char>().allocate(n);
> > }
> >
> > we currently emit an erroneous fix-it hint that would generate this
> > nonsensical patch:
> >
> > {
> > - return std::alocator<char>().allocate(n);
> > + return allocate::alocator<char>().allocate(n);
> > }
> >
> > whereas we ought to emit a fix-it hint that would generate this
> > patch:
> >
> > {
> > - return std::alocator<char>().allocate(n);
> > + return std::allocator<char>().allocate(n);
> > }
> >
> > This patch fixes the suggestions, in two parts:
> >
> > The incorrect name in the suggestion is fixed by introducing a
> > new function "suggest_alternative_in_explicit_scope"
> > for use by qualified_name_lookup_error when handling failures
> > in explicitly-given namespaces, looking for hint candidates within
> > just that namespace. The function suggest_alternatives_for gains a
> > "suggest_misspellings" bool param, so that we can disable fuzzy
> > name
> > lookup for the case where we've ruled out hint candidates in the
> > explicitly-given namespace.
> >
> > This lets us suggest "allocator" (found in "std") rather "allocate"
> > (found in the global ns).
>
> This looks good.
>
> > The patch fixes the location for the replacement by updating
> > local "unqualified_id" in cp_parser_id_expression from tree to
> > cp_expr to avoid implicitly dropping location information, and
> > passing this location to a new param of finish_id_expression.
> > There are multiple users of finish_id_expression, and it wasn't
> > possible to provide location information for the id for all of them
> > so the new location information is assumed to be optional there.
>
> > This fixes the underlined location, and ensures that the fix-it
> > hint
> > replaces "alocator", rather than "std".
>
> I'm dubious about this approach, as I think this will fix some cases
> and not others. The general problem is that we aren't sure what to
> do
> with the location of a qualified-id: sometimes we use the location of
> the unqualified-id, sometimes we use the beginning of the first
> nested-name-specifier. I think the right answer is probably to use a
> rich location with the caret on the unqualified-id. Then the fix-it
> hint can use the caret location for the fix-it. Does that make
> sense?
Sorry, I'm not sure I follow you.
By "rich location" do you mean providing multiple ranges (e.g. one for
the nested-name-specifier, another for the unqualified-id)?
e.g.
::foo::bar
~~~ ^~~
| |
| `-(primary location and range)
`-(secondary range)
or:
::foo::bar
~~~~~ ^~~
| |
| `-(primary location and
range)
`-(secondary range)
(if that ASCII art makes sense)
Note that such a rich location (with more than one range) can only
exist during the emission of a diagnostic; it's not something we can
use as the location of a tree node.
Or do you mean that we should supply a range for the unqualified-id,
with the caret at the start of the unqualified-id, e.g.:
::foo::bar
^~~
(a tree node code can have such a location).
It seems to me that we ought to have
::foo::bar
^~~~~~~~~~
as the location of such a tree node, and only use the range of just
"bar" as the location when handling name lookup errors (such as when
emitting fix-it hints).
So maybe we should have:
::foo::bar
~~~~~ ^~~
| |
| `-(primary location)
`-(secondary location)
as the location when reporting name lookup errors (and thus using "bar"
as the location for replacement fix-it hints), and:
::foo::bar
^~~~~~~~~~
as the location of the tree node, once name-lookup is done?
(this seems invasive; maybe inappropriate for this stage? I was hoping
for a simpler fix)
finish_id_expression (which can emit the fix-it hint) can be called by
5 different sites:
* in cp_parser_primary_expression, after cp_parser_id_expression
* in cp_parser_lambda_introducer, after a call to
cp_parser_lookup_name_simple
* in cp_parser_decltype_expr, after a call to cp_parser_id_expression
* in tsubst_copy_and_build
* in omp_reduction_lookup
My patch used UNKNOWN_LOCATION for the replacement location for all of
these apart from the first one: I was only confident about passing in
correct location information from the first callsite.
Should I attempt to fix all of these cases so that the location that's
passed in is that of the unqualified-id?
Thanks; hope this makes sense
Dave
More information about the Gcc-patches
mailing list