On 11/29/18 2:29 PM, David Malcolm wrote:
On Wed, 2018-11-21 at 13:41 -0500, Jason Merrill wrote:
On 11/21/18 8:35 AM, David Malcolm wrote:
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, as gcc 9 now 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.

The root cause is that dump_scope doesn't print anything when
called for
CONST_DECL in a namespace: the scope is an ENUMERAL_TYPE, rather
than
a namespace.

Although that's only true for unscoped enums.

This patch tweaks dump_scope to detect ENUMERAL_TYPE, and to use
the
enclosing namespace, so that the CONST_DECL is dumped as
"json::JSON_OBJECT".
@@ -182,6 +182,12 @@ dump_scope (cxx_pretty_printer *pp, tree
scope, int flags)
     if (scope == NULL_TREE)
       return;

+  /* Enum values will be CONST_DECL with an ENUMERAL_TYPE as their
+     "scope".  Use CP_TYPE_CONTEXT of the ENUMERAL_TYPE, so as to
+     print the enclosing namespace.  */
+  if (TREE_CODE (scope) == ENUMERAL_TYPE)
+    scope = CP_TYPE_CONTEXT (scope);

This needs to handle scoped enums differently.

I attempted to trigger this code path (printing a *value* within a
scoped enum via %qE, I believe), but wasn't able to), so I extended
the, ahem, scope of the patch a little, so that when scanning
namespaces for exact matches for a name, we also scan inside scoped
enums, to cover the case where someone doesn't supply the scope.

Hence with the updated 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").

diff --git a/gcc/testsuite/g++.dg/lookup/suggestions-scoped-enums.C
b/gcc/testsuite/g++.dg/lookup/suggestions-scoped-enums.C
new file mode 100644
index 0000000..2bf3ed6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/suggestions-scoped-enums.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+enum class vegetable { CARROT, TURNIP };
+
+void misspelled_value_in_scoped_enum ()
+{
+  vegetable::TURNUP; // { dg-error "'TURNUP' is not a member of
'vegetable'" }
+  /* { dg-begin-multiline-output "" }
+   vegetable::TURNUP;
+              ^~~~~~
+     { dg-end-multiline-output "" } */
+}

I don't see any suggestion in the expected output, and would hope for
it
to suggest vegetable::TURNIP.

The updated patch also adds spell-corrections within a scoped enum,
giving:

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

As before, the patch fixes the bogus suggestion in PR c++/88121.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.

OK for trunk?

OK, thanks.

Jason

Reply via email to