From: David Malcolm <dmalcolm@redhat.com>
To: Jeff Law <law@redhat.com>
Cc: "Richard Biener" <richard.guenther@gmail.com>,
"Manuel López-Ibáñez" <lopezibanez@gmail.com>,
"GCC Patches" <gcc-patches@gcc.gnu.org>,
"David Malcolm" <dmalcolm@redhat.com>
Subject: [PATCH 2/2] C FE: suggest corrections for misspelled field names
Date: Fri, 30 Oct 2015 12:30:00 -0000 [thread overview]
Message-ID: <1446209267-49800-3-git-send-email-dmalcolm@redhat.com> (raw)
In-Reply-To: <1446209267-49800-1-git-send-email-dmalcolm@redhat.com>
This is similar to the field-name part of the v2 patch:
https://gcc.gnu.org/ml/gcc-patches/2015-09/msg01090.html
with the following changes:
- don't call unit tests from lookup_field_fuzzy
(instead, see patch 1 in the kit)
- use a cutoff: if more than half of the letters
were misspelled, the suggestion is likely to
be meaningless, so don't offer it.
- more test coverage
- deferral of the hints for type-name lookup (this can
wait to a later patch, since it seemed more
controversial)
gcc/c/ChangeLog:
* c-typeck.c: Include spellcheck.h.
(lookup_field_fuzzy_find_candidates): New function.
(lookup_field_fuzzy): New function.
(build_component_ref): If the field was not found, try using
lookup_field_fuzzy and potentially offer a suggestion.
gcc/testsuite/ChangeLog:
* gcc.dg/spellcheck-fields.c: New file.
---
gcc/c/c-typeck.c | 74 +++++++++++++++++++++++++++++++-
gcc/testsuite/gcc.dg/spellcheck-fields.c | 63 +++++++++++++++++++++++++++
2 files changed, 136 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/spellcheck-fields.c
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 61c5313..0660610 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-ubsan.h"
#include "cilk.h"
#include "gomp-constants.h"
+#include "spellcheck.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
@@ -2249,6 +2250,72 @@ lookup_field (tree type, tree component)
return tree_cons (NULL_TREE, field, NULL_TREE);
}
+/* Recursively append candidate IDENTIFIER_NODEs to CANDIDATES. */
+
+static void
+lookup_field_fuzzy_find_candidates (tree type, tree component,
+ vec<tree> *candidates)
+{
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
+ {
+ lookup_field_fuzzy_find_candidates (TREE_TYPE (field),
+ component,
+ candidates);
+ }
+
+ if (DECL_NAME (field))
+ candidates->safe_push (DECL_NAME (field));
+ }
+}
+
+/* Like "lookup_field", but find the closest matching IDENTIFIER_NODE,
+ rather than returning a TREE_LIST for an exact match. */
+
+static tree
+lookup_field_fuzzy (tree type, tree component)
+{
+ gcc_assert (TREE_CODE (component) == IDENTIFIER_NODE);
+
+ /* First, gather a list of candidates. */
+ auto_vec <tree> candidates;
+
+ lookup_field_fuzzy_find_candidates (type, component,
+ &candidates);
+
+ /* Now determine which is closest. */
+ int i;
+ tree identifier;
+ tree best_identifier = NULL;
+ edit_distance_t best_distance = MAX_EDIT_DISTANCE;
+ FOR_EACH_VEC_ELT (candidates, i, identifier)
+ {
+ gcc_assert (TREE_CODE (identifier) == IDENTIFIER_NODE);
+ edit_distance_t dist = levenshtein_distance (component, identifier);
+ if (dist < best_distance)
+ {
+ best_distance = dist;
+ best_identifier = identifier;
+ }
+ }
+
+ /* If more than half of the letters were misspelled, the suggestion is
+ likely to be meaningless. */
+ if (best_identifier)
+ {
+ unsigned int cutoff = MAX (IDENTIFIER_LENGTH (component),
+ IDENTIFIER_LENGTH (best_identifier)) / 2;
+ if (best_distance > cutoff)
+ return NULL;
+ }
+
+ return best_identifier;
+}
+
/* Make an expression to refer to the COMPONENT field of structure or
union value DATUM. COMPONENT is an IDENTIFIER_NODE. LOC is the
location of the COMPONENT_REF. */
@@ -2284,7 +2351,12 @@ build_component_ref (location_t loc, tree datum, tree component)
if (!field)
{
- error_at (loc, "%qT has no member named %qE", type, component);
+ tree guessed_id = lookup_field_fuzzy (type, component);
+ if (guessed_id)
+ error_at (loc, "%qT has no member named %qE; did you mean %qE?",
+ type, component, guessed_id);
+ else
+ error_at (loc, "%qT has no member named %qE", type, component);
return error_mark_node;
}
diff --git a/gcc/testsuite/gcc.dg/spellcheck-fields.c b/gcc/testsuite/gcc.dg/spellcheck-fields.c
new file mode 100644
index 0000000..01be550
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/spellcheck-fields.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+
+struct foo
+{
+ int foo;
+ int bar;
+ int baz;
+};
+
+int test (struct foo *ptr)
+{
+ return ptr->m_bar; /* { dg-error "'struct foo' has no member named 'm_bar'; did you mean 'bar'?" } */
+}
+
+int test2 (void)
+{
+ struct foo instance = {0, 0, 0};
+ return instance.m_bar; /* { dg-error "'struct foo' has no member named 'm_bar'; did you mean 'bar'?" } */
+}
+
+struct s {
+ struct j { int aa; } kk;
+ int ab;
+};
+
+void test3 (struct s x)
+{
+ x.ac; /* { dg-error "'struct s' has no member named 'ac'; did you mean 'ab'?" } */
+}
+
+int test4 (struct foo *ptr)
+{
+ return sizeof (ptr->foa); /* { dg-error "'struct foo' has no member named 'foa'; did you mean 'foo'?" } */
+}
+
+/* Verify that we don't offer nonsensical suggestions. */
+
+int test5 (struct foo *ptr)
+{
+ return ptr->this_is_unlike_any_of_the_fields; /* { dg-bogus "did you mean" } */
+ /* { dg-error "has no member named" "" { target *-*-* } 40 } */
+}
+
+union u
+{
+ int color;
+ int shape;
+};
+
+int test6 (union u *ptr)
+{
+ return ptr->colour; /* { dg-error "'union u' has no member named 'colour'; did you mean 'color'?" } */
+}
+
+struct has_anon
+{
+ struct { int color; } s;
+};
+
+int test7 (struct has_anon *ptr)
+{
+ return ptr->s.colour; /* { dg-error "'struct <anonymous>' has no member named 'colour'; did you mean 'color'?" } */
+}
--
1.8.5.3
next prev parent reply other threads:[~2015-10-30 12:30 UTC|newest]
Thread overview: 133+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-10 20:12 [PATCH 00/22] RFC: Overhaul of diagnostics David Malcolm
2015-09-10 20:12 ` [PATCH 01/22] Change of location_get_source_line signature David Malcolm
2015-09-14 19:28 ` Jeff Law
2015-09-15 17:02 ` David Malcolm
2015-09-10 20:13 ` [PATCH 13/22] gcc-rich-location.[ch]: add methods for working with tree ranges David Malcolm
2015-09-10 20:13 ` [PATCH 03/22] Move diagnostic_show_locus and friends out into a new source file David Malcolm
2015-09-14 19:37 ` Jeff Law
2015-09-18 18:31 ` David Malcolm
2015-09-10 20:13 ` [PATCH 09/22] C frontend: store and use token ranges in c_declspecs David Malcolm
2015-09-10 20:13 ` [PATCH 20/22] Use rich locations in c-family/c-format.c David Malcolm
2015-09-10 20:13 ` [PATCH 11/22] Objective C: c/c-parser.c: use token ranges in two places David Malcolm
2015-09-10 20:13 ` [PATCH 08/22] C frontend: use token ranges in various diagnostics David Malcolm
2015-09-10 20:13 ` [PATCH 10/22] C++ FE: Use token ranges for " David Malcolm
2015-09-10 20:13 ` [PATCH 02/22] Testsuite: add dg-{begin|end}-multiline-output commands David Malcolm
2015-09-14 19:35 ` Jeff Law
2015-09-14 22:17 ` Bernhard Reutner-Fischer
2015-09-14 22:45 ` Jeff Law
2015-09-15 17:53 ` dejagnu version update? Mike Stump
2015-09-15 19:23 ` David Malcolm
2015-09-15 20:29 ` Jeff Law
2015-09-15 21:15 ` Bernhard Reutner-Fischer
2017-05-13 10:38 ` Bernhard Reutner-Fischer
2017-05-13 11:06 ` Jakub Jelinek
2017-05-13 21:12 ` Jeff Law
2017-05-14 23:10 ` NightStrike
2017-05-15 8:14 ` Richard Biener
2017-05-15 19:24 ` Mike Stump
2017-05-15 20:52 ` Andreas Schwab
2017-05-16 9:56 ` Jonathan Wakely
2017-05-16 12:16 ` Bernhard Reutner-Fischer
2017-05-16 12:35 ` Jonathan Wakely
2017-05-16 12:55 ` Bernhard Reutner-Fischer
2017-05-16 18:41 ` Matthias Klose
2017-05-16 19:09 ` Mike Stump
2018-08-04 16:32 ` Bernhard Reutner-Fischer
2018-08-06 14:33 ` Jonathan Wakely
2018-08-06 15:26 ` Mike Stump
2018-08-07 16:34 ` Segher Boessenkool
2018-08-08 11:18 ` Bernhard Reutner-Fischer
2018-08-08 13:35 ` Richard Earnshaw (lists)
2018-08-08 14:37 ` Michael Matz
2018-08-08 16:45 ` Segher Boessenkool
2021-10-27 23:00 ` Bernhard Reutner-Fischer
2021-10-28 19:11 ` Jeff Law
2021-10-29 0:41 ` [PATCH] Bump required minimum DejaGnu version to 1.5.3 Bernhard Reutner-Fischer
2021-10-29 7:32 ` Richard Biener
2021-11-04 11:55 ` Segher Boessenkool
2021-11-04 12:22 ` Martin Liška
2021-11-04 19:09 ` Segher Boessenkool
2021-11-05 9:33 ` Richard Biener
2021-11-05 11:39 ` Jonathan Wakely
2021-11-04 12:41 ` Richard Biener
2021-11-04 13:50 ` Jonathan Wakely
2015-09-15 19:53 ` dejagnu version update? Bernhard Reutner-Fischer
2015-09-15 20:05 ` Jeff Law
2015-09-15 23:12 ` Mike Stump
2015-09-16 7:41 ` Andreas Schwab
2015-09-16 16:19 ` Mike Stump
2015-09-16 16:32 ` Ramana Radhakrishnan
2015-09-16 16:39 ` Jeff Law
2015-09-16 17:26 ` Trevor Saunders
2015-09-16 17:46 ` David Malcolm
2015-09-16 19:09 ` Bernhard Reutner-Fischer
2015-09-16 19:51 ` Mike Stump
2015-09-17 0:07 ` Segher Boessenkool
2015-09-17 13:57 ` Richard Earnshaw
2015-09-16 18:04 ` Mike Stump
2015-09-16 18:58 ` Bernhard Reutner-Fischer
2015-09-16 19:37 ` Ramana Radhakrishnan
2015-09-16 13:17 ` Matthias Klose
2015-09-16 15:46 ` Bernhard Reutner-Fischer
2015-09-10 20:13 ` [PATCH 06/22] PR/62314: add ability to add fixit-hints David Malcolm
2015-09-10 20:28 ` [PATCH 07/22] Implement token range tracking within libcpp and C/C++ FEs David Malcolm
2015-09-11 14:08 ` Michael Matz
2015-09-14 19:41 ` Jeff Law
2015-09-15 10:20 ` Richard Biener
2015-09-15 10:28 ` Jakub Jelinek
2015-09-15 10:48 ` Richard Biener
2015-09-15 11:01 ` Jakub Jelinek
2015-09-16 20:29 ` David Malcolm
2015-09-17 16:54 ` David Malcolm
2015-09-17 19:15 ` Jeff Law
2015-09-17 20:06 ` David Malcolm
2015-09-17 19:25 ` Jeff Law
2015-09-15 12:09 ` Manuel López-Ibáñez
2015-09-15 12:18 ` Richard Biener
2015-09-15 12:57 ` Manuel López-Ibáñez
2015-09-17 19:11 ` Jeff Law
2015-09-17 19:13 ` Jeff Law
2015-09-15 13:53 ` David Malcolm
2015-09-10 20:29 ` [PATCH 05/22] Add overloads of inform, warning_at, etc that take a source_range David Malcolm
2015-09-10 20:29 ` [PATCH 04/22] Reimplement diagnostic_show_locus, introducing rich_location classes David Malcolm
2015-09-11 13:44 ` Michael Matz
2015-09-11 14:12 ` Michael Matz
2015-09-11 15:15 ` David Malcolm
2015-09-10 20:30 ` [PATCH 14/22] C: capture tree ranges for various expressions David Malcolm
2015-09-10 20:30 ` [PATCH 12/22] Add source-ranges for trees David Malcolm
2015-09-10 20:30 ` [PATCH 15/22] Add plugin to recursively dump the source-ranges in a tree David Malcolm
2015-09-11 3:19 ` Martin Sebor
2015-09-10 20:31 ` [PATCH 18/22] Track locations within string literals in tree_string David Malcolm
2015-09-10 20:31 ` [PATCH 19/22] gcc-rich-location.[ch]: add debug methods for cpp_string_location David Malcolm
2015-09-10 20:32 ` [PATCH 21/22] Use Levenshtein distance for various misspellings in C frontend David Malcolm
2015-09-10 21:11 ` Andi Kleen
2015-09-11 15:31 ` Manuel López-Ibáñez
2015-09-15 15:25 ` [PATCH WIP] Use Levenshtein distance for various misspellings in C frontend v2 David Malcolm
2015-09-15 16:25 ` Manuel López-Ibáñez
2015-09-16 8:45 ` Richard Biener
2015-09-16 13:33 ` Michael Matz
2015-09-16 14:00 ` Richard Biener
2015-09-16 15:49 ` Manuel López-Ibáñez
2015-09-17 8:46 ` Richard Biener
2015-09-17 19:32 ` Jeff Law
2015-09-17 20:05 ` David Malcolm
2015-09-17 20:52 ` Manuel López-Ibáñez
2015-10-30 12:30 ` [PATCH 0/2] Levenshtein-based suggestions (v3) David Malcolm
2015-10-30 12:30 ` David Malcolm [this message]
2015-10-30 12:36 ` [PATCH 1/2] Implement Levenshtein distance David Malcolm
2015-11-02 10:56 ` Mikael Morin
2015-11-02 6:44 ` [PATCH 0/2] Levenshtein-based suggestions (v3) Jeff Law
2015-11-13 2:08 ` David Malcolm
2015-11-13 6:57 ` Marek Polacek
2015-11-13 12:16 ` David Malcolm
2015-11-13 15:11 ` Marek Polacek
2015-11-13 15:44 ` Bernd Schmidt
2015-11-13 15:53 ` Marek Polacek
2015-11-13 15:56 ` Jakub Jelinek
2015-11-13 16:02 ` Marek Polacek
2015-09-10 20:32 ` [PATCH 16/22] C/C++ frontend: use tree ranges in various diagnostics David Malcolm
2015-09-10 20:32 ` [PATCH 17/22] libcpp: add location tracking within string literals David Malcolm
2015-09-10 20:50 ` [PATCH 22/22] Add fixit hints to spellchecker suggestions David Malcolm
2015-09-14 17:49 ` [PATCH 00/22] RFC: Overhaul of diagnostics Bernd Schmidt
2015-09-14 19:44 ` Jeff Law
2015-09-15 1:11 ` David Malcolm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1446209267-49800-3-git-send-email-dmalcolm@redhat.com \
--to=dmalcolm@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
--cc=lopezibanez@gmail.com \
--cc=richard.guenther@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).