[PING for gcc 8] Re: [PATCH] Fix spelling suggestions for reserved words (PR c++/80177)
David Malcolm
dmalcolm@redhat.com
Mon Apr 24 19:27:00 GMT 2017
Ping for gcc 8.
On Fri, 2017-03-31 at 12:41 -0400, David Malcolm wrote:
> As noted in the PR, the C++ frontend currently offers a poor
> suggestion for this misspelling:
>
> a.C: In function âvoid f()â:
> a.C:3:3: error: âstatic_assertionâ was not declared in this scope
> static_assertion (1 == 0, "1 == 0");
> ^~~~~~~~~~~~~~~~
> a.C:3:3: note: suggested alternative: â__cpp_static_assertâ
> static_assertion (1 == 0, "1 == 0");
> ^~~~~~~~~~~~~~~~
> __cpp_static_assert
>
> when it ought to offer "static_assert" as a suggestion instead.
>
> The root causes are two issues within lookup_name_fuzzy
> (called here with FUZZY_LOOKUP_NAME):
>
> (a) If it finds a good enough match in the preprocessor it will
> return the best match *before* considering reserved words,
> rather than picking the closest match overall.
>
> The fix is to have merge all the results into one best_match
> instance, and pick the overall winner. However, given that
> some candidates are identifiers (trees), and others are cpp
> macros, the best_match instance's candidate type needs to
> be converted from tree to const char *. This has some minor
> knock-on effects within name-lookup.c. Sadly it means some
> extra calls to strlen (one per candidate), but this will be
> purely when error-handling.
>
> (b) It rejects "static_assert" here:
>
> 4998 if (!cp_keyword_starts_decl_specifier_p (resword->rid))
> 4999 continue;
>
> as "static_assert" doesn't start a decl specifier.
>
> The fix is to only apply this rejection criterion if we're
> looking
> for typenames, rather than for names in general.
>
> This patch addresses both issues and adds test coverage.
>
> Successfully bootstrapped®rtested on x86_64-pc-linux-gnu.
> Adds 7 PASS and 1 UNSUPPORTED (for -std=c++98) to g++.sum
>
> OK for next stage 1?
>
> gcc/cp/ChangeLog:
> PR c++/80177
> * name-lookup.c (suggest_alternative_in_explicit_scope):
> Convert
> candidate type of bm from tree to const char *.
> (consider_binding_level): Likewise.
> (lookup_name_fuzzy): Likewise, using this to merge the best
> result from the preprocessor into bm, rather than immediately
> returning, so that better matches from reserved words can
> "win".
> Guard the rejection of keywords that don't start decl
> -specifiers
> so it only happens for FUZZY_LOOKUP_TYPENAME.
>
> gcc/testsuite/ChangeLog:
> PR c++/80177
> * g++.dg/spellcheck-pr80177.C: New test case.
> ---
> gcc/cp/name-lookup.c | 37 +++++++++++++--------
> ----------
> gcc/testsuite/g++.dg/spellcheck-pr80177.C | 7 ++++++
> 2 files changed, 23 insertions(+), 21 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/spellcheck-pr80177.C
>
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index 994f7f0..16ec0a1 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -48,7 +48,8 @@ static bool lookup_using_namespace (tree, struct
> scope_binding *, tree,
> tree, int);
> static bool qualified_lookup_using_namespace (tree, tree,
> struct scope_binding
> *, int);
> -static void consider_binding_level (tree name, best_match <tree,
> tree> &bm,
> +static void consider_binding_level (tree name,
> + best_match <tree, const char *>
> &bm,
> cp_binding_level *lvl,
> bool look_within_fields,
> enum lookup_name_fuzzy_kind
> kind);
> @@ -4550,14 +4551,13 @@ suggest_alternative_in_explicit_scope
> (location_t location, tree name,
>
> cp_binding_level *level = NAMESPACE_LEVEL (scope);
>
> - best_match <tree, tree> bm (name);
> + best_match <tree, const char *> bm (name);
> consider_binding_level (name, bm, level, false,
> FUZZY_LOOKUP_NAME);
>
> /* See if we have a good suggesion for the user. */
> - tree best_id = bm.get_best_meaningful_candidate ();
> - if (best_id)
> + const char *fuzzy_name = bm.get_best_meaningful_candidate ();
> + if (fuzzy_name)
> {
> - const char *fuzzy_name = IDENTIFIER_POINTER (best_id);
> gcc_rich_location richloc (location);
> richloc.add_fixit_replace (fuzzy_name);
> inform_at_rich_loc (&richloc, "suggested alternative: %qs",
> @@ -4797,7 +4797,7 @@ qualified_lookup_using_namespace (tree name,
> tree scope,
> Traverse binding level LVL, looking for good name matches for
> NAME
> (and BM). */
> static void
> -consider_binding_level (tree name, best_match <tree, tree> &bm,
> +consider_binding_level (tree name, best_match <tree, const char *>
> &bm,
> cp_binding_level *lvl, bool
> look_within_fields,
> enum lookup_name_fuzzy_kind kind)
> {
> @@ -4809,7 +4809,7 @@ consider_binding_level (tree name, best_match
> <tree, tree> &bm,
> tree best_matching_field
> = lookup_member_fuzzy (type, name, want_type_p);
> if (best_matching_field)
> - bm.consider (best_matching_field);
> + bm.consider (IDENTIFIER_POINTER (best_matching_field));
> }
>
> for (tree t = lvl->names; t; t = TREE_CHAIN (t))
> @@ -4838,7 +4838,7 @@ consider_binding_level (tree name, best_match
> <tree, tree> &bm,
> if (tree name = DECL_NAME (d))
> /* Ignore internal names with spaces in them. */
> if (!strchr (IDENTIFIER_POINTER (name), ' '))
> - bm.consider (DECL_NAME (d));
> + bm.consider (IDENTIFIER_POINTER (name));
> }
> }
>
> @@ -4851,7 +4851,7 @@ lookup_name_fuzzy (tree name, enum
> lookup_name_fuzzy_kind kind)
> {
> gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
>
> - best_match <tree, tree> bm (name);
> + best_match <tree, const char *> bm (name);
>
> cp_binding_level *lvl;
> for (lvl = scope_chain->class_bindings; lvl; lvl = lvl
> ->level_chain)
> @@ -4874,9 +4874,9 @@ lookup_name_fuzzy (tree name, enum
> lookup_name_fuzzy_kind kind)
> the identifiers already checked. */
> best_macro_match bmm (name, bm.get_best_distance (), parse_in);
> cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate ();
> - /* If a macro is the closest so far to NAME, suggest it. */
> + /* If a macro is the closest so far to NAME, consider it. */
> if (best_macro)
> - return (const char *)best_macro->ident.str;
> + bm.consider ((const char *)best_macro->ident.str);
>
> /* Try the "starts_decl_specifier_p" keywords to detect
> "singed" vs "signed" typos. */
> @@ -4884,8 +4884,9 @@ lookup_name_fuzzy (tree name, enum
> lookup_name_fuzzy_kind kind)
> {
> const c_common_resword *resword = &c_common_reswords[i];
>
> - if (!cp_keyword_starts_decl_specifier_p (resword->rid))
> - continue;
> + if (kind == FUZZY_LOOKUP_TYPENAME)
> + if (!cp_keyword_starts_decl_specifier_p (resword->rid))
> + continue;
>
> tree resword_identifier = ridpointers [resword->rid];
> if (!resword_identifier)
> @@ -4897,16 +4898,10 @@ lookup_name_fuzzy (tree name, enum
> lookup_name_fuzzy_kind kind)
> if (!C_IS_RESERVED_WORD (resword_identifier))
> continue;
>
> - bm.consider (resword_identifier);
> + bm.consider (IDENTIFIER_POINTER (resword_identifier));
> }
>
> - /* See if we have a good suggesion for the user. */
> - tree best_id = bm.get_best_meaningful_candidate ();
> - if (best_id)
> - return IDENTIFIER_POINTER (best_id);
> -
> - /* No meaningful suggestion available. */
> - return NULL;
> + return bm.get_best_meaningful_candidate ();
> }
>
> /* Subroutine of outer_binding.
> diff --git a/gcc/testsuite/g++.dg/spellcheck-pr80177.C
> b/gcc/testsuite/g++.dg/spellcheck-pr80177.C
> new file mode 100644
> index 0000000..2ff24e8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/spellcheck-pr80177.C
> @@ -0,0 +1,7 @@
> +// { dg-do compile { target c++11 } }
> +
> +void pr80177 ()
> +{
> + static_assertion (1 == 0, "1 == 0"); // { dg-error "3:
> 'static_assertion' was not declared in this scope" }
> + // { dg-message "3: suggested alternative: 'static_assert'" "" {
> target *-*-* } .-1 }
> +}
More information about the Gcc-patches
mailing list