aboutsummaryrefslogtreecommitdiff
path: root/gcc/opts.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-01-11 17:25:40 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-01-11 17:25:40 +0000
commit19ff0049cd22794359a46c86d34fa19be655ba3d (patch)
treef7ccc235482effbed0bd9a6cbea869c2ac6b3d44 /gcc/opts.c
parentd29bd378ab8da3e646e3735c5ba140ec07f3c9fa (diff)
downloadgcc-19ff0049cd22794359a46c86d34fa19be655ba3d.zip
gcc-19ff0049cd22794359a46c86d34fa19be655ba3d.tar.gz
gcc-19ff0049cd22794359a46c86d34fa19be655ba3d.tar.bz2
Offer suggestions for unrecognized sanitizer options (PR driver/78877)
gcc/ChangeLog: PR driver/78877 * opts.c: Include "spellcheck.h" (struct string_fragment): New struct. (struct edit_distance_traits<const string_fragment &>): New struct. (get_closest_sanitizer_option): New function. (parse_sanitizer_options): Offer suggestions for unrecognized arguments. gcc/testsuite/ChangeLog: PR driver/78877 * gcc.dg/spellcheck-options-14.c: New test case. * gcc.dg/spellcheck-options-15.c: New test case. * gcc.dg/spellcheck-options-16.c: New test case. * gcc.dg/spellcheck-options-17.c: New test case. From-SVN: r244325
Diffstat (limited to 'gcc/opts.c')
-rw-r--r--gcc/opts.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/gcc/opts.c b/gcc/opts.c
index c5a14e4..5f573a1 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "opts-diagnostic.h"
#include "insn-attr-common.h"
#include "common/common-target.h"
+#include "spellcheck.h"
static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
@@ -1511,6 +1512,65 @@ const struct sanitizer_opts_s sanitizer_opts[] =
{ NULL, 0U, 0UL, false }
};
+/* A struct for describing a run of chars within a string. */
+
+struct string_fragment
+{
+ string_fragment (const char *start, size_t len)
+ : m_start (start), m_len (len) {}
+
+ const char *m_start;
+ size_t m_len;
+};
+
+/* Specialization of edit_distance_traits for string_fragment,
+ for use by get_closest_sanitizer_option. */
+
+template <>
+struct edit_distance_traits<const string_fragment &>
+{
+ static size_t get_length (const string_fragment &fragment)
+ {
+ return fragment.m_len;
+ }
+
+ static const char *get_string (const string_fragment &fragment)
+ {
+ return fragment.m_start;
+ }
+};
+
+/* Given ARG, an unrecognized sanitizer option, return the best
+ matching sanitizer option, or NULL if there isn't one.
+ CODE is OPT_fsanitize_ or OPT_fsanitize_recover_.
+ VALUE is non-zero for the regular form of the option, zero
+ for the "no-" form (e.g. "-fno-sanitize-recover="). */
+
+static const char *
+get_closest_sanitizer_option (const string_fragment &arg,
+ enum opt_code code, int value)
+{
+ best_match <const string_fragment &, const char*> bm (arg);
+ for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+ {
+ /* -fsanitize=all is not valid, so don't offer it. */
+ if (sanitizer_opts[i].flag == ~0U
+ && code == OPT_fsanitize_
+ && value)
+ continue;
+
+ /* For -fsanitize-recover= (and not -fno-sanitize-recover=),
+ don't offer the non-recoverable options. */
+ if (!sanitizer_opts[i].can_recover
+ && code == OPT_fsanitize_recover_
+ && value)
+ continue;
+
+ bm.consider (sanitizer_opts[i].name);
+ }
+ return bm.get_best_meaningful_candidate ();
+}
+
/* Parse comma separated sanitizer suboptions from P for option SCODE,
adjust previous FLAGS and return new ones. If COMPLAIN is false,
don't issue diagnostics. */
@@ -1572,8 +1632,25 @@ parse_sanitizer_options (const char *p, location_t loc, int scode,
}
if (! found && complain)
- error_at (loc, "unrecognized argument to -fsanitize%s= option: %q.*s",
- code == OPT_fsanitize_ ? "" : "-recover", (int) len, p);
+ {
+ const char *hint
+ = get_closest_sanitizer_option (string_fragment (p, len),
+ code, value);
+
+ if (hint)
+ error_at (loc,
+ "unrecognized argument to -f%ssanitize%s= option: %q.*s;"
+ " did you mean %qs",
+ value ? "" : "no-",
+ code == OPT_fsanitize_ ? "" : "-recover",
+ (int) len, p, hint);
+ else
+ error_at (loc,
+ "unrecognized argument to -f%ssanitize%s= option: %q.*s",
+ value ? "" : "no-",
+ code == OPT_fsanitize_ ? "" : "-recover",
+ (int) len, p);
+ }
if (comma == NULL)
break;