C++: avoid most reserved words as misspelling suggestions (PR c++/81610 and PR c...
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 7 Feb 2018 17:55:54 +0000 (17:55 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Wed, 7 Feb 2018 17:55:54 +0000 (17:55 +0000)
lookup_name_fuzzy can offer some reserved words as suggestions for
misspelled words, helping with "singed"/"signed" typos.

PR c++/81610 and PR c++/80567 report problems where the C++ frontend
suggested "if", "for" and "else" as corrections for misspelled variable
names.

The root cause is that in r247233
  ("Fix spelling suggestions for reserved words (PR c++/80177)")
I loosened the conditions on these reserved words, adding this condition:
   if (kind == FUZZY_LOOKUP_TYPENAME)
to the logic for rejecting words that don't start decl-specifiers, to
allow for "static_assert" to be offered.

This is too loose a condition: we don't want to suggest *any* reserved word
when we're in a context where we don't know we expect a typename.

For the kinds of error-recover situations where we're suggesting
spelling corrections we don't have much contextual information, so it
seems prudent to be stricter about which reserved words we offer
as spelling suggestions; I don't think it makes sense for us to
suggest e.g. "for".

This patch implements that by effectively reinstating the old logic,
but special-casing RID_STATIC_ASSERT, moving the logic to a new
subroutine (in case we want to allow for other special-cases).

I attempted to add suggestions for the various RID_*CAST, to cope
with e.g. "reinterptet_cast" (I can never type that correctly on the
first try), but the following '<' token confuses the error-recovery
enough that the suggestion code isn't triggered.

gcc/cp/ChangeLog:
PR c++/81610
PR c++/80567
* name-lookup.c (suggest_rid_p): New function.
(lookup_name_fuzzy): Replace enum-rid-filtering logic with call to
suggest_rid_p.

gcc/testsuite/ChangeLog:
PR c++/81610
PR c++/80567
* g++.dg/spellcheck-reswords.C: New test case.
* g++.dg/spellcheck-stdlib.C: Remove xfail from dg-bogus
suggestion of "if".

From-SVN: r257456

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/spellcheck-reswords.C [new file with mode: 0644]
gcc/testsuite/g++.dg/spellcheck-stdlib.C

index ce0b759..42c3cbf 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-07  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/81610
+       PR c++/80567
+       * name-lookup.c (suggest_rid_p): New function.
+       (lookup_name_fuzzy): Replace enum-rid-filtering logic with call to
+       suggest_rid_p.
+
 2018-02-07  Jason Merrill  <jason@redhat.com>
 
        PR c++/84182 - ICE with captured lambda
index d0488c0..e5a3400 100644 (file)
@@ -5705,6 +5705,32 @@ class macro_use_before_def : public deferred_diagnostic
   cpp_hashnode *m_macro;
 };
 
+/* Determine if it can ever make sense to offer RID as a suggestion for
+   a misspelling.
+
+   Subroutine of lookup_name_fuzzy.  */
+
+static bool
+suggest_rid_p  (enum rid rid)
+{
+  switch (rid)
+    {
+    /* Support suggesting function-like keywords.  */
+    case RID_STATIC_ASSERT:
+      return true;
+
+    default:
+      /* Support suggesting the various decl-specifier words, to handle
+        e.g. "singed" vs "signed" typos.  */
+      if (cp_keyword_starts_decl_specifier_p (rid))
+       return true;
+
+      /* Otherwise, don't offer it.  This avoids suggesting e.g. "if"
+        and "do" for short misspellings, which are likely to lead to
+        nonsensical results.  */
+      return false;
+    }
+}
 
 /* Search for near-matches for NAME within the current bindings, and within
    macro names, returning the best match as a const char *, or NULL if
@@ -5769,9 +5795,8 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
     {
       const c_common_resword *resword = &c_common_reswords[i];
 
-      if (kind == FUZZY_LOOKUP_TYPENAME)
-       if (!cp_keyword_starts_decl_specifier_p (resword->rid))
-         continue;
+      if (!suggest_rid_p (resword->rid))
+       continue;
 
       tree resword_identifier = ridpointers [resword->rid];
       if (!resword_identifier)
index 42f163a..ec17df1 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-07  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/81610
+       PR c++/80567
+       * g++.dg/spellcheck-reswords.C: New test case.
+       * g++.dg/spellcheck-stdlib.C: Remove xfail from dg-bogus
+       suggestion of "if".
+
 2018-02-07  Martin Liska  <mliska@suse.cz>
 
        PR c++/84059.
diff --git a/gcc/testsuite/g++.dg/spellcheck-reswords.C b/gcc/testsuite/g++.dg/spellcheck-reswords.C
new file mode 100644 (file)
index 0000000..db6104b
--- /dev/null
@@ -0,0 +1,11 @@
+void pr81610 (void *p)
+{  
+  forget (p); // { dg-error "not declared" }
+  // { dg-bogus "'for'" "" { target *-*-*} .-1 }
+}
+
+void pr80567 (void *p)
+{
+  memset (p, 0, 4); // { dg-error "not declared" }
+  // { dg-bogus "'else'" "" { target *-*-*} .-1 }
+}
index 6e6ab1d..c7a6626 100644 (file)
@@ -16,7 +16,7 @@ void test_cstdio (void)
   FILE *f; // { dg-error "'FILE' was not declared in this scope" }
   // { dg-message "'FILE' is defined in header '<cstdio>'; did you forget to '#include <cstdio>'?" "" { target *-*-* } .-1 }
   // { dg-error "'f' was not declared in this scope" "" { target *-*-* } .-2 }
-  // { dg-bogus "suggested alternative: 'if'" "PR c++/80567" { xfail *-*-* } .-3 }
+  // { dg-bogus "suggested alternative: 'if'" "PR c++/80567" { target *-*-* } .-3 }
 
   char buf[BUFSIZ]; // { dg-error "'BUFSIZ' was not declared" }
   // { dg-message "'BUFSIZ' is defined in header '<cstdio>'; did you forget to '#include <cstdio>'?" "" { target *-*-* } .-1 }