1 /* Provide option suggestion for --complete option and a misspelled
3 Copyright (C) 2016-2018 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "spellcheck.h"
28 #include "opt-suggestions.h"
31 option_proposer::~option_proposer ()
33 delete m_option_suggestions
;
37 option_proposer::suggest_option (const char *bad_opt
)
39 /* Lazily populate m_option_suggestions. */
40 if (!m_option_suggestions
)
41 build_option_suggestions ();
42 gcc_assert (m_option_suggestions
);
44 /* "m_option_suggestions" is now populated. Use it. */
45 return find_closest_string
47 (auto_vec
<const char *> *) m_option_suggestions
);
50 /* Populate RESULTS with valid completions of options that begin
51 with OPTION_PREFIX. */
54 option_proposer::get_completions (const char *option_prefix
,
55 auto_string_vec
&results
)
57 /* Bail out for an invalid input. */
58 if (option_prefix
== NULL
|| option_prefix
[0] == '\0')
61 /* Option suggestions are built without first leading dash character. */
62 if (option_prefix
[0] == '-')
65 size_t length
= strlen (option_prefix
);
67 /* Handle OPTION_PREFIX starting with "-param". */
68 const char *prefix
= "-param";
69 if (length
>= strlen (prefix
)
70 && strstr (option_prefix
, prefix
) == option_prefix
)
72 /* We support both '-param-xyz=123' and '-param xyz=123' */
73 option_prefix
+= strlen (prefix
);
74 char separator
= option_prefix
[0];
76 if (separator
== ' ' || separator
== '=')
77 find_param_completions (separator
, option_prefix
, results
);
81 /* Lazily populate m_option_suggestions. */
82 if (!m_option_suggestions
)
83 build_option_suggestions ();
84 gcc_assert (m_option_suggestions
);
86 for (unsigned i
= 0; i
< m_option_suggestions
->length (); i
++)
88 char *candidate
= (*m_option_suggestions
)[i
];
89 if (strlen (candidate
) >= length
90 && strstr (candidate
, option_prefix
) == candidate
)
91 results
.safe_push (concat ("-", candidate
, NULL
));
96 /* Print on stdout a list of valid options that begin with OPTION_PREFIX,
97 one per line, suitable for use by Bash completion.
99 Implementation of the "-completion=" option. */
102 option_proposer::suggest_completion (const char *option_prefix
)
104 auto_string_vec results
;
105 get_completions (option_prefix
, results
);
106 for (unsigned i
= 0; i
< results
.length (); i
++)
107 printf ("%s\n", results
[i
]);
111 option_proposer::build_option_suggestions (void)
113 gcc_assert (m_option_suggestions
== NULL
);
114 m_option_suggestions
= new auto_string_vec ();
116 /* We build a vec of m_option_suggestions, using add_misspelling_candidates
117 to add copies of strings, without a leading dash. */
119 for (unsigned int i
= 0; i
< cl_options_count
; i
++)
121 const struct cl_option
*option
= &cl_options
[i
];
122 const char *opt_text
= option
->opt_text
;
126 if (option
->var_type
== CLVC_ENUM
)
128 const struct cl_enum
*e
= &cl_enums
[option
->var_enum
];
129 for (unsigned j
= 0; e
->values
[j
].arg
!= NULL
; j
++)
131 char *with_arg
= concat (opt_text
, e
->values
[j
].arg
, NULL
);
132 add_misspelling_candidates (m_option_suggestions
, option
,
138 add_misspelling_candidates (m_option_suggestions
, option
,
143 case OPT_fsanitize_recover_
:
144 /* -fsanitize= and -fsanitize-recover= can take
145 a comma-separated list of arguments. Given that combinations
146 are supported, we can't add all potential candidates to the
147 vec, but if we at least add them individually without commas,
148 we should do a better job e.g. correcting
152 rather than to "-Wframe-address" (PR driver/69265). */
154 for (int j
= 0; sanitizer_opts
[j
].name
!= NULL
; ++j
)
156 struct cl_option optb
;
157 /* -fsanitize=all is not valid, only -fno-sanitize=all.
158 So don't register the positive misspelling candidates
160 if (sanitizer_opts
[j
].flag
== ~0U && i
== OPT_fsanitize_
)
163 optb
.opt_text
= opt_text
= "-fno-sanitize=";
164 optb
.cl_reject_negative
= true;
167 /* Get one arg at a time e.g. "-fsanitize=address". */
168 char *with_arg
= concat (opt_text
,
169 sanitizer_opts
[j
].name
,
171 /* Add with_arg and all of its variant spellings e.g.
172 "-fno-sanitize=address" to candidates (albeit without
174 add_misspelling_candidates (m_option_suggestions
, option
,
184 /* Find parameter completions for --param format with SEPARATOR.
185 Again, save the completions into results. */
188 option_proposer::find_param_completions (const char separator
,
189 const char *param_prefix
,
190 auto_string_vec
&results
)
192 char separator_str
[] = {separator
, '\0'};
193 size_t length
= strlen (param_prefix
);
194 for (unsigned i
= 0; i
< get_num_compiler_params (); ++i
)
196 const char *candidate
= compiler_params
[i
].option
;
197 if (strlen (candidate
) >= length
198 && strstr (candidate
, param_prefix
) == candidate
)
199 results
.safe_push (concat ("--param", separator_str
, candidate
, NULL
));
207 /* Verify that PROPOSER generates sane auto-completion suggestions
208 for OPTION_PREFIX. */
211 verify_autocompletions (option_proposer
&proposer
, const char *option_prefix
)
213 auto_string_vec suggestions
;
214 proposer
.get_completions (option_prefix
, suggestions
);
216 /* There must be at least one suggestion, and every suggestion must
217 indeed begin with OPTION_PREFIX. */
219 ASSERT_GT (suggestions
.length (), 0);
221 for (unsigned i
= 0; i
< suggestions
.length (); i
++)
222 ASSERT_STR_STARTSWITH (suggestions
[i
], option_prefix
);
225 /* Verify that valid options are auto-completed correctly. */
228 test_completion_valid_options (option_proposer
&proposer
)
230 const char *option_prefixes
[] =
232 "-fno-var-tracking-assignments-toggle",
233 "-fpredictive-commoning",
234 "--param=stack-clash-protection-guard-size",
235 "--param=max-predicted-iterations",
236 "-ftree-loop-distribute-patterns",
239 "--param=ipa-cp-value-list-size",
242 "--param=tracer-dynamic-coverage-feedback",
243 "-Wno-format-contains-nul",
245 "-fisolate-erroneous-paths-attribute",
248 "--param=asan-globals",
251 "-Wformat-zero-length",
252 "-Wstringop-truncation",
255 "-Warray-temporaries",
257 "-Wreturn-local-addr",
258 "--param=sms-dfa-history",
259 "--param=asan-instrument-reads",
263 "--param=max-fields-for-field-sensitive",
264 "-fisolate-erroneous-paths-dereference",
266 "-Wcast-align=strict",
268 "-Wpacked-not-aligned",
272 "--param=max-iterations-computation-cost",
273 "-Wmultiple-inheritance",
274 "-fno-sel-sched-reschedule-pipelined",
275 "-Wassign-intercept",
276 "-Wno-format-security",
277 "-fno-sched-stalled-insns",
278 "-fbtr-bb-exclusive",
279 "-fno-tree-tail-merge",
281 "-Wno-unused-but-set-parameter",
285 for (const char **ptr
= option_prefixes
; *ptr
!= NULL
; ptr
++)
286 verify_autocompletions (proposer
, *ptr
);
289 /* Verify that valid parameters are auto-completed correctly,
290 both with the "--param=PARAM" form and the "--param PARAM" form. */
293 test_completion_valid_params (option_proposer
&proposer
)
295 const char *option_prefixes
[] =
297 "--param=sched-state-edge-prob-cutoff",
298 "--param=iv-consider-all-candidates-bound",
299 "--param=align-threshold",
300 "--param=prefetch-min-insn-to-mem-ratio",
301 "--param=max-unrolled-insns",
302 "--param=max-early-inliner-iterations",
303 "--param=max-vartrack-reverse-op-size",
304 "--param=ipa-cp-loop-hint-bonus",
305 "--param=tracer-min-branch-ratio",
306 "--param=graphite-max-arrays-per-scop",
307 "--param=sink-frequency-threshold",
308 "--param=max-cse-path-length",
309 "--param=sra-max-scalarization-size-Osize",
310 "--param=prefetch-latency",
311 "--param=dse-max-object-size",
312 "--param=asan-globals",
313 "--param=max-vartrack-size",
314 "--param=case-values-threshold",
315 "--param=max-slsr-cand-scan",
316 "--param=min-insn-to-prefetch-ratio",
317 "--param=tracer-min-branch-probability",
318 "--param sink-frequency-threshold",
319 "--param max-cse-path-length",
320 "--param sra-max-scalarization-size-Osize",
321 "--param prefetch-latency",
322 "--param dse-max-object-size",
323 "--param asan-globals",
324 "--param max-vartrack-size",
328 for (const char **ptr
= option_prefixes
; *ptr
!= NULL
; ptr
++)
329 verify_autocompletions (proposer
, *ptr
);
332 /* Return true when EXPECTED is one of completions for OPTION_PREFIX string. */
335 in_completion_p (option_proposer
&proposer
, const char *option_prefix
,
336 const char *expected
)
338 auto_string_vec suggestions
;
339 proposer
.get_completions (option_prefix
, suggestions
);
341 for (unsigned i
= 0; i
< suggestions
.length (); i
++)
343 char *r
= suggestions
[i
];
344 if (strcmp (r
, expected
) == 0)
351 /* Return true when PROPOSER does not find any partial completion
352 for OPTION_PREFIX. */
355 empty_completion_p (option_proposer
&proposer
, const char *option_prefix
)
357 auto_string_vec suggestions
;
358 proposer
.get_completions (option_prefix
, suggestions
);
359 return suggestions
.is_empty ();
362 /* Verify autocompletions of partially-complete options. */
365 test_completion_partial_match (option_proposer
&proposer
)
367 ASSERT_TRUE (in_completion_p (proposer
, "-fsani", "-fsanitize=address"));
368 ASSERT_TRUE (in_completion_p (proposer
, "-fsani",
369 "-fsanitize-address-use-after-scope"));
370 ASSERT_TRUE (in_completion_p (proposer
, "-fipa-icf", "-fipa-icf-functions"));
371 ASSERT_TRUE (in_completion_p (proposer
, "-fipa-icf", "-fipa-icf"));
372 ASSERT_TRUE (in_completion_p (proposer
, "--param=",
373 "--param=max-vartrack-reverse-op-size"));
374 ASSERT_TRUE (in_completion_p (proposer
, "--param ",
375 "--param max-vartrack-reverse-op-size"));
377 ASSERT_FALSE (in_completion_p (proposer
, "-fipa-icf", "-fipa"));
378 ASSERT_FALSE (in_completion_p (proposer
, "-fipa-icf-functions", "-fipa-icf"));
380 ASSERT_FALSE (empty_completion_p (proposer
, "-"));
381 ASSERT_FALSE (empty_completion_p (proposer
, "-fipa"));
382 ASSERT_FALSE (empty_completion_p (proposer
, "--par"));
385 /* Verify that autocompletion does not return any match for garbage inputs. */
388 test_completion_garbage (option_proposer
&proposer
)
390 ASSERT_TRUE (empty_completion_p (proposer
, NULL
));
391 ASSERT_TRUE (empty_completion_p (proposer
, ""));
392 ASSERT_TRUE (empty_completion_p (proposer
, "- "));
393 ASSERT_TRUE (empty_completion_p (proposer
, "123456789"));
394 ASSERT_TRUE (empty_completion_p (proposer
, "---------"));
395 ASSERT_TRUE (empty_completion_p (proposer
, "#########"));
396 ASSERT_TRUE (empty_completion_p (proposer
, "- - - - - -"));
397 ASSERT_TRUE (empty_completion_p (proposer
, "-fsanitize=address2"));
400 /* Run all of the selftests within this file. */
403 opt_proposer_c_tests ()
405 option_proposer proposer
;
407 test_completion_valid_options (proposer
);
408 test_completion_valid_params (proposer
);
409 test_completion_partial_match (proposer
);
410 test_completion_garbage (proposer
);
413 } // namespace selftest
415 #endif /* #if CHECKING_P */