comparison gcc/opt-suggestions.c @ 132:d34655255c78

update gcc-8.2
author mir3636
date Thu, 25 Oct 2018 10:21:07 +0900
parents 84e7813d76e9
children 1830386684a0
comparison
equal deleted inserted replaced
130:e108057fa461 132:d34655255c78
1 /* Provide option suggestion for --complete option and a misspelled
2 used by a user.
3 Copyright (C) 2016-2018 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
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
10 version.
11
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
15 for more details.
16
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/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "opts.h"
26 #include "params.h"
27 #include "spellcheck.h"
28 #include "opt-suggestions.h"
29 #include "common/common-target.h"
30 #include "selftest.h"
31
32 option_proposer::~option_proposer ()
33 {
34 delete m_option_suggestions;
35 }
36
37 const char *
38 option_proposer::suggest_option (const char *bad_opt)
39 {
40 /* Lazily populate m_option_suggestions. */
41 if (!m_option_suggestions)
42 build_option_suggestions (NULL);
43 gcc_assert (m_option_suggestions);
44
45 /* "m_option_suggestions" is now populated. Use it. */
46 return find_closest_string
47 (bad_opt,
48 (auto_vec <const char *> *) m_option_suggestions);
49 }
50
51 /* Populate RESULTS with valid completions of options that begin
52 with OPTION_PREFIX. */
53
54 void
55 option_proposer::get_completions (const char *option_prefix,
56 auto_string_vec &results)
57 {
58 /* Bail out for an invalid input. */
59 if (option_prefix == NULL || option_prefix[0] == '\0')
60 return;
61
62 /* Option suggestions are built without first leading dash character. */
63 if (option_prefix[0] == '-')
64 option_prefix++;
65
66 size_t length = strlen (option_prefix);
67
68 /* Handle OPTION_PREFIX starting with "-param". */
69 const char *prefix = "-param";
70 if (length >= strlen (prefix)
71 && strstr (option_prefix, prefix) == option_prefix)
72 {
73 /* We support both '-param-xyz=123' and '-param xyz=123' */
74 option_prefix += strlen (prefix);
75 char separator = option_prefix[0];
76 option_prefix++;
77 if (separator == ' ' || separator == '=')
78 find_param_completions (separator, option_prefix, results);
79 }
80 else
81 {
82 /* Lazily populate m_option_suggestions. */
83 if (!m_option_suggestions)
84 build_option_suggestions (option_prefix);
85 gcc_assert (m_option_suggestions);
86
87 for (unsigned i = 0; i < m_option_suggestions->length (); i++)
88 {
89 char *candidate = (*m_option_suggestions)[i];
90 if (strlen (candidate) >= length
91 && strstr (candidate, option_prefix) == candidate)
92 results.safe_push (concat ("-", candidate, NULL));
93 }
94 }
95 }
96
97 /* Print on stdout a list of valid options that begin with OPTION_PREFIX,
98 one per line, suitable for use by Bash completion.
99
100 Implementation of the "-completion=" option. */
101
102 void
103 option_proposer::suggest_completion (const char *option_prefix)
104 {
105 auto_string_vec results;
106 get_completions (option_prefix, results);
107 for (unsigned i = 0; i < results.length (); i++)
108 printf ("%s\n", results[i]);
109 }
110
111 void
112 option_proposer::build_option_suggestions (const char *prefix)
113 {
114 gcc_assert (m_option_suggestions == NULL);
115 m_option_suggestions = new auto_string_vec ();
116
117 /* We build a vec of m_option_suggestions, using add_misspelling_candidates
118 to add copies of strings, without a leading dash. */
119
120 for (unsigned int i = 0; i < cl_options_count; i++)
121 {
122 const struct cl_option *option = &cl_options[i];
123 const char *opt_text = option->opt_text;
124 switch (i)
125 {
126 default:
127 if (option->var_type == CLVC_ENUM)
128 {
129 const struct cl_enum *e = &cl_enums[option->var_enum];
130 for (unsigned j = 0; e->values[j].arg != NULL; j++)
131 {
132 char *with_arg = concat (opt_text, e->values[j].arg, NULL);
133 add_misspelling_candidates (m_option_suggestions, option,
134 with_arg);
135 free (with_arg);
136 }
137 }
138 else
139 {
140 if (option->flags & CL_TARGET)
141 {
142 vec<const char *> option_values
143 = targetm_common.get_valid_option_values (i, prefix);
144 if (!option_values.is_empty ())
145 {
146 for (unsigned j = 0; j < option_values.length (); j++)
147 {
148 char *with_arg = concat (opt_text, option_values[j],
149 NULL);
150 add_misspelling_candidates (m_option_suggestions, option,
151 with_arg);
152 free (with_arg);
153 }
154 }
155 option_values.release ();
156 }
157 else
158 add_misspelling_candidates (m_option_suggestions, option,
159 opt_text);
160 }
161 break;
162
163 case OPT_fsanitize_:
164 case OPT_fsanitize_recover_:
165 /* -fsanitize= and -fsanitize-recover= can take
166 a comma-separated list of arguments. Given that combinations
167 are supported, we can't add all potential candidates to the
168 vec, but if we at least add them individually without commas,
169 we should do a better job e.g. correcting
170 "-sanitize=address"
171 to
172 "-fsanitize=address"
173 rather than to "-Wframe-address" (PR driver/69265). */
174 {
175 for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
176 {
177 struct cl_option optb;
178 /* -fsanitize=all is not valid, only -fno-sanitize=all.
179 So don't register the positive misspelling candidates
180 for it. */
181 if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
182 {
183 optb = *option;
184 optb.opt_text = opt_text = "-fno-sanitize=";
185 optb.cl_reject_negative = true;
186 option = &optb;
187 }
188 /* Get one arg at a time e.g. "-fsanitize=address". */
189 char *with_arg = concat (opt_text,
190 sanitizer_opts[j].name,
191 NULL);
192 /* Add with_arg and all of its variant spellings e.g.
193 "-fno-sanitize=address" to candidates (albeit without
194 leading dashes). */
195 add_misspelling_candidates (m_option_suggestions, option,
196 with_arg);
197 free (with_arg);
198 }
199 }
200 break;
201 }
202 }
203 }
204
205 /* Find parameter completions for --param format with SEPARATOR.
206 Again, save the completions into results. */
207
208 void
209 option_proposer::find_param_completions (const char separator,
210 const char *param_prefix,
211 auto_string_vec &results)
212 {
213 char separator_str[] = {separator, '\0'};
214 size_t length = strlen (param_prefix);
215 for (unsigned i = 0; i < get_num_compiler_params (); ++i)
216 {
217 const char *candidate = compiler_params[i].option;
218 if (strlen (candidate) >= length
219 && strstr (candidate, param_prefix) == candidate)
220 results.safe_push (concat ("--param", separator_str, candidate, NULL));
221 }
222 }
223
224 #if CHECKING_P
225
226 namespace selftest {
227
228 /* Verify that PROPOSER generates sane auto-completion suggestions
229 for OPTION_PREFIX. */
230
231 static void
232 verify_autocompletions (option_proposer &proposer, const char *option_prefix)
233 {
234 auto_string_vec suggestions;
235 proposer.get_completions (option_prefix, suggestions);
236
237 /* There must be at least one suggestion, and every suggestion must
238 indeed begin with OPTION_PREFIX. */
239
240 ASSERT_GT (suggestions.length (), 0);
241
242 for (unsigned i = 0; i < suggestions.length (); i++)
243 ASSERT_STR_STARTSWITH (suggestions[i], option_prefix);
244 }
245
246 /* Verify that valid options are auto-completed correctly. */
247
248 static void
249 test_completion_valid_options (option_proposer &proposer)
250 {
251 const char *option_prefixes[] =
252 {
253 "-fno-var-tracking-assignments-toggle",
254 "-fpredictive-commoning",
255 "--param=stack-clash-protection-guard-size",
256 "--param=max-predicted-iterations",
257 "-ftree-loop-distribute-patterns",
258 "-fno-var-tracking",
259 "-Walloc-zero",
260 "--param=ipa-cp-value-list-size",
261 "-Wsync-nand",
262 "-Wno-attributes",
263 "--param=tracer-dynamic-coverage-feedback",
264 "-Wno-format-contains-nul",
265 "-Wnamespaces",
266 "-fisolate-erroneous-paths-attribute",
267 "-Wno-underflow",
268 "-Wtarget-lifetime",
269 "--param=asan-globals",
270 "-Wno-empty-body",
271 "-Wno-odr",
272 "-Wformat-zero-length",
273 "-Wstringop-truncation",
274 "-fno-ipa-vrp",
275 "-fmath-errno",
276 "-Warray-temporaries",
277 "-Wno-unused-label",
278 "-Wreturn-local-addr",
279 "--param=sms-dfa-history",
280 "--param=asan-instrument-reads",
281 "-Wreturn-type",
282 "-Wc++17-compat",
283 "-Wno-effc++",
284 "--param=max-fields-for-field-sensitive",
285 "-fisolate-erroneous-paths-dereference",
286 "-fno-defer-pop",
287 "-Wcast-align=strict",
288 "-foptimize-strlen",
289 "-Wpacked-not-aligned",
290 "-funroll-loops",
291 "-fif-conversion2",
292 "-Wdesignated-init",
293 "--param=max-iterations-computation-cost",
294 "-Wmultiple-inheritance",
295 "-fno-sel-sched-reschedule-pipelined",
296 "-Wassign-intercept",
297 "-Wno-format-security",
298 "-fno-sched-stalled-insns",
299 "-fbtr-bb-exclusive",
300 "-fno-tree-tail-merge",
301 "-Wlong-long",
302 "-Wno-unused-but-set-parameter",
303 NULL
304 };
305
306 for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
307 verify_autocompletions (proposer, *ptr);
308 }
309
310 /* Verify that valid parameters are auto-completed correctly,
311 both with the "--param=PARAM" form and the "--param PARAM" form. */
312
313 static void
314 test_completion_valid_params (option_proposer &proposer)
315 {
316 const char *option_prefixes[] =
317 {
318 "--param=sched-state-edge-prob-cutoff",
319 "--param=iv-consider-all-candidates-bound",
320 "--param=align-threshold",
321 "--param=prefetch-min-insn-to-mem-ratio",
322 "--param=max-unrolled-insns",
323 "--param=max-early-inliner-iterations",
324 "--param=max-vartrack-reverse-op-size",
325 "--param=ipa-cp-loop-hint-bonus",
326 "--param=tracer-min-branch-ratio",
327 "--param=graphite-max-arrays-per-scop",
328 "--param=sink-frequency-threshold",
329 "--param=max-cse-path-length",
330 "--param=sra-max-scalarization-size-Osize",
331 "--param=prefetch-latency",
332 "--param=dse-max-object-size",
333 "--param=asan-globals",
334 "--param=max-vartrack-size",
335 "--param=case-values-threshold",
336 "--param=max-slsr-cand-scan",
337 "--param=min-insn-to-prefetch-ratio",
338 "--param=tracer-min-branch-probability",
339 "--param sink-frequency-threshold",
340 "--param max-cse-path-length",
341 "--param sra-max-scalarization-size-Osize",
342 "--param prefetch-latency",
343 "--param dse-max-object-size",
344 "--param asan-globals",
345 "--param max-vartrack-size",
346 NULL
347 };
348
349 for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
350 verify_autocompletions (proposer, *ptr);
351 }
352
353 /* Return true when EXPECTED is one of completions for OPTION_PREFIX string. */
354
355 static bool
356 in_completion_p (option_proposer &proposer, const char *option_prefix,
357 const char *expected)
358 {
359 auto_string_vec suggestions;
360 proposer.get_completions (option_prefix, suggestions);
361
362 for (unsigned i = 0; i < suggestions.length (); i++)
363 {
364 char *r = suggestions[i];
365 if (strcmp (r, expected) == 0)
366 return true;
367 }
368
369 return false;
370 }
371
372 /* Return true when PROPOSER does not find any partial completion
373 for OPTION_PREFIX. */
374
375 static bool
376 empty_completion_p (option_proposer &proposer, const char *option_prefix)
377 {
378 auto_string_vec suggestions;
379 proposer.get_completions (option_prefix, suggestions);
380 return suggestions.is_empty ();
381 }
382
383 /* Verify autocompletions of partially-complete options. */
384
385 static void
386 test_completion_partial_match (option_proposer &proposer)
387 {
388 ASSERT_TRUE (in_completion_p (proposer, "-fsani", "-fsanitize=address"));
389 ASSERT_TRUE (in_completion_p (proposer, "-fsani",
390 "-fsanitize-address-use-after-scope"));
391 ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf-functions"));
392 ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf"));
393 ASSERT_TRUE (in_completion_p (proposer, "--param=",
394 "--param=max-vartrack-reverse-op-size"));
395 ASSERT_TRUE (in_completion_p (proposer, "--param ",
396 "--param max-vartrack-reverse-op-size"));
397
398 ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf", "-fipa"));
399 ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf-functions", "-fipa-icf"));
400
401 ASSERT_FALSE (empty_completion_p (proposer, "-"));
402 ASSERT_FALSE (empty_completion_p (proposer, "-fipa"));
403 ASSERT_FALSE (empty_completion_p (proposer, "--par"));
404 }
405
406 /* Verify that autocompletion does not return any match for garbage inputs. */
407
408 static void
409 test_completion_garbage (option_proposer &proposer)
410 {
411 ASSERT_TRUE (empty_completion_p (proposer, NULL));
412 ASSERT_TRUE (empty_completion_p (proposer, ""));
413 ASSERT_TRUE (empty_completion_p (proposer, "- "));
414 ASSERT_TRUE (empty_completion_p (proposer, "123456789"));
415 ASSERT_TRUE (empty_completion_p (proposer, "---------"));
416 ASSERT_TRUE (empty_completion_p (proposer, "#########"));
417 ASSERT_TRUE (empty_completion_p (proposer, "- - - - - -"));
418 ASSERT_TRUE (empty_completion_p (proposer, "-fsanitize=address2"));
419 }
420
421 /* Run all of the selftests within this file. */
422
423 void
424 opt_proposer_c_tests ()
425 {
426 option_proposer proposer;
427
428 test_completion_valid_options (proposer);
429 test_completion_valid_params (proposer);
430 test_completion_partial_match (proposer);
431 test_completion_garbage (proposer);
432 }
433
434 } // namespace selftest
435
436 #endif /* #if CHECKING_P */