https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88121

--- Comment #2 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Author: dmalcolm
Date: Thu Nov 29 21:21:56 2018
New Revision: 266644

URL: https://gcc.gnu.org/viewcvs?rev=266644&root=gcc&view=rev
Log:
C++: namespaces and scopes for enum values (PR c++/88121)

Consider this test case:

namespace json
{
  enum { JSON_OBJECT };
}

void test ()
{
  JSON_OBJECT;
}

which erroneously accesses an enum value in another namespace without
qualifying the access.

GCC 6 through 8 issue a suggestion that doesn't mention the namespace:

<source>: In function 'void test()':
<source>:8:3: error: 'JSON_OBJECT' was not declared in this scope
   JSON_OBJECT;
   ^~~~~~~~~~~
<source>:8:3: note: suggested alternative:
<source>:3:10: note:   'JSON_OBJECT'
   enum { JSON_OBJECT };
          ^~~~~~~~~~~

which is suboptimal.

I made the problem worse with r265610, which consolidates the single
suggestion into the error, and emits:

<source>: In function 'void test()':
<source>:8:3: error: 'JSON_OBJECT' was not declared in this scope; did
   you mean 'JSON_OBJECT'?
    8 |   JSON_OBJECT;
      |   ^~~~~~~~~~~
      |   JSON_OBJECT
<source>:3:10: note: 'JSON_OBJECT' declared here
    3 |   enum { JSON_OBJECT };
      |          ^~~~~~~~~~~

where the message:
  'JSON_OBJECT' was not declared in this scope; did you mean 'JSON_OBJECT'?
is nonsensical.

This patch tweaks dump_scope to detect unscoped enums, and to use the
enclosing namespace for them, so that the CONST_DECL is dumped as
"json::JSON_OBJECT".

This changes the output for the above so that it refers to the
namespace, fixing the issue:

<source>:8:3: error: 'JSON_OBJECT' was not declared in this scope; did
   you mean 'json::JSON_OBJECT'?
    9 |   JSON_OBJECT;
      |   ^~~~~~~~~~~
      |   json::JSON_OBJECT
<source>3:10: note: 'json::JSON_OBJECT' declared here
    3 |   enum { JSON_OBJECT };
      |          ^~~~~~~~~~~

The patch also fixes scope-printing for values within scoped enums.
To exercise this, the patch extends the scanner for namespaces for
exact matches for a name, so that we also scan inside scoped
enums, to cover the case where someone doesn't supply the scope.

Hence with the patch given e.g.:

enum class vegetable { CARROT, TURNIP };

we're able to offer e.g.:

suggestions-scoped-enums.C:50:3: error: 'CARROT' was not declared in
  this scope; did you mean 'vegetable::CARROT'?
   50 |   CARROT;
      |   ^~~~~~
      |   vegetable::CARROT

and this exercises the code path above.  The patch updates dump_scope
for scoped enums so that we print the scope when printing the
value ("vegetable::CARROT"), rather than just the name of the value
("CARROT").

Finally, the patch adds spell-corrections within a scoped enum,
giving e.g.:

suggestions-scoped-enums.C:18:14: error: 'TURNUP' is not a member of
  'vegetable'; did you mean 'TURNIP'?
   18 |   vegetable::TURNUP;
      |              ^~~~~~
      |              TURNIP

gcc/cp/ChangeLog:
        PR c++/88121
        * cp-name-hint.h (suggest_alternative_in_scoped_enum): New decl.
        * error.c (dump_scope): Ensure that we print any scope for values
        of unscoped enums.  Print the scope of values of scoped enums.
        (qualified_name_lookup_error): Offer suggestions for failures
        within scoped enums by calling suggest_alternative_in_scoped_enum.
        * name-lookup.c (class namespace_hints): Update comment to mention
        scoped enums.
        (namespace_hints::namespace_hints): Call
        maybe_add_candidate_for_scoped_enum.
        (namespace_hints::maybe_add_candidate_for_scoped_enum): New member
        (suggest_alternatives_for): Update comment to mention scoped
        enums.
        (suggest_alternative_in_scoped_enum): New function.

gcc/testsuite/ChangeLog:
        PR c++/88121
        * g++.dg/lookup/suggestions-scoped-enums.C: New test.
        * g++.dg/lookup/suggestions-unscoped-enums.C: New test.


Added:
    trunk/gcc/testsuite/g++.dg/lookup/suggestions-scoped-enums.C
    trunk/gcc/testsuite/g++.dg/lookup/suggestions-unscoped-enums.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-name-hint.h
    trunk/gcc/cp/error.c
    trunk/gcc/cp/name-lookup.c
    trunk/gcc/testsuite/ChangeLog

Reply via email to