]>
Commit | Line | Data |
---|---|---|
2772ef3e | 1 | /* Command line option handling. |
8d9254fc | 2 | Copyright (C) 2002-2020 Free Software Foundation, Inc. |
2772ef3e NB |
3 | Contributed by Neil Booth. |
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 | |
9dcd6f09 | 9 | Software Foundation; either version 3, or (at your option) any later |
2772ef3e NB |
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 | |
9dcd6f09 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
2772ef3e NB |
20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
cf03fd63 | 23 | #include "intl.h" |
2772ef3e | 24 | #include "coretypes.h" |
7d5a5747 | 25 | #include "opts.h" |
903f5c23 | 26 | #include "tm.h" |
d7b42618 | 27 | #include "flags.h" |
de32c0cb | 28 | #include "diagnostic.h" |
5f0f4a3b | 29 | #include "opts-diagnostic.h" |
88a00ef7 | 30 | #include "insn-attr-common.h" |
677f3fa8 | 31 | #include "common/common-target.h" |
19ff0049 | 32 | #include "spellcheck.h" |
5bcc5a3b | 33 | #include "opt-suggestions.h" |
fa5baeed | 34 | #include "diagnostic-color.h" |
fa29cf0c | 35 | #include "selftest.h" |
2772ef3e | 36 | |
65d4f2cd MLI |
37 | static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); |
38 | ||
a7d0d30f JM |
39 | /* Indexed by enum debug_info_type. */ |
40 | const char *const debug_type_names[] = | |
41 | { | |
180295ed | 42 | "none", "stabs", "dwarf-2", "xcoff", "vms" |
a7d0d30f JM |
43 | }; |
44 | ||
39ef6592 LC |
45 | /* Parse the -femit-struct-debug-detailed option value |
46 | and set the flag variables. */ | |
47 | ||
48 | #define MATCH( prefix, string ) \ | |
49 | ((strncmp (prefix, string, sizeof prefix - 1) == 0) \ | |
50 | ? ((string += sizeof prefix - 1), 1) : 0) | |
51 | ||
52 | void | |
299404a1 JM |
53 | set_struct_debug_option (struct gcc_options *opts, location_t loc, |
54 | const char *spec) | |
39ef6592 LC |
55 | { |
56 | /* various labels for comparison */ | |
0576d21f JM |
57 | static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:"; |
58 | static const char ord_lbl[] = "ord:", gen_lbl[] = "gen:"; | |
59 | static const char none_lbl[] = "none", any_lbl[] = "any"; | |
60 | static const char base_lbl[] = "base", sys_lbl[] = "sys"; | |
39ef6592 LC |
61 | |
62 | enum debug_struct_file files = DINFO_STRUCT_FILE_ANY; | |
63 | /* Default is to apply to as much as possible. */ | |
64 | enum debug_info_usage usage = DINFO_USAGE_NUM_ENUMS; | |
65 | int ord = 1, gen = 1; | |
66 | ||
67 | /* What usage? */ | |
68 | if (MATCH (dfn_lbl, spec)) | |
69 | usage = DINFO_USAGE_DFN; | |
70 | else if (MATCH (dir_lbl, spec)) | |
71 | usage = DINFO_USAGE_DIR_USE; | |
72 | else if (MATCH (ind_lbl, spec)) | |
73 | usage = DINFO_USAGE_IND_USE; | |
74 | ||
75 | /* Generics or not? */ | |
76 | if (MATCH (ord_lbl, spec)) | |
77 | gen = 0; | |
78 | else if (MATCH (gen_lbl, spec)) | |
79 | ord = 0; | |
80 | ||
81 | /* What allowable environment? */ | |
82 | if (MATCH (none_lbl, spec)) | |
83 | files = DINFO_STRUCT_FILE_NONE; | |
84 | else if (MATCH (any_lbl, spec)) | |
85 | files = DINFO_STRUCT_FILE_ANY; | |
86 | else if (MATCH (sys_lbl, spec)) | |
87 | files = DINFO_STRUCT_FILE_SYS; | |
88 | else if (MATCH (base_lbl, spec)) | |
89 | files = DINFO_STRUCT_FILE_BASE; | |
90 | else | |
299404a1 JM |
91 | error_at (loc, |
92 | "argument %qs to %<-femit-struct-debug-detailed%> " | |
93 | "not recognized", | |
94 | spec); | |
39ef6592 LC |
95 | |
96 | /* Effect the specification. */ | |
97 | if (usage == DINFO_USAGE_NUM_ENUMS) | |
98 | { | |
99 | if (ord) | |
100 | { | |
69ccdddb JM |
101 | opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files; |
102 | opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; | |
103 | opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; | |
39ef6592 LC |
104 | } |
105 | if (gen) | |
106 | { | |
69ccdddb JM |
107 | opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files; |
108 | opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files; | |
109 | opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files; | |
39ef6592 LC |
110 | } |
111 | } | |
112 | else | |
113 | { | |
114 | if (ord) | |
69ccdddb | 115 | opts->x_debug_struct_ordinary[usage] = files; |
39ef6592 | 116 | if (gen) |
69ccdddb | 117 | opts->x_debug_struct_generic[usage] = files; |
39ef6592 LC |
118 | } |
119 | ||
120 | if (*spec == ',') | |
299404a1 | 121 | set_struct_debug_option (opts, loc, spec+1); |
39ef6592 LC |
122 | else |
123 | { | |
124 | /* No more -femit-struct-debug-detailed specifications. | |
125 | Do final checks. */ | |
126 | if (*spec != '\0') | |
299404a1 JM |
127 | error_at (loc, |
128 | "argument %qs to %<-femit-struct-debug-detailed%> unknown", | |
129 | spec); | |
69ccdddb JM |
130 | if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] |
131 | < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] | |
132 | || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] | |
133 | < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE]) | |
299404a1 JM |
134 | error_at (loc, |
135 | "%<-femit-struct-debug-detailed=dir:...%> must allow " | |
136 | "at least as much as " | |
137 | "%<-femit-struct-debug-detailed=ind:...%>"); | |
39ef6592 LC |
138 | } |
139 | } | |
140 | ||
c98cd5bf JM |
141 | /* Strip off a legitimate source ending from the input string NAME of |
142 | length LEN. Rather than having to know the names used by all of | |
143 | our front ends, we strip off an ending of a period followed by | |
ed5cd5bc | 144 | up to fource characters. (C++ uses ".cpp".) */ |
c98cd5bf JM |
145 | |
146 | void | |
147 | strip_off_ending (char *name, int len) | |
148 | { | |
149 | int i; | |
ed5cd5bc | 150 | for (i = 2; i < 5 && len > i; i++) |
c98cd5bf JM |
151 | { |
152 | if (name[len - i] == '.') | |
153 | { | |
154 | name[len - i] = '\0'; | |
155 | break; | |
156 | } | |
157 | } | |
158 | } | |
159 | ||
39ef6592 LC |
160 | /* Find the base name of a path, stripping off both directories and |
161 | a single final extension. */ | |
69ccdddb | 162 | int |
39ef6592 LC |
163 | base_of_path (const char *path, const char **base_out) |
164 | { | |
165 | const char *base = path; | |
166 | const char *dot = 0; | |
167 | const char *p = path; | |
168 | char c = *p; | |
169 | while (c) | |
170 | { | |
c3284718 | 171 | if (IS_DIR_SEPARATOR (c)) |
39ef6592 LC |
172 | { |
173 | base = p + 1; | |
174 | dot = 0; | |
175 | } | |
176 | else if (c == '.') | |
177 | dot = p; | |
178 | c = *++p; | |
179 | } | |
180 | if (!dot) | |
181 | dot = p; | |
182 | *base_out = base; | |
183 | return dot - base; | |
184 | } | |
185 | ||
2cc98056 | 186 | /* What to print when a switch has no documentation. */ |
a7b2e184 MS |
187 | static const char undocumented_msg[] = N_("This option lacks documentation."); |
188 | static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed."); | |
2cc98056 | 189 | |
8d5a7d1f | 190 | typedef char *char_p; /* For DEF_VEC_P. */ |
8d5a7d1f | 191 | |
df38ffef | 192 | static void set_debug_level (enum debug_info_type type, int extended, |
0576d21f | 193 | const char *arg, struct gcc_options *opts, |
299404a1 JM |
194 | struct gcc_options *opts_set, |
195 | location_t loc); | |
d5478783 | 196 | static void set_fast_math_flags (struct gcc_options *opts, int set); |
299404a1 JM |
197 | static void decode_d_option (const char *arg, struct gcc_options *opts, |
198 | location_t loc, diagnostic_context *dc); | |
d5478783 JM |
199 | static void set_unsafe_math_optimizations_flags (struct gcc_options *opts, |
200 | int set); | |
a4d8c676 JM |
201 | static void enable_warning_as_error (const char *arg, int value, |
202 | unsigned int lang_mask, | |
203 | const struct cl_option_handlers *handlers, | |
c5fa0890 JM |
204 | struct gcc_options *opts, |
205 | struct gcc_options *opts_set, | |
a4d8c676 JM |
206 | location_t loc, |
207 | diagnostic_context *dc); | |
2772ef3e | 208 | |
5f20c657 JM |
209 | /* Handle a back-end option; arguments and return value as for |
210 | handle_option. */ | |
2772ef3e | 211 | |
c98cd5bf | 212 | bool |
46625112 | 213 | target_handle_option (struct gcc_options *opts, |
d4d24ba4 | 214 | struct gcc_options *opts_set, |
46625112 | 215 | const struct cl_decoded_option *decoded, |
481e1176 | 216 | unsigned int lang_mask ATTRIBUTE_UNUSED, int kind, |
96e45421 | 217 | location_t loc, |
d5478783 | 218 | const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED, |
130fcab0 | 219 | diagnostic_context *dc, void (*) (void)) |
5f20c657 | 220 | { |
d5478783 | 221 | gcc_assert (dc == global_dc); |
5f20c657 | 222 | gcc_assert (kind == DK_UNSPECIFIED); |
677f3fa8 | 223 | return targetm_common.handle_option (opts, opts_set, decoded, loc); |
2772ef3e | 224 | } |
d7b42618 | 225 | |
1ebc7e68 | 226 | /* Add comma-separated strings to a char_p vector. */ |
8d5a7d1f ILT |
227 | |
228 | static void | |
6a1f6c9c | 229 | add_comma_separated_to_vector (void **pvec, const char *arg) |
8d5a7d1f ILT |
230 | { |
231 | char *tmp; | |
232 | char *r; | |
233 | char *w; | |
234 | char *token_start; | |
9771b263 DN |
235 | vec<char_p> *v = (vec<char_p> *) *pvec; |
236 | ||
237 | vec_check_alloc (v, 1); | |
8d5a7d1f ILT |
238 | |
239 | /* We never free this string. */ | |
240 | tmp = xstrdup (arg); | |
241 | ||
242 | r = tmp; | |
243 | w = tmp; | |
244 | token_start = tmp; | |
245 | ||
246 | while (*r != '\0') | |
247 | { | |
248 | if (*r == ',') | |
249 | { | |
250 | *w++ = '\0'; | |
251 | ++r; | |
9771b263 | 252 | v->safe_push (token_start); |
8d5a7d1f ILT |
253 | token_start = w; |
254 | } | |
255 | if (*r == '\\' && r[1] == ',') | |
256 | { | |
257 | *w++ = ','; | |
258 | r += 2; | |
259 | } | |
260 | else | |
261 | *w++ = *r++; | |
262 | } | |
efab3e3a OB |
263 | |
264 | *w = '\0'; | |
8d5a7d1f | 265 | if (*token_start != '\0') |
9771b263 | 266 | v->safe_push (token_start); |
8d5a7d1f | 267 | |
9771b263 | 268 | *pvec = v; |
8d5a7d1f ILT |
269 | } |
270 | ||
d6874f56 | 271 | /* Initialize opts_obstack. */ |
de5672fc ML |
272 | |
273 | void | |
274 | init_opts_obstack (void) | |
275 | { | |
d6874f56 | 276 | gcc_obstack_init (&opts_obstack); |
de5672fc ML |
277 | } |
278 | ||
a75bfaa6 JM |
279 | /* Initialize OPTS and OPTS_SET before using them in parsing options. */ |
280 | ||
281 | void | |
282 | init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set) | |
283 | { | |
d6874f56 DM |
284 | /* Ensure that opts_obstack has already been initialized by the time |
285 | that we initialize any gcc_options instances (PR jit/68446). */ | |
286 | gcc_assert (opts_obstack.chunk_size > 0); | |
dc357798 | 287 | |
a75bfaa6 | 288 | *opts = global_options_init; |
bf7b5747 ST |
289 | |
290 | if (opts_set) | |
291 | memset (opts_set, 0, sizeof (*opts_set)); | |
a75bfaa6 | 292 | |
a75bfaa6 JM |
293 | /* Initialize whether `char' is signed. */ |
294 | opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR; | |
295 | /* Set this to a special "uninitialized" value. The actual default | |
296 | is set after target options have been processed. */ | |
297 | opts->x_flag_short_enums = 2; | |
298 | ||
677f3fa8 | 299 | /* Initialize target_flags before default_options_optimization |
a75bfaa6 | 300 | so the latter can modify it. */ |
677f3fa8 | 301 | opts->x_target_flags = targetm_common.default_target_flags; |
a75bfaa6 JM |
302 | |
303 | /* Some targets have ABI-specified unwind tables. */ | |
677f3fa8 | 304 | opts->x_flag_unwind_tables = targetm_common.unwind_tables_default; |
7e4aae92 JM |
305 | |
306 | /* Some targets have other target-specific initialization. */ | |
677f3fa8 | 307 | targetm_common.option_init_struct (opts); |
a75bfaa6 JM |
308 | } |
309 | ||
3020190e | 310 | /* If indicated by the optimization level LEVEL (-Os if SIZE is set, |
bf7a7185 RG |
311 | -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT |
312 | to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language | |
313 | mask LANG_MASK and option handlers HANDLERS. */ | |
3020190e JM |
314 | |
315 | static void | |
316 | maybe_default_option (struct gcc_options *opts, | |
317 | struct gcc_options *opts_set, | |
318 | const struct default_options *default_opt, | |
bf7a7185 | 319 | int level, bool size, bool fast, bool debug, |
3020190e JM |
320 | unsigned int lang_mask, |
321 | const struct cl_option_handlers *handlers, | |
a4d8c676 | 322 | location_t loc, |
3020190e JM |
323 | diagnostic_context *dc) |
324 | { | |
325 | const struct cl_option *option = &cl_options[default_opt->opt_index]; | |
326 | bool enabled; | |
327 | ||
328 | if (size) | |
329 | gcc_assert (level == 2); | |
330 | if (fast) | |
331 | gcc_assert (level == 3); | |
bf7a7185 RG |
332 | if (debug) |
333 | gcc_assert (level == 1); | |
3020190e JM |
334 | |
335 | switch (default_opt->levels) | |
336 | { | |
337 | case OPT_LEVELS_ALL: | |
338 | enabled = true; | |
339 | break; | |
340 | ||
341 | case OPT_LEVELS_0_ONLY: | |
342 | enabled = (level == 0); | |
343 | break; | |
344 | ||
345 | case OPT_LEVELS_1_PLUS: | |
346 | enabled = (level >= 1); | |
347 | break; | |
348 | ||
349 | case OPT_LEVELS_1_PLUS_SPEED_ONLY: | |
bf7a7185 RG |
350 | enabled = (level >= 1 && !size && !debug); |
351 | break; | |
352 | ||
353 | case OPT_LEVELS_1_PLUS_NOT_DEBUG: | |
354 | enabled = (level >= 1 && !debug); | |
3020190e JM |
355 | break; |
356 | ||
357 | case OPT_LEVELS_2_PLUS: | |
358 | enabled = (level >= 2); | |
359 | break; | |
360 | ||
361 | case OPT_LEVELS_2_PLUS_SPEED_ONLY: | |
bf7a7185 | 362 | enabled = (level >= 2 && !size && !debug); |
3020190e JM |
363 | break; |
364 | ||
365 | case OPT_LEVELS_3_PLUS: | |
366 | enabled = (level >= 3); | |
367 | break; | |
368 | ||
369 | case OPT_LEVELS_3_PLUS_AND_SIZE: | |
370 | enabled = (level >= 3 || size); | |
371 | break; | |
372 | ||
373 | case OPT_LEVELS_SIZE: | |
374 | enabled = size; | |
375 | break; | |
376 | ||
377 | case OPT_LEVELS_FAST: | |
378 | enabled = fast; | |
379 | break; | |
380 | ||
381 | case OPT_LEVELS_NONE: | |
382 | default: | |
383 | gcc_unreachable (); | |
384 | } | |
385 | ||
386 | if (enabled) | |
387 | handle_generated_option (opts, opts_set, default_opt->opt_index, | |
388 | default_opt->arg, default_opt->value, | |
a4d8c676 | 389 | lang_mask, DK_UNSPECIFIED, loc, |
b9822443 | 390 | handlers, true, dc); |
3020190e | 391 | else if (default_opt->arg == NULL |
78a502ca ML |
392 | && !option->cl_reject_negative |
393 | && !(option->flags & CL_PARAMS)) | |
3020190e JM |
394 | handle_generated_option (opts, opts_set, default_opt->opt_index, |
395 | default_opt->arg, !default_opt->value, | |
a4d8c676 | 396 | lang_mask, DK_UNSPECIFIED, loc, |
b9822443 | 397 | handlers, true, dc); |
3020190e JM |
398 | } |
399 | ||
400 | /* As indicated by the optimization level LEVEL (-Os if SIZE is set, | |
401 | -Ofast if FAST is set), apply the options in array DEFAULT_OPTS to | |
a4d8c676 JM |
402 | OPTS and OPTS_SET, diagnostic context DC, location LOC, with |
403 | language mask LANG_MASK and option handlers HANDLERS. */ | |
3020190e JM |
404 | |
405 | static void | |
406 | maybe_default_options (struct gcc_options *opts, | |
407 | struct gcc_options *opts_set, | |
408 | const struct default_options *default_opts, | |
bf7a7185 | 409 | int level, bool size, bool fast, bool debug, |
3020190e JM |
410 | unsigned int lang_mask, |
411 | const struct cl_option_handlers *handlers, | |
a4d8c676 | 412 | location_t loc, |
3020190e JM |
413 | diagnostic_context *dc) |
414 | { | |
415 | size_t i; | |
416 | ||
417 | for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++) | |
418 | maybe_default_option (opts, opts_set, &default_opts[i], | |
bf7a7185 RG |
419 | level, size, fast, debug, |
420 | lang_mask, handlers, loc, dc); | |
3020190e JM |
421 | } |
422 | ||
ded7b411 SL |
423 | /* Table of options enabled by default at different levels. |
424 | Please keep this list sorted by level and alphabetized within | |
425 | each level; this makes it easier to keep the documentation | |
426 | in sync. */ | |
3020190e JM |
427 | |
428 | static const struct default_options default_options_table[] = | |
429 | { | |
ded7b411 SL |
430 | /* -O1 and -Og optimizations. */ |
431 | { OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 }, | |
432 | { OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 }, | |
3020190e | 433 | { OPT_LEVELS_1_PLUS, OPT_fcprop_registers, NULL, 1 }, |
ded7b411 | 434 | { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 }, |
3020190e | 435 | { OPT_LEVELS_1_PLUS, OPT_fforward_propagate, NULL, 1 }, |
ded7b411 SL |
436 | { OPT_LEVELS_1_PLUS, OPT_fguess_branch_probability, NULL, 1 }, |
437 | { OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 }, | |
3020190e JM |
438 | { OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 }, |
439 | { OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 }, | |
2e14744f | 440 | { OPT_LEVELS_1_PLUS, OPT_fipa_reference_addressable, NULL, 1 }, |
3020190e | 441 | { OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 }, |
ded7b411 | 442 | { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, |
59faab7c | 443 | { OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 }, |
484db665 | 444 | { OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 }, |
3020190e | 445 | { OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 }, |
ded7b411 | 446 | { OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 }, |
3020190e | 447 | { OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 }, |
ded7b411 | 448 | { OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 }, |
1f9ceff1 | 449 | { OPT_LEVELS_1_PLUS, OPT_ftree_coalesce_vars, NULL, 1 }, |
ded7b411 | 450 | { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 }, |
3020190e JM |
451 | { OPT_LEVELS_1_PLUS, OPT_ftree_dce, NULL, 1 }, |
452 | { OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 }, | |
3020190e | 453 | { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 }, |
3020190e | 454 | { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 }, |
75cfe445 | 455 | { OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 }, |
ded7b411 SL |
456 | { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 }, |
457 | ||
458 | /* -O1 (and not -Og) optimizations. */ | |
14379e66 | 459 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 }, |
ded7b411 SL |
460 | #if DELAY_SLOTS |
461 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fdelayed_branch, NULL, 1 }, | |
462 | #endif | |
c0fe6bce | 463 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fdse, NULL, 1 }, |
ded7b411 SL |
464 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion, NULL, 1 }, |
465 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 }, | |
466 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 }, | |
14379e66 | 467 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 }, |
68f6df73 | 468 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 }, |
ded7b411 | 469 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 }, |
c0fe6bce | 470 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_dse, NULL, 1 }, |
ded7b411 | 471 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 }, |
c0fe6bce | 472 | { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 }, |
3020190e | 473 | |
ded7b411 SL |
474 | /* -O2 and -Os optimizations. */ |
475 | { OPT_LEVELS_2_PLUS, OPT_fcaller_saves, NULL, 1 }, | |
476 | { OPT_LEVELS_2_PLUS, OPT_fcode_hoisting, NULL, 1 }, | |
3020190e | 477 | { OPT_LEVELS_2_PLUS, OPT_fcrossjumping, NULL, 1 }, |
3020190e | 478 | { OPT_LEVELS_2_PLUS, OPT_fcse_follow_jumps, NULL, 1 }, |
ded7b411 SL |
479 | { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 }, |
480 | { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 }, | |
3020190e | 481 | { OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 }, |
ded7b411 SL |
482 | { OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 }, |
483 | { OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 }, | |
484 | { OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 }, | |
485 | { OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 }, | |
486 | { OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 }, | |
487 | { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 }, | |
488 | { OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 }, | |
489 | { OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 }, | |
490 | { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 }, | |
491 | { OPT_LEVELS_2_PLUS, OPT_fipa_vrp, NULL, 1 }, | |
492 | { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 }, | |
493 | { OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 }, | |
494 | { OPT_LEVELS_2_PLUS, OPT_foptimize_sibling_calls, NULL, 1 }, | |
495 | { OPT_LEVELS_2_PLUS, OPT_fpartial_inlining, NULL, 1 }, | |
3020190e | 496 | { OPT_LEVELS_2_PLUS, OPT_fpeephole2, NULL, 1 }, |
ded7b411 SL |
497 | { OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 }, |
498 | { OPT_LEVELS_2_PLUS, OPT_frerun_cse_after_loop, NULL, 1 }, | |
3020190e | 499 | #ifdef INSN_SCHEDULING |
3020190e JM |
500 | { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 }, |
501 | #endif | |
3020190e | 502 | { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 }, |
ded7b411 SL |
503 | { OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 }, |
504 | { OPT_LEVELS_2_PLUS, OPT_fthread_jumps, NULL, 1 }, | |
3020190e JM |
505 | { OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 }, |
506 | { OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 }, | |
c9e93168 | 507 | { OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 }, |
ded7b411 | 508 | { OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 }, |
d6d11272 | 509 | { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP }, |
562d1e95 | 510 | { OPT_LEVELS_2_PLUS, OPT_finline_functions, NULL, 1 }, |
afb4cc68 | 511 | { OPT_LEVELS_2_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 }, |
ded7b411 | 512 | |
9b6e95d3 | 513 | /* -O2 and above optimizations, but not -Os or -Og. */ |
ded7b411 SL |
514 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 }, |
515 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_jumps, NULL, 1 }, | |
516 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_labels, NULL, 1 }, | |
517 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_loops, NULL, 1 }, | |
d8878031 | 518 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 }, |
ded7b411 SL |
519 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL, |
520 | REORDER_BLOCKS_ALGORITHM_STC }, | |
521 | #ifdef INSN_SCHEDULING | |
522 | /* Only run the pre-regalloc scheduling pass if optimizing for speed. */ | |
523 | { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 }, | |
524 | #endif | |
3020190e | 525 | |
ded7b411 | 526 | /* -O3 and -Os optimizations. */ |
ded7b411 SL |
527 | |
528 | /* -O3 optimizations. */ | |
3020190e | 529 | { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 }, |
ded7b411 SL |
530 | { OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 }, |
531 | { OPT_LEVELS_3_PLUS, OPT_floop_interchange, NULL, 1 }, | |
532 | { OPT_LEVELS_3_PLUS, OPT_floop_unroll_and_jam, NULL, 1 }, | |
533 | { OPT_LEVELS_3_PLUS, OPT_fpeel_loops, NULL, 1 }, | |
534 | { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 }, | |
535 | { OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 }, | |
536 | { OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 }, | |
ded7b411 | 537 | { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 }, |
ea0f3e87 | 538 | { OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 }, |
ded7b411 | 539 | { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 }, |
ea0f3e87 | 540 | { OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 }, |
ded7b411 | 541 | { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 }, |
d6d11272 | 542 | { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC }, |
13e08dc9 | 543 | { OPT_LEVELS_3_PLUS, OPT_fversion_loops_for_strides, NULL, 1 }, |
3020190e | 544 | |
78a502ca ML |
545 | /* -O3 parameters. */ |
546 | { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_auto_, NULL, 30 }, | |
9340d345 JH |
547 | { OPT_LEVELS_3_PLUS, OPT__param_early_inlining_insns_, NULL, 14 }, |
548 | { OPT_LEVELS_3_PLUS, OPT__param_inline_heuristics_hint_percent_, NULL, 600 }, | |
549 | { OPT_LEVELS_3_PLUS, OPT__param_inline_min_speedup_, NULL, 15 }, | |
550 | { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_single_, NULL, 200 }, | |
78a502ca | 551 | |
3020190e JM |
552 | /* -Ofast adds optimizations to -O3. */ |
553 | { OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 }, | |
e622a32d | 554 | { OPT_LEVELS_FAST, OPT_fallow_store_data_races, NULL, 1 }, |
3020190e JM |
555 | |
556 | { OPT_LEVELS_NONE, 0, NULL, 0 } | |
557 | }; | |
558 | ||
a75bfaa6 JM |
559 | /* Default the options in OPTS and OPTS_SET based on the optimization |
560 | settings in DECODED_OPTIONS and DECODED_OPTIONS_COUNT. */ | |
c98cd5bf | 561 | void |
a75bfaa6 JM |
562 | default_options_optimization (struct gcc_options *opts, |
563 | struct gcc_options *opts_set, | |
564 | struct cl_decoded_option *decoded_options, | |
3020190e | 565 | unsigned int decoded_options_count, |
a4d8c676 | 566 | location_t loc, |
3020190e JM |
567 | unsigned int lang_mask, |
568 | const struct cl_option_handlers *handlers, | |
569 | diagnostic_context *dc) | |
a75bfaa6 JM |
570 | { |
571 | unsigned int i; | |
ab442df7 | 572 | int opt2; |
597a8ab9 | 573 | bool openacc_mode = false; |
9756310a NB |
574 | |
575 | /* Scan to see what optimization level has been specified. That will | |
576 | determine the default value of many flags. */ | |
a75bfaa6 | 577 | for (i = 1; i < decoded_options_count; i++) |
9756310a | 578 | { |
a75bfaa6 | 579 | struct cl_decoded_option *opt = &decoded_options[i]; |
6e2f1956 | 580 | switch (opt->opt_index) |
9756310a | 581 | { |
6e2f1956 JM |
582 | case OPT_O: |
583 | if (*opt->arg == '\0') | |
be6d3f0e | 584 | { |
3020190e JM |
585 | opts->x_optimize = 1; |
586 | opts->x_optimize_size = 0; | |
0a8134ca | 587 | opts->x_optimize_fast = 0; |
bf7a7185 | 588 | opts->x_optimize_debug = 0; |
9756310a NB |
589 | } |
590 | else | |
591 | { | |
6e2f1956 JM |
592 | const int optimize_val = integral_argument (opt->arg); |
593 | if (optimize_val == -1) | |
33879b9f MP |
594 | error_at (loc, "argument to %<-O%> should be a non-negative " |
595 | "integer, %<g%>, %<s%> or %<fast%>"); | |
6e2f1956 | 596 | else |
9756310a | 597 | { |
3020190e JM |
598 | opts->x_optimize = optimize_val; |
599 | if ((unsigned int) opts->x_optimize > 255) | |
600 | opts->x_optimize = 255; | |
601 | opts->x_optimize_size = 0; | |
0a8134ca | 602 | opts->x_optimize_fast = 0; |
bf7a7185 | 603 | opts->x_optimize_debug = 0; |
9756310a NB |
604 | } |
605 | } | |
6e2f1956 JM |
606 | break; |
607 | ||
608 | case OPT_Os: | |
3020190e | 609 | opts->x_optimize_size = 1; |
6e2f1956 JM |
610 | |
611 | /* Optimizing for size forces optimize to be 2. */ | |
3020190e | 612 | opts->x_optimize = 2; |
0a8134ca | 613 | opts->x_optimize_fast = 0; |
bf7a7185 | 614 | opts->x_optimize_debug = 0; |
6e2f1956 JM |
615 | break; |
616 | ||
617 | case OPT_Ofast: | |
618 | /* -Ofast only adds flags to -O3. */ | |
3020190e JM |
619 | opts->x_optimize_size = 0; |
620 | opts->x_optimize = 3; | |
0a8134ca | 621 | opts->x_optimize_fast = 1; |
bf7a7185 RG |
622 | opts->x_optimize_debug = 0; |
623 | break; | |
624 | ||
625 | case OPT_Og: | |
626 | /* -Og selects optimization level 1. */ | |
627 | opts->x_optimize_size = 0; | |
628 | opts->x_optimize = 1; | |
629 | opts->x_optimize_fast = 0; | |
630 | opts->x_optimize_debug = 1; | |
6e2f1956 JM |
631 | break; |
632 | ||
597a8ab9 TV |
633 | case OPT_fopenacc: |
634 | if (opt->value) | |
635 | openacc_mode = true; | |
636 | break; | |
637 | ||
6e2f1956 JM |
638 | default: |
639 | /* Ignore other options in this prescan. */ | |
640 | break; | |
9756310a NB |
641 | } |
642 | } | |
b8698a0f | 643 | |
3020190e JM |
644 | maybe_default_options (opts, opts_set, default_options_table, |
645 | opts->x_optimize, opts->x_optimize_size, | |
bf7a7185 RG |
646 | opts->x_optimize_fast, opts->x_optimize_debug, |
647 | lang_mask, handlers, loc, dc); | |
3020190e JM |
648 | |
649 | /* -O2 param settings. */ | |
650 | opt2 = (opts->x_optimize >= 2); | |
116cb604 | 651 | |
6ed76044 ML |
652 | if (openacc_mode) |
653 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_pta, true); | |
597a8ab9 | 654 | |
ab442df7 | 655 | /* Track fields in field-sensitive alias analysis. */ |
028d4092 ML |
656 | if (opt2) |
657 | SET_OPTION_IF_UNSET (opts, opts_set, param_max_fields_for_field_sensitive, | |
658 | 100); | |
e9e0aa2c | 659 | |
3020190e JM |
660 | if (opts->x_optimize_size) |
661 | /* We want to crossjump as much as possible. */ | |
028d4092 | 662 | SET_OPTION_IF_UNSET (opts, opts_set, param_min_crossjump_insns, 1); |
f736cb3e | 663 | |
b30e733a RB |
664 | /* Restrict the amount of work combine does at -Og while retaining |
665 | most of its useful transforms. */ | |
666 | if (opts->x_optimize_debug) | |
028d4092 | 667 | SET_OPTION_IF_UNSET (opts, opts_set, param_max_combine_insns, 2); |
b30e733a | 668 | |
a75bfaa6 | 669 | /* Allow default optimizations to be specified on a per-machine basis. */ |
3020190e | 670 | maybe_default_options (opts, opts_set, |
677f3fa8 | 671 | targetm_common.option_optimization_table, |
3020190e | 672 | opts->x_optimize, opts->x_optimize_size, |
bf7a7185 RG |
673 | opts->x_optimize_fast, opts->x_optimize_debug, |
674 | lang_mask, handlers, loc, dc); | |
a75bfaa6 JM |
675 | } |
676 | ||
6fd6a2ff QZ |
677 | /* Control IPA optimizations based on different live patching LEVEL. */ |
678 | static void | |
679 | control_options_for_live_patching (struct gcc_options *opts, | |
680 | struct gcc_options *opts_set, | |
681 | enum live_patching_level level, | |
682 | location_t loc) | |
683 | { | |
684 | gcc_assert (level > LIVE_PATCHING_NONE); | |
685 | ||
686 | switch (level) | |
687 | { | |
688 | case LIVE_PATCHING_INLINE_ONLY_STATIC: | |
689 | if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone) | |
690 | error_at (loc, | |
691 | "%<-fipa-cp-clone%> is incompatible with " | |
692 | "%<-flive-patching=inline-only-static%>"); | |
693 | else | |
694 | opts->x_flag_ipa_cp_clone = 0; | |
695 | ||
696 | if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra) | |
697 | error_at (loc, | |
698 | "%<-fipa-sra%> is incompatible with " | |
699 | "%<-flive-patching=inline-only-static%>"); | |
700 | else | |
701 | opts->x_flag_ipa_sra = 0; | |
702 | ||
703 | if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining) | |
704 | error_at (loc, | |
705 | "%<-fpartial-inlining%> is incompatible with " | |
706 | "%<-flive-patching=inline-only-static%>"); | |
707 | else | |
708 | opts->x_flag_partial_inlining = 0; | |
709 | ||
710 | if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp) | |
711 | error_at (loc, | |
712 | "%<-fipa-cp%> is incompatible with " | |
713 | "%<-flive-patching=inline-only-static%>"); | |
714 | else | |
715 | opts->x_flag_ipa_cp = 0; | |
716 | ||
717 | /* FALLTHROUGH. */ | |
718 | case LIVE_PATCHING_INLINE_CLONE: | |
719 | /* live patching should disable whole-program optimization. */ | |
720 | if (opts_set->x_flag_whole_program && opts->x_flag_whole_program) | |
721 | error_at (loc, | |
722 | "%<-fwhole-program%> is incompatible with " | |
723 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
724 | else | |
725 | opts->x_flag_whole_program = 0; | |
726 | ||
727 | /* visibility change should be excluded by !flag_whole_program | |
728 | && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra | |
729 | && !flag_partial_inlining. */ | |
730 | ||
731 | if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta) | |
732 | error_at (loc, | |
733 | "%<-fipa-pta%> is incompatible with " | |
734 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
735 | else | |
736 | opts->x_flag_ipa_pta = 0; | |
737 | ||
738 | if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference) | |
739 | error_at (loc, | |
740 | "%<-fipa-reference%> is incompatible with " | |
741 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
742 | else | |
743 | opts->x_flag_ipa_reference = 0; | |
744 | ||
745 | if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra) | |
746 | error_at (loc, | |
747 | "%<-fipa-ra%> is incompatible with " | |
748 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
749 | else | |
750 | opts->x_flag_ipa_ra = 0; | |
751 | ||
752 | if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf) | |
753 | error_at (loc, | |
754 | "%<-fipa-icf%> is incompatible with " | |
755 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
756 | else | |
757 | opts->x_flag_ipa_icf = 0; | |
758 | ||
759 | if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions) | |
760 | error_at (loc, | |
761 | "%<-fipa-icf-functions%> is incompatible with " | |
762 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
763 | else | |
764 | opts->x_flag_ipa_icf_functions = 0; | |
765 | ||
766 | if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables) | |
767 | error_at (loc, | |
768 | "%<-fipa-icf-variables%> is incompatible with " | |
769 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
770 | else | |
771 | opts->x_flag_ipa_icf_variables = 0; | |
772 | ||
773 | if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp) | |
774 | error_at (loc, | |
775 | "%<-fipa-bit-cp%> is incompatible with " | |
776 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
777 | else | |
778 | opts->x_flag_ipa_bit_cp = 0; | |
779 | ||
780 | if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp) | |
781 | error_at (loc, | |
782 | "%<-fipa-vrp%> is incompatible with " | |
783 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
784 | else | |
785 | opts->x_flag_ipa_vrp = 0; | |
786 | ||
787 | if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const) | |
788 | error_at (loc, | |
789 | "%<-fipa-pure-const%> is incompatible with " | |
790 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
791 | else | |
792 | opts->x_flag_ipa_pure_const = 0; | |
793 | ||
794 | /* FIXME: disable unreachable code removal. */ | |
795 | ||
796 | /* discovery of functions/variables with no address taken. */ | |
797 | if (opts_set->x_flag_ipa_reference_addressable | |
798 | && opts->x_flag_ipa_reference_addressable) | |
799 | error_at (loc, | |
800 | "%<-fipa-reference-addressable%> is incompatible with " | |
801 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
802 | else | |
803 | opts->x_flag_ipa_reference_addressable = 0; | |
804 | ||
805 | /* ipa stack alignment propagation. */ | |
806 | if (opts_set->x_flag_ipa_stack_alignment | |
807 | && opts->x_flag_ipa_stack_alignment) | |
808 | error_at (loc, | |
809 | "%<-fipa-stack-alignment%> is incompatible with " | |
810 | "%<-flive-patching=inline-only-static|inline-clone%>"); | |
811 | else | |
812 | opts->x_flag_ipa_stack_alignment = 0; | |
813 | break; | |
814 | default: | |
815 | gcc_unreachable (); | |
816 | } | |
817 | } | |
818 | ||
2dcfc872 | 819 | /* --help option argument if set. */ |
bc405869 | 820 | vec<const char *> help_option_arguments; |
2dcfc872 | 821 | |
2dcfc872 | 822 | |
299404a1 JM |
823 | /* After all options at LOC have been read into OPTS and OPTS_SET, |
824 | finalize settings of those options and diagnose incompatible | |
a75bfaa6 | 825 | combinations. */ |
c98cd5bf | 826 | void |
299404a1 | 827 | finish_options (struct gcc_options *opts, struct gcc_options *opts_set, |
f66409e0 | 828 | location_t loc) |
a75bfaa6 | 829 | { |
a75bfaa6 JM |
830 | enum unwind_info_type ui_except; |
831 | ||
91035653 | 832 | if (opts->x_dump_base_name |
91035653 | 833 | && ! opts->x_dump_base_name_prefixed) |
e71da632 | 834 | { |
f35629b7 NS |
835 | const char *sep = opts->x_dump_base_name; |
836 | ||
837 | for (; *sep; sep++) | |
838 | if (IS_DIR_SEPARATOR (*sep)) | |
839 | break; | |
840 | ||
841 | if (*sep) | |
842 | /* If dump_base_path contains subdirectories, don't prepend | |
843 | anything. */; | |
844 | else if (opts->x_dump_dir_name) | |
845 | /* We have a DUMP_DIR_NAME, prepend that. */ | |
dc357798 JJ |
846 | opts->x_dump_base_name = opts_concat (opts->x_dump_dir_name, |
847 | opts->x_dump_base_name, NULL); | |
dd3b31fb L |
848 | else if (opts->x_aux_base_name |
849 | && strcmp (opts->x_aux_base_name, HOST_BIT_BUCKET) != 0) | |
f35629b7 NS |
850 | /* AUX_BASE_NAME is set and is not the bit bucket. If it |
851 | contains a directory component, prepend those directories. | |
852 | Typically this places things in the same directory as the | |
853 | object file. */ | |
e71da632 | 854 | { |
d7fb0a6d L |
855 | const char *aux_base; |
856 | ||
d5478783 JM |
857 | base_of_path (opts->x_aux_base_name, &aux_base); |
858 | if (opts->x_aux_base_name != aux_base) | |
d7fb0a6d | 859 | { |
d5478783 | 860 | int dir_len = aux_base - opts->x_aux_base_name; |
dc357798 JJ |
861 | char *new_dump_base_name |
862 | = XOBNEWVEC (&opts_obstack, char, | |
863 | strlen (opts->x_dump_base_name) + dir_len + 1); | |
d7fb0a6d | 864 | |
d5478783 JM |
865 | /* Copy directory component from OPTS->X_AUX_BASE_NAME. */ |
866 | memcpy (new_dump_base_name, opts->x_aux_base_name, dir_len); | |
867 | /* Append existing OPTS->X_DUMP_BASE_NAME. */ | |
868 | strcpy (new_dump_base_name + dir_len, opts->x_dump_base_name); | |
869 | opts->x_dump_base_name = new_dump_base_name; | |
d7fb0a6d | 870 | } |
e71da632 | 871 | } |
f35629b7 NS |
872 | |
873 | /* It is definitely prefixed now. */ | |
874 | opts->x_dump_base_name_prefixed = true; | |
e71da632 MH |
875 | } |
876 | ||
93a4f5e0 JJ |
877 | /* Handle related options for unit-at-a-time, toplevel-reorder, and |
878 | section-anchors. */ | |
d5478783 | 879 | if (!opts->x_flag_unit_at_a_time) |
57b08d04 | 880 | { |
d5478783 | 881 | if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors) |
299404a1 JM |
882 | error_at (loc, "section anchors must be disabled when unit-at-a-time " |
883 | "is disabled"); | |
d5478783 JM |
884 | opts->x_flag_section_anchors = 0; |
885 | if (opts->x_flag_toplevel_reorder == 1) | |
299404a1 JM |
886 | error_at (loc, "toplevel reorder must be disabled when unit-at-a-time " |
887 | "is disabled"); | |
d5478783 | 888 | opts->x_flag_toplevel_reorder = 0; |
57b08d04 | 889 | } |
7ea6b6cf | 890 | |
3615816d AH |
891 | /* -fself-test depends on the state of the compiler prior to |
892 | compiling anything. Ideally it should be run on an empty source | |
893 | file. However, in case we get run with actual source, assume | |
894 | -fsyntax-only which will inhibit any compiler initialization | |
895 | which may confuse the self tests. */ | |
896 | if (opts->x_flag_self_test) | |
897 | opts->x_flag_syntax_only = 1; | |
898 | ||
ee777b71 AH |
899 | if (opts->x_flag_tm && opts->x_flag_non_call_exceptions) |
900 | sorry ("transactional memory is not supported with non-call exceptions"); | |
901 | ||
5ffebee7 JJ |
902 | /* Unless the user has asked for section anchors, we disable toplevel |
903 | reordering at -O0 to disable transformations that might be surprising | |
904 | to end users and to get -fno-toplevel-reorder tested. */ | |
299404a1 | 905 | if (!opts->x_optimize |
d5478783 JM |
906 | && opts->x_flag_toplevel_reorder == 2 |
907 | && !(opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)) | |
93a4f5e0 | 908 | { |
d5478783 JM |
909 | opts->x_flag_toplevel_reorder = 0; |
910 | opts->x_flag_section_anchors = 0; | |
93a4f5e0 | 911 | } |
d5478783 | 912 | if (!opts->x_flag_toplevel_reorder) |
57b08d04 | 913 | { |
d5478783 | 914 | if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors) |
299404a1 JM |
915 | error_at (loc, "section anchors must be disabled when toplevel reorder" |
916 | " is disabled"); | |
d5478783 | 917 | opts->x_flag_section_anchors = 0; |
57b08d04 ST |
918 | } |
919 | ||
299404a1 | 920 | if (!opts->x_flag_opts_finished) |
ab442df7 | 921 | { |
428b3812 L |
922 | /* We initialize opts->x_flag_pie to -1 so that targets can set a |
923 | default value. */ | |
924 | if (opts->x_flag_pie == -1) | |
925 | { | |
b57e6e18 L |
926 | /* We initialize opts->x_flag_pic to -1 so that we can tell if |
927 | -fpic, -fPIC, -fno-pic or -fno-PIC is used. */ | |
928 | if (opts->x_flag_pic == -1) | |
428b3812 L |
929 | opts->x_flag_pie = DEFAULT_FLAG_PIE; |
930 | else | |
931 | opts->x_flag_pie = 0; | |
932 | } | |
b57e6e18 | 933 | /* If -fPIE or -fpie is used, turn on PIC. */ |
d5478783 JM |
934 | if (opts->x_flag_pie) |
935 | opts->x_flag_pic = opts->x_flag_pie; | |
b57e6e18 L |
936 | else if (opts->x_flag_pic == -1) |
937 | opts->x_flag_pic = 0; | |
d5478783 JM |
938 | if (opts->x_flag_pic && !opts->x_flag_pie) |
939 | opts->x_flag_shlib = 1; | |
b294a75e | 940 | opts->x_flag_opts_finished = true; |
ab442df7 | 941 | } |
9756310a | 942 | |
e0f6cba0 MG |
943 | /* We initialize opts->x_flag_stack_protect to -1 so that targets |
944 | can set a default value. */ | |
945 | if (opts->x_flag_stack_protect == -1) | |
946 | opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; | |
947 | ||
299404a1 | 948 | if (opts->x_optimize == 0) |
9756310a NB |
949 | { |
950 | /* Inlining does not work if not optimizing, | |
951 | so force it not to be done. */ | |
d5478783 JM |
952 | opts->x_warn_inline = 0; |
953 | opts->x_flag_no_inline = 1; | |
9756310a NB |
954 | } |
955 | ||
750054a2 CT |
956 | /* The optimization to partition hot and cold basic blocks into separate |
957 | sections of the .o and executable files does not work (currently) | |
e395963f | 958 | with exception handling. This is because there is no support for |
d5478783 JM |
959 | generating unwind info. If opts->x_flag_exceptions is turned on |
960 | we need to turn off the partitioning optimization. */ | |
750054a2 | 961 | |
677f3fa8 | 962 | ui_except = targetm_common.except_unwind_info (opts); |
f0a0390e | 963 | |
d5478783 JM |
964 | if (opts->x_flag_exceptions |
965 | && opts->x_flag_reorder_blocks_and_partition | |
bf1431e3 | 966 | && (ui_except == UI_SJLJ || ui_except >= UI_TARGET)) |
750054a2 | 967 | { |
32ad0f03 TJ |
968 | if (opts_set->x_flag_reorder_blocks_and_partition) |
969 | inform (loc, | |
4f4b35a0 ML |
970 | "%<-freorder-blocks-and-partition%> does not work " |
971 | "with exceptions on this architecture"); | |
d5478783 JM |
972 | opts->x_flag_reorder_blocks_and_partition = 0; |
973 | opts->x_flag_reorder_blocks = 1; | |
750054a2 | 974 | } |
c7466dee | 975 | |
e395963f JW |
976 | /* If user requested unwind info, then turn off the partitioning |
977 | optimization. */ | |
978 | ||
d5478783 | 979 | if (opts->x_flag_unwind_tables |
677f3fa8 | 980 | && !targetm_common.unwind_tables_default |
d5478783 | 981 | && opts->x_flag_reorder_blocks_and_partition |
bf1431e3 | 982 | && (ui_except == UI_SJLJ || ui_except >= UI_TARGET)) |
e395963f | 983 | { |
32ad0f03 TJ |
984 | if (opts_set->x_flag_reorder_blocks_and_partition) |
985 | inform (loc, | |
4f4b35a0 ML |
986 | "%<-freorder-blocks-and-partition%> does not support " |
987 | "unwind info on this architecture"); | |
d5478783 JM |
988 | opts->x_flag_reorder_blocks_and_partition = 0; |
989 | opts->x_flag_reorder_blocks = 1; | |
e395963f JW |
990 | } |
991 | ||
992 | /* If the target requested unwind info, then turn off the partitioning | |
993 | optimization with a different message. Likewise, if the target does not | |
994 | support named sections. */ | |
995 | ||
d5478783 | 996 | if (opts->x_flag_reorder_blocks_and_partition |
677f3fa8 | 997 | && (!targetm_common.have_named_sections |
d5478783 | 998 | || (opts->x_flag_unwind_tables |
677f3fa8 | 999 | && targetm_common.unwind_tables_default |
bf1431e3 | 1000 | && (ui_except == UI_SJLJ || ui_except >= UI_TARGET)))) |
c7466dee | 1001 | { |
32ad0f03 TJ |
1002 | if (opts_set->x_flag_reorder_blocks_and_partition) |
1003 | inform (loc, | |
4f4b35a0 ML |
1004 | "%<-freorder-blocks-and-partition%> does not work " |
1005 | "on this architecture"); | |
d5478783 JM |
1006 | opts->x_flag_reorder_blocks_and_partition = 0; |
1007 | opts->x_flag_reorder_blocks = 1; | |
c7466dee | 1008 | } |
ab442df7 | 1009 | |
940c4160 | 1010 | |
e855c69d AB |
1011 | /* Pipelining of outer loops is only possible when general pipelining |
1012 | capabilities are requested. */ | |
d5478783 JM |
1013 | if (!opts->x_flag_sel_sched_pipelining) |
1014 | opts->x_flag_sel_sched_pipelining_outer_loops = 0; | |
e855c69d | 1015 | |
d5478783 | 1016 | if (opts->x_flag_conserve_stack) |
6a78eaa3 | 1017 | { |
028d4092 ML |
1018 | SET_OPTION_IF_UNSET (opts, opts_set, param_large_stack_frame, 100); |
1019 | SET_OPTION_IF_UNSET (opts, opts_set, param_stack_frame_growth, 40); | |
6a78eaa3 JH |
1020 | } |
1021 | ||
014d92e1 | 1022 | if (opts->x_flag_lto) |
e3b8749b RG |
1023 | { |
1024 | #ifdef ENABLE_LTO | |
d5478783 | 1025 | opts->x_flag_generate_lto = 1; |
e3b8749b RG |
1026 | |
1027 | /* When generating IL, do not operate in whole-program mode. | |
1028 | Otherwise, symbols will be privatized too early, causing link | |
1029 | errors later. */ | |
d5478783 | 1030 | opts->x_flag_whole_program = 0; |
e3b8749b | 1031 | #else |
299404a1 | 1032 | error_at (loc, "LTO support has not been enabled in this configuration"); |
e3b8749b | 1033 | #endif |
063d671d JH |
1034 | if (!opts->x_flag_fat_lto_objects |
1035 | && (!HAVE_LTO_PLUGIN | |
1036 | || (opts_set->x_flag_use_linker_plugin | |
1037 | && !opts->x_flag_use_linker_plugin))) | |
e9f67e62 JH |
1038 | { |
1039 | if (opts_set->x_flag_fat_lto_objects) | |
4f4b35a0 ML |
1040 | error_at (loc, "%<-fno-fat-lto-objects%> are supported only with " |
1041 | "linker plugin"); | |
e9f67e62 JH |
1042 | opts->x_flag_fat_lto_objects = 1; |
1043 | } | |
22fdf6af RB |
1044 | |
1045 | /* -gsplit-dwarf isn't compatible with LTO, see PR88389. */ | |
1046 | if (opts->x_dwarf_split_debug_info) | |
1047 | { | |
1048 | inform (loc, "%<-gsplit-dwarf%> is not supported with LTO," | |
1049 | " disabling"); | |
1050 | opts->x_dwarf_split_debug_info = 0; | |
1051 | } | |
e9f67e62 | 1052 | } |
e3b8749b | 1053 | |
d5478783 | 1054 | /* We initialize opts->x_flag_split_stack to -1 so that targets can set a |
7458026b | 1055 | default value if they choose based on other options. */ |
d5478783 JM |
1056 | if (opts->x_flag_split_stack == -1) |
1057 | opts->x_flag_split_stack = 0; | |
1058 | else if (opts->x_flag_split_stack) | |
7458026b | 1059 | { |
677f3fa8 | 1060 | if (!targetm_common.supports_split_stack (true, opts)) |
7458026b | 1061 | { |
299404a1 JM |
1062 | error_at (loc, "%<-fsplit-stack%> is not supported by " |
1063 | "this compiler configuration"); | |
d5478783 | 1064 | opts->x_flag_split_stack = 0; |
7458026b ILT |
1065 | } |
1066 | } | |
bfe068c3 | 1067 | |
227b76c3 JH |
1068 | /* If stack splitting is turned on, and the user did not explicitly |
1069 | request function partitioning, turn off partitioning, as it | |
1070 | confuses the linker when trying to handle partitioned split-stack | |
1071 | code that calls a non-split-stack functions. But if partitioning | |
1072 | was turned on explicitly just hope for the best. */ | |
1073 | if (opts->x_flag_split_stack | |
6ed76044 ML |
1074 | && opts->x_flag_reorder_blocks_and_partition) |
1075 | SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_blocks_and_partition, 0); | |
227b76c3 | 1076 | |
6ed76044 ML |
1077 | if (opts->x_flag_reorder_blocks_and_partition) |
1078 | SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_functions, 1); | |
227b76c3 | 1079 | |
bd5c3baa | 1080 | /* The -gsplit-dwarf option requires -ggnu-pubnames. */ |
99ea153e | 1081 | if (opts->x_dwarf_split_debug_info) |
bd5c3baa | 1082 | opts->x_debug_generate_pub_sections = 2; |
fec4842d | 1083 | |
05abad4c ML |
1084 | if ((opts->x_flag_sanitize |
1085 | & (SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS)) == 0) | |
1086 | { | |
1087 | if (opts->x_flag_sanitize & SANITIZE_POINTER_COMPARE) | |
1088 | error_at (loc, | |
1089 | "%<-fsanitize=pointer-compare%> must be combined with " | |
1090 | "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>"); | |
1091 | if (opts->x_flag_sanitize & SANITIZE_POINTER_SUBTRACT) | |
1092 | error_at (loc, | |
1093 | "%<-fsanitize=pointer-subtract%> must be combined with " | |
1094 | "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>"); | |
1095 | } | |
1096 | ||
fed4de37 | 1097 | /* Userspace and kernel ASan conflict with each other. */ |
d95a2703 JJ |
1098 | if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) |
1099 | && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)) | |
fec4842d | 1100 | error_at (loc, |
6d28654e ML |
1101 | "%<-fsanitize=address%> is incompatible with " |
1102 | "%<-fsanitize=kernel-address%>"); | |
fec4842d | 1103 | |
fed4de37 | 1104 | /* And with TSan. */ |
d95a2703 JJ |
1105 | if ((opts->x_flag_sanitize & SANITIZE_ADDRESS) |
1106 | && (opts->x_flag_sanitize & SANITIZE_THREAD)) | |
fec4842d | 1107 | error_at (loc, |
6d28654e ML |
1108 | "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> " |
1109 | "are incompatible with %<-fsanitize=thread%>"); | |
d95a2703 | 1110 | |
5cc6c41c ML |
1111 | if ((opts->x_flag_sanitize & SANITIZE_LEAK) |
1112 | && (opts->x_flag_sanitize & SANITIZE_THREAD)) | |
1113 | error_at (loc, | |
6d28654e | 1114 | "%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>"); |
d95a2703 | 1115 | |
5cc6c41c ML |
1116 | /* Check error recovery for -fsanitize-recover option. */ |
1117 | for (int i = 0; sanitizer_opts[i].name != NULL; ++i) | |
1118 | if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag) | |
1119 | && !sanitizer_opts[i].can_recover) | |
6d28654e | 1120 | error_at (loc, "%<-fsanitize-recover=%s%> is not supported", |
5cc6c41c | 1121 | sanitizer_opts[i].name); |
9ca0032c MZ |
1122 | |
1123 | /* When instrumenting the pointers, we don't want to remove | |
1124 | the null pointer checks. */ | |
1125 | if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE | |
1126 | | SANITIZE_RETURNS_NONNULL_ATTRIBUTE)) | |
1127 | opts->x_flag_delete_null_pointer_checks = 0; | |
1128 | ||
1129 | /* Aggressive compiler optimizations may cause false negatives. */ | |
866c72a8 | 1130 | if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE)) |
2bf54d93 | 1131 | opts->x_flag_aggressive_loop_optimizations = 0; |
6dc4a604 ML |
1132 | |
1133 | /* Enable -fsanitize-address-use-after-scope if address sanitizer is | |
1134 | enabled. */ | |
6ed76044 ML |
1135 | if (opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) |
1136 | SET_OPTION_IF_UNSET (opts, opts_set, flag_sanitize_address_use_after_scope, | |
1137 | true); | |
6dc4a604 ML |
1138 | |
1139 | /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope | |
1140 | is enabled. */ | |
1141 | if (opts->x_flag_sanitize_address_use_after_scope) | |
1142 | { | |
1143 | if (opts->x_flag_stack_reuse != SR_NONE | |
1144 | && opts_set->x_flag_stack_reuse != SR_NONE) | |
1145 | error_at (loc, | |
6d28654e ML |
1146 | "%<-fsanitize-address-use-after-scope%> requires " |
1147 | "%<-fstack-reuse=none%> option"); | |
6dc4a604 ML |
1148 | |
1149 | opts->x_flag_stack_reuse = SR_NONE; | |
1150 | } | |
26c5b549 ML |
1151 | |
1152 | if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && opts->x_flag_tm) | |
1153 | sorry ("transactional memory is not supported with %<-fsanitize=address%>"); | |
1154 | ||
1155 | if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm) | |
1156 | sorry ("transactional memory is not supported with " | |
1157 | "%<-fsanitize=kernel-address%>"); | |
6fd6a2ff QZ |
1158 | |
1159 | /* Currently live patching is not support for LTO. */ | |
1160 | if (opts->x_flag_live_patching && opts->x_flag_lto) | |
1161 | sorry ("live patching is not supported with LTO"); | |
1162 | ||
9eb730b8 CT |
1163 | /* Currently vtable verification is not supported for LTO */ |
1164 | if (opts->x_flag_vtable_verify && opts->x_flag_lto) | |
1165 | sorry ("vtable verification is not supported with LTO"); | |
1166 | ||
6fd6a2ff QZ |
1167 | /* Control IPA optimizations based on different -flive-patching level. */ |
1168 | if (opts->x_flag_live_patching) | |
1169 | { | |
1170 | control_options_for_live_patching (opts, opts_set, | |
1171 | opts->x_flag_live_patching, | |
1172 | loc); | |
1173 | } | |
9756310a NB |
1174 | } |
1175 | ||
c662432e NC |
1176 | #define LEFT_COLUMN 27 |
1177 | ||
1178 | /* Output ITEM, of length ITEM_WIDTH, in the left column, | |
1179 | followed by word-wrapped HELP in a second column. */ | |
1180 | static void | |
1181 | wrap_help (const char *help, | |
1182 | const char *item, | |
1183 | unsigned int item_width, | |
1184 | unsigned int columns) | |
1185 | { | |
1186 | unsigned int col_width = LEFT_COLUMN; | |
1187 | unsigned int remaining, room, len; | |
1188 | ||
1189 | remaining = strlen (help); | |
1190 | ||
1191 | do | |
1192 | { | |
1193 | room = columns - 3 - MAX (col_width, item_width); | |
1194 | if (room > columns) | |
1195 | room = 0; | |
1196 | len = remaining; | |
1197 | ||
1198 | if (room < len) | |
1199 | { | |
1200 | unsigned int i; | |
1201 | ||
1202 | for (i = 0; help[i]; i++) | |
1203 | { | |
1204 | if (i >= room && len != remaining) | |
1205 | break; | |
1206 | if (help[i] == ' ') | |
1207 | len = i; | |
1208 | else if ((help[i] == '-' || help[i] == '/') | |
1209 | && help[i + 1] != ' ' | |
1210 | && i > 0 && ISALPHA (help[i - 1])) | |
1211 | len = i + 1; | |
1212 | } | |
1213 | } | |
1214 | ||
c3284718 | 1215 | printf (" %-*.*s %.*s\n", col_width, item_width, item, len, help); |
c662432e NC |
1216 | item_width = 0; |
1217 | while (help[len] == ' ') | |
1218 | len++; | |
1219 | help += len; | |
1220 | remaining -= len; | |
1221 | } | |
1222 | while (remaining); | |
1223 | } | |
1224 | ||
c98c2430 ML |
1225 | /* Data structure used to print list of valid option values. */ |
1226 | ||
6c1dae73 | 1227 | class option_help_tuple |
c98c2430 | 1228 | { |
6c1dae73 | 1229 | public: |
c98c2430 ML |
1230 | option_help_tuple (int code, vec<const char *> values): |
1231 | m_code (code), m_values (values) | |
1232 | {} | |
1233 | ||
1234 | /* Code of an option. */ | |
1235 | int m_code; | |
1236 | ||
1237 | /* List of possible values. */ | |
1238 | vec<const char *> m_values; | |
1239 | }; | |
1240 | ||
c662432e NC |
1241 | /* Print help for a specific front-end, etc. */ |
1242 | static void | |
1243 | print_filtered_help (unsigned int include_flags, | |
1244 | unsigned int exclude_flags, | |
1245 | unsigned int any_flags, | |
0576d21f | 1246 | unsigned int columns, |
e6d4b984 JM |
1247 | struct gcc_options *opts, |
1248 | unsigned int lang_mask) | |
c662432e NC |
1249 | { |
1250 | unsigned int i; | |
1251 | const char *help; | |
c662432e NC |
1252 | bool found = false; |
1253 | bool displayed = false; | |
a7b2e184 | 1254 | char new_help[256]; |
c662432e | 1255 | |
299404a1 JM |
1256 | if (!opts->x_help_printed) |
1257 | opts->x_help_printed = XCNEWVAR (char, cl_options_count); | |
c662432e | 1258 | |
e6d4b984 JM |
1259 | if (!opts->x_help_enum_printed) |
1260 | opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count); | |
1261 | ||
c98c2430 ML |
1262 | auto_vec<option_help_tuple> help_tuples; |
1263 | ||
c662432e NC |
1264 | for (i = 0; i < cl_options_count; i++) |
1265 | { | |
c662432e NC |
1266 | const struct cl_option *option = cl_options + i; |
1267 | unsigned int len; | |
1268 | const char *opt; | |
1269 | const char *tab; | |
1270 | ||
1271 | if (include_flags == 0 | |
1272 | || ((option->flags & include_flags) != include_flags)) | |
1273 | { | |
1274 | if ((option->flags & any_flags) == 0) | |
1275 | continue; | |
1276 | } | |
1277 | ||
1278 | /* Skip unwanted switches. */ | |
1279 | if ((option->flags & exclude_flags) != 0) | |
1280 | continue; | |
1281 | ||
603349bf JM |
1282 | /* The driver currently prints its own help text. */ |
1283 | if ((option->flags & CL_DRIVER) != 0 | |
1284 | && (option->flags & (((1U << cl_lang_count) - 1) | |
1285 | | CL_COMMON | CL_TARGET)) == 0) | |
1286 | continue; | |
1287 | ||
e97a3063 ML |
1288 | /* If an option contains a language specification, |
1289 | exclude it from common unless all languages are present. */ | |
1290 | if ((include_flags & CL_COMMON) | |
1291 | && !(option->flags & CL_DRIVER) | |
1292 | && (option->flags & CL_LANG_ALL) | |
1293 | && (option->flags & CL_LANG_ALL) != CL_LANG_ALL) | |
1294 | continue; | |
1295 | ||
c662432e NC |
1296 | found = true; |
1297 | /* Skip switches that have already been printed. */ | |
299404a1 | 1298 | if (opts->x_help_printed[i]) |
c662432e NC |
1299 | continue; |
1300 | ||
299404a1 | 1301 | opts->x_help_printed[i] = true; |
c662432e NC |
1302 | |
1303 | help = option->help; | |
1304 | if (help == NULL) | |
1305 | { | |
1306 | if (exclude_flags & CL_UNDOCUMENTED) | |
1307 | continue; | |
a7b2e184 | 1308 | |
c662432e NC |
1309 | help = undocumented_msg; |
1310 | } | |
1311 | ||
8d1780b5 JJ |
1312 | /* Get the translation. */ |
1313 | help = _(help); | |
1314 | ||
a7b2e184 MS |
1315 | if (option->alias_target < N_OPTS |
1316 | && cl_options [option->alias_target].help) | |
1317 | { | |
d326e958 | 1318 | const struct cl_option *target = cl_options + option->alias_target; |
8d1780b5 | 1319 | if (option->help == NULL) |
a7b2e184 | 1320 | { |
d326e958 LH |
1321 | /* The option is undocumented but is an alias for an option that |
1322 | is documented. If the option has alias arguments, then its | |
1323 | purpose is to provide certain arguments to the other option, so | |
1324 | inform the reader of this. Otherwise, point the reader to the | |
1325 | other option in preference to the former. */ | |
1326 | ||
1327 | if (option->alias_arg) | |
1328 | { | |
1329 | if (option->neg_alias_arg) | |
1330 | snprintf (new_help, sizeof new_help, | |
1331 | _("Same as %s%s (or, in negated form, %s%s)."), | |
1332 | target->opt_text, option->alias_arg, | |
1333 | target->opt_text, option->neg_alias_arg); | |
1334 | else | |
1335 | snprintf (new_help, sizeof new_help, | |
1336 | _("Same as %s%s."), | |
1337 | target->opt_text, option->alias_arg); | |
1338 | } | |
1339 | else | |
1340 | snprintf (new_help, sizeof new_help, | |
1341 | _("Same as %s."), | |
1342 | target->opt_text); | |
a7b2e184 MS |
1343 | } |
1344 | else | |
1345 | { | |
1346 | /* For documented options with aliases, mention the aliased | |
1347 | option's name for reference. */ | |
1348 | snprintf (new_help, sizeof new_help, | |
1349 | _("%s Same as %s."), | |
1350 | help, cl_options [option->alias_target].opt_text); | |
1351 | } | |
1352 | ||
1353 | help = new_help; | |
1354 | } | |
1355 | ||
1356 | if (option->warn_message) | |
1357 | { | |
1358 | /* Mention that the use of the option will trigger a warning. */ | |
1359 | if (help == new_help) | |
1360 | snprintf (new_help + strlen (new_help), | |
1361 | sizeof new_help - strlen (new_help), | |
1362 | " %s", _(use_diagnosed_msg)); | |
1363 | else | |
1364 | snprintf (new_help, sizeof new_help, | |
1365 | "%s %s", help, _(use_diagnosed_msg)); | |
1366 | ||
1367 | help = new_help; | |
1368 | } | |
1369 | ||
c662432e NC |
1370 | /* Find the gap between the name of the |
1371 | option and its descriptive text. */ | |
1372 | tab = strchr (help, '\t'); | |
1373 | if (tab) | |
1374 | { | |
1375 | len = tab - help; | |
1376 | opt = help; | |
1377 | help = tab + 1; | |
1378 | } | |
1379 | else | |
1380 | { | |
1381 | opt = option->opt_text; | |
1382 | len = strlen (opt); | |
1383 | } | |
1384 | ||
1385 | /* With the -Q option enabled we change the descriptive text associated | |
1386 | with an option to be an indication of its current setting. */ | |
a7d0d30f | 1387 | if (!opts->x_quiet_flag) |
c662432e | 1388 | { |
0576d21f | 1389 | void *flag_var = option_flag_var (i, opts); |
46625112 | 1390 | |
c662432e NC |
1391 | if (len < (LEFT_COLUMN + 2)) |
1392 | strcpy (new_help, "\t\t"); | |
1393 | else | |
1394 | strcpy (new_help, "\t"); | |
1395 | ||
fa5baeed MS |
1396 | /* Set to print whether the option is enabled or disabled, |
1397 | or, if it's an alias for another option, the name of | |
1398 | the aliased option. */ | |
1399 | bool print_state = false; | |
1400 | ||
21bf1558 JM |
1401 | if (flag_var != NULL |
1402 | && option->var_type != CLVC_DEFER) | |
c662432e | 1403 | { |
fa5baeed MS |
1404 | /* If OPTION is only available for a specific subset |
1405 | of languages other than this one, mention them. */ | |
1406 | bool avail_for_lang = true; | |
1407 | if (unsigned langset = option->flags & CL_LANG_ALL) | |
1408 | { | |
1409 | if (!(langset & lang_mask)) | |
1410 | { | |
1411 | avail_for_lang = false; | |
1412 | strcat (new_help, _("[available in ")); | |
1413 | for (unsigned i = 0, n = 0; (1U << i) < CL_LANG_ALL; ++i) | |
1414 | if (langset & (1U << i)) | |
1415 | { | |
1416 | if (n++) | |
1417 | strcat (new_help, ", "); | |
1418 | strcat (new_help, lang_names[i]); | |
1419 | } | |
1420 | strcat (new_help, "]"); | |
1421 | } | |
1422 | } | |
1423 | if (!avail_for_lang) | |
1424 | ; /* Print nothing else if the option is not available | |
1425 | in the current language. */ | |
1426 | else if (option->flags & CL_JOINED) | |
c662432e NC |
1427 | { |
1428 | if (option->var_type == CLVC_STRING) | |
1429 | { | |
46625112 | 1430 | if (* (const char **) flag_var != NULL) |
c662432e NC |
1431 | snprintf (new_help + strlen (new_help), |
1432 | sizeof (new_help) - strlen (new_help), | |
81018dcf | 1433 | "%s", * (const char **) flag_var); |
c662432e | 1434 | } |
e6d4b984 JM |
1435 | else if (option->var_type == CLVC_ENUM) |
1436 | { | |
1437 | const struct cl_enum *e = &cl_enums[option->var_enum]; | |
1438 | int value; | |
1439 | const char *arg = NULL; | |
1440 | ||
1441 | value = e->get (flag_var); | |
1442 | enum_value_to_arg (e->values, &arg, value, lang_mask); | |
1443 | if (arg == NULL) | |
1444 | arg = _("[default]"); | |
1445 | snprintf (new_help + strlen (new_help), | |
1446 | sizeof (new_help) - strlen (new_help), | |
81018dcf | 1447 | "%s", arg); |
e6d4b984 | 1448 | } |
c662432e | 1449 | else |
fa5baeed MS |
1450 | { |
1451 | if (option->cl_host_wide_int) | |
1452 | sprintf (new_help + strlen (new_help), | |
1453 | _("%llu bytes"), (unsigned long long) | |
1454 | *(unsigned HOST_WIDE_INT *) flag_var); | |
1455 | else | |
1456 | sprintf (new_help + strlen (new_help), | |
1457 | "%i", * (int *) flag_var); | |
1458 | } | |
1459 | } | |
1460 | else | |
1461 | print_state = true; | |
1462 | } | |
1463 | else | |
1464 | /* When there is no argument, print the option state only | |
1465 | if the option takes no argument. */ | |
1466 | print_state = !(option->flags & CL_JOINED); | |
1467 | ||
1468 | if (print_state) | |
1469 | { | |
1470 | if (option->alias_target < N_OPTS | |
68a57628 | 1471 | && option->alias_target != OPT_SPECIAL_warn_removed |
fa5baeed MS |
1472 | && option->alias_target != OPT_SPECIAL_ignore |
1473 | && option->alias_target != OPT_SPECIAL_input_file | |
1474 | && option->alias_target != OPT_SPECIAL_program_name | |
1475 | && option->alias_target != OPT_SPECIAL_unknown) | |
1476 | { | |
1477 | const struct cl_option *target | |
1478 | = &cl_options[option->alias_target]; | |
1479 | sprintf (new_help + strlen (new_help), "%s%s", | |
1480 | target->opt_text, | |
1481 | option->alias_arg ? option->alias_arg : ""); | |
c662432e | 1482 | } |
fa5baeed MS |
1483 | else if (option->alias_target == OPT_SPECIAL_ignore) |
1484 | strcat (new_help, ("[ignored]")); | |
c662432e | 1485 | else |
fa5baeed MS |
1486 | { |
1487 | /* Print the state for an on/off option. */ | |
1488 | int ena = option_enabled (i, lang_mask, opts); | |
1489 | if (ena > 0) | |
1490 | strcat (new_help, _("[enabled]")); | |
1491 | else if (ena == 0) | |
1492 | strcat (new_help, _("[disabled]")); | |
1493 | } | |
c662432e NC |
1494 | } |
1495 | ||
1496 | help = new_help; | |
1497 | } | |
1498 | ||
63010089 ML |
1499 | if (option->range_max != -1) |
1500 | { | |
1501 | char b[128]; | |
1502 | snprintf (b, sizeof (b), "<%d,%d>", option->range_min, | |
1503 | option->range_max); | |
1504 | opt = concat (opt, b, NULL); | |
1505 | len += strlen (b); | |
1506 | } | |
1507 | ||
c662432e NC |
1508 | wrap_help (help, opt, len, columns); |
1509 | displayed = true; | |
e6d4b984 JM |
1510 | |
1511 | if (option->var_type == CLVC_ENUM | |
1512 | && opts->x_help_enum_printed[option->var_enum] != 2) | |
1513 | opts->x_help_enum_printed[option->var_enum] = 1; | |
c98c2430 ML |
1514 | else |
1515 | { | |
1516 | vec<const char *> option_values | |
1517 | = targetm_common.get_valid_option_values (i, NULL); | |
1518 | if (!option_values.is_empty ()) | |
1519 | help_tuples.safe_push (option_help_tuple (i, option_values)); | |
1520 | } | |
c662432e NC |
1521 | } |
1522 | ||
1523 | if (! found) | |
b3eaaf1a NC |
1524 | { |
1525 | unsigned int langs = include_flags & CL_LANG_ALL; | |
1526 | ||
1527 | if (langs == 0) | |
1528 | printf (_(" No options with the desired characteristics were found\n")); | |
1529 | else | |
1530 | { | |
1531 | unsigned int i; | |
1532 | ||
1533 | /* PR 31349: Tell the user how to see all of the | |
1534 | options supported by a specific front end. */ | |
1535 | for (i = 0; (1U << i) < CL_LANG_ALL; i ++) | |
1536 | if ((1U << i) & langs) | |
a7b2e184 | 1537 | printf (_(" None found. Use --help=%s to show *all* the options supported by the %s front-end.\n"), |
b3eaaf1a NC |
1538 | lang_names[i], lang_names[i]); |
1539 | } | |
b8698a0f | 1540 | |
b3eaaf1a | 1541 | } |
c662432e NC |
1542 | else if (! displayed) |
1543 | printf (_(" All options with the desired characteristics have already been displayed\n")); | |
1544 | ||
1545 | putchar ('\n'); | |
e6d4b984 JM |
1546 | |
1547 | /* Print details of enumerated option arguments, if those | |
1548 | enumerations have help text headings provided. If no help text | |
1549 | is provided, presume that the possible values are listed in the | |
1550 | help text for the relevant options. */ | |
1551 | for (i = 0; i < cl_enums_count; i++) | |
1552 | { | |
1553 | unsigned int j, pos; | |
1554 | ||
1555 | if (opts->x_help_enum_printed[i] != 1) | |
1556 | continue; | |
1557 | if (cl_enums[i].help == NULL) | |
1558 | continue; | |
1559 | printf (" %s\n ", _(cl_enums[i].help)); | |
1560 | pos = 4; | |
1561 | for (j = 0; cl_enums[i].values[j].arg != NULL; j++) | |
1562 | { | |
1563 | unsigned int len = strlen (cl_enums[i].values[j].arg); | |
1564 | ||
1565 | if (pos > 4 && pos + 1 + len <= columns) | |
1566 | { | |
1567 | printf (" %s", cl_enums[i].values[j].arg); | |
1568 | pos += 1 + len; | |
1569 | } | |
1570 | else | |
1571 | { | |
1572 | if (pos > 4) | |
1573 | { | |
1574 | printf ("\n "); | |
1575 | pos = 4; | |
1576 | } | |
1577 | printf ("%s", cl_enums[i].values[j].arg); | |
1578 | pos += len; | |
1579 | } | |
1580 | } | |
1581 | printf ("\n\n"); | |
1582 | opts->x_help_enum_printed[i] = 2; | |
1583 | } | |
c98c2430 ML |
1584 | |
1585 | for (unsigned i = 0; i < help_tuples.length (); i++) | |
1586 | { | |
1587 | const struct cl_option *option = cl_options + help_tuples[i].m_code; | |
3f58b66d ML |
1588 | printf (_(" Known valid arguments for %s option:\n "), |
1589 | option->opt_text); | |
c98c2430 ML |
1590 | for (unsigned j = 0; j < help_tuples[i].m_values.length (); j++) |
1591 | printf (" %s", help_tuples[i].m_values[j]); | |
1592 | printf ("\n\n"); | |
1593 | } | |
c662432e NC |
1594 | } |
1595 | ||
1596 | /* Display help for a specified type of option. | |
1597 | The options must have ALL of the INCLUDE_FLAGS set | |
1598 | ANY of the flags in the ANY_FLAGS set | |
0576d21f | 1599 | and NONE of the EXCLUDE_FLAGS set. The current option state is in |
e6d4b984 | 1600 | OPTS; LANG_MASK is used for interpreting enumerated option state. */ |
c662432e NC |
1601 | static void |
1602 | print_specific_help (unsigned int include_flags, | |
1603 | unsigned int exclude_flags, | |
0576d21f | 1604 | unsigned int any_flags, |
e6d4b984 JM |
1605 | struct gcc_options *opts, |
1606 | unsigned int lang_mask) | |
c662432e NC |
1607 | { |
1608 | unsigned int all_langs_mask = (1U << cl_lang_count) - 1; | |
1609 | const char * description = NULL; | |
1610 | const char * descrip_extra = ""; | |
1611 | size_t i; | |
1612 | unsigned int flag; | |
c662432e NC |
1613 | |
1614 | /* Sanity check: Make sure that we do not have more | |
1615 | languages than we have bits available to enumerate them. */ | |
58265ea6 | 1616 | gcc_assert ((1U << cl_lang_count) <= CL_MIN_OPTION_CLASS); |
c662432e NC |
1617 | |
1618 | /* If we have not done so already, obtain | |
1619 | the desired maximum width of the output. */ | |
299404a1 | 1620 | if (opts->x_help_columns == 0) |
c662432e | 1621 | { |
c9db45aa TB |
1622 | opts->x_help_columns = get_terminal_width (); |
1623 | if (opts->x_help_columns == INT_MAX) | |
c662432e | 1624 | /* Use a reasonable default. */ |
299404a1 | 1625 | opts->x_help_columns = 80; |
c662432e NC |
1626 | } |
1627 | ||
1628 | /* Decide upon the title for the options that we are going to display. */ | |
1629 | for (i = 0, flag = 1; flag <= CL_MAX_OPTION_CLASS; flag <<= 1, i ++) | |
1630 | { | |
1631 | switch (flag & include_flags) | |
1632 | { | |
1633 | case 0: | |
603349bf | 1634 | case CL_DRIVER: |
c662432e NC |
1635 | break; |
1636 | ||
1637 | case CL_TARGET: | |
1638 | description = _("The following options are target specific"); | |
1639 | break; | |
1640 | case CL_WARNING: | |
1641 | description = _("The following options control compiler warning messages"); | |
1642 | break; | |
1643 | case CL_OPTIMIZATION: | |
1644 | description = _("The following options control optimizations"); | |
1645 | break; | |
1646 | case CL_COMMON: | |
1647 | description = _("The following options are language-independent"); | |
1648 | break; | |
1649 | case CL_PARAMS: | |
76c26af9 | 1650 | description = _("The following options control parameters"); |
c662432e NC |
1651 | break; |
1652 | default: | |
1653 | if (i >= cl_lang_count) | |
1654 | break; | |
0631b69f | 1655 | if (exclude_flags & all_langs_mask) |
c01c261d | 1656 | description = _("The following options are specific to just the language "); |
c662432e | 1657 | else |
b5456e04 | 1658 | description = _("The following options are supported by the language "); |
b3eaaf1a | 1659 | descrip_extra = lang_names [i]; |
c662432e NC |
1660 | break; |
1661 | } | |
1662 | } | |
1663 | ||
1664 | if (description == NULL) | |
1665 | { | |
1666 | if (any_flags == 0) | |
1667 | { | |
0631b69f | 1668 | if (include_flags & CL_UNDOCUMENTED) |
c662432e | 1669 | description = _("The following options are not documented"); |
0631b69f RW |
1670 | else if (include_flags & CL_SEPARATE) |
1671 | description = _("The following options take separate arguments"); | |
1672 | else if (include_flags & CL_JOINED) | |
1673 | description = _("The following options take joined arguments"); | |
c662432e NC |
1674 | else |
1675 | { | |
a9c697b8 MS |
1676 | internal_error ("unrecognized %<include_flags 0x%x%> passed " |
1677 | "to %<print_specific_help%>", | |
c662432e NC |
1678 | include_flags); |
1679 | return; | |
1680 | } | |
1681 | } | |
1682 | else | |
1683 | { | |
1684 | if (any_flags & all_langs_mask) | |
1685 | description = _("The following options are language-related"); | |
1686 | else | |
1687 | description = _("The following options are language-independent"); | |
1688 | } | |
1689 | } | |
1690 | ||
1691 | printf ("%s%s:\n", description, descrip_extra); | |
299404a1 | 1692 | print_filtered_help (include_flags, exclude_flags, any_flags, |
e6d4b984 | 1693 | opts->x_help_columns, opts, lang_mask); |
c662432e NC |
1694 | } |
1695 | ||
be3c16c4 DC |
1696 | /* Enable FDO-related flags. */ |
1697 | ||
1698 | static void | |
1699 | enable_fdo_optimizations (struct gcc_options *opts, | |
1700 | struct gcc_options *opts_set, | |
1701 | int value) | |
1702 | { | |
6ed76044 ML |
1703 | SET_OPTION_IF_UNSET (opts, opts_set, flag_branch_probabilities, value); |
1704 | SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value); | |
1705 | SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_loops, value); | |
1706 | SET_OPTION_IF_UNSET (opts, opts_set, flag_peel_loops, value); | |
1707 | SET_OPTION_IF_UNSET (opts, opts_set, flag_tracer, value); | |
1708 | SET_OPTION_IF_UNSET (opts, opts_set, flag_value_profile_transformations, | |
1709 | value); | |
1710 | SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value); | |
1711 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp, value); | |
1712 | if (value) | |
1713 | { | |
1714 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp_clone, 1); | |
1715 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, 1); | |
1716 | } | |
1717 | SET_OPTION_IF_UNSET (opts, opts_set, flag_predictive_commoning, value); | |
1718 | SET_OPTION_IF_UNSET (opts, opts_set, flag_split_loops, value); | |
1719 | SET_OPTION_IF_UNSET (opts, opts_set, flag_unswitch_loops, value); | |
1720 | SET_OPTION_IF_UNSET (opts, opts_set, flag_gcse_after_reload, value); | |
1721 | SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_vectorize, value); | |
1722 | SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_slp_vectorize, value); | |
1723 | SET_OPTION_IF_UNSET (opts, opts_set, flag_version_loops_for_strides, value); | |
1724 | SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model, | |
1725 | VECT_COST_MODEL_DYNAMIC); | |
1726 | SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribute_patterns, | |
1727 | value); | |
1728 | SET_OPTION_IF_UNSET (opts, opts_set, flag_loop_interchange, value); | |
1729 | SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_jam, value); | |
1730 | SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value); | |
be3c16c4 DC |
1731 | } |
1732 | ||
b1b46af0 | 1733 | /* -f{,no-}sanitize{,-recover}= suboptions. */ |
61789eed | 1734 | const struct sanitizer_opts_s sanitizer_opts[] = |
b1b46af0 | 1735 | { |
5cc6c41c ML |
1736 | #define SANITIZER_OPT(name, flags, recover) \ |
1737 | { #name, flags, sizeof #name - 1, recover } | |
6dc4a604 ML |
1738 | SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true), |
1739 | SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS), | |
5cc6c41c | 1740 | true), |
05abad4c ML |
1741 | SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true), |
1742 | SANITIZER_OPT (pointer-subtract, SANITIZE_POINTER_SUBTRACT, true), | |
5cc6c41c ML |
1743 | SANITIZER_OPT (thread, SANITIZE_THREAD, false), |
1744 | SANITIZER_OPT (leak, SANITIZE_LEAK, false), | |
1745 | SANITIZER_OPT (shift, SANITIZE_SHIFT, true), | |
2e955d50 JJ |
1746 | SANITIZER_OPT (shift-base, SANITIZE_SHIFT_BASE, true), |
1747 | SANITIZER_OPT (shift-exponent, SANITIZE_SHIFT_EXPONENT, true), | |
5cc6c41c ML |
1748 | SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true), |
1749 | SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true), | |
1750 | SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false), | |
1751 | SANITIZER_OPT (vla-bound, SANITIZE_VLA, true), | |
1752 | SANITIZER_OPT (return, SANITIZE_RETURN, false), | |
1753 | SANITIZER_OPT (null, SANITIZE_NULL, true), | |
1754 | SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true), | |
1755 | SANITIZER_OPT (bool, SANITIZE_BOOL, true), | |
1756 | SANITIZER_OPT (enum, SANITIZE_ENUM, true), | |
1757 | SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true), | |
1758 | SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true), | |
1759 | SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true), | |
1760 | SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true), | |
1761 | SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true), | |
1762 | SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true), | |
1763 | SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE, | |
1764 | true), | |
1765 | SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true), | |
1766 | SANITIZER_OPT (vptr, SANITIZE_VPTR, true), | |
c9b39a49 | 1767 | SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true), |
07d7c611 | 1768 | SANITIZER_OPT (builtin, SANITIZE_BUILTIN, true), |
5cc6c41c | 1769 | SANITIZER_OPT (all, ~0U, true), |
b1b46af0 | 1770 | #undef SANITIZER_OPT |
5cc6c41c | 1771 | { NULL, 0U, 0UL, false } |
b1b46af0 JJ |
1772 | }; |
1773 | ||
f6e50a7d WW |
1774 | /* -f{,no-}sanitize-coverage= suboptions. */ |
1775 | const struct sanitizer_opts_s coverage_sanitizer_opts[] = | |
1776 | { | |
1777 | #define COVERAGE_SANITIZER_OPT(name, flags) \ | |
1778 | { #name, flags, sizeof #name - 1, true } | |
1779 | COVERAGE_SANITIZER_OPT (trace-pc, SANITIZE_COV_TRACE_PC), | |
1780 | COVERAGE_SANITIZER_OPT (trace-cmp, SANITIZE_COV_TRACE_CMP), | |
1781 | #undef COVERAGE_SANITIZER_OPT | |
1782 | { NULL, 0U, 0UL, false } | |
1783 | }; | |
1784 | ||
19ff0049 DM |
1785 | /* A struct for describing a run of chars within a string. */ |
1786 | ||
6c1dae73 | 1787 | class string_fragment |
19ff0049 | 1788 | { |
6c1dae73 | 1789 | public: |
19ff0049 DM |
1790 | string_fragment (const char *start, size_t len) |
1791 | : m_start (start), m_len (len) {} | |
1792 | ||
1793 | const char *m_start; | |
1794 | size_t m_len; | |
1795 | }; | |
1796 | ||
1797 | /* Specialization of edit_distance_traits for string_fragment, | |
1798 | for use by get_closest_sanitizer_option. */ | |
1799 | ||
1800 | template <> | |
1801 | struct edit_distance_traits<const string_fragment &> | |
1802 | { | |
1803 | static size_t get_length (const string_fragment &fragment) | |
1804 | { | |
1805 | return fragment.m_len; | |
1806 | } | |
1807 | ||
1808 | static const char *get_string (const string_fragment &fragment) | |
1809 | { | |
1810 | return fragment.m_start; | |
1811 | } | |
1812 | }; | |
1813 | ||
1814 | /* Given ARG, an unrecognized sanitizer option, return the best | |
1815 | matching sanitizer option, or NULL if there isn't one. | |
f6e50a7d WW |
1816 | OPTS is array of candidate sanitizer options. |
1817 | CODE is OPT_fsanitize_, OPT_fsanitize_recover_ or | |
1818 | OPT_fsanitize_coverage_. | |
19ff0049 DM |
1819 | VALUE is non-zero for the regular form of the option, zero |
1820 | for the "no-" form (e.g. "-fno-sanitize-recover="). */ | |
1821 | ||
1822 | static const char * | |
1823 | get_closest_sanitizer_option (const string_fragment &arg, | |
f6e50a7d | 1824 | const struct sanitizer_opts_s *opts, |
19ff0049 DM |
1825 | enum opt_code code, int value) |
1826 | { | |
1827 | best_match <const string_fragment &, const char*> bm (arg); | |
f6e50a7d | 1828 | for (int i = 0; opts[i].name != NULL; ++i) |
19ff0049 DM |
1829 | { |
1830 | /* -fsanitize=all is not valid, so don't offer it. */ | |
f6e50a7d WW |
1831 | if (code == OPT_fsanitize_ |
1832 | && opts[i].flag == ~0U | |
19ff0049 DM |
1833 | && value) |
1834 | continue; | |
1835 | ||
1836 | /* For -fsanitize-recover= (and not -fno-sanitize-recover=), | |
1837 | don't offer the non-recoverable options. */ | |
f6e50a7d WW |
1838 | if (code == OPT_fsanitize_recover_ |
1839 | && !opts[i].can_recover | |
19ff0049 DM |
1840 | && value) |
1841 | continue; | |
1842 | ||
f6e50a7d | 1843 | bm.consider (opts[i].name); |
19ff0049 DM |
1844 | } |
1845 | return bm.get_best_meaningful_candidate (); | |
1846 | } | |
1847 | ||
b1b46af0 JJ |
1848 | /* Parse comma separated sanitizer suboptions from P for option SCODE, |
1849 | adjust previous FLAGS and return new ones. If COMPLAIN is false, | |
1850 | don't issue diagnostics. */ | |
1851 | ||
1852 | unsigned int | |
1853 | parse_sanitizer_options (const char *p, location_t loc, int scode, | |
1854 | unsigned int flags, int value, bool complain) | |
1855 | { | |
1856 | enum opt_code code = (enum opt_code) scode; | |
f6e50a7d WW |
1857 | |
1858 | const struct sanitizer_opts_s *opts; | |
1859 | if (code == OPT_fsanitize_coverage_) | |
1860 | opts = coverage_sanitizer_opts; | |
1861 | else | |
1862 | opts = sanitizer_opts; | |
1863 | ||
b1b46af0 JJ |
1864 | while (*p != 0) |
1865 | { | |
1866 | size_t len, i; | |
1867 | bool found = false; | |
1868 | const char *comma = strchr (p, ','); | |
1869 | ||
1870 | if (comma == NULL) | |
1871 | len = strlen (p); | |
1872 | else | |
1873 | len = comma - p; | |
1874 | if (len == 0) | |
1875 | { | |
1876 | p = comma + 1; | |
1877 | continue; | |
1878 | } | |
1879 | ||
1880 | /* Check to see if the string matches an option class name. */ | |
f6e50a7d WW |
1881 | for (i = 0; opts[i].name != NULL; ++i) |
1882 | if (len == opts[i].len && memcmp (p, opts[i].name, len) == 0) | |
b1b46af0 JJ |
1883 | { |
1884 | /* Handle both -fsanitize and -fno-sanitize cases. */ | |
f6e50a7d | 1885 | if (value && opts[i].flag == ~0U) |
b1b46af0 JJ |
1886 | { |
1887 | if (code == OPT_fsanitize_) | |
1888 | { | |
1889 | if (complain) | |
6d28654e | 1890 | error_at (loc, "%<-fsanitize=all%> option is not valid"); |
b1b46af0 JJ |
1891 | } |
1892 | else | |
5cc6c41c ML |
1893 | flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK |
1894 | | SANITIZE_UNREACHABLE | SANITIZE_RETURN); | |
b1b46af0 JJ |
1895 | } |
1896 | else if (value) | |
5cc6c41c ML |
1897 | { |
1898 | /* Do not enable -fsanitize-recover=unreachable and | |
1899 | -fsanitize-recover=return if -fsanitize-recover=undefined | |
1900 | is selected. */ | |
c944c6a2 | 1901 | if (code == OPT_fsanitize_recover_ |
f6e50a7d | 1902 | && opts[i].flag == SANITIZE_UNDEFINED) |
5cc6c41c ML |
1903 | flags |= (SANITIZE_UNDEFINED |
1904 | & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)); | |
1905 | else | |
f6e50a7d | 1906 | flags |= opts[i].flag; |
5cc6c41c | 1907 | } |
b1b46af0 | 1908 | else |
f6e50a7d | 1909 | flags &= ~opts[i].flag; |
b1b46af0 JJ |
1910 | found = true; |
1911 | break; | |
1912 | } | |
1913 | ||
1914 | if (! found && complain) | |
19ff0049 DM |
1915 | { |
1916 | const char *hint | |
1917 | = get_closest_sanitizer_option (string_fragment (p, len), | |
f6e50a7d WW |
1918 | opts, code, value); |
1919 | ||
1920 | const char *suffix; | |
1921 | if (code == OPT_fsanitize_recover_) | |
1922 | suffix = "-recover"; | |
1923 | else if (code == OPT_fsanitize_coverage_) | |
1924 | suffix = "-coverage"; | |
1925 | else | |
1926 | suffix = ""; | |
19ff0049 DM |
1927 | |
1928 | if (hint) | |
1929 | error_at (loc, | |
a3f9f006 ML |
1930 | "unrecognized argument to %<-f%ssanitize%s=%> " |
1931 | "option: %q.*s; did you mean %qs?", | |
19ff0049 | 1932 | value ? "" : "no-", |
f6e50a7d | 1933 | suffix, (int) len, p, hint); |
19ff0049 DM |
1934 | else |
1935 | error_at (loc, | |
a3f9f006 ML |
1936 | "unrecognized argument to %<-f%ssanitize%s=%> option: " |
1937 | "%q.*s", value ? "" : "no-", | |
f6e50a7d | 1938 | suffix, (int) len, p); |
19ff0049 | 1939 | } |
b1b46af0 JJ |
1940 | |
1941 | if (comma == NULL) | |
1942 | break; | |
1943 | p = comma + 1; | |
1944 | } | |
1945 | return flags; | |
1946 | } | |
1947 | ||
45b2222a | 1948 | /* Parse string values of no_sanitize attribute passed in VALUE. |
3a266bcd | 1949 | Values are separated with comma. */ |
45b2222a ML |
1950 | |
1951 | unsigned int | |
3a266bcd | 1952 | parse_no_sanitize_attribute (char *value) |
45b2222a ML |
1953 | { |
1954 | unsigned int flags = 0; | |
1955 | unsigned int i; | |
1956 | char *q = strtok (value, ","); | |
1957 | ||
1958 | while (q != NULL) | |
1959 | { | |
1960 | for (i = 0; sanitizer_opts[i].name != NULL; ++i) | |
1961 | if (strcmp (sanitizer_opts[i].name, q) == 0) | |
1962 | { | |
1963 | flags |= sanitizer_opts[i].flag; | |
1964 | if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED) | |
1965 | flags |= SANITIZE_UNDEFINED_NONDEFAULT; | |
1966 | break; | |
1967 | } | |
1968 | ||
1969 | if (sanitizer_opts[i].name == NULL) | |
3a266bcd | 1970 | warning (OPT_Wattributes, |
a9c697b8 | 1971 | "%qs attribute directive ignored", q); |
45b2222a ML |
1972 | |
1973 | q = strtok (NULL, ","); | |
1974 | } | |
1975 | ||
1976 | return flags; | |
1977 | } | |
1978 | ||
c518c102 ML |
1979 | /* Parse -falign-NAME format for a FLAG value. Return individual |
1980 | parsed integer values into RESULT_VALUES array. If REPORT_ERROR is | |
1981 | set, print error message at LOC location. */ | |
1982 | ||
1983 | bool | |
1984 | parse_and_check_align_values (const char *flag, | |
1985 | const char *name, | |
1986 | auto_vec<unsigned> &result_values, | |
1987 | bool report_error, | |
1988 | location_t loc) | |
1989 | { | |
1990 | char *str = xstrdup (flag); | |
1991 | for (char *p = strtok (str, ":"); p; p = strtok (NULL, ":")) | |
1992 | { | |
1993 | char *end; | |
1994 | int v = strtol (p, &end, 10); | |
1995 | if (*end != '\0' || v < 0) | |
1996 | { | |
1997 | if (report_error) | |
1998 | error_at (loc, "invalid arguments for %<-falign-%s%> option: %qs", | |
1999 | name, flag); | |
2000 | ||
2001 | return false; | |
2002 | } | |
2003 | ||
2004 | result_values.safe_push ((unsigned)v); | |
2005 | } | |
2006 | ||
2007 | free (str); | |
2008 | ||
2009 | /* Check that we have a correct number of values. */ | |
49f3f450 | 2010 | if (result_values.is_empty () || result_values.length () > 4) |
c518c102 ML |
2011 | { |
2012 | if (report_error) | |
2013 | error_at (loc, "invalid number of arguments for %<-falign-%s%> " | |
2014 | "option: %qs", name, flag); | |
2015 | return false; | |
2016 | } | |
2017 | ||
c518c102 ML |
2018 | for (unsigned i = 0; i < result_values.length (); i++) |
2019 | if (result_values[i] > MAX_CODE_ALIGN_VALUE) | |
2020 | { | |
2021 | if (report_error) | |
2022 | error_at (loc, "%<-falign-%s%> is not between 0 and %d", | |
2023 | name, MAX_CODE_ALIGN_VALUE); | |
2024 | return false; | |
2025 | } | |
2026 | ||
2027 | return true; | |
2028 | } | |
2029 | ||
2030 | /* Check that alignment value FLAG for -falign-NAME is valid at a given | |
2031 | location LOC. */ | |
2032 | ||
2033 | static void | |
2034 | check_alignment_argument (location_t loc, const char *flag, const char *name) | |
2035 | { | |
2036 | auto_vec<unsigned> align_result; | |
2037 | parse_and_check_align_values (flag, name, align_result, true, loc); | |
2038 | } | |
2039 | ||
2dcfc872 ML |
2040 | /* Print help when OPT__help_ is set. */ |
2041 | ||
f66409e0 | 2042 | void |
bc405869 ML |
2043 | print_help (struct gcc_options *opts, unsigned int lang_mask, |
2044 | const char *help_option_argument) | |
2dcfc872 ML |
2045 | { |
2046 | const char *a = help_option_argument; | |
2047 | unsigned int include_flags = 0; | |
2048 | /* Note - by default we include undocumented options when listing | |
2049 | specific classes. If you only want to see documented options | |
2050 | then add ",^undocumented" to the --help= option. E.g.: | |
2051 | ||
2052 | --help=target,^undocumented */ | |
2053 | unsigned int exclude_flags = 0; | |
2054 | ||
2055 | if (lang_mask == CL_DRIVER) | |
2056 | return; | |
2057 | ||
2058 | /* Walk along the argument string, parsing each word in turn. | |
2059 | The format is: | |
2060 | arg = [^]{word}[,{arg}] | |
2061 | word = {optimizers|target|warnings|undocumented| | |
2062 | params|common|<language>} */ | |
2063 | while (*a != 0) | |
2064 | { | |
2065 | static const struct | |
2066 | { | |
2067 | const char *string; | |
2068 | unsigned int flag; | |
2069 | } | |
2070 | specifics[] = | |
2071 | { | |
2072 | { "optimizers", CL_OPTIMIZATION }, | |
2073 | { "target", CL_TARGET }, | |
2074 | { "warnings", CL_WARNING }, | |
2075 | { "undocumented", CL_UNDOCUMENTED }, | |
2076 | { "params", CL_PARAMS }, | |
2077 | { "joined", CL_JOINED }, | |
2078 | { "separate", CL_SEPARATE }, | |
2079 | { "common", CL_COMMON }, | |
2080 | { NULL, 0 } | |
2081 | }; | |
2082 | unsigned int *pflags; | |
2083 | const char *comma; | |
2084 | unsigned int lang_flag, specific_flag; | |
2085 | unsigned int len; | |
2086 | unsigned int i; | |
2087 | ||
2088 | if (*a == '^') | |
2089 | { | |
2090 | ++a; | |
2091 | if (*a == '\0') | |
2092 | { | |
2093 | error ("missing argument to %qs", "--help=^"); | |
2094 | break; | |
2095 | } | |
2096 | pflags = &exclude_flags; | |
2097 | } | |
2098 | else | |
2099 | pflags = &include_flags; | |
2100 | ||
2101 | comma = strchr (a, ','); | |
2102 | if (comma == NULL) | |
2103 | len = strlen (a); | |
2104 | else | |
2105 | len = comma - a; | |
2106 | if (len == 0) | |
2107 | { | |
2108 | a = comma + 1; | |
2109 | continue; | |
2110 | } | |
2111 | ||
2112 | /* Check to see if the string matches an option class name. */ | |
2113 | for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++) | |
2114 | if (strncasecmp (a, specifics[i].string, len) == 0) | |
2115 | { | |
2116 | specific_flag = specifics[i].flag; | |
2117 | break; | |
2118 | } | |
2119 | ||
2120 | /* Check to see if the string matches a language name. | |
2121 | Note - we rely upon the alpha-sorted nature of the entries in | |
2122 | the lang_names array, specifically that shorter names appear | |
2123 | before their longer variants. (i.e. C before C++). That way | |
2124 | when we are attempting to match --help=c for example we will | |
2125 | match with C first and not C++. */ | |
2126 | for (i = 0, lang_flag = 0; i < cl_lang_count; i++) | |
2127 | if (strncasecmp (a, lang_names[i], len) == 0) | |
2128 | { | |
2129 | lang_flag = 1U << i; | |
2130 | break; | |
2131 | } | |
2132 | ||
2133 | if (specific_flag != 0) | |
2134 | { | |
2135 | if (lang_flag == 0) | |
2136 | *pflags |= specific_flag; | |
2137 | else | |
2138 | { | |
2139 | /* The option's argument matches both the start of a | |
2140 | language name and the start of an option class name. | |
2141 | We have a special case for when the user has | |
2142 | specified "--help=c", but otherwise we have to issue | |
2143 | a warning. */ | |
2144 | if (strncasecmp (a, "c", len) == 0) | |
2145 | *pflags |= lang_flag; | |
2146 | else | |
2147 | warning (0, | |
a9c697b8 | 2148 | "%<--help%> argument %q.*s is ambiguous, " |
2dcfc872 ML |
2149 | "please be more specific", |
2150 | len, a); | |
2151 | } | |
2152 | } | |
2153 | else if (lang_flag != 0) | |
2154 | *pflags |= lang_flag; | |
2155 | else | |
2156 | warning (0, | |
a9c697b8 | 2157 | "unrecognized argument to %<--help=%> option: %q.*s", |
2dcfc872 ML |
2158 | len, a); |
2159 | ||
2160 | if (comma == NULL) | |
2161 | break; | |
2162 | a = comma + 1; | |
2163 | } | |
2164 | ||
5ab08934 ML |
2165 | /* We started using PerFunction/Optimization for parameters and |
2166 | a warning. We should exclude these from optimization options. */ | |
2167 | if (include_flags & CL_OPTIMIZATION) | |
10fe5cbe ML |
2168 | exclude_flags |= CL_WARNING; |
2169 | if (!(include_flags & CL_PARAMS)) | |
2170 | exclude_flags |= CL_PARAMS; | |
5ab08934 | 2171 | |
2dcfc872 ML |
2172 | if (include_flags) |
2173 | print_specific_help (include_flags, exclude_flags, 0, opts, | |
2174 | lang_mask); | |
2175 | } | |
2176 | ||
d7b42618 | 2177 | /* Handle target- and language-independent options. Return zero to |
50431bc4 ZD |
2178 | generate an "unknown option" message. Only options that need |
2179 | extra handling need to be listed here; if you simply want | |
481e1176 | 2180 | DECODED->value assigned to a variable, it happens automatically. */ |
50431bc4 | 2181 | |
c98cd5bf | 2182 | bool |
46625112 | 2183 | common_handle_option (struct gcc_options *opts, |
d4d24ba4 | 2184 | struct gcc_options *opts_set, |
46625112 | 2185 | const struct cl_decoded_option *decoded, |
5f20c657 | 2186 | unsigned int lang_mask, int kind ATTRIBUTE_UNUSED, |
a4d8c676 | 2187 | location_t loc, |
d5478783 | 2188 | const struct cl_option_handlers *handlers, |
130fcab0 ML |
2189 | diagnostic_context *dc, |
2190 | void (*target_option_override_hook) (void)) | |
d7b42618 | 2191 | { |
481e1176 JM |
2192 | size_t scode = decoded->opt_index; |
2193 | const char *arg = decoded->arg; | |
00abf86c | 2194 | HOST_WIDE_INT value = decoded->value; |
d7b42618 NB |
2195 | enum opt_code code = (enum opt_code) scode; |
2196 | ||
481e1176 JM |
2197 | gcc_assert (decoded->canonical_option_num_elements <= 2); |
2198 | ||
d7b42618 NB |
2199 | switch (code) |
2200 | { | |
c662432e NC |
2201 | case OPT__help: |
2202 | { | |
2203 | unsigned int all_langs_mask = (1U << cl_lang_count) - 1; | |
2204 | unsigned int undoc_mask; | |
2205 | unsigned int i; | |
2206 | ||
a7d0d30f | 2207 | if (lang_mask == CL_DRIVER) |
6f3d1a5e | 2208 | break; |
a7d0d30f | 2209 | |
d5478783 JM |
2210 | undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings) |
2211 | ? 0 | |
2212 | : CL_UNDOCUMENTED); | |
130fcab0 | 2213 | target_option_override_hook (); |
c662432e NC |
2214 | /* First display any single language specific options. */ |
2215 | for (i = 0; i < cl_lang_count; i++) | |
2216 | print_specific_help | |
e6d4b984 JM |
2217 | (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts, |
2218 | lang_mask); | |
c662432e | 2219 | /* Next display any multi language specific options. */ |
e6d4b984 | 2220 | print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask); |
c662432e NC |
2221 | /* Then display any remaining, non-language options. */ |
2222 | for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1) | |
603349bf | 2223 | if (i != CL_DRIVER) |
e6d4b984 | 2224 | print_specific_help (i, undoc_mask, 0, opts, lang_mask); |
0576d21f | 2225 | opts->x_exit_after_options = true; |
c662432e NC |
2226 | break; |
2227 | } | |
2228 | ||
d185d268 | 2229 | case OPT__target_help: |
a7d0d30f JM |
2230 | if (lang_mask == CL_DRIVER) |
2231 | break; | |
2232 | ||
130fcab0 | 2233 | target_option_override_hook (); |
e6d4b984 | 2234 | print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts, lang_mask); |
0576d21f | 2235 | opts->x_exit_after_options = true; |
d185d268 NB |
2236 | break; |
2237 | ||
c662432e NC |
2238 | case OPT__help_: |
2239 | { | |
bc405869 | 2240 | help_option_arguments.safe_push (arg); |
0576d21f | 2241 | opts->x_exit_after_options = true; |
c662432e NC |
2242 | break; |
2243 | } | |
2244 | ||
d185d268 | 2245 | case OPT__version: |
a7d0d30f JM |
2246 | if (lang_mask == CL_DRIVER) |
2247 | break; | |
2248 | ||
0576d21f | 2249 | opts->x_exit_after_options = true; |
d185d268 NB |
2250 | break; |
2251 | ||
d86c7648 ML |
2252 | case OPT__completion_: |
2253 | break; | |
2254 | ||
de5a5fa1 | 2255 | case OPT_fsanitize_: |
b1b46af0 JJ |
2256 | opts->x_flag_sanitize |
2257 | = parse_sanitizer_options (arg, loc, code, | |
2258 | opts->x_flag_sanitize, value, true); | |
de5a5fa1 | 2259 | |
b1b46af0 JJ |
2260 | /* Kernel ASan implies normal ASan but does not yet support |
2261 | all features. */ | |
2262 | if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) | |
2263 | { | |
028d4092 ML |
2264 | SET_OPTION_IF_UNSET (opts, opts_set, |
2265 | param_asan_instrumentation_with_call_threshold, | |
2266 | 0); | |
2267 | SET_OPTION_IF_UNSET (opts, opts_set, param_asan_globals, 0); | |
2268 | SET_OPTION_IF_UNSET (opts, opts_set, param_asan_stack, 0); | |
2269 | SET_OPTION_IF_UNSET (opts, opts_set, param_asan_protect_allocas, 0); | |
2270 | SET_OPTION_IF_UNSET (opts, opts_set, param_asan_use_after_return, 0); | |
b1b46af0 JJ |
2271 | } |
2272 | break; | |
fec4842d | 2273 | |
b1b46af0 JJ |
2274 | case OPT_fsanitize_recover_: |
2275 | opts->x_flag_sanitize_recover | |
2276 | = parse_sanitizer_options (arg, loc, code, | |
2277 | opts->x_flag_sanitize_recover, value, true); | |
2278 | break; | |
de5a5fa1 | 2279 | |
fd960af2 YG |
2280 | case OPT_fasan_shadow_offset_: |
2281 | /* Deferred. */ | |
2282 | break; | |
2283 | ||
6dc4a604 ML |
2284 | case OPT_fsanitize_address_use_after_scope: |
2285 | opts->x_flag_sanitize_address_use_after_scope = value; | |
2286 | break; | |
2287 | ||
d95a2703 JJ |
2288 | case OPT_fsanitize_recover: |
2289 | if (value) | |
2290 | opts->x_flag_sanitize_recover | |
45b2222a | 2291 | |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT) |
5cc6c41c | 2292 | & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN); |
d95a2703 JJ |
2293 | else |
2294 | opts->x_flag_sanitize_recover | |
45b2222a | 2295 | &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); |
d95a2703 JJ |
2296 | break; |
2297 | ||
f6e50a7d WW |
2298 | case OPT_fsanitize_coverage_: |
2299 | opts->x_flag_sanitize_coverage | |
2300 | = parse_sanitizer_options (arg, loc, code, | |
2301 | opts->x_flag_sanitize_coverage, value, true); | |
2302 | break; | |
2303 | ||
903caebf NB |
2304 | case OPT_O: |
2305 | case OPT_Os: | |
c3a02647 | 2306 | case OPT_Ofast: |
bf7a7185 | 2307 | case OPT_Og: |
903caebf NB |
2308 | /* Currently handled in a prescan. */ |
2309 | break; | |
2310 | ||
aee15221 RG |
2311 | case OPT_Werror: |
2312 | dc->warning_as_error_requested = value; | |
2313 | break; | |
2314 | ||
79cf5994 | 2315 | case OPT_Werror_: |
a7d0d30f JM |
2316 | if (lang_mask == CL_DRIVER) |
2317 | break; | |
2318 | ||
c5fa0890 JM |
2319 | enable_warning_as_error (arg, value, lang_mask, handlers, |
2320 | opts, opts_set, loc, dc); | |
79cf5994 DD |
2321 | break; |
2322 | ||
5f0f4a3b | 2323 | case OPT_Wfatal_errors: |
d5478783 | 2324 | dc->fatal_errors = value; |
5f0f4a3b JM |
2325 | break; |
2326 | ||
a11e0df4 | 2327 | case OPT_Wstack_usage_: |
a11e0df4 EB |
2328 | opts->x_flag_stack_usage_info = value != -1; |
2329 | break; | |
2330 | ||
e01cc6dc | 2331 | case OPT_Wstrict_aliasing: |
d5478783 | 2332 | set_Wstrict_aliasing (opts, value); |
e01cc6dc NB |
2333 | break; |
2334 | ||
6ac01510 | 2335 | case OPT_Wstrict_overflow: |
d5478783 JM |
2336 | opts->x_warn_strict_overflow = (value |
2337 | ? (int) WARN_STRICT_OVERFLOW_CONDITIONAL | |
2338 | : 0); | |
6ac01510 ILT |
2339 | break; |
2340 | ||
5f0f4a3b | 2341 | case OPT_Wsystem_headers: |
d5478783 | 2342 | dc->dc_warn_system_headers = value; |
903caebf NB |
2343 | break; |
2344 | ||
d185d268 | 2345 | case OPT_aux_info: |
d5478783 | 2346 | opts->x_flag_gen_aux_info = 1; |
d185d268 NB |
2347 | break; |
2348 | ||
2349 | case OPT_auxbase_strip: | |
2350 | { | |
2351 | char *tmp = xstrdup (arg); | |
2352 | strip_off_ending (tmp, strlen (tmp)); | |
2353 | if (tmp[0]) | |
d5478783 | 2354 | opts->x_aux_base_name = tmp; |
fc429b48 TB |
2355 | else |
2356 | free (tmp); | |
d185d268 NB |
2357 | } |
2358 | break; | |
2359 | ||
2360 | case OPT_d: | |
299404a1 | 2361 | decode_d_option (arg, opts, loc, dc); |
d185d268 NB |
2362 | break; |
2363 | ||
058de654 | 2364 | case OPT_fcall_used_: |
058de654 | 2365 | case OPT_fcall_saved_: |
21bf1558 | 2366 | /* Deferred. */ |
058de654 | 2367 | break; |
6fb5fa3c DB |
2368 | |
2369 | case OPT_fdbg_cnt_: | |
68d070ac ML |
2370 | /* Deferred. */ |
2371 | break; | |
2372 | ||
0a090f42 | 2373 | case OPT_fdbg_cnt_list: |
299404a1 | 2374 | /* Deferred. */ |
68d070ac | 2375 | opts->x_exit_after_options = true; |
0a090f42 | 2376 | break; |
058de654 | 2377 | |
c8aea42c | 2378 | case OPT_fdebug_prefix_map_: |
7365279f | 2379 | case OPT_ffile_prefix_map_: |
299404a1 | 2380 | /* Deferred. */ |
c8aea42c PB |
2381 | break; |
2382 | ||
3cf3da88 EB |
2383 | case OPT_fcallgraph_info: |
2384 | opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED; | |
2385 | break; | |
2386 | ||
2387 | case OPT_fcallgraph_info_: | |
2388 | { | |
2389 | char *my_arg, *p; | |
2390 | my_arg = xstrdup (arg); | |
2391 | p = strtok (my_arg, ","); | |
2392 | while (p) | |
2393 | { | |
2394 | if (strcmp (p, "su") == 0) | |
2395 | { | |
2396 | opts->x_flag_callgraph_info |= CALLGRAPH_INFO_STACK_USAGE; | |
2397 | opts->x_flag_stack_usage_info = true; | |
2398 | } | |
2399 | else if (strcmp (p, "da") == 0) | |
2400 | opts->x_flag_callgraph_info |= CALLGRAPH_INFO_DYNAMIC_ALLOC; | |
2401 | else | |
2402 | return 0; | |
2403 | p = strtok (NULL, ","); | |
2404 | } | |
2405 | free (my_arg); | |
2406 | } | |
2407 | break; | |
2408 | ||
de32c0cb | 2409 | case OPT_fdiagnostics_show_location_: |
e6d4b984 | 2410 | diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value; |
de32c0cb | 2411 | break; |
9fec0042 MLI |
2412 | |
2413 | case OPT_fdiagnostics_show_caret: | |
2414 | dc->show_caret = value; | |
2415 | break; | |
de32c0cb | 2416 | |
96e6ae57 DM |
2417 | case OPT_fdiagnostics_show_labels: |
2418 | dc->show_labels_p = value; | |
2419 | break; | |
2420 | ||
56b61d7f DM |
2421 | case OPT_fdiagnostics_show_line_numbers: |
2422 | dc->show_line_numbers_p = value; | |
2423 | break; | |
2424 | ||
4b84d650 | 2425 | case OPT_fdiagnostics_color_: |
97aa8bb6 | 2426 | diagnostic_color_init (dc, value); |
4b84d650 JJ |
2427 | break; |
2428 | ||
d2608235 DM |
2429 | case OPT_fdiagnostics_urls_: |
2430 | diagnostic_urls_init (dc, value); | |
2431 | break; | |
2432 | ||
478dd60d DM |
2433 | case OPT_fdiagnostics_format_: |
2434 | diagnostic_output_format_init (dc, | |
2435 | (enum diagnostics_output_format)value); | |
2436 | break; | |
2437 | ||
a93eac6a DM |
2438 | case OPT_fdiagnostics_parseable_fixits: |
2439 | dc->parseable_fixits_p = value; | |
2440 | break; | |
2441 | ||
6d4a35ca DM |
2442 | case OPT_fdiagnostics_show_cwe: |
2443 | dc->show_cwe = value; | |
2444 | break; | |
2445 | ||
4bc1899b DM |
2446 | case OPT_fdiagnostics_path_format_: |
2447 | dc->path_format = (enum diagnostic_path_format)value; | |
2448 | break; | |
2449 | ||
2450 | case OPT_fdiagnostics_show_path_depths: | |
2451 | dc->show_path_depths = value; | |
2452 | break; | |
2453 | ||
2098fe9e | 2454 | case OPT_fdiagnostics_show_option: |
d5478783 | 2455 | dc->show_option_requested = value; |
2098fe9e DD |
2456 | break; |
2457 | ||
0141ab44 DM |
2458 | case OPT_fdiagnostics_minimum_margin_width_: |
2459 | dc->min_margin_width = value; | |
2460 | break; | |
2461 | ||
6de9cd9a | 2462 | case OPT_fdump_: |
21bf1558 | 2463 | /* Deferred. */ |
6de9cd9a DN |
2464 | break; |
2465 | ||
058de654 | 2466 | case OPT_ffast_math: |
d5478783 | 2467 | set_fast_math_flags (opts, value); |
058de654 NB |
2468 | break; |
2469 | ||
a1a82611 | 2470 | case OPT_funsafe_math_optimizations: |
d5478783 | 2471 | set_unsafe_math_optimizations_flags (opts, value); |
a1a82611 RE |
2472 | break; |
2473 | ||
058de654 | 2474 | case OPT_ffixed_: |
21bf1558 | 2475 | /* Deferred. */ |
058de654 NB |
2476 | break; |
2477 | ||
d302c9d6 | 2478 | case OPT_finline_limit_: |
8cc5fcaf ML |
2479 | SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_single, |
2480 | value / 2); | |
2481 | SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto, | |
2482 | value / 2); | |
d302c9d6 NB |
2483 | break; |
2484 | ||
8d5a7d1f | 2485 | case OPT_finstrument_functions_exclude_function_list_: |
1ebc7e68 | 2486 | add_comma_separated_to_vector |
6a1f6c9c | 2487 | (&opts->x_flag_instrument_functions_exclude_functions, arg); |
8d5a7d1f ILT |
2488 | break; |
2489 | ||
2490 | case OPT_finstrument_functions_exclude_file_list_: | |
1ebc7e68 | 2491 | add_comma_separated_to_vector |
6a1f6c9c | 2492 | (&opts->x_flag_instrument_functions_exclude_files, arg); |
8d5a7d1f ILT |
2493 | break; |
2494 | ||
de32c0cb | 2495 | case OPT_fmessage_length_: |
d5478783 | 2496 | pp_set_line_maximum_length (dc->printer, value); |
9fec0042 | 2497 | diagnostic_set_caret_max_width (dc, value); |
de32c0cb NB |
2498 | break; |
2499 | ||
78c60e3d SS |
2500 | case OPT_fopt_info: |
2501 | case OPT_fopt_info_: | |
2502 | /* Deferred. */ | |
2503 | break; | |
2504 | ||
c713ddc0 | 2505 | case OPT_foffload_: |
b2b40051 MJ |
2506 | { |
2507 | const char *p = arg; | |
2508 | opts->x_flag_disable_hsa = true; | |
2509 | while (*p != 0) | |
2510 | { | |
2511 | const char *comma = strchr (p, ','); | |
2512 | ||
2513 | if ((strncmp (p, "disable", 7) == 0) | |
2514 | && (p[7] == ',' || p[7] == '\0')) | |
2515 | { | |
2516 | opts->x_flag_disable_hsa = true; | |
2517 | break; | |
2518 | } | |
2519 | ||
2520 | if ((strncmp (p, "hsa", 3) == 0) | |
2521 | && (p[3] == ',' || p[3] == '\0')) | |
2522 | { | |
2523 | #ifdef ENABLE_HSA | |
2524 | opts->x_flag_disable_hsa = false; | |
2525 | #else | |
2526 | sorry ("HSA has not been enabled during configuration"); | |
2527 | #endif | |
2528 | } | |
2529 | if (!comma) | |
2530 | break; | |
2531 | p = comma + 1; | |
2532 | } | |
2533 | break; | |
2534 | } | |
c713ddc0 BS |
2535 | |
2536 | #ifndef ACCEL_COMPILER | |
2537 | case OPT_foffload_abi_: | |
4f4b35a0 | 2538 | error_at (loc, "%<-foffload-abi%> option can be specified only for " |
c713ddc0 BS |
2539 | "offload compiler"); |
2540 | break; | |
2541 | #endif | |
2542 | ||
467cecf3 JB |
2543 | case OPT_fpack_struct_: |
2544 | if (value <= 0 || (value & (value - 1)) || value > 16) | |
299404a1 | 2545 | error_at (loc, |
00abf86c | 2546 | "structure alignment must be a small power of two, not %wu", |
299404a1 | 2547 | value); |
467cecf3 | 2548 | else |
299404a1 | 2549 | opts->x_initial_max_fld_align = value; |
467cecf3 JB |
2550 | break; |
2551 | ||
68a607d8 | 2552 | case OPT_fplugin_: |
68a607d8 | 2553 | case OPT_fplugin_arg_: |
21bf1558 | 2554 | /* Deferred. */ |
68a607d8 DN |
2555 | break; |
2556 | ||
2f908293 | 2557 | case OPT_fprofile_use_: |
0576d21f | 2558 | opts->x_profile_data_prefix = xstrdup (arg); |
d5478783 | 2559 | opts->x_flag_profile_use = true; |
2f908293 SP |
2560 | value = true; |
2561 | /* No break here - do -fprofile-use processing. */ | |
191816a3 | 2562 | /* FALLTHRU */ |
a8a5f53a | 2563 | case OPT_fprofile_use: |
be3c16c4 | 2564 | enable_fdo_optimizations (opts, opts_set, value); |
6ed76044 ML |
2565 | SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_reorder_functions, |
2566 | value); | |
be3c16c4 DC |
2567 | /* Indirect call profiling should do all useful transformations |
2568 | speculative devirtualization does. */ | |
6ed76044 ML |
2569 | if (opts->x_flag_value_profile_transformations) |
2570 | SET_OPTION_IF_UNSET (opts, opts_set, flag_devirtualize_speculatively, | |
2571 | false); | |
a8a5f53a JH |
2572 | break; |
2573 | ||
be3c16c4 DC |
2574 | case OPT_fauto_profile_: |
2575 | opts->x_auto_profile_file = xstrdup (arg); | |
2576 | opts->x_flag_auto_profile = true; | |
2577 | value = true; | |
2578 | /* No break here - do -fauto-profile processing. */ | |
191816a3 | 2579 | /* FALLTHRU */ |
be3c16c4 DC |
2580 | case OPT_fauto_profile: |
2581 | enable_fdo_optimizations (opts, opts_set, value); | |
6ed76044 | 2582 | SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value); |
028d4092 ML |
2583 | SET_OPTION_IF_UNSET (opts, opts_set, |
2584 | param_early_inliner_max_iterations, 10); | |
be3c16c4 DC |
2585 | break; |
2586 | ||
2f908293 | 2587 | case OPT_fprofile_generate_: |
0576d21f | 2588 | opts->x_profile_data_prefix = xstrdup (arg); |
2f908293 SP |
2589 | value = true; |
2590 | /* No break here - do -fprofile-generate processing. */ | |
191816a3 | 2591 | /* FALLTHRU */ |
a8a5f53a | 2592 | case OPT_fprofile_generate: |
6ed76044 ML |
2593 | SET_OPTION_IF_UNSET (opts, opts_set, profile_arc_flag, value); |
2594 | SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value); | |
2595 | SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value); | |
2596 | SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value); | |
a8a5f53a JH |
2597 | break; |
2598 | ||
417ca011 TD |
2599 | case OPT_fpatchable_function_entry_: |
2600 | { | |
2601 | char *patch_area_arg = xstrdup (arg); | |
2602 | char *comma = strchr (patch_area_arg, ','); | |
2603 | if (comma) | |
2604 | { | |
2605 | *comma = '\0'; | |
2606 | function_entry_patch_area_size = | |
2607 | integral_argument (patch_area_arg); | |
2608 | function_entry_patch_area_start = | |
2609 | integral_argument (comma + 1); | |
2610 | } | |
2611 | else | |
2612 | { | |
2613 | function_entry_patch_area_size = | |
2614 | integral_argument (patch_area_arg); | |
2615 | function_entry_patch_area_start = 0; | |
2616 | } | |
2617 | if (function_entry_patch_area_size < 0 | |
2618 | || function_entry_patch_area_start < 0 | |
2619 | || function_entry_patch_area_size | |
2620 | < function_entry_patch_area_start) | |
2621 | error ("invalid arguments for %<-fpatchable_function_entry%>"); | |
2622 | free (patch_area_arg); | |
2623 | } | |
2624 | break; | |
2625 | ||
ea0f3e87 | 2626 | case OPT_ftree_vectorize: |
26d476cd JG |
2627 | /* Automatically sets -ftree-loop-vectorize and |
2628 | -ftree-slp-vectorize. Nothing more to do here. */ | |
ea0f3e87 | 2629 | break; |
5f0f4a3b | 2630 | case OPT_fshow_column: |
d5478783 | 2631 | dc->show_column = value; |
5f0f4a3b JM |
2632 | break; |
2633 | ||
de32c0cb NB |
2634 | case OPT_frandom_seed: |
2635 | /* The real switch is -fno-random-seed. */ | |
2636 | if (value) | |
5f20c657 | 2637 | return false; |
299404a1 | 2638 | /* Deferred. */ |
de32c0cb NB |
2639 | break; |
2640 | ||
2641 | case OPT_frandom_seed_: | |
299404a1 | 2642 | /* Deferred. */ |
de32c0cb NB |
2643 | break; |
2644 | ||
de32c0cb NB |
2645 | case OPT_fsched_verbose_: |
2646 | #ifdef INSN_SCHEDULING | |
299404a1 | 2647 | /* Handled with Var in common.opt. */ |
de32c0cb NB |
2648 | break; |
2649 | #else | |
5f20c657 | 2650 | return false; |
de32c0cb NB |
2651 | #endif |
2652 | ||
569fa502 | 2653 | case OPT_fsched_stalled_insns_: |
d5478783 JM |
2654 | opts->x_flag_sched_stalled_insns = value; |
2655 | if (opts->x_flag_sched_stalled_insns == 0) | |
2656 | opts->x_flag_sched_stalled_insns = -1; | |
569fa502 DN |
2657 | break; |
2658 | ||
569fa502 | 2659 | case OPT_fsched_stalled_insns_dep_: |
d5478783 | 2660 | opts->x_flag_sched_stalled_insns_dep = value; |
569fa502 | 2661 | break; |
6ff3a151 | 2662 | |
b38f3813 EB |
2663 | case OPT_fstack_check_: |
2664 | if (!strcmp (arg, "no")) | |
5e471ea6 | 2665 | opts->x_flag_stack_check = NO_STACK_CHECK; |
b38f3813 EB |
2666 | else if (!strcmp (arg, "generic")) |
2667 | /* This is the old stack checking method. */ | |
5e471ea6 | 2668 | opts->x_flag_stack_check = STACK_CHECK_BUILTIN |
b38f3813 EB |
2669 | ? FULL_BUILTIN_STACK_CHECK |
2670 | : GENERIC_STACK_CHECK; | |
2671 | else if (!strcmp (arg, "specific")) | |
2672 | /* This is the new stack checking method. */ | |
5e471ea6 | 2673 | opts->x_flag_stack_check = STACK_CHECK_BUILTIN |
b38f3813 EB |
2674 | ? FULL_BUILTIN_STACK_CHECK |
2675 | : STACK_CHECK_STATIC_BUILTIN | |
2676 | ? STATIC_BUILTIN_STACK_CHECK | |
2677 | : GENERIC_STACK_CHECK; | |
2678 | else | |
778e02fd | 2679 | warning_at (loc, 0, "unknown stack check parameter %qs", arg); |
b38f3813 EB |
2680 | break; |
2681 | ||
de32c0cb NB |
2682 | case OPT_fstack_limit: |
2683 | /* The real switch is -fno-stack-limit. */ | |
2684 | if (value) | |
5f20c657 | 2685 | return false; |
21bf1558 | 2686 | /* Deferred. */ |
de32c0cb NB |
2687 | break; |
2688 | ||
058de654 | 2689 | case OPT_fstack_limit_register_: |
058de654 | 2690 | case OPT_fstack_limit_symbol_: |
21bf1558 | 2691 | /* Deferred. */ |
058de654 NB |
2692 | break; |
2693 | ||
a11e0df4 EB |
2694 | case OPT_fstack_usage: |
2695 | opts->x_flag_stack_usage = value; | |
2696 | opts->x_flag_stack_usage_info = value != 0; | |
2697 | break; | |
2698 | ||
e01cc6dc | 2699 | case OPT_g: |
bc91b0e0 CC |
2700 | set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set, |
2701 | loc); | |
df38ffef NB |
2702 | break; |
2703 | ||
6782438d | 2704 | case OPT_gdwarf: |
f0defe58 | 2705 | if (arg && strlen (arg) != 0) |
6782438d | 2706 | { |
a3f9f006 ML |
2707 | error_at (loc, "%<-gdwarf%s%> is ambiguous; " |
2708 | "use %<-gdwarf-%s%> for DWARF version " | |
2709 | "or %<-gdwarf%> %<-g%s%> for debug level", arg, arg, arg); | |
6782438d SKS |
2710 | break; |
2711 | } | |
2712 | else | |
f0defe58 SKS |
2713 | value = opts->x_dwarf_version; |
2714 | ||
2715 | /* FALLTHRU */ | |
53b2323e | 2716 | case OPT_gdwarf_: |
5d45c9c0 | 2717 | if (value < 2 || value > 5) |
00abf86c | 2718 | error_at (loc, "dwarf version %wu is not supported", value); |
53b2323e | 2719 | else |
a7d0d30f | 2720 | opts->x_dwarf_version = value; |
299404a1 | 2721 | set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc); |
df38ffef NB |
2722 | break; |
2723 | ||
99ea153e SA |
2724 | case OPT_gsplit_dwarf: |
2725 | set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "", opts, opts_set, | |
2726 | loc); | |
2727 | break; | |
2728 | ||
df38ffef | 2729 | case OPT_ggdb: |
299404a1 | 2730 | set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc); |
df38ffef NB |
2731 | break; |
2732 | ||
2733 | case OPT_gstabs: | |
2734 | case OPT_gstabs_: | |
299404a1 JM |
2735 | set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set, |
2736 | loc); | |
df38ffef NB |
2737 | break; |
2738 | ||
2739 | case OPT_gvms: | |
299404a1 | 2740 | set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc); |
df38ffef NB |
2741 | break; |
2742 | ||
2743 | case OPT_gxcoff: | |
2744 | case OPT_gxcoff_: | |
299404a1 JM |
2745 | set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set, |
2746 | loc); | |
e01cc6dc NB |
2747 | break; |
2748 | ||
29d7cbd1 RO |
2749 | case OPT_gz: |
2750 | case OPT_gz_: | |
2751 | /* Handled completely via specs. */ | |
2752 | break; | |
2753 | ||
d185d268 | 2754 | case OPT_pedantic_errors: |
d5478783 | 2755 | dc->pedantic_errors = 1; |
63bbf46d | 2756 | control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value, |
9b095bf1 MLI |
2757 | loc, lang_mask, |
2758 | handlers, opts, opts_set, | |
2759 | dc); | |
c04b6b38 RG |
2760 | break; |
2761 | ||
014d92e1 | 2762 | case OPT_flto: |
595c8dfa | 2763 | opts->x_flag_lto = value ? "" : NULL; |
e10909ce AK |
2764 | break; |
2765 | ||
40077d15 ML |
2766 | case OPT_flto_: |
2767 | if (strcmp (arg, "none") != 0 | |
2768 | && strcmp (arg, "jobserver") != 0 | |
279dc7a3 | 2769 | && strcmp (arg, "auto") != 0 |
40077d15 ML |
2770 | && atoi (arg) == 0) |
2771 | error_at (loc, | |
2772 | "unrecognized argument to %<-flto=%> option: %qs", arg); | |
2773 | break; | |
2774 | ||
5f0f4a3b | 2775 | case OPT_w: |
d5478783 | 2776 | dc->dc_inhibit_warnings = true; |
5f0f4a3b JM |
2777 | break; |
2778 | ||
3a789837 NF |
2779 | case OPT_fmax_errors_: |
2780 | dc->max_errors = value; | |
2781 | break; | |
2782 | ||
b352afba NC |
2783 | case OPT_fuse_ld_bfd: |
2784 | case OPT_fuse_ld_gold: | |
d69ac8b7 | 2785 | case OPT_fuse_ld_lld: |
da18ea94 RAE |
2786 | case OPT_fuse_linker_plugin: |
2787 | /* No-op. Used by the driver and passed to us because it starts with f.*/ | |
2788 | break; | |
2789 | ||
955f5a07 JJ |
2790 | case OPT_fwrapv: |
2791 | if (value) | |
2792 | opts->x_flag_trapv = 0; | |
2793 | break; | |
2794 | ||
2795 | case OPT_ftrapv: | |
2796 | if (value) | |
2797 | opts->x_flag_wrapv = 0; | |
2798 | break; | |
2799 | ||
3fccbb9e JJ |
2800 | case OPT_fstrict_overflow: |
2801 | opts->x_flag_wrapv = !value; | |
2802 | opts->x_flag_wrapv_pointer = !value; | |
2803 | if (!value) | |
2804 | opts->x_flag_trapv = 0; | |
2805 | break; | |
2806 | ||
b84d4347 | 2807 | case OPT_fipa_icf: |
9d4ded75 ML |
2808 | opts->x_flag_ipa_icf_functions = value; |
2809 | opts->x_flag_ipa_icf_variables = value; | |
b84d4347 ML |
2810 | break; |
2811 | ||
c518c102 ML |
2812 | case OPT_falign_loops_: |
2813 | check_alignment_argument (loc, arg, "loops"); | |
2814 | break; | |
2815 | ||
2816 | case OPT_falign_jumps_: | |
2817 | check_alignment_argument (loc, arg, "jumps"); | |
2818 | break; | |
2819 | ||
2820 | case OPT_falign_labels_: | |
2821 | check_alignment_argument (loc, arg, "labels"); | |
2822 | break; | |
2823 | ||
2824 | case OPT_falign_functions_: | |
2825 | check_alignment_argument (loc, arg, "functions"); | |
2826 | break; | |
2827 | ||
50431bc4 ZD |
2828 | default: |
2829 | /* If the flag was handled in a standard way, assume the lack of | |
2830 | processing here is intentional. */ | |
46625112 | 2831 | gcc_assert (option_flag_var (scode, opts)); |
0e61db61 | 2832 | break; |
d7b42618 NB |
2833 | } |
2834 | ||
7d5a5747 MLI |
2835 | common_handle_option_auto (opts, opts_set, decoded, lang_mask, kind, |
2836 | loc, handlers, dc); | |
5f20c657 | 2837 | return true; |
d7b42618 | 2838 | } |
903caebf | 2839 | |
d5478783 | 2840 | /* Used to set the level of strict aliasing warnings in OPTS, |
79bedddc SR |
2841 | when no level is specified (i.e., when -Wstrict-aliasing, and not |
2842 | -Wstrict-aliasing=level was given). | |
2843 | ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified, | |
2844 | and 0 otherwise. After calling this function, wstrict_aliasing will be | |
2845 | set to the default value of -Wstrict_aliasing=level, currently 3. */ | |
65d4f2cd | 2846 | static void |
d5478783 | 2847 | set_Wstrict_aliasing (struct gcc_options *opts, int onoff) |
79bedddc SR |
2848 | { |
2849 | gcc_assert (onoff == 0 || onoff == 1); | |
2850 | if (onoff != 0) | |
d5478783 | 2851 | opts->x_warn_strict_aliasing = 3; |
621b5ed6 | 2852 | else |
d5478783 | 2853 | opts->x_warn_strict_aliasing = 0; |
79bedddc SR |
2854 | } |
2855 | ||
058de654 NB |
2856 | /* The following routines are useful in setting all the flags that |
2857 | -ffast-math and -fno-fast-math imply. */ | |
7bb3487f | 2858 | static void |
d5478783 | 2859 | set_fast_math_flags (struct gcc_options *opts, int set) |
058de654 | 2860 | { |
5e46b0c6 ILT |
2861 | if (!opts->frontend_set_flag_unsafe_math_optimizations) |
2862 | { | |
2863 | opts->x_flag_unsafe_math_optimizations = set; | |
2864 | set_unsafe_math_optimizations_flags (opts, set); | |
2865 | } | |
2866 | if (!opts->frontend_set_flag_finite_math_only) | |
2867 | opts->x_flag_finite_math_only = set; | |
2868 | if (!opts->frontend_set_flag_errno_math) | |
2869 | opts->x_flag_errno_math = !set; | |
058de654 | 2870 | if (set) |
039c3d42 | 2871 | { |
df375b03 JJ |
2872 | if (opts->frontend_set_flag_excess_precision == EXCESS_PRECISION_DEFAULT) |
2873 | opts->x_flag_excess_precision | |
314e1b47 | 2874 | = set ? EXCESS_PRECISION_FAST : EXCESS_PRECISION_DEFAULT; |
5e46b0c6 ILT |
2875 | if (!opts->frontend_set_flag_signaling_nans) |
2876 | opts->x_flag_signaling_nans = 0; | |
2877 | if (!opts->frontend_set_flag_rounding_math) | |
2878 | opts->x_flag_rounding_math = 0; | |
2879 | if (!opts->frontend_set_flag_cx_limited_range) | |
2880 | opts->x_flag_cx_limited_range = 1; | |
039c3d42 | 2881 | } |
058de654 NB |
2882 | } |
2883 | ||
b8698a0f L |
2884 | /* When -funsafe-math-optimizations is set the following |
2885 | flags are set as well. */ | |
7bb3487f | 2886 | static void |
d5478783 | 2887 | set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set) |
a1a82611 | 2888 | { |
5e46b0c6 ILT |
2889 | if (!opts->frontend_set_flag_trapping_math) |
2890 | opts->x_flag_trapping_math = !set; | |
2891 | if (!opts->frontend_set_flag_signed_zeros) | |
2892 | opts->x_flag_signed_zeros = !set; | |
2893 | if (!opts->frontend_set_flag_associative_math) | |
2894 | opts->x_flag_associative_math = set; | |
2895 | if (!opts->frontend_set_flag_reciprocal_math) | |
2896 | opts->x_flag_reciprocal_math = set; | |
a1a82611 RE |
2897 | } |
2898 | ||
0576d21f | 2899 | /* Return true iff flags in OPTS are set as if -ffast-math. */ |
058de654 | 2900 | bool |
0576d21f | 2901 | fast_math_flags_set_p (const struct gcc_options *opts) |
058de654 | 2902 | { |
0576d21f JM |
2903 | return (!opts->x_flag_trapping_math |
2904 | && opts->x_flag_unsafe_math_optimizations | |
2905 | && opts->x_flag_finite_math_only | |
2906 | && !opts->x_flag_signed_zeros | |
314e1b47 | 2907 | && !opts->x_flag_errno_math |
df375b03 | 2908 | && opts->x_flag_excess_precision == EXCESS_PRECISION_FAST); |
058de654 | 2909 | } |
cf03fd63 | 2910 | |
ab442df7 MM |
2911 | /* Return true iff flags are set as if -ffast-math but using the flags stored |
2912 | in the struct cl_optimization structure. */ | |
2913 | bool | |
2914 | fast_math_flags_struct_set_p (struct cl_optimization *opt) | |
2915 | { | |
e3339d0f JM |
2916 | return (!opt->x_flag_trapping_math |
2917 | && opt->x_flag_unsafe_math_optimizations | |
2918 | && opt->x_flag_finite_math_only | |
2919 | && !opt->x_flag_signed_zeros | |
2920 | && !opt->x_flag_errno_math); | |
ab442df7 MM |
2921 | } |
2922 | ||
0576d21f JM |
2923 | /* Handle a debug output -g switch for options OPTS |
2924 | (OPTS_SET->x_write_symbols storing whether a debug type was passed | |
299404a1 JM |
2925 | explicitly), location LOC. EXTENDED is true or false to support |
2926 | extended output (2 is special and means "-ggdb" was given). */ | |
df38ffef | 2927 | static void |
0576d21f | 2928 | set_debug_level (enum debug_info_type type, int extended, const char *arg, |
299404a1 JM |
2929 | struct gcc_options *opts, struct gcc_options *opts_set, |
2930 | location_t loc) | |
df38ffef | 2931 | { |
0576d21f | 2932 | opts->x_use_gnu_debug_info_extensions = extended; |
df38ffef NB |
2933 | |
2934 | if (type == NO_DEBUG) | |
2935 | { | |
0576d21f | 2936 | if (opts->x_write_symbols == NO_DEBUG) |
df38ffef | 2937 | { |
0576d21f | 2938 | opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE; |
df38ffef NB |
2939 | |
2940 | if (extended == 2) | |
2941 | { | |
c9665100 | 2942 | #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO |
0576d21f | 2943 | opts->x_write_symbols = DWARF2_DEBUG; |
df38ffef | 2944 | #elif defined DBX_DEBUGGING_INFO |
0576d21f | 2945 | opts->x_write_symbols = DBX_DEBUG; |
df38ffef NB |
2946 | #endif |
2947 | } | |
2948 | ||
0576d21f | 2949 | if (opts->x_write_symbols == NO_DEBUG) |
299404a1 | 2950 | warning_at (loc, 0, "target system does not support debug output"); |
df38ffef NB |
2951 | } |
2952 | } | |
2953 | else | |
2954 | { | |
2955 | /* Does it conflict with an already selected type? */ | |
0576d21f JM |
2956 | if (opts_set->x_write_symbols != NO_DEBUG |
2957 | && opts->x_write_symbols != NO_DEBUG | |
2958 | && type != opts->x_write_symbols) | |
778e02fd | 2959 | error_at (loc, "debug format %qs conflicts with prior selection", |
299404a1 | 2960 | debug_type_names[type]); |
0576d21f JM |
2961 | opts->x_write_symbols = type; |
2962 | opts_set->x_write_symbols = type; | |
df38ffef NB |
2963 | } |
2964 | ||
bc91b0e0 CC |
2965 | /* A debug flag without a level defaults to level 2. |
2966 | If off or at level 1, set it to level 2, but if already | |
2967 | at level 3, don't lower it. */ | |
df38ffef NB |
2968 | if (*arg == '\0') |
2969 | { | |
bc91b0e0 | 2970 | if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL) |
0576d21f | 2971 | opts->x_debug_info_level = DINFO_LEVEL_NORMAL; |
df38ffef NB |
2972 | } |
2973 | else | |
2974 | { | |
32e8bb8e ILT |
2975 | int argval = integral_argument (arg); |
2976 | if (argval == -1) | |
bd2c6270 | 2977 | error_at (loc, "unrecognized debug output level %qs", arg); |
32e8bb8e | 2978 | else if (argval > 3) |
778e02fd | 2979 | error_at (loc, "debug output level %qs is too high", arg); |
32e8bb8e | 2980 | else |
0576d21f | 2981 | opts->x_debug_info_level = (enum debug_info_levels) argval; |
df38ffef NB |
2982 | } |
2983 | } | |
2984 | ||
299404a1 JM |
2985 | /* Arrange to dump core on error for diagnostic context DC. (The |
2986 | regular error message is still printed first, except in the case of | |
2987 | abort ().) */ | |
75685792 | 2988 | |
c98cd5bf | 2989 | static void |
299404a1 | 2990 | setup_core_dumping (diagnostic_context *dc) |
75685792 | 2991 | { |
c98cd5bf JM |
2992 | #ifdef SIGABRT |
2993 | signal (SIGABRT, SIG_DFL); | |
2994 | #endif | |
2995 | #if defined(HAVE_SETRLIMIT) | |
2996 | { | |
2997 | struct rlimit rlim; | |
2998 | if (getrlimit (RLIMIT_CORE, &rlim) != 0) | |
40fecdd6 | 2999 | fatal_error (input_location, "getting core file size maximum limit: %m"); |
c98cd5bf JM |
3000 | rlim.rlim_cur = rlim.rlim_max; |
3001 | if (setrlimit (RLIMIT_CORE, &rlim) != 0) | |
40fecdd6 JM |
3002 | fatal_error (input_location, |
3003 | "setting core file size limit to maximum: %m"); | |
c98cd5bf JM |
3004 | } |
3005 | #endif | |
299404a1 | 3006 | diagnostic_abort_on_error (dc); |
75685792 | 3007 | } |
5c60a017 | 3008 | |
299404a1 JM |
3009 | /* Parse a -d<ARG> command line switch for OPTS, location LOC, |
3010 | diagnostic context DC. */ | |
5c60a017 | 3011 | |
c98cd5bf | 3012 | static void |
299404a1 JM |
3013 | decode_d_option (const char *arg, struct gcc_options *opts, |
3014 | location_t loc, diagnostic_context *dc) | |
5c60a017 | 3015 | { |
c98cd5bf | 3016 | int c; |
5c60a017 | 3017 | |
c98cd5bf JM |
3018 | while (*arg) |
3019 | switch (c = *arg++) | |
3020 | { | |
3021 | case 'A': | |
299404a1 | 3022 | opts->x_flag_debug_asm = 1; |
c98cd5bf JM |
3023 | break; |
3024 | case 'p': | |
299404a1 | 3025 | opts->x_flag_print_asm_name = 1; |
c98cd5bf JM |
3026 | break; |
3027 | case 'P': | |
299404a1 JM |
3028 | opts->x_flag_dump_rtl_in_asm = 1; |
3029 | opts->x_flag_print_asm_name = 1; | |
c98cd5bf | 3030 | break; |
c98cd5bf | 3031 | case 'x': |
299404a1 | 3032 | opts->x_rtl_dump_and_exit = 1; |
c98cd5bf JM |
3033 | break; |
3034 | case 'D': /* These are handled by the preprocessor. */ | |
3035 | case 'I': | |
3036 | case 'M': | |
3037 | case 'N': | |
3038 | case 'U': | |
3039 | break; | |
3040 | case 'H': | |
299404a1 | 3041 | setup_core_dumping (dc); |
c98cd5bf JM |
3042 | break; |
3043 | case 'a': | |
299404a1 | 3044 | opts->x_flag_dump_all_passed = true; |
c98cd5bf | 3045 | break; |
21bf1558 | 3046 | |
c98cd5bf | 3047 | default: |
299404a1 | 3048 | warning_at (loc, 0, "unrecognized gcc debugging option: %c", c); |
c98cd5bf JM |
3049 | break; |
3050 | } | |
5c60a017 | 3051 | } |
dc90f45b | 3052 | |
1ebe4b4f | 3053 | /* Enable (or disable if VALUE is 0) a warning option ARG (language |
c5fa0890 JM |
3054 | mask LANG_MASK, option handlers HANDLERS) as an error for option |
3055 | structures OPTS and OPTS_SET, diagnostic context DC (possibly | |
3056 | NULL), location LOC. This is used by -Werror=. */ | |
dc90f45b | 3057 | |
a4d8c676 | 3058 | static void |
5f20c657 | 3059 | enable_warning_as_error (const char *arg, int value, unsigned int lang_mask, |
1ebe4b4f | 3060 | const struct cl_option_handlers *handlers, |
c5fa0890 JM |
3061 | struct gcc_options *opts, |
3062 | struct gcc_options *opts_set, | |
a4d8c676 | 3063 | location_t loc, diagnostic_context *dc) |
dc90f45b MLI |
3064 | { |
3065 | char *new_option; | |
3066 | int option_index; | |
3067 | ||
3068 | new_option = XNEWVEC (char, strlen (arg) + 2); | |
3069 | new_option[0] = 'W'; | |
3070 | strcpy (new_option + 1, arg); | |
3071 | option_index = find_opt (new_option, lang_mask); | |
6e2f1956 | 3072 | if (option_index == OPT_SPECIAL_unknown) |
5bcc5a3b ML |
3073 | { |
3074 | option_proposer op; | |
3075 | const char *hint = op.suggest_option (new_option); | |
3076 | if (hint) | |
3077 | error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>;" | |
3078 | " did you mean %<-%s%>?", value ? "" : "no-", | |
3079 | arg, new_option, hint); | |
3080 | else | |
3081 | error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>", | |
3082 | value ? "" : "no-", arg, new_option); | |
3083 | } | |
35632122 | 3084 | else if (!(cl_options[option_index].flags & CL_WARNING)) |
5bcc5a3b ML |
3085 | error_at (loc, "%<-Werror=%s%>: %<-%s%> is not an option that " |
3086 | "controls warnings", arg, new_option); | |
dc90f45b MLI |
3087 | else |
3088 | { | |
87cf0651 | 3089 | const diagnostic_t kind = value ? DK_ERROR : DK_WARNING; |
63bbf46d | 3090 | const char *arg = NULL; |
87cf0651 | 3091 | |
63bbf46d JJ |
3092 | if (cl_options[option_index].flags & CL_JOINED) |
3093 | arg = new_option + cl_options[option_index].opt_len; | |
3094 | control_warning_option (option_index, (int) kind, arg, value, | |
c5fa0890 JM |
3095 | loc, lang_mask, |
3096 | handlers, opts, opts_set, dc); | |
dc90f45b MLI |
3097 | } |
3098 | free (new_option); | |
3099 | } | |
5f0f4a3b JM |
3100 | |
3101 | /* Return malloced memory for the name of the option OPTION_INDEX | |
3102 | which enabled a diagnostic (context CONTEXT), originally of type | |
3103 | ORIG_DIAG_KIND but possibly converted to DIAG_KIND by options such | |
3104 | as -Werror. */ | |
3105 | ||
3106 | char * | |
3107 | option_name (diagnostic_context *context, int option_index, | |
3108 | diagnostic_t orig_diag_kind, diagnostic_t diag_kind) | |
3109 | { | |
3110 | if (option_index) | |
3111 | { | |
3112 | /* A warning classified as an error. */ | |
3113 | if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN) | |
3114 | && diag_kind == DK_ERROR) | |
3115 | return concat (cl_options[OPT_Werror_].opt_text, | |
3116 | /* Skip over "-W". */ | |
3117 | cl_options[option_index].opt_text + 2, | |
3118 | NULL); | |
3119 | /* A warning with option. */ | |
3120 | else | |
3121 | return xstrdup (cl_options[option_index].opt_text); | |
3122 | } | |
3123 | /* A warning without option classified as an error. */ | |
9f8da907 RS |
3124 | else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN |
3125 | || diag_kind == DK_WARNING) | |
3126 | && context->warning_as_error_requested) | |
3127 | return xstrdup (cl_options[OPT_Werror].opt_text); | |
5f0f4a3b JM |
3128 | else |
3129 | return NULL; | |
3130 | } | |
b4c7ca2e | 3131 | |
fa29cf0c DM |
3132 | /* Get the page within the documentation for this option. */ |
3133 | ||
3134 | static const char * | |
3135 | get_option_html_page (int option_index) | |
3136 | { | |
3137 | const cl_option *cl_opt = &cl_options[option_index]; | |
3138 | ||
3139 | /* Analyzer options are on their own page. */ | |
3140 | if (strstr(cl_opt->opt_text, "analyzer-")) | |
3141 | return "gcc/Static-Analyzer-Options.html"; | |
3142 | ||
3143 | #ifdef CL_Fortran | |
3144 | if (cl_opt->flags & CL_Fortran) | |
3145 | { | |
3146 | switch (option_index) | |
3147 | { | |
3148 | default: | |
3149 | /* Most Fortran warnings are documented on this page. */ | |
3150 | return "gfortran/Error-and-Warning-Options.html"; | |
3151 | ||
3152 | case OPT_Wdate_time: | |
3153 | case OPT_Wconversion: | |
3154 | case OPT_Wconversion_extra: | |
3155 | case OPT_Wmissing_include_dirs: | |
3156 | case OPT_Wopenmp_simd: | |
3157 | /* These warnings are marked in fortran/lang.opt as | |
3158 | "Documented in C" and thus use the common | |
3159 | Warning-Options page below. */ | |
3160 | break; | |
3161 | } | |
3162 | } | |
3163 | #endif | |
3164 | ||
3165 | return "gcc/Warning-Options.html"; | |
3166 | } | |
3167 | ||
b4c7ca2e DM |
3168 | /* Return malloced memory for a URL describing the option OPTION_INDEX |
3169 | which enabled a diagnostic (context CONTEXT). */ | |
3170 | ||
3171 | char * | |
3172 | get_option_url (diagnostic_context *, int option_index) | |
3173 | { | |
3174 | if (option_index) | |
fa29cf0c DM |
3175 | return concat (/* DOCUMENTATION_ROOT_URL should be supplied via -D by |
3176 | the Makefile (see --with-documentation-root-url), and | |
3177 | should have a trailing slash. */ | |
3178 | DOCUMENTATION_ROOT_URL, | |
3179 | ||
3180 | /* get_option_html_page will return something like | |
3181 | "gcc/Warning-Options.html". */ | |
3182 | get_option_html_page (option_index), | |
3183 | ||
3184 | /* Expect an anchor of the form "index-Wfoo" e.g. | |
3185 | <a name="index-Wformat"></a>, and thus an id within | |
3186 | the URL of "#index-Wformat". */ | |
b4c7ca2e DM |
3187 | "#index", cl_options[option_index].opt_text, |
3188 | NULL); | |
3189 | else | |
3190 | return NULL; | |
3191 | } | |
fa29cf0c | 3192 | |
691eeb65 JJ |
3193 | /* Given "gcc-10/changes.html#foobar", return that URL under |
3194 | CHANGES_ROOT_URL (see --with-changes-root-url). | |
3195 | The caller is responsible for freeing the returned string. */ | |
3196 | ||
3197 | char * | |
3198 | get_changes_url (const char *str) | |
3199 | { | |
3200 | return concat (CHANGES_ROOT_URL, str, NULL); | |
3201 | } | |
3202 | ||
fa29cf0c DM |
3203 | #if CHECKING_P |
3204 | ||
3205 | namespace selftest { | |
3206 | ||
3207 | /* Verify that get_option_html_page works as expected. */ | |
3208 | ||
3209 | static void | |
3210 | test_get_option_html_page () | |
3211 | { | |
3212 | ASSERT_STREQ (get_option_html_page (OPT_Wcpp), "gcc/Warning-Options.html"); | |
3213 | ASSERT_STREQ (get_option_html_page (OPT_Wanalyzer_double_free), | |
3214 | "gcc/Static-Analyzer-Options.html"); | |
3215 | #ifdef CL_Fortran | |
3216 | ASSERT_STREQ (get_option_html_page (OPT_Wline_truncation), | |
3217 | "gfortran/Error-and-Warning-Options.html"); | |
3218 | #endif | |
3219 | } | |
3220 | ||
3221 | /* Run all of the selftests within this file. */ | |
3222 | ||
3223 | void | |
3224 | opts_c_tests () | |
3225 | { | |
3226 | test_get_option_html_page (); | |
3227 | } | |
3228 | ||
3229 | } // namespace selftest | |
3230 | ||
3231 | #endif /* #if CHECKING_P */ |