aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gcc.c')
-rw-r--r--gcc/gcc.c112
1 files changed, 84 insertions, 28 deletions
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 683b30f..99fa5e3 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -7135,7 +7135,8 @@ compare_files (char *cmpfile[])
driver::driver (bool can_finalize, bool debug) :
explicit_link_files (NULL),
- decoded_options (NULL)
+ decoded_options (NULL),
+ m_option_suggestions (NULL)
{
env.init (can_finalize, debug);
}
@@ -7144,6 +7145,14 @@ driver::~driver ()
{
XDELETEVEC (explicit_link_files);
XDELETEVEC (decoded_options);
+ if (m_option_suggestions)
+ {
+ int i;
+ char *str;
+ FOR_EACH_VEC_ELT (*m_option_suggestions, i, str)
+ free (str);
+ delete m_option_suggestions;
+ }
}
/* driver::main is implemented as a series of driver:: method calls. */
@@ -7632,49 +7641,96 @@ driver::maybe_putenv_OFFLOAD_TARGETS () const
offload_targets = NULL;
}
-/* Helper function for driver::handle_unrecognized_options.
+/* Helper function for driver::suggest_option. Populate
+ m_option_suggestions with candidate strings for misspelled options.
+ The strings will be freed by the driver's dtor. */
- Given an unrecognized option BAD_OPT (without the leading dash),
- locate the closest reasonable matching option (again, without the
- leading dash), or NULL. */
-
-static const char *
-suggest_option (const char *bad_opt)
+void
+driver::build_option_suggestions (void)
{
- const cl_option *best_option = NULL;
- edit_distance_t best_distance = MAX_EDIT_DISTANCE;
+ gcc_assert (m_option_suggestions == NULL);
+ m_option_suggestions = new auto_vec <char *> ();
+
+ /* We build a vec of m_option_suggestions, using add_misspelling_candidates
+ to add copies of strings, without a leading dash. */
for (unsigned int i = 0; i < cl_options_count; i++)
{
- edit_distance_t dist = levenshtein_distance (bad_opt,
- cl_options[i].opt_text + 1);
- if (dist < best_distance)
+ const struct cl_option *option = &cl_options[i];
+ const char *opt_text = option->opt_text;
+ switch (i)
{
- best_distance = dist;
- best_option = &cl_options[i];
+ default:
+ if (option->var_type == CLVC_ENUM)
+ {
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+ for (unsigned j = 0; e->values[j].arg != NULL; j++)
+ {
+ char *with_arg = concat (opt_text, e->values[j].arg, NULL);
+ add_misspelling_candidates (m_option_suggestions, with_arg);
+ free (with_arg);
+ }
+ }
+ else
+ add_misspelling_candidates (m_option_suggestions, opt_text);
+ break;
+
+ case OPT_fsanitize_:
+ case OPT_fsanitize_recover_:
+ /* -fsanitize= and -fsanitize-recover= can take
+ a comma-separated list of arguments. Given that combinations
+ are supported, we can't add all potential candidates to the
+ vec, but if we at least add them individually without commas,
+ we should do a better job e.g. correcting
+ "-sanitize=address"
+ to
+ "-fsanitize=address"
+ rather than to "-Wframe-address" (PR driver/69265). */
+ {
+ for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
+ {
+ /* Get one arg at a time e.g. "-fsanitize=address". */
+ char *with_arg = concat (opt_text,
+ sanitizer_opts[j].name,
+ NULL);
+ /* Add with_arg and all of its variant spellings e.g.
+ "-fno-sanitize=address" to candidates (albeit without
+ leading dashes). */
+ add_misspelling_candidates (m_option_suggestions, with_arg);
+ free (with_arg);
+ }
+ }
+ break;
}
}
+}
- if (!best_option)
- return NULL;
+/* Helper function for driver::handle_unrecognized_options.
- /* If more than half of the letters were misspelled, the suggestion is
- likely to be meaningless. */
- if (best_option)
- {
- unsigned int cutoff = MAX (strlen (bad_opt),
- strlen (best_option->opt_text + 1)) / 2;
- if (best_distance > cutoff)
- return NULL;
- }
+ Given an unrecognized option BAD_OPT (without the leading dash),
+ locate the closest reasonable matching option (again, without the
+ leading dash), or NULL.
+
+ The returned string is owned by the driver instance. */
+
+const char *
+driver::suggest_option (const char *bad_opt)
+{
+ /* Lazily populate m_option_suggestions. */
+ if (!m_option_suggestions)
+ build_option_suggestions ();
+ gcc_assert (m_option_suggestions);
- return best_option->opt_text + 1;
+ /* "m_option_suggestions" is now populated. Use it. */
+ return find_closest_string
+ (bad_opt,
+ (auto_vec <const char *> *) m_option_suggestions);
}
/* Reject switches that no pass was interested in. */
void
-driver::handle_unrecognized_options () const
+driver::handle_unrecognized_options ()
{
for (size_t i = 0; (int) i < n_switches; i++)
if (! switches[i].validated)