Mercurial > hg > CbC > CbC_gcc
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 */ |