1/* Command line option handling.
2 Copyright (C) 2002-2023 Free Software Foundation, Inc.
3 Contributed by Neil Booth.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "intl.h"
24#include "coretypes.h"
25#include "opts.h"
26#include "tm.h"
27#include "flags.h"
28#include "diagnostic.h"
29#include "opts-diagnostic.h"
30#include "insn-attr-common.h"
31#include "common/common-target.h"
32#include "spellcheck.h"
33#include "opt-suggestions.h"
34#include "diagnostic-color.h"
35#include "version.h"
36#include "selftest.h"
37#include "file-prefix-map.h"
38
39/* In this file all option sets are explicit. */
40#undef OPTION_SET_P
41
42/* Set by -fcanon-prefix-map. */
43bool flag_canon_prefix_map;
44
45static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
46
47/* Names of fundamental debug info formats indexed by enum
48 debug_info_type. */
49
50const char *const debug_type_names[] =
51{
52 "none", "dwarf-2", "vms", "ctf", "btf"
53};
54
55/* Bitmasks of fundamental debug info formats indexed by enum
56 debug_info_type. */
57
58static uint32_t debug_type_masks[] =
59{
60 NO_DEBUG, DWARF2_DEBUG, VMS_DEBUG,
61 CTF_DEBUG, BTF_DEBUG
62};
63
64/* Names of the set of debug formats requested by user. Updated and accessed
65 via debug_set_names. */
66
67static char df_set_names[sizeof "none dwarf-2 vms ctf btf"];
68
69/* Get enum debug_info_type of the specified debug format, for error messages.
70 Can be used only for individual debug format types. */
71
72enum debug_info_type
73debug_set_to_format (uint32_t debug_info_set)
74{
75 int idx = 0;
76 enum debug_info_type dinfo_type = DINFO_TYPE_NONE;
77 /* Find first set bit. */
78 if (debug_info_set)
79 idx = exact_log2 (x: debug_info_set & - debug_info_set);
80 /* Check that only one bit is set, if at all. This function is meant to be
81 used only for vanilla debug_info_set bitmask values, i.e. for individual
82 debug format types upto DINFO_TYPE_MAX. */
83 gcc_assert ((debug_info_set & (debug_info_set - 1)) == 0);
84 dinfo_type = (enum debug_info_type)idx;
85 gcc_assert (dinfo_type <= DINFO_TYPE_MAX);
86 return dinfo_type;
87}
88
89/* Get the number of debug formats enabled for output. */
90
91unsigned int
92debug_set_count (uint32_t w_symbols)
93{
94 unsigned int count = 0;
95 while (w_symbols)
96 {
97 ++ count;
98 w_symbols &= ~ (w_symbols & - w_symbols);
99 }
100 return count;
101}
102
103/* Get the names of the debug formats enabled for output. */
104
105const char *
106debug_set_names (uint32_t w_symbols)
107{
108 uint32_t df_mask = 0;
109 /* Reset the string to be returned. */
110 memset (s: df_set_names, c: 0, n: sizeof (df_set_names));
111 /* Get the popcount. */
112 int num_set_df = debug_set_count (w_symbols);
113 /* Iterate over the debug formats. Add name string for those enabled. */
114 for (int i = DINFO_TYPE_NONE; i <= DINFO_TYPE_MAX; i++)
115 {
116 df_mask = debug_type_masks[i];
117 if (w_symbols & df_mask)
118 {
119 strcat (dest: df_set_names, src: debug_type_names[i]);
120 num_set_df--;
121 if (num_set_df)
122 strcat (dest: df_set_names, src: " ");
123 else
124 break;
125 }
126 else if (!w_symbols)
127 {
128 /* No debug formats enabled. */
129 gcc_assert (i == DINFO_TYPE_NONE);
130 strcat (dest: df_set_names, src: debug_type_names[i]);
131 break;
132 }
133 }
134 return df_set_names;
135}
136
137/* Return TRUE iff BTF debug info is enabled. */
138
139bool
140btf_debuginfo_p ()
141{
142 return (write_symbols & BTF_DEBUG);
143}
144
145/* Return TRUE iff BTF with CO-RE debug info is enabled. */
146
147bool
148btf_with_core_debuginfo_p ()
149{
150 return (write_symbols & BTF_WITH_CORE_DEBUG);
151}
152
153/* Return TRUE iff CTF debug info is enabled. */
154
155bool
156ctf_debuginfo_p ()
157{
158 return (write_symbols & CTF_DEBUG);
159}
160
161/* Return TRUE iff dwarf2 debug info is enabled. */
162
163bool
164dwarf_debuginfo_p (struct gcc_options *opts)
165{
166 return (opts->x_write_symbols & DWARF2_DEBUG);
167}
168
169/* Return true iff the debug info format is to be generated based on DWARF
170 DIEs (like CTF and BTF debug info formats). */
171
172bool dwarf_based_debuginfo_p ()
173{
174 return ((write_symbols & CTF_DEBUG)
175 || (write_symbols & BTF_DEBUG));
176}
177
178/* All flag uses below need to explicitely reference the option sets
179 to operate on. */
180#define global_options DO_NOT_USE
181#define global_options_set DO_NOT_USE
182
183/* Parse the -femit-struct-debug-detailed option value
184 and set the flag variables. */
185
186#define MATCH( prefix, string ) \
187 ((strncmp (prefix, string, sizeof prefix - 1) == 0) \
188 ? ((string += sizeof prefix - 1), 1) : 0)
189
190void
191set_struct_debug_option (struct gcc_options *opts, location_t loc,
192 const char *spec)
193{
194 /* various labels for comparison */
195 static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
196 static const char ord_lbl[] = "ord:", gen_lbl[] = "gen:";
197 static const char none_lbl[] = "none", any_lbl[] = "any";
198 static const char base_lbl[] = "base", sys_lbl[] = "sys";
199
200 enum debug_struct_file files = DINFO_STRUCT_FILE_ANY;
201 /* Default is to apply to as much as possible. */
202 enum debug_info_usage usage = DINFO_USAGE_NUM_ENUMS;
203 int ord = 1, gen = 1;
204
205 /* What usage? */
206 if (MATCH (dfn_lbl, spec))
207 usage = DINFO_USAGE_DFN;
208 else if (MATCH (dir_lbl, spec))
209 usage = DINFO_USAGE_DIR_USE;
210 else if (MATCH (ind_lbl, spec))
211 usage = DINFO_USAGE_IND_USE;
212
213 /* Generics or not? */
214 if (MATCH (ord_lbl, spec))
215 gen = 0;
216 else if (MATCH (gen_lbl, spec))
217 ord = 0;
218
219 /* What allowable environment? */
220 if (MATCH (none_lbl, spec))
221 files = DINFO_STRUCT_FILE_NONE;
222 else if (MATCH (any_lbl, spec))
223 files = DINFO_STRUCT_FILE_ANY;
224 else if (MATCH (sys_lbl, spec))
225 files = DINFO_STRUCT_FILE_SYS;
226 else if (MATCH (base_lbl, spec))
227 files = DINFO_STRUCT_FILE_BASE;
228 else
229 error_at (loc,
230 "argument %qs to %<-femit-struct-debug-detailed%> "
231 "not recognized",
232 spec);
233
234 /* Effect the specification. */
235 if (usage == DINFO_USAGE_NUM_ENUMS)
236 {
237 if (ord)
238 {
239 opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files;
240 opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files;
241 opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files;
242 }
243 if (gen)
244 {
245 opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files;
246 opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files;
247 opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files;
248 }
249 }
250 else
251 {
252 if (ord)
253 opts->x_debug_struct_ordinary[usage] = files;
254 if (gen)
255 opts->x_debug_struct_generic[usage] = files;
256 }
257
258 if (*spec == ',')
259 set_struct_debug_option (opts, loc, spec: spec+1);
260 else
261 {
262 /* No more -femit-struct-debug-detailed specifications.
263 Do final checks. */
264 if (*spec != '\0')
265 error_at (loc,
266 "argument %qs to %<-femit-struct-debug-detailed%> unknown",
267 spec);
268 if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE]
269 < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE]
270 || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE]
271 < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE])
272 error_at (loc,
273 "%<-femit-struct-debug-detailed=dir:...%> must allow "
274 "at least as much as "
275 "%<-femit-struct-debug-detailed=ind:...%>");
276 }
277}
278
279/* Strip off a legitimate source ending from the input string NAME of
280 length LEN. Rather than having to know the names used by all of
281 our front ends, we strip off an ending of a period followed by
282 up to fource characters. (C++ uses ".cpp".) */
283
284void
285strip_off_ending (char *name, int len)
286{
287 int i;
288 for (i = 2; i < 5 && len > i; i++)
289 {
290 if (name[len - i] == '.')
291 {
292 name[len - i] = '\0';
293 break;
294 }
295 }
296}
297
298/* Find the base name of a path, stripping off both directories and
299 a single final extension. */
300int
301base_of_path (const char *path, const char **base_out)
302{
303 const char *base = path;
304 const char *dot = 0;
305 const char *p = path;
306 char c = *p;
307 while (c)
308 {
309 if (IS_DIR_SEPARATOR (c))
310 {
311 base = p + 1;
312 dot = 0;
313 }
314 else if (c == '.')
315 dot = p;
316 c = *++p;
317 }
318 if (!dot)
319 dot = p;
320 *base_out = base;
321 return dot - base;
322}
323
324/* What to print when a switch has no documentation. */
325static const char undocumented_msg[] = N_("This option lacks documentation.");
326static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed.");
327
328typedef char *char_p; /* For DEF_VEC_P. */
329
330static void set_debug_level (uint32_t dinfo, int extended,
331 const char *arg, struct gcc_options *opts,
332 struct gcc_options *opts_set,
333 location_t loc);
334static void set_fast_math_flags (struct gcc_options *opts, int set);
335static void decode_d_option (const char *arg, struct gcc_options *opts,
336 location_t loc, diagnostic_context *dc);
337static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
338 int set);
339static void enable_warning_as_error (const char *arg, int value,
340 unsigned int lang_mask,
341 const struct cl_option_handlers *handlers,
342 struct gcc_options *opts,
343 struct gcc_options *opts_set,
344 location_t loc,
345 diagnostic_context *dc);
346
347/* Handle a back-end option; arguments and return value as for
348 handle_option. */
349
350bool
351target_handle_option (struct gcc_options *opts,
352 struct gcc_options *opts_set,
353 const struct cl_decoded_option *decoded,
354 unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
355 location_t loc,
356 const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
357 diagnostic_context *dc, void (*) (void))
358{
359 gcc_assert (dc == global_dc);
360 gcc_assert (kind == DK_UNSPECIFIED);
361 return targetm_common.handle_option (opts, opts_set, decoded, loc);
362}
363
364/* Add comma-separated strings to a char_p vector. */
365
366static void
367add_comma_separated_to_vector (void **pvec, const char *arg)
368{
369 char *tmp;
370 char *r;
371 char *w;
372 char *token_start;
373 vec<char_p> *v = (vec<char_p> *) *pvec;
374
375 vec_check_alloc (vec&: v, nelems: 1);
376
377 /* We never free this string. */
378 tmp = xstrdup (arg);
379
380 r = tmp;
381 w = tmp;
382 token_start = tmp;
383
384 while (*r != '\0')
385 {
386 if (*r == ',')
387 {
388 *w++ = '\0';
389 ++r;
390 v->safe_push (obj: token_start);
391 token_start = w;
392 }
393 if (*r == '\\' && r[1] == ',')
394 {
395 *w++ = ',';
396 r += 2;
397 }
398 else
399 *w++ = *r++;
400 }
401
402 *w = '\0';
403 if (*token_start != '\0')
404 v->safe_push (obj: token_start);
405
406 *pvec = v;
407}
408
409/* Initialize opts_obstack. */
410
411void
412init_opts_obstack (void)
413{
414 gcc_obstack_init (&opts_obstack);
415}
416
417/* Initialize OPTS and OPTS_SET before using them in parsing options. */
418
419void
420init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
421{
422 /* Ensure that opts_obstack has already been initialized by the time
423 that we initialize any gcc_options instances (PR jit/68446). */
424 gcc_assert (opts_obstack.chunk_size > 0);
425
426 *opts = global_options_init;
427
428 if (opts_set)
429 memset (s: opts_set, c: 0, n: sizeof (*opts_set));
430
431 /* Initialize whether `char' is signed. */
432 opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
433 /* Set this to a special "uninitialized" value. The actual default
434 is set after target options have been processed. */
435 opts->x_flag_short_enums = 2;
436
437 /* Initialize target_flags before default_options_optimization
438 so the latter can modify it. */
439 opts->x_target_flags = targetm_common.default_target_flags;
440
441 /* Some targets have ABI-specified unwind tables. */
442 opts->x_flag_unwind_tables = targetm_common.unwind_tables_default;
443
444 /* Some targets have other target-specific initialization. */
445 targetm_common.option_init_struct (opts);
446}
447
448/* If indicated by the optimization level LEVEL (-Os if SIZE is set,
449 -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT
450 to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language
451 mask LANG_MASK and option handlers HANDLERS. */
452
453static void
454maybe_default_option (struct gcc_options *opts,
455 struct gcc_options *opts_set,
456 const struct default_options *default_opt,
457 int level, bool size, bool fast, bool debug,
458 unsigned int lang_mask,
459 const struct cl_option_handlers *handlers,
460 location_t loc,
461 diagnostic_context *dc)
462{
463 const struct cl_option *option = &cl_options[default_opt->opt_index];
464 bool enabled;
465
466 if (size)
467 gcc_assert (level == 2);
468 if (fast)
469 gcc_assert (level == 3);
470 if (debug)
471 gcc_assert (level == 1);
472
473 switch (default_opt->levels)
474 {
475 case OPT_LEVELS_ALL:
476 enabled = true;
477 break;
478
479 case OPT_LEVELS_0_ONLY:
480 enabled = (level == 0);
481 break;
482
483 case OPT_LEVELS_1_PLUS:
484 enabled = (level >= 1);
485 break;
486
487 case OPT_LEVELS_1_PLUS_SPEED_ONLY:
488 enabled = (level >= 1 && !size && !debug);
489 break;
490
491 case OPT_LEVELS_1_PLUS_NOT_DEBUG:
492 enabled = (level >= 1 && !debug);
493 break;
494
495 case OPT_LEVELS_2_PLUS:
496 enabled = (level >= 2);
497 break;
498
499 case OPT_LEVELS_2_PLUS_SPEED_ONLY:
500 enabled = (level >= 2 && !size && !debug);
501 break;
502
503 case OPT_LEVELS_3_PLUS:
504 enabled = (level >= 3);
505 break;
506
507 case OPT_LEVELS_3_PLUS_AND_SIZE:
508 enabled = (level >= 3 || size);
509 break;
510
511 case OPT_LEVELS_SIZE:
512 enabled = size;
513 break;
514
515 case OPT_LEVELS_FAST:
516 enabled = fast;
517 break;
518
519 case OPT_LEVELS_NONE:
520 default:
521 gcc_unreachable ();
522 }
523
524 if (enabled)
525 handle_generated_option (opts, opts_set, opt_index: default_opt->opt_index,
526 arg: default_opt->arg, value: default_opt->value,
527 lang_mask, kind: DK_UNSPECIFIED, loc,
528 handlers, generated_p: true, dc);
529 else if (default_opt->arg == NULL
530 && !option->cl_reject_negative
531 && !(option->flags & CL_PARAMS))
532 handle_generated_option (opts, opts_set, opt_index: default_opt->opt_index,
533 arg: default_opt->arg, value: !default_opt->value,
534 lang_mask, kind: DK_UNSPECIFIED, loc,
535 handlers, generated_p: true, dc);
536}
537
538/* As indicated by the optimization level LEVEL (-Os if SIZE is set,
539 -Ofast if FAST is set), apply the options in array DEFAULT_OPTS to
540 OPTS and OPTS_SET, diagnostic context DC, location LOC, with
541 language mask LANG_MASK and option handlers HANDLERS. */
542
543static void
544maybe_default_options (struct gcc_options *opts,
545 struct gcc_options *opts_set,
546 const struct default_options *default_opts,
547 int level, bool size, bool fast, bool debug,
548 unsigned int lang_mask,
549 const struct cl_option_handlers *handlers,
550 location_t loc,
551 diagnostic_context *dc)
552{
553 size_t i;
554
555 for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
556 maybe_default_option (opts, opts_set, default_opt: &default_opts[i],
557 level, size, fast, debug,
558 lang_mask, handlers, loc, dc);
559}
560
561/* Table of options enabled by default at different levels.
562 Please keep this list sorted by level and alphabetized within
563 each level; this makes it easier to keep the documentation
564 in sync. */
565
566static const struct default_options default_options_table[] =
567 {
568 /* -O1 and -Og optimizations. */
569 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fcombine_stack_adjustments, NULL, .value: 1 },
570 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fcompare_elim, NULL, .value: 1 },
571 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fcprop_registers, NULL, .value: 1 },
572 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fdefer_pop, NULL, .value: 1 },
573 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fforward_propagate, NULL, .value: 1 },
574 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fguess_branch_probability, NULL, .value: 1 },
575 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fipa_profile, NULL, .value: 1 },
576 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fipa_pure_const, NULL, .value: 1 },
577 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fipa_reference, NULL, .value: 1 },
578 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fipa_reference_addressable, NULL, .value: 1 },
579 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fmerge_constants, NULL, .value: 1 },
580 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fomit_frame_pointer, NULL, .value: 1 },
581 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_freorder_blocks, NULL, .value: 1 },
582 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fshrink_wrap, NULL, .value: 1 },
583 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fsplit_wide_types, NULL, .value: 1 },
584 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fthread_jumps, NULL, .value: 1 },
585 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_builtin_call_dce, NULL, .value: 1 },
586 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_ccp, NULL, .value: 1 },
587 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_ch, NULL, .value: 1 },
588 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_coalesce_vars, NULL, .value: 1 },
589 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_copy_prop, NULL, .value: 1 },
590 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_dce, NULL, .value: 1 },
591 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_dominator_opts, NULL, .value: 1 },
592 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_fre, NULL, .value: 1 },
593 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_sink, NULL, .value: 1 },
594 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_slsr, NULL, .value: 1 },
595 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_ftree_ter, NULL, .value: 1 },
596 { .levels: OPT_LEVELS_1_PLUS, .opt_index: OPT_fvar_tracking, NULL, .value: 1 },
597
598 /* -O1 (and not -Og) optimizations. */
599 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fbranch_count_reg, NULL, .value: 1 },
600#if DELAY_SLOTS
601 { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fdelayed_branch, NULL, 1 },
602#endif
603 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fdse, NULL, .value: 1 },
604 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fif_conversion, NULL, .value: 1 },
605 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fif_conversion2, NULL, .value: 1 },
606 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_finline_functions_called_once, NULL, .value: 1 },
607 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fmove_loop_invariants, NULL, .value: 1 },
608 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fmove_loop_stores, NULL, .value: 1 },
609 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fssa_phiopt, NULL, .value: 1 },
610 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_fipa_modref, NULL, .value: 1 },
611 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_ftree_bit_ccp, NULL, .value: 1 },
612 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_ftree_dse, NULL, .value: 1 },
613 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_ftree_pta, NULL, .value: 1 },
614 { .levels: OPT_LEVELS_1_PLUS_NOT_DEBUG, .opt_index: OPT_ftree_sra, NULL, .value: 1 },
615
616 /* -O2 and -Os optimizations. */
617 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fcaller_saves, NULL, .value: 1 },
618 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fcode_hoisting, NULL, .value: 1 },
619 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fcrossjumping, NULL, .value: 1 },
620 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fcse_follow_jumps, NULL, .value: 1 },
621 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fdevirtualize, NULL, .value: 1 },
622 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fdevirtualize_speculatively, NULL, .value: 1 },
623 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fexpensive_optimizations, NULL, .value: 1 },
624 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fgcse, NULL, .value: 1 },
625 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fhoist_adjacent_loads, NULL, .value: 1 },
626 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_findirect_inlining, NULL, .value: 1 },
627 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_finline_small_functions, NULL, .value: 1 },
628 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_bit_cp, NULL, .value: 1 },
629 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_cp, NULL, .value: 1 },
630 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_icf, NULL, .value: 1 },
631 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_ra, NULL, .value: 1 },
632 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_sra, NULL, .value: 1 },
633 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fipa_vrp, NULL, .value: 1 },
634 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fisolate_erroneous_paths_dereference, NULL, .value: 1 },
635 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_flra_remat, NULL, .value: 1 },
636 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_foptimize_sibling_calls, NULL, .value: 1 },
637 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fpartial_inlining, NULL, .value: 1 },
638 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fpeephole2, NULL, .value: 1 },
639 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_freorder_functions, NULL, .value: 1 },
640 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_frerun_cse_after_loop, NULL, .value: 1 },
641#ifdef INSN_SCHEDULING
642 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fschedule_insns2, NULL, .value: 1 },
643#endif
644 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fstrict_aliasing, NULL, .value: 1 },
645 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fstore_merging, NULL, .value: 1 },
646 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_ftree_pre, NULL, .value: 1 },
647 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_ftree_switch_conversion, NULL, .value: 1 },
648 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_ftree_tail_merge, NULL, .value: 1 },
649 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_ftree_vrp, NULL, .value: 1 },
650 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_fvect_cost_model_, NULL,
651 .value: VECT_COST_MODEL_VERY_CHEAP },
652 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_finline_functions, NULL, .value: 1 },
653 { .levels: OPT_LEVELS_2_PLUS, .opt_index: OPT_ftree_loop_distribute_patterns, NULL, .value: 1 },
654
655 /* -O2 and above optimizations, but not -Os or -Og. */
656 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_falign_functions, NULL, .value: 1 },
657 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_falign_jumps, NULL, .value: 1 },
658 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_falign_labels, NULL, .value: 1 },
659 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_falign_loops, NULL, .value: 1 },
660 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_foptimize_strlen, NULL, .value: 1 },
661 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_freorder_blocks_algorithm_, NULL,
662 .value: REORDER_BLOCKS_ALGORITHM_STC },
663 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_ftree_loop_vectorize, NULL, .value: 1 },
664 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_ftree_slp_vectorize, NULL, .value: 1 },
665 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_fopenmp_target_simd_clone_, NULL,
666 .value: OMP_TARGET_SIMD_CLONE_NOHOST },
667#ifdef INSN_SCHEDULING
668 /* Only run the pre-regalloc scheduling pass if optimizing for speed. */
669 { .levels: OPT_LEVELS_2_PLUS_SPEED_ONLY, .opt_index: OPT_fschedule_insns, NULL, .value: 1 },
670#endif
671
672 /* -O3 and -Os optimizations. */
673
674 /* -O3 optimizations. */
675 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fgcse_after_reload, NULL, .value: 1 },
676 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fipa_cp_clone, NULL, .value: 1 },
677 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_floop_interchange, NULL, .value: 1 },
678 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_floop_unroll_and_jam, NULL, .value: 1 },
679 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fpeel_loops, NULL, .value: 1 },
680 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fpredictive_commoning, NULL, .value: 1 },
681 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fsplit_loops, NULL, .value: 1 },
682 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fsplit_paths, NULL, .value: 1 },
683 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_ftree_loop_distribution, NULL, .value: 1 },
684 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_ftree_partial_pre, NULL, .value: 1 },
685 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_funswitch_loops, NULL, .value: 1 },
686 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fvect_cost_model_, NULL, .value: VECT_COST_MODEL_DYNAMIC },
687 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT_fversion_loops_for_strides, NULL, .value: 1 },
688
689 /* -O3 parameters. */
690 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT__param_max_inline_insns_auto_, NULL, .value: 30 },
691 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT__param_early_inlining_insns_, NULL, .value: 14 },
692 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT__param_inline_heuristics_hint_percent_, NULL, .value: 600 },
693 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT__param_inline_min_speedup_, NULL, .value: 15 },
694 { .levels: OPT_LEVELS_3_PLUS, .opt_index: OPT__param_max_inline_insns_single_, NULL, .value: 200 },
695
696 /* -Ofast adds optimizations to -O3. */
697 { .levels: OPT_LEVELS_FAST, .opt_index: OPT_ffast_math, NULL, .value: 1 },
698 { .levels: OPT_LEVELS_FAST, .opt_index: OPT_fallow_store_data_races, NULL, .value: 1 },
699 { .levels: OPT_LEVELS_FAST, .opt_index: OPT_fsemantic_interposition, NULL, .value: 0 },
700
701 { .levels: OPT_LEVELS_NONE, .opt_index: 0, NULL, .value: 0 }
702 };
703
704/* Default the options in OPTS and OPTS_SET based on the optimization
705 settings in DECODED_OPTIONS and DECODED_OPTIONS_COUNT. */
706void
707default_options_optimization (struct gcc_options *opts,
708 struct gcc_options *opts_set,
709 struct cl_decoded_option *decoded_options,
710 unsigned int decoded_options_count,
711 location_t loc,
712 unsigned int lang_mask,
713 const struct cl_option_handlers *handlers,
714 diagnostic_context *dc)
715{
716 unsigned int i;
717 int opt2;
718 bool openacc_mode = false;
719
720 /* Scan to see what optimization level has been specified. That will
721 determine the default value of many flags. */
722 for (i = 1; i < decoded_options_count; i++)
723 {
724 struct cl_decoded_option *opt = &decoded_options[i];
725 switch (opt->opt_index)
726 {
727 case OPT_O:
728 if (*opt->arg == '\0')
729 {
730 opts->x_optimize = 1;
731 opts->x_optimize_size = 0;
732 opts->x_optimize_fast = 0;
733 opts->x_optimize_debug = 0;
734 }
735 else
736 {
737 const int optimize_val = integral_argument (arg: opt->arg);
738 if (optimize_val == -1)
739 error_at (loc, "argument to %<-O%> should be a non-negative "
740 "integer, %<g%>, %<s%>, %<z%> or %<fast%>");
741 else
742 {
743 opts->x_optimize = optimize_val;
744 if ((unsigned int) opts->x_optimize > 255)
745 opts->x_optimize = 255;
746 opts->x_optimize_size = 0;
747 opts->x_optimize_fast = 0;
748 opts->x_optimize_debug = 0;
749 }
750 }
751 break;
752
753 case OPT_Os:
754 opts->x_optimize_size = 1;
755
756 /* Optimizing for size forces optimize to be 2. */
757 opts->x_optimize = 2;
758 opts->x_optimize_fast = 0;
759 opts->x_optimize_debug = 0;
760 break;
761
762 case OPT_Oz:
763 opts->x_optimize_size = 2;
764
765 /* Optimizing for size forces optimize to be 2. */
766 opts->x_optimize = 2;
767 opts->x_optimize_fast = 0;
768 opts->x_optimize_debug = 0;
769 break;
770
771 case OPT_Ofast:
772 /* -Ofast only adds flags to -O3. */
773 opts->x_optimize_size = 0;
774 opts->x_optimize = 3;
775 opts->x_optimize_fast = 1;
776 opts->x_optimize_debug = 0;
777 break;
778
779 case OPT_Og:
780 /* -Og selects optimization level 1. */
781 opts->x_optimize_size = 0;
782 opts->x_optimize = 1;
783 opts->x_optimize_fast = 0;
784 opts->x_optimize_debug = 1;
785 break;
786
787 case OPT_fopenacc:
788 if (opt->value)
789 openacc_mode = true;
790 break;
791
792 default:
793 /* Ignore other options in this prescan. */
794 break;
795 }
796 }
797
798 maybe_default_options (opts, opts_set, default_opts: default_options_table,
799 level: opts->x_optimize, size: opts->x_optimize_size,
800 fast: opts->x_optimize_fast, debug: opts->x_optimize_debug,
801 lang_mask, handlers, loc, dc);
802
803 /* -O2 param settings. */
804 opt2 = (opts->x_optimize >= 2);
805
806 if (openacc_mode)
807 SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_pta, true);
808
809 /* Track fields in field-sensitive alias analysis. */
810 if (opt2)
811 SET_OPTION_IF_UNSET (opts, opts_set, param_max_fields_for_field_sensitive,
812 100);
813
814 if (opts->x_optimize_size)
815 /* We want to crossjump as much as possible. */
816 SET_OPTION_IF_UNSET (opts, opts_set, param_min_crossjump_insns, 1);
817
818 /* Restrict the amount of work combine does at -Og while retaining
819 most of its useful transforms. */
820 if (opts->x_optimize_debug)
821 SET_OPTION_IF_UNSET (opts, opts_set, param_max_combine_insns, 2);
822
823 /* Allow default optimizations to be specified on a per-machine basis. */
824 maybe_default_options (opts, opts_set,
825 default_opts: targetm_common.option_optimization_table,
826 level: opts->x_optimize, size: opts->x_optimize_size,
827 fast: opts->x_optimize_fast, debug: opts->x_optimize_debug,
828 lang_mask, handlers, loc, dc);
829}
830
831/* Control IPA optimizations based on different live patching LEVEL. */
832static void
833control_options_for_live_patching (struct gcc_options *opts,
834 struct gcc_options *opts_set,
835 enum live_patching_level level,
836 location_t loc)
837{
838 gcc_assert (level > LIVE_PATCHING_NONE);
839
840 switch (level)
841 {
842 case LIVE_PATCHING_INLINE_ONLY_STATIC:
843#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static"
844 if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
845 error_at (loc, "%qs is incompatible with %qs",
846 "-fipa-cp-clone", LIVE_PATCHING_OPTION);
847 else
848 opts->x_flag_ipa_cp_clone = 0;
849
850 if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
851 error_at (loc, "%qs is incompatible with %qs",
852 "-fipa-sra", LIVE_PATCHING_OPTION);
853 else
854 opts->x_flag_ipa_sra = 0;
855
856 if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
857 error_at (loc, "%qs is incompatible with %qs",
858 "-fpartial-inlining", LIVE_PATCHING_OPTION);
859 else
860 opts->x_flag_partial_inlining = 0;
861
862 if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
863 error_at (loc, "%qs is incompatible with %qs",
864 "-fipa-cp", LIVE_PATCHING_OPTION);
865 else
866 opts->x_flag_ipa_cp = 0;
867
868 /* FALLTHROUGH. */
869 case LIVE_PATCHING_INLINE_CLONE:
870#undef LIVE_PATCHING_OPTION
871#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static|inline-clone"
872 /* live patching should disable whole-program optimization. */
873 if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
874 error_at (loc, "%qs is incompatible with %qs",
875 "-fwhole-program", LIVE_PATCHING_OPTION);
876 else
877 opts->x_flag_whole_program = 0;
878
879 /* visibility change should be excluded by !flag_whole_program
880 && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra
881 && !flag_partial_inlining. */
882
883 if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
884 error_at (loc, "%qs is incompatible with %qs",
885 "-fipa-pta", LIVE_PATCHING_OPTION);
886 else
887 opts->x_flag_ipa_pta = 0;
888
889 if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
890 error_at (loc, "%qs is incompatible with %qs",
891 "-fipa-reference", LIVE_PATCHING_OPTION);
892 else
893 opts->x_flag_ipa_reference = 0;
894
895 if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra)
896 error_at (loc, "%qs is incompatible with %qs",
897 "-fipa-ra", LIVE_PATCHING_OPTION);
898 else
899 opts->x_flag_ipa_ra = 0;
900
901 if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
902 error_at (loc, "%qs is incompatible with %qs",
903 "-fipa-icf", LIVE_PATCHING_OPTION);
904 else
905 opts->x_flag_ipa_icf = 0;
906
907 if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
908 error_at (loc, "%qs is incompatible with %qs",
909 "-fipa-icf-functions", LIVE_PATCHING_OPTION);
910 else
911 opts->x_flag_ipa_icf_functions = 0;
912
913 if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
914 error_at (loc, "%qs is incompatible with %qs",
915 "-fipa-icf-variables", LIVE_PATCHING_OPTION);
916 else
917 opts->x_flag_ipa_icf_variables = 0;
918
919 if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
920 error_at (loc, "%qs is incompatible with %qs",
921 "-fipa-bit-cp", LIVE_PATCHING_OPTION);
922 else
923 opts->x_flag_ipa_bit_cp = 0;
924
925 if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
926 error_at (loc, "%qs is incompatible with %qs",
927 "-fipa-vrp", LIVE_PATCHING_OPTION);
928 else
929 opts->x_flag_ipa_vrp = 0;
930
931 if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
932 error_at (loc, "%qs is incompatible with %qs",
933 "-fipa-pure-const", LIVE_PATCHING_OPTION);
934 else
935 opts->x_flag_ipa_pure_const = 0;
936
937 if (opts_set->x_flag_ipa_modref && opts->x_flag_ipa_modref)
938 error_at (loc,
939 "%<-fipa-modref%> is incompatible with %qs",
940 LIVE_PATCHING_OPTION);
941 else
942 opts->x_flag_ipa_modref = 0;
943
944 /* FIXME: disable unreachable code removal. */
945
946 /* discovery of functions/variables with no address taken. */
947 if (opts_set->x_flag_ipa_reference_addressable
948 && opts->x_flag_ipa_reference_addressable)
949 error_at (loc, "%qs is incompatible with %qs",
950 "-fipa-reference-addressable", LIVE_PATCHING_OPTION);
951 else
952 opts->x_flag_ipa_reference_addressable = 0;
953
954 /* ipa stack alignment propagation. */
955 if (opts_set->x_flag_ipa_stack_alignment
956 && opts->x_flag_ipa_stack_alignment)
957 error_at (loc, "%qs is incompatible with %qs",
958 "-fipa-stack-alignment", LIVE_PATCHING_OPTION);
959 else
960 opts->x_flag_ipa_stack_alignment = 0;
961 break;
962 default:
963 gcc_unreachable ();
964 }
965
966#undef LIVE_PATCHING_OPTION
967}
968
969/* --help option argument if set. */
970vec<const char *> help_option_arguments;
971
972/* Return the string name describing a sanitizer argument which has been
973 provided on the command line and has set this particular flag. */
974const char *
975find_sanitizer_argument (struct gcc_options *opts, unsigned int flags)
976{
977 for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
978 {
979 /* Need to find the sanitizer_opts element which:
980 a) Could have set the flags requested.
981 b) Has been set on the command line.
982
983 Can have (a) without (b) if the flag requested is e.g.
984 SANITIZE_ADDRESS, since both -fsanitize=address and
985 -fsanitize=kernel-address set this flag.
986
987 Can have (b) without (a) by requesting more than one sanitizer on the
988 command line. */
989 if ((sanitizer_opts[i].flag & opts->x_flag_sanitize)
990 != sanitizer_opts[i].flag)
991 continue;
992 if ((sanitizer_opts[i].flag & flags) != flags)
993 continue;
994 return sanitizer_opts[i].name;
995 }
996 return NULL;
997}
998
999
1000/* Report an error to the user about sanitizer options they have requested
1001 which have set conflicting flags.
1002
1003 LEFT and RIGHT indicate sanitizer flags which conflict with each other, this
1004 function reports an error if both have been set in OPTS->x_flag_sanitize and
1005 ensures the error identifies the requested command line options that have
1006 set these flags. */
1007static void
1008report_conflicting_sanitizer_options (struct gcc_options *opts, location_t loc,
1009 unsigned int left, unsigned int right)
1010{
1011 unsigned int left_seen = (opts->x_flag_sanitize & left);
1012 unsigned int right_seen = (opts->x_flag_sanitize & right);
1013 if (left_seen && right_seen)
1014 {
1015 const char* left_arg = find_sanitizer_argument (opts, flags: left_seen);
1016 const char* right_arg = find_sanitizer_argument (opts, flags: right_seen);
1017 gcc_assert (left_arg && right_arg);
1018 error_at (loc,
1019 "%<-fsanitize=%s%> is incompatible with %<-fsanitize=%s%>",
1020 left_arg, right_arg);
1021 }
1022}
1023
1024/* After all options at LOC have been read into OPTS and OPTS_SET,
1025 finalize settings of those options and diagnose incompatible
1026 combinations. */
1027void
1028finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
1029 location_t loc)
1030{
1031 if (opts->x_dump_base_name
1032 && ! opts->x_dump_base_name_prefixed)
1033 {
1034 const char *sep = opts->x_dump_base_name;
1035
1036 for (; *sep; sep++)
1037 if (IS_DIR_SEPARATOR (*sep))
1038 break;
1039
1040 if (*sep)
1041 /* If dump_base_path contains subdirectories, don't prepend
1042 anything. */;
1043 else if (opts->x_dump_dir_name)
1044 /* We have a DUMP_DIR_NAME, prepend that. */
1045 opts->x_dump_base_name = opts_concat (first: opts->x_dump_dir_name,
1046 opts->x_dump_base_name, NULL);
1047
1048 /* It is definitely prefixed now. */
1049 opts->x_dump_base_name_prefixed = true;
1050 }
1051
1052 /* Handle related options for unit-at-a-time, toplevel-reorder, and
1053 section-anchors. */
1054 if (!opts->x_flag_unit_at_a_time)
1055 {
1056 if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
1057 error_at (loc, "section anchors must be disabled when unit-at-a-time "
1058 "is disabled");
1059 opts->x_flag_section_anchors = 0;
1060 if (opts->x_flag_toplevel_reorder == 1)
1061 error_at (loc, "toplevel reorder must be disabled when unit-at-a-time "
1062 "is disabled");
1063 opts->x_flag_toplevel_reorder = 0;
1064 }
1065
1066 /* -fself-test depends on the state of the compiler prior to
1067 compiling anything. Ideally it should be run on an empty source
1068 file. However, in case we get run with actual source, assume
1069 -fsyntax-only which will inhibit any compiler initialization
1070 which may confuse the self tests. */
1071 if (opts->x_flag_self_test)
1072 opts->x_flag_syntax_only = 1;
1073
1074 if (opts->x_flag_tm && opts->x_flag_non_call_exceptions)
1075 sorry ("transactional memory is not supported with non-call exceptions");
1076
1077 /* Unless the user has asked for section anchors, we disable toplevel
1078 reordering at -O0 to disable transformations that might be surprising
1079 to end users and to get -fno-toplevel-reorder tested. */
1080 if (!opts->x_optimize
1081 && opts->x_flag_toplevel_reorder == 2
1082 && !(opts->x_flag_section_anchors && opts_set->x_flag_section_anchors))
1083 {
1084 opts->x_flag_toplevel_reorder = 0;
1085 opts->x_flag_section_anchors = 0;
1086 }
1087 if (!opts->x_flag_toplevel_reorder)
1088 {
1089 if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
1090 error_at (loc, "section anchors must be disabled when toplevel reorder"
1091 " is disabled");
1092 opts->x_flag_section_anchors = 0;
1093 }
1094
1095 if (!opts->x_flag_opts_finished)
1096 {
1097 /* We initialize opts->x_flag_pie to -1 so that targets can set a
1098 default value. */
1099 if (opts->x_flag_pie == -1)
1100 {
1101 /* We initialize opts->x_flag_pic to -1 so that we can tell if
1102 -fpic, -fPIC, -fno-pic or -fno-PIC is used. */
1103 if (opts->x_flag_pic == -1)
1104 opts->x_flag_pie = DEFAULT_FLAG_PIE;
1105 else
1106 opts->x_flag_pie = 0;
1107 }
1108 /* If -fPIE or -fpie is used, turn on PIC. */
1109 if (opts->x_flag_pie)
1110 opts->x_flag_pic = opts->x_flag_pie;
1111 else if (opts->x_flag_pic == -1)
1112 opts->x_flag_pic = 0;
1113 if (opts->x_flag_pic && !opts->x_flag_pie)
1114 opts->x_flag_shlib = 1;
1115 opts->x_flag_opts_finished = true;
1116 }
1117
1118 /* We initialize opts->x_flag_stack_protect to -1 so that targets
1119 can set a default value. */
1120 if (opts->x_flag_stack_protect == -1)
1121 opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
1122
1123 if (opts->x_optimize == 0)
1124 {
1125 /* Inlining does not work if not optimizing,
1126 so force it not to be done. */
1127 opts->x_warn_inline = 0;
1128 opts->x_flag_no_inline = 1;
1129 }
1130
1131 /* At -O0 or -Og, turn __builtin_unreachable into a trap. */
1132 if (!opts->x_optimize || opts->x_optimize_debug)
1133 SET_OPTION_IF_UNSET (opts, opts_set, flag_unreachable_traps, true);
1134
1135 /* Pipelining of outer loops is only possible when general pipelining
1136 capabilities are requested. */
1137 if (!opts->x_flag_sel_sched_pipelining)
1138 opts->x_flag_sel_sched_pipelining_outer_loops = 0;
1139
1140 if (opts->x_flag_conserve_stack)
1141 {
1142 SET_OPTION_IF_UNSET (opts, opts_set, param_large_stack_frame, 100);
1143 SET_OPTION_IF_UNSET (opts, opts_set, param_stack_frame_growth, 40);
1144 }
1145
1146 if (opts->x_flag_lto)
1147 {
1148#ifdef ENABLE_LTO
1149 opts->x_flag_generate_lto = 1;
1150
1151 /* When generating IL, do not operate in whole-program mode.
1152 Otherwise, symbols will be privatized too early, causing link
1153 errors later. */
1154 opts->x_flag_whole_program = 0;
1155#else
1156 error_at (loc, "LTO support has not been enabled in this configuration");
1157#endif
1158 if (!opts->x_flag_fat_lto_objects
1159 && (!HAVE_LTO_PLUGIN
1160 || (opts_set->x_flag_use_linker_plugin
1161 && !opts->x_flag_use_linker_plugin)))
1162 {
1163 if (opts_set->x_flag_fat_lto_objects)
1164 error_at (loc, "%<-fno-fat-lto-objects%> are supported only with "
1165 "linker plugin");
1166 opts->x_flag_fat_lto_objects = 1;
1167 }
1168
1169 /* -gsplit-dwarf isn't compatible with LTO, see PR88389. */
1170 if (opts->x_dwarf_split_debug_info)
1171 {
1172 inform (loc, "%<-gsplit-dwarf%> is not supported with LTO,"
1173 " disabling");
1174 opts->x_dwarf_split_debug_info = 0;
1175 }
1176 }
1177
1178 /* We initialize opts->x_flag_split_stack to -1 so that targets can set a
1179 default value if they choose based on other options. */
1180 if (opts->x_flag_split_stack == -1)
1181 opts->x_flag_split_stack = 0;
1182 else if (opts->x_flag_split_stack)
1183 {
1184 if (!targetm_common.supports_split_stack (true, opts))
1185 {
1186 error_at (loc, "%<-fsplit-stack%> is not supported by "
1187 "this compiler configuration");
1188 opts->x_flag_split_stack = 0;
1189 }
1190 }
1191
1192 /* If stack splitting is turned on, and the user did not explicitly
1193 request function partitioning, turn off partitioning, as it
1194 confuses the linker when trying to handle partitioned split-stack
1195 code that calls a non-split-stack functions. But if partitioning
1196 was turned on explicitly just hope for the best. */
1197 if (opts->x_flag_split_stack
1198 && opts->x_flag_reorder_blocks_and_partition)
1199 SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_blocks_and_partition, 0);
1200
1201 if (opts->x_flag_reorder_blocks_and_partition)
1202 SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_functions, 1);
1203
1204 /* The -gsplit-dwarf option requires -ggnu-pubnames. */
1205 if (opts->x_dwarf_split_debug_info)
1206 opts->x_debug_generate_pub_sections = 2;
1207
1208 if ((opts->x_flag_sanitize
1209 & (SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS)) == 0)
1210 {
1211 if (opts->x_flag_sanitize & SANITIZE_POINTER_COMPARE)
1212 error_at (loc,
1213 "%<-fsanitize=pointer-compare%> must be combined with "
1214 "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
1215 if (opts->x_flag_sanitize & SANITIZE_POINTER_SUBTRACT)
1216 error_at (loc,
1217 "%<-fsanitize=pointer-subtract%> must be combined with "
1218 "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
1219 }
1220
1221 /* Address sanitizers conflict with the thread sanitizer. */
1222 report_conflicting_sanitizer_options (opts, loc, left: SANITIZE_THREAD,
1223 right: SANITIZE_ADDRESS);
1224 report_conflicting_sanitizer_options (opts, loc, left: SANITIZE_THREAD,
1225 right: SANITIZE_HWADDRESS);
1226 /* The leak sanitizer conflicts with the thread sanitizer. */
1227 report_conflicting_sanitizer_options (opts, loc, left: SANITIZE_LEAK,
1228 right: SANITIZE_THREAD);
1229
1230 /* No combination of HWASAN and ASAN work together. */
1231 report_conflicting_sanitizer_options (opts, loc,
1232 left: SANITIZE_HWADDRESS, right: SANITIZE_ADDRESS);
1233
1234 /* The userspace and kernel address sanitizers conflict with each other. */
1235 report_conflicting_sanitizer_options (opts, loc, left: SANITIZE_USER_HWADDRESS,
1236 right: SANITIZE_KERNEL_HWADDRESS);
1237 report_conflicting_sanitizer_options (opts, loc, left: SANITIZE_USER_ADDRESS,
1238 right: SANITIZE_KERNEL_ADDRESS);
1239
1240 /* Check error recovery for -fsanitize-recover option. */
1241 for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
1242 if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
1243 && !sanitizer_opts[i].can_recover)
1244 error_at (loc, "%<-fsanitize-recover=%s%> is not supported",
1245 sanitizer_opts[i].name);
1246
1247 /* Check -fsanitize-trap option. */
1248 for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
1249 if ((opts->x_flag_sanitize_trap & sanitizer_opts[i].flag)
1250 && !sanitizer_opts[i].can_trap
1251 /* Allow -fsanitize-trap=all or -fsanitize-trap=undefined
1252 to set flag_sanitize_trap & SANITIZE_VPTR bit which will
1253 effectively disable -fsanitize=vptr, just disallow
1254 explicit -fsanitize-trap=vptr. */
1255 && sanitizer_opts[i].flag != SANITIZE_VPTR)
1256 error_at (loc, "%<-fsanitize-trap=%s%> is not supported",
1257 sanitizer_opts[i].name);
1258
1259 /* When instrumenting the pointers, we don't want to remove
1260 the null pointer checks. */
1261 if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
1262 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
1263 opts->x_flag_delete_null_pointer_checks = 0;
1264
1265 /* Aggressive compiler optimizations may cause false negatives. */
1266 if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE))
1267 opts->x_flag_aggressive_loop_optimizations = 0;
1268
1269 /* Enable -fsanitize-address-use-after-scope if either address sanitizer is
1270 enabled. */
1271 if (opts->x_flag_sanitize
1272 & (SANITIZE_USER_ADDRESS | SANITIZE_USER_HWADDRESS))
1273 SET_OPTION_IF_UNSET (opts, opts_set, flag_sanitize_address_use_after_scope,
1274 true);
1275
1276 /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope
1277 is enabled. */
1278 if (opts->x_flag_sanitize_address_use_after_scope)
1279 {
1280 if (opts->x_flag_stack_reuse != SR_NONE
1281 && opts_set->x_flag_stack_reuse != SR_NONE)
1282 error_at (loc,
1283 "%<-fsanitize-address-use-after-scope%> requires "
1284 "%<-fstack-reuse=none%> option");
1285
1286 opts->x_flag_stack_reuse = SR_NONE;
1287 }
1288
1289 if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && opts->x_flag_tm)
1290 sorry ("transactional memory is not supported with %<-fsanitize=address%>");
1291
1292 if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm)
1293 sorry ("transactional memory is not supported with "
1294 "%<-fsanitize=kernel-address%>");
1295
1296 /* Currently live patching is not support for LTO. */
1297 if (opts->x_flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC && opts->x_flag_lto)
1298 sorry ("live patching (with %qs) is not supported with LTO",
1299 "inline-only-static");
1300
1301 /* Currently vtable verification is not supported for LTO */
1302 if (opts->x_flag_vtable_verify && opts->x_flag_lto)
1303 sorry ("vtable verification is not supported with LTO");
1304
1305 /* Control IPA optimizations based on different -flive-patching level. */
1306 if (opts->x_flag_live_patching)
1307 control_options_for_live_patching (opts, opts_set,
1308 level: opts->x_flag_live_patching,
1309 loc);
1310
1311 /* Allow cunroll to grow size accordingly. */
1312 if (!opts_set->x_flag_cunroll_grow_size)
1313 opts->x_flag_cunroll_grow_size
1314 = (opts->x_flag_unroll_loops
1315 || opts->x_flag_peel_loops
1316 || opts->x_optimize >= 3);
1317
1318 /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
1319 if (opts->x_flag_cx_limited_range)
1320 opts->x_flag_complex_method = 0;
1321 else if (opts_set->x_flag_cx_limited_range)
1322 opts->x_flag_complex_method = opts->x_flag_default_complex_method;
1323
1324 /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
1325 if (opts->x_flag_cx_fortran_rules)
1326 opts->x_flag_complex_method = 1;
1327 else if (opts_set->x_flag_cx_fortran_rules)
1328 opts->x_flag_complex_method = opts->x_flag_default_complex_method;
1329
1330 /* Use -fvect-cost-model=cheap instead of -fvect-cost-mode=very-cheap
1331 by default with explicit -ftree-{loop,slp}-vectorize. */
1332 if (opts->x_optimize == 2
1333 && (opts_set->x_flag_tree_loop_vectorize
1334 || opts_set->x_flag_tree_vectorize))
1335 SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model,
1336 VECT_COST_MODEL_CHEAP);
1337
1338 if (opts->x_flag_gtoggle)
1339 {
1340 /* Make sure to process -gtoggle only once. */
1341 opts->x_flag_gtoggle = false;
1342 if (opts->x_debug_info_level == DINFO_LEVEL_NONE)
1343 {
1344 opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
1345
1346 if (opts->x_write_symbols == NO_DEBUG)
1347 opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE;
1348 }
1349 else
1350 opts->x_debug_info_level = DINFO_LEVEL_NONE;
1351 }
1352
1353 if (!opts_set->x_debug_nonbind_markers_p)
1354 opts->x_debug_nonbind_markers_p
1355 = (opts->x_optimize
1356 && opts->x_debug_info_level >= DINFO_LEVEL_NORMAL
1357 && dwarf_debuginfo_p (opts)
1358 && !(opts->x_flag_selective_scheduling
1359 || opts->x_flag_selective_scheduling2));
1360
1361 /* We know which debug output will be used so we can set flag_var_tracking
1362 and flag_var_tracking_uninit if the user has not specified them. */
1363 if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL
1364 || !dwarf_debuginfo_p (opts)
1365 /* We have not yet initialized debug hooks so match that to check
1366 whether we're only doing DWARF2_LINENO_DEBUGGING_INFO. */
1367#ifndef DWARF2_DEBUGGING_INFO
1368 || true
1369#endif
1370 )
1371 {
1372 if ((opts_set->x_flag_var_tracking && opts->x_flag_var_tracking == 1)
1373 || (opts_set->x_flag_var_tracking_uninit
1374 && opts->x_flag_var_tracking_uninit == 1))
1375 {
1376 if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
1377 warning_at (UNKNOWN_LOCATION, 0,
1378 "variable tracking requested, but useless unless "
1379 "producing debug info");
1380 else
1381 warning_at (UNKNOWN_LOCATION, 0,
1382 "variable tracking requested, but not supported "
1383 "by this debug format");
1384 }
1385 opts->x_flag_var_tracking = 0;
1386 opts->x_flag_var_tracking_uninit = 0;
1387 opts->x_flag_var_tracking_assignments = 0;
1388 }
1389
1390 /* One could use EnabledBy, but it would lead to a circular dependency. */
1391 if (!opts_set->x_flag_var_tracking_uninit)
1392 opts->x_flag_var_tracking_uninit = opts->x_flag_var_tracking;
1393
1394 if (!opts_set->x_flag_var_tracking_assignments)
1395 opts->x_flag_var_tracking_assignments
1396 = (opts->x_flag_var_tracking
1397 && !(opts->x_flag_selective_scheduling
1398 || opts->x_flag_selective_scheduling2));
1399
1400 if (opts->x_flag_var_tracking_assignments_toggle)
1401 opts->x_flag_var_tracking_assignments
1402 = !opts->x_flag_var_tracking_assignments;
1403
1404 if (opts->x_flag_var_tracking_assignments && !opts->x_flag_var_tracking)
1405 opts->x_flag_var_tracking = opts->x_flag_var_tracking_assignments = -1;
1406
1407 if (opts->x_flag_var_tracking_assignments
1408 && (opts->x_flag_selective_scheduling
1409 || opts->x_flag_selective_scheduling2))
1410 warning_at (loc, 0,
1411 "var-tracking-assignments changes selective scheduling");
1412
1413 if (opts->x_flag_syntax_only)
1414 {
1415 opts->x_write_symbols = NO_DEBUG;
1416 opts->x_profile_flag = 0;
1417 }
1418
1419 if (opts->x_warn_strict_flex_arrays)
1420 if (opts->x_flag_strict_flex_arrays == 0)
1421 {
1422 opts->x_warn_strict_flex_arrays = 0;
1423 warning_at (UNKNOWN_LOCATION, 0,
1424 "%<-Wstrict-flex-arrays%> is ignored when"
1425 " %<-fstrict-flex-arrays%> is not present");
1426 }
1427
1428 diagnose_options (opts, opts_set, loc);
1429}
1430
1431/* The function diagnoses incompatible combinations for provided options
1432 (OPTS and OPTS_SET) at a given LOCation. The function is called both
1433 when command line is parsed (after the target optimization hook) and
1434 when an optimize/target attribute (or pragma) is used. */
1435
1436void diagnose_options (gcc_options *opts, gcc_options *opts_set,
1437 location_t loc)
1438{
1439 /* The optimization to partition hot and cold basic blocks into separate
1440 sections of the .o and executable files does not work (currently)
1441 with exception handling. This is because there is no support for
1442 generating unwind info. If opts->x_flag_exceptions is turned on
1443 we need to turn off the partitioning optimization. */
1444
1445 enum unwind_info_type ui_except
1446 = targetm_common.except_unwind_info (opts);
1447
1448 if (opts->x_flag_exceptions
1449 && opts->x_flag_reorder_blocks_and_partition
1450 && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
1451 {
1452 if (opts_set->x_flag_reorder_blocks_and_partition)
1453 inform (loc,
1454 "%<-freorder-blocks-and-partition%> does not work "
1455 "with exceptions on this architecture");
1456 opts->x_flag_reorder_blocks_and_partition = 0;
1457 opts->x_flag_reorder_blocks = 1;
1458 }
1459
1460 /* If user requested unwind info, then turn off the partitioning
1461 optimization. */
1462
1463 if (opts->x_flag_unwind_tables
1464 && !targetm_common.unwind_tables_default
1465 && opts->x_flag_reorder_blocks_and_partition
1466 && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
1467 {
1468 if (opts_set->x_flag_reorder_blocks_and_partition)
1469 inform (loc,
1470 "%<-freorder-blocks-and-partition%> does not support "
1471 "unwind info on this architecture");
1472 opts->x_flag_reorder_blocks_and_partition = 0;
1473 opts->x_flag_reorder_blocks = 1;
1474 }
1475
1476 /* If the target requested unwind info, then turn off the partitioning
1477 optimization with a different message. Likewise, if the target does not
1478 support named sections. */
1479
1480 if (opts->x_flag_reorder_blocks_and_partition
1481 && (!targetm_common.have_named_sections
1482 || (opts->x_flag_unwind_tables
1483 && targetm_common.unwind_tables_default
1484 && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))))
1485 {
1486 if (opts_set->x_flag_reorder_blocks_and_partition)
1487 inform (loc,
1488 "%<-freorder-blocks-and-partition%> does not work "
1489 "on this architecture");
1490 opts->x_flag_reorder_blocks_and_partition = 0;
1491 opts->x_flag_reorder_blocks = 1;
1492 }
1493
1494
1495}
1496
1497#define LEFT_COLUMN 27
1498
1499/* Output ITEM, of length ITEM_WIDTH, in the left column,
1500 followed by word-wrapped HELP in a second column. */
1501static void
1502wrap_help (const char *help,
1503 const char *item,
1504 unsigned int item_width,
1505 unsigned int columns)
1506{
1507 unsigned int col_width = LEFT_COLUMN;
1508 unsigned int remaining, room, len;
1509
1510 remaining = strlen (s: help);
1511
1512 do
1513 {
1514 room = columns - 3 - MAX (col_width, item_width);
1515 if (room > columns)
1516 room = 0;
1517 len = remaining;
1518
1519 if (room < len)
1520 {
1521 unsigned int i;
1522
1523 for (i = 0; help[i]; i++)
1524 {
1525 if (i >= room && len != remaining)
1526 break;
1527 if (help[i] == ' ')
1528 len = i;
1529 else if ((help[i] == '-' || help[i] == '/')
1530 && help[i + 1] != ' '
1531 && i > 0 && ISALPHA (help[i - 1]))
1532 len = i + 1;
1533 }
1534 }
1535
1536 printf (format: " %-*.*s %.*s\n", col_width, item_width, item, len, help);
1537 item_width = 0;
1538 while (help[len] == ' ')
1539 len++;
1540 help += len;
1541 remaining -= len;
1542 }
1543 while (remaining);
1544}
1545
1546/* Data structure used to print list of valid option values. */
1547
1548class option_help_tuple
1549{
1550public:
1551 option_help_tuple (int code, vec<const char *> values):
1552 m_code (code), m_values (values)
1553 {}
1554
1555 /* Code of an option. */
1556 int m_code;
1557
1558 /* List of possible values. */
1559 vec<const char *> m_values;
1560};
1561
1562/* Print help for a specific front-end, etc. */
1563static void
1564print_filtered_help (unsigned int include_flags,
1565 unsigned int exclude_flags,
1566 unsigned int any_flags,
1567 unsigned int columns,
1568 struct gcc_options *opts,
1569 unsigned int lang_mask)
1570{
1571 unsigned int i;
1572 const char *help;
1573 bool found = false;
1574 bool displayed = false;
1575 char new_help[256];
1576
1577 if (!opts->x_help_printed)
1578 opts->x_help_printed = XCNEWVAR (char, cl_options_count);
1579
1580 if (!opts->x_help_enum_printed)
1581 opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
1582
1583 auto_vec<option_help_tuple> help_tuples;
1584
1585 for (i = 0; i < cl_options_count; i++)
1586 {
1587 const struct cl_option *option = cl_options + i;
1588 unsigned int len;
1589 const char *opt;
1590 const char *tab;
1591
1592 if (include_flags == 0
1593 || ((option->flags & include_flags) != include_flags))
1594 {
1595 if ((option->flags & any_flags) == 0)
1596 continue;
1597 }
1598
1599 /* Skip unwanted switches. */
1600 if ((option->flags & exclude_flags) != 0)
1601 continue;
1602
1603 /* The driver currently prints its own help text. */
1604 if ((option->flags & CL_DRIVER) != 0
1605 && (option->flags & (((1U << cl_lang_count) - 1)
1606 | CL_COMMON | CL_TARGET)) == 0)
1607 continue;
1608
1609 /* If an option contains a language specification,
1610 exclude it from common unless all languages are present. */
1611 if ((include_flags & CL_COMMON)
1612 && !(option->flags & CL_DRIVER)
1613 && (option->flags & CL_LANG_ALL)
1614 && (option->flags & CL_LANG_ALL) != CL_LANG_ALL)
1615 continue;
1616
1617 found = true;
1618 /* Skip switches that have already been printed. */
1619 if (opts->x_help_printed[i])
1620 continue;
1621
1622 opts->x_help_printed[i] = true;
1623
1624 help = option->help;
1625 if (help == NULL)
1626 {
1627 if (exclude_flags & CL_UNDOCUMENTED)
1628 continue;
1629
1630 help = undocumented_msg;
1631 }
1632
1633 /* Get the translation. */
1634 help = _(help);
1635
1636 if (option->alias_target < N_OPTS
1637 && cl_options [option->alias_target].help)
1638 {
1639 const struct cl_option *target = cl_options + option->alias_target;
1640 if (option->help == NULL)
1641 {
1642 /* The option is undocumented but is an alias for an option that
1643 is documented. If the option has alias arguments, then its
1644 purpose is to provide certain arguments to the other option, so
1645 inform the reader of this. Otherwise, point the reader to the
1646 other option in preference to the former. */
1647
1648 if (option->alias_arg)
1649 {
1650 if (option->neg_alias_arg)
1651 snprintf (s: new_help, maxlen: sizeof new_help,
1652 _("Same as %s%s (or, in negated form, %s%s)."),
1653 target->opt_text, option->alias_arg,
1654 target->opt_text, option->neg_alias_arg);
1655 else
1656 snprintf (s: new_help, maxlen: sizeof new_help,
1657 _("Same as %s%s."),
1658 target->opt_text, option->alias_arg);
1659 }
1660 else
1661 snprintf (s: new_help, maxlen: sizeof new_help,
1662 _("Same as %s."),
1663 target->opt_text);
1664 }
1665 else
1666 {
1667 /* For documented options with aliases, mention the aliased
1668 option's name for reference. */
1669 snprintf (s: new_help, maxlen: sizeof new_help,
1670 _("%s Same as %s."),
1671 help, cl_options [option->alias_target].opt_text);
1672 }
1673
1674 help = new_help;
1675 }
1676
1677 if (option->warn_message)
1678 {
1679 /* Mention that the use of the option will trigger a warning. */
1680 if (help == new_help)
1681 snprintf (s: new_help + strlen (s: new_help),
1682 maxlen: sizeof new_help - strlen (s: new_help),
1683 format: " %s", _(use_diagnosed_msg));
1684 else
1685 snprintf (s: new_help, maxlen: sizeof new_help,
1686 format: "%s %s", help, _(use_diagnosed_msg));
1687
1688 help = new_help;
1689 }
1690
1691 /* Find the gap between the name of the
1692 option and its descriptive text. */
1693 tab = strchr (s: help, c: '\t');
1694 if (tab)
1695 {
1696 len = tab - help;
1697 opt = help;
1698 help = tab + 1;
1699 }
1700 else
1701 {
1702 opt = option->opt_text;
1703 len = strlen (s: opt);
1704 }
1705
1706 /* With the -Q option enabled we change the descriptive text associated
1707 with an option to be an indication of its current setting. */
1708 if (!opts->x_quiet_flag)
1709 {
1710 void *flag_var = option_flag_var (opt_index: i, opts);
1711
1712 if (len < (LEFT_COLUMN + 2))
1713 strcpy (dest: new_help, src: "\t\t");
1714 else
1715 strcpy (dest: new_help, src: "\t");
1716
1717 /* Set to print whether the option is enabled or disabled,
1718 or, if it's an alias for another option, the name of
1719 the aliased option. */
1720 bool print_state = false;
1721
1722 if (flag_var != NULL
1723 && option->var_type != CLVC_DEFER)
1724 {
1725 /* If OPTION is only available for a specific subset
1726 of languages other than this one, mention them. */
1727 bool avail_for_lang = true;
1728 if (unsigned langset = option->flags & CL_LANG_ALL)
1729 {
1730 if (!(langset & lang_mask))
1731 {
1732 avail_for_lang = false;
1733 strcat (dest: new_help, _("[available in "));
1734 for (unsigned i = 0, n = 0; (1U << i) < CL_LANG_ALL; ++i)
1735 if (langset & (1U << i))
1736 {
1737 if (n++)
1738 strcat (dest: new_help, src: ", ");
1739 strcat (dest: new_help, src: lang_names[i]);
1740 }
1741 strcat (dest: new_help, src: "]");
1742 }
1743 }
1744 if (!avail_for_lang)
1745 ; /* Print nothing else if the option is not available
1746 in the current language. */
1747 else if (option->flags & CL_JOINED)
1748 {
1749 if (option->var_type == CLVC_STRING)
1750 {
1751 if (* (const char **) flag_var != NULL)
1752 snprintf (s: new_help + strlen (s: new_help),
1753 maxlen: sizeof (new_help) - strlen (s: new_help),
1754 format: "%s", * (const char **) flag_var);
1755 }
1756 else if (option->var_type == CLVC_ENUM)
1757 {
1758 const struct cl_enum *e = &cl_enums[option->var_enum];
1759 int value;
1760 const char *arg = NULL;
1761
1762 value = e->get (flag_var);
1763 enum_value_to_arg (enum_args: e->values, argp: &arg, value, lang_mask);
1764 if (arg == NULL)
1765 arg = _("[default]");
1766 snprintf (s: new_help + strlen (s: new_help),
1767 maxlen: sizeof (new_help) - strlen (s: new_help),
1768 format: "%s", arg);
1769 }
1770 else
1771 {
1772 if (option->cl_host_wide_int)
1773 sprintf (s: new_help + strlen (s: new_help),
1774 _("%llu bytes"), (unsigned long long)
1775 *(unsigned HOST_WIDE_INT *) flag_var);
1776 else
1777 sprintf (s: new_help + strlen (s: new_help),
1778 format: "%i", * (int *) flag_var);
1779 }
1780 }
1781 else
1782 print_state = true;
1783 }
1784 else
1785 /* When there is no argument, print the option state only
1786 if the option takes no argument. */
1787 print_state = !(option->flags & CL_JOINED);
1788
1789 if (print_state)
1790 {
1791 if (option->alias_target < N_OPTS
1792 && option->alias_target != OPT_SPECIAL_warn_removed
1793 && option->alias_target != OPT_SPECIAL_ignore
1794 && option->alias_target != OPT_SPECIAL_input_file
1795 && option->alias_target != OPT_SPECIAL_program_name
1796 && option->alias_target != OPT_SPECIAL_unknown)
1797 {
1798 const struct cl_option *target
1799 = &cl_options[option->alias_target];
1800 sprintf (s: new_help + strlen (s: new_help), format: "%s%s",
1801 target->opt_text,
1802 option->alias_arg ? option->alias_arg : "");
1803 }
1804 else if (option->alias_target == OPT_SPECIAL_ignore)
1805 strcat (dest: new_help, src: ("[ignored]"));
1806 else
1807 {
1808 /* Print the state for an on/off option. */
1809 int ena = option_enabled (opt_idx: i, lang_mask, opts);
1810 if (ena > 0)
1811 strcat (dest: new_help, _("[enabled]"));
1812 else if (ena == 0)
1813 strcat (dest: new_help, _("[disabled]"));
1814 }
1815 }
1816
1817 help = new_help;
1818 }
1819
1820 if (option->range_max != -1 && tab == NULL)
1821 {
1822 char b[128];
1823 snprintf (s: b, maxlen: sizeof (b), format: "<%d,%d>", option->range_min,
1824 option->range_max);
1825 opt = concat (opt, b, NULL);
1826 len += strlen (s: b);
1827 }
1828
1829 wrap_help (help, item: opt, item_width: len, columns);
1830 displayed = true;
1831
1832 if (option->var_type == CLVC_ENUM
1833 && opts->x_help_enum_printed[option->var_enum] != 2)
1834 opts->x_help_enum_printed[option->var_enum] = 1;
1835 else
1836 {
1837 vec<const char *> option_values
1838 = targetm_common.get_valid_option_values (i, NULL);
1839 if (!option_values.is_empty ())
1840 help_tuples.safe_push (obj: option_help_tuple (i, option_values));
1841 }
1842 }
1843
1844 if (! found)
1845 {
1846 unsigned int langs = include_flags & CL_LANG_ALL;
1847
1848 if (langs == 0)
1849 printf (_(" No options with the desired characteristics were found\n"));
1850 else
1851 {
1852 unsigned int i;
1853
1854 /* PR 31349: Tell the user how to see all of the
1855 options supported by a specific front end. */
1856 for (i = 0; (1U << i) < CL_LANG_ALL; i ++)
1857 if ((1U << i) & langs)
1858 printf (_(" None found. Use --help=%s to show *all* the options supported by the %s front-end.\n"),
1859 lang_names[i], lang_names[i]);
1860 }
1861
1862 }
1863 else if (! displayed)
1864 printf (_(" All options with the desired characteristics have already been displayed\n"));
1865
1866 putchar (c: '\n');
1867
1868 /* Print details of enumerated option arguments, if those
1869 enumerations have help text headings provided. If no help text
1870 is provided, presume that the possible values are listed in the
1871 help text for the relevant options. */
1872 for (i = 0; i < cl_enums_count; i++)
1873 {
1874 unsigned int j, pos;
1875
1876 if (opts->x_help_enum_printed[i] != 1)
1877 continue;
1878 if (cl_enums[i].help == NULL)
1879 continue;
1880 printf (format: " %s\n ", _(cl_enums[i].help));
1881 pos = 4;
1882 for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
1883 {
1884 unsigned int len = strlen (s: cl_enums[i].values[j].arg);
1885
1886 if (pos > 4 && pos + 1 + len <= columns)
1887 {
1888 printf (format: " %s", cl_enums[i].values[j].arg);
1889 pos += 1 + len;
1890 }
1891 else
1892 {
1893 if (pos > 4)
1894 {
1895 printf (format: "\n ");
1896 pos = 4;
1897 }
1898 printf (format: "%s", cl_enums[i].values[j].arg);
1899 pos += len;
1900 }
1901 }
1902 printf (format: "\n\n");
1903 opts->x_help_enum_printed[i] = 2;
1904 }
1905
1906 for (unsigned i = 0; i < help_tuples.length (); i++)
1907 {
1908 const struct cl_option *option = cl_options + help_tuples[i].m_code;
1909 printf (_(" Known valid arguments for %s option:\n "),
1910 option->opt_text);
1911 for (unsigned j = 0; j < help_tuples[i].m_values.length (); j++)
1912 printf (format: " %s", help_tuples[i].m_values[j]);
1913 printf (format: "\n\n");
1914 }
1915}
1916
1917/* Display help for a specified type of option.
1918 The options must have ALL of the INCLUDE_FLAGS set
1919 ANY of the flags in the ANY_FLAGS set
1920 and NONE of the EXCLUDE_FLAGS set. The current option state is in
1921 OPTS; LANG_MASK is used for interpreting enumerated option state. */
1922static void
1923print_specific_help (unsigned int include_flags,
1924 unsigned int exclude_flags,
1925 unsigned int any_flags,
1926 struct gcc_options *opts,
1927 unsigned int lang_mask)
1928{
1929 unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
1930 const char * description = NULL;
1931 const char * descrip_extra = "";
1932 size_t i;
1933 unsigned int flag;
1934
1935 /* Sanity check: Make sure that we do not have more
1936 languages than we have bits available to enumerate them. */
1937 gcc_assert ((1U << cl_lang_count) <= CL_MIN_OPTION_CLASS);
1938
1939 /* If we have not done so already, obtain
1940 the desired maximum width of the output. */
1941 if (opts->x_help_columns == 0)
1942 {
1943 opts->x_help_columns = get_terminal_width ();
1944 if (opts->x_help_columns == INT_MAX)
1945 /* Use a reasonable default. */
1946 opts->x_help_columns = 80;
1947 }
1948
1949 /* Decide upon the title for the options that we are going to display. */
1950 for (i = 0, flag = 1; flag <= CL_MAX_OPTION_CLASS; flag <<= 1, i ++)
1951 {
1952 switch (flag & include_flags)
1953 {
1954 case 0:
1955 case CL_DRIVER:
1956 break;
1957
1958 case CL_TARGET:
1959 description = _("The following options are target specific");
1960 break;
1961 case CL_WARNING:
1962 description = _("The following options control compiler warning messages");
1963 break;
1964 case CL_OPTIMIZATION:
1965 description = _("The following options control optimizations");
1966 break;
1967 case CL_COMMON:
1968 description = _("The following options are language-independent");
1969 break;
1970 case CL_PARAMS:
1971 description = _("The following options control parameters");
1972 break;
1973 default:
1974 if (i >= cl_lang_count)
1975 break;
1976 if (exclude_flags & all_langs_mask)
1977 description = _("The following options are specific to just the language ");
1978 else
1979 description = _("The following options are supported by the language ");
1980 descrip_extra = lang_names [i];
1981 break;
1982 }
1983 }
1984
1985 if (description == NULL)
1986 {
1987 if (any_flags == 0)
1988 {
1989 if (include_flags & CL_UNDOCUMENTED)
1990 description = _("The following options are not documented");
1991 else if (include_flags & CL_SEPARATE)
1992 description = _("The following options take separate arguments");
1993 else if (include_flags & CL_JOINED)
1994 description = _("The following options take joined arguments");
1995 else
1996 {
1997 internal_error ("unrecognized %<include_flags 0x%x%> passed "
1998 "to %<print_specific_help%>",
1999 include_flags);
2000 return;
2001 }
2002 }
2003 else
2004 {
2005 if (any_flags & all_langs_mask)
2006 description = _("The following options are language-related");
2007 else
2008 description = _("The following options are language-independent");
2009 }
2010 }
2011
2012 printf (format: "%s%s:\n", description, descrip_extra);
2013 print_filtered_help (include_flags, exclude_flags, any_flags,
2014 columns: opts->x_help_columns, opts, lang_mask);
2015}
2016
2017/* Enable FDO-related flags. */
2018
2019static void
2020enable_fdo_optimizations (struct gcc_options *opts,
2021 struct gcc_options *opts_set,
2022 int value)
2023{
2024 SET_OPTION_IF_UNSET (opts, opts_set, flag_branch_probabilities, value);
2025 SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value);
2026 SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_loops, value);
2027 SET_OPTION_IF_UNSET (opts, opts_set, flag_peel_loops, value);
2028 SET_OPTION_IF_UNSET (opts, opts_set, flag_tracer, value);
2029 SET_OPTION_IF_UNSET (opts, opts_set, flag_value_profile_transformations,
2030 value);
2031 SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value);
2032 SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp, value);
2033 if (value)
2034 {
2035 SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp_clone, 1);
2036 SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, 1);
2037 }
2038 SET_OPTION_IF_UNSET (opts, opts_set, flag_predictive_commoning, value);
2039 SET_OPTION_IF_UNSET (opts, opts_set, flag_split_loops, value);
2040 SET_OPTION_IF_UNSET (opts, opts_set, flag_unswitch_loops, value);
2041 SET_OPTION_IF_UNSET (opts, opts_set, flag_gcse_after_reload, value);
2042 SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_vectorize, value);
2043 SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_slp_vectorize, value);
2044 SET_OPTION_IF_UNSET (opts, opts_set, flag_version_loops_for_strides, value);
2045 SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model,
2046 VECT_COST_MODEL_DYNAMIC);
2047 SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribute_patterns,
2048 value);
2049 SET_OPTION_IF_UNSET (opts, opts_set, flag_loop_interchange, value);
2050 SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_jam, value);
2051 SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value);
2052}
2053
2054/* -f{,no-}sanitize{,-recover}= suboptions. */
2055const struct sanitizer_opts_s sanitizer_opts[] =
2056{
2057#define SANITIZER_OPT(name, flags, recover, trap) \
2058 { #name, flags, sizeof #name - 1, recover, trap }
2059 SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true,
2060 false),
2061 SANITIZER_OPT (hwaddress, (SANITIZE_HWADDRESS | SANITIZE_USER_HWADDRESS),
2062 true, false),
2063 SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
2064 true, false),
2065 SANITIZER_OPT (kernel-hwaddress,
2066 (SANITIZE_HWADDRESS | SANITIZE_KERNEL_HWADDRESS),
2067 true, false),
2068 SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true, false),
2069 SANITIZER_OPT (pointer-subtract, SANITIZE_POINTER_SUBTRACT, true, false),
2070 SANITIZER_OPT (thread, SANITIZE_THREAD, false, false),
2071 SANITIZER_OPT (leak, SANITIZE_LEAK, false, false),
2072 SANITIZER_OPT (shift, SANITIZE_SHIFT, true, true),
2073 SANITIZER_OPT (shift-base, SANITIZE_SHIFT_BASE, true, true),
2074 SANITIZER_OPT (shift-exponent, SANITIZE_SHIFT_EXPONENT, true, true),
2075 SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true, true),
2076 SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true, true),
2077 SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false, true),
2078 SANITIZER_OPT (vla-bound, SANITIZE_VLA, true, true),
2079 SANITIZER_OPT (return, SANITIZE_RETURN, false, true),
2080 SANITIZER_OPT (null, SANITIZE_NULL, true, true),
2081 SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true, true),
2082 SANITIZER_OPT (bool, SANITIZE_BOOL, true, true),
2083 SANITIZER_OPT (enum, SANITIZE_ENUM, true, true),
2084 SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true, true),
2085 SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true, true),
2086 SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true, true),
2087 SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true,
2088 true),
2089 SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true, true),
2090 SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true, true),
2091 SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
2092 true, true),
2093 SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true, true),
2094 SANITIZER_OPT (vptr, SANITIZE_VPTR, true, false),
2095 SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true, true),
2096 SANITIZER_OPT (builtin, SANITIZE_BUILTIN, true, true),
2097 SANITIZER_OPT (shadow-call-stack, SANITIZE_SHADOW_CALL_STACK, false, false),
2098 SANITIZER_OPT (all, ~0U, true, true),
2099#undef SANITIZER_OPT
2100 { NULL, .flag: 0U, .len: 0UL, .can_recover: false, .can_trap: false }
2101};
2102
2103/* -fzero-call-used-regs= suboptions. */
2104const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
2105{
2106#define ZERO_CALL_USED_REGS_OPT(name, flags) \
2107 { #name, flags }
2108 ZERO_CALL_USED_REGS_OPT (skip, zero_regs_flags::SKIP),
2109 ZERO_CALL_USED_REGS_OPT (used-gpr-arg, zero_regs_flags::USED_GPR_ARG),
2110 ZERO_CALL_USED_REGS_OPT (used-gpr, zero_regs_flags::USED_GPR),
2111 ZERO_CALL_USED_REGS_OPT (used-arg, zero_regs_flags::USED_ARG),
2112 ZERO_CALL_USED_REGS_OPT (used, zero_regs_flags::USED),
2113 ZERO_CALL_USED_REGS_OPT (all-gpr-arg, zero_regs_flags::ALL_GPR_ARG),
2114 ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
2115 ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
2116 ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
2117 ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
2118 ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
2119 ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
2120 ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
2121#undef ZERO_CALL_USED_REGS_OPT
2122 {NULL, .flag: 0U}
2123};
2124
2125/* A struct for describing a run of chars within a string. */
2126
2127class string_fragment
2128{
2129public:
2130 string_fragment (const char *start, size_t len)
2131 : m_start (start), m_len (len) {}
2132
2133 const char *m_start;
2134 size_t m_len;
2135};
2136
2137/* Specialization of edit_distance_traits for string_fragment,
2138 for use by get_closest_sanitizer_option. */
2139
2140template <>
2141struct edit_distance_traits<const string_fragment &>
2142{
2143 static size_t get_length (const string_fragment &fragment)
2144 {
2145 return fragment.m_len;
2146 }
2147
2148 static const char *get_string (const string_fragment &fragment)
2149 {
2150 return fragment.m_start;
2151 }
2152};
2153
2154/* Given ARG, an unrecognized sanitizer option, return the best
2155 matching sanitizer option, or NULL if there isn't one.
2156 OPTS is array of candidate sanitizer options.
2157 CODE is OPT_fsanitize_, OPT_fsanitize_recover_ or OPT_fsanitize_trap_.
2158 VALUE is non-zero for the regular form of the option, zero
2159 for the "no-" form (e.g. "-fno-sanitize-recover="). */
2160
2161static const char *
2162get_closest_sanitizer_option (const string_fragment &arg,
2163 const struct sanitizer_opts_s *opts,
2164 enum opt_code code, int value)
2165{
2166 best_match <const string_fragment &, const char*> bm (arg);
2167 for (int i = 0; opts[i].name != NULL; ++i)
2168 {
2169 /* -fsanitize=all is not valid, so don't offer it. */
2170 if (code == OPT_fsanitize_
2171 && opts[i].flag == ~0U
2172 && value)
2173 continue;
2174
2175 /* For -fsanitize-recover= (and not -fno-sanitize-recover=),
2176 don't offer the non-recoverable options. */
2177 if (code == OPT_fsanitize_recover_
2178 && !opts[i].can_recover
2179 && value)
2180 continue;
2181
2182 /* For -fsanitize-trap= (and not -fno-sanitize-trap=),
2183 don't offer the non-trapping options. */
2184 if (code == OPT_fsanitize_trap_
2185 && !opts[i].can_trap
2186 && value)
2187 continue;
2188
2189 bm.consider (candidate: opts[i].name);
2190 }
2191 return bm.get_best_meaningful_candidate ();
2192}
2193
2194/* Parse comma separated sanitizer suboptions from P for option SCODE,
2195 adjust previous FLAGS and return new ones. If COMPLAIN is false,
2196 don't issue diagnostics. */
2197
2198unsigned int
2199parse_sanitizer_options (const char *p, location_t loc, int scode,
2200 unsigned int flags, int value, bool complain)
2201{
2202 enum opt_code code = (enum opt_code) scode;
2203
2204 while (*p != 0)
2205 {
2206 size_t len, i;
2207 bool found = false;
2208 const char *comma = strchr (s: p, c: ',');
2209
2210 if (comma == NULL)
2211 len = strlen (s: p);
2212 else
2213 len = comma - p;
2214 if (len == 0)
2215 {
2216 p = comma + 1;
2217 continue;
2218 }
2219
2220 /* Check to see if the string matches an option class name. */
2221 for (i = 0; sanitizer_opts[i].name != NULL; ++i)
2222 if (len == sanitizer_opts[i].len
2223 && memcmp (s1: p, s2: sanitizer_opts[i].name, n: len) == 0)
2224 {
2225 /* Handle both -fsanitize and -fno-sanitize cases. */
2226 if (value && sanitizer_opts[i].flag == ~0U)
2227 {
2228 if (code == OPT_fsanitize_)
2229 {
2230 if (complain)
2231 error_at (loc, "%<-fsanitize=all%> option is not valid");
2232 }
2233 else if (code == OPT_fsanitize_recover_)
2234 flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK
2235 | SANITIZE_UNREACHABLE | SANITIZE_RETURN
2236 | SANITIZE_SHADOW_CALL_STACK);
2237 else /* if (code == OPT_fsanitize_trap_) */
2238 flags |= (SANITIZE_UNDEFINED
2239 | SANITIZE_UNDEFINED_NONDEFAULT);
2240 }
2241 else if (value)
2242 {
2243 /* Do not enable -fsanitize-recover=unreachable and
2244 -fsanitize-recover=return if -fsanitize-recover=undefined
2245 is selected. */
2246 if (code == OPT_fsanitize_recover_
2247 && sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
2248 flags |= (SANITIZE_UNDEFINED
2249 & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN));
2250 else if (code == OPT_fsanitize_trap_
2251 && sanitizer_opts[i].flag == SANITIZE_VPTR)
2252 error_at (loc, "%<-fsanitize-trap=%s%> is not supported",
2253 sanitizer_opts[i].name);
2254 else
2255 flags |= sanitizer_opts[i].flag;
2256 }
2257 else
2258 {
2259 flags &= ~sanitizer_opts[i].flag;
2260 /* Don't always clear SANITIZE_ADDRESS if it was previously
2261 set: -fsanitize=address -fno-sanitize=kernel-address should
2262 leave SANITIZE_ADDRESS set. */
2263 if (flags & (SANITIZE_KERNEL_ADDRESS | SANITIZE_USER_ADDRESS))
2264 flags |= SANITIZE_ADDRESS;
2265 }
2266 found = true;
2267 break;
2268 }
2269
2270 if (! found && complain)
2271 {
2272 const char *hint
2273 = get_closest_sanitizer_option (arg: string_fragment (p, len),
2274 opts: sanitizer_opts, code, value);
2275
2276 const char *suffix;
2277 if (code == OPT_fsanitize_recover_)
2278 suffix = "-recover";
2279 else if (code == OPT_fsanitize_trap_)
2280 suffix = "-trap";
2281 else
2282 suffix = "";
2283
2284 if (hint)
2285 error_at (loc,
2286 "unrecognized argument to %<-f%ssanitize%s=%> "
2287 "option: %q.*s; did you mean %qs?",
2288 value ? "" : "no-",
2289 suffix, (int) len, p, hint);
2290 else
2291 error_at (loc,
2292 "unrecognized argument to %<-f%ssanitize%s=%> option: "
2293 "%q.*s", value ? "" : "no-",
2294 suffix, (int) len, p);
2295 }
2296
2297 if (comma == NULL)
2298 break;
2299 p = comma + 1;
2300 }
2301 return flags;
2302}
2303
2304/* Parse string values of no_sanitize attribute passed in VALUE.
2305 Values are separated with comma. */
2306
2307unsigned int
2308parse_no_sanitize_attribute (char *value)
2309{
2310 unsigned int flags = 0;
2311 unsigned int i;
2312 char *q = strtok (s: value, delim: ",");
2313
2314 while (q != NULL)
2315 {
2316 for (i = 0; sanitizer_opts[i].name != NULL; ++i)
2317 if (strcmp (s1: sanitizer_opts[i].name, s2: q) == 0)
2318 {
2319 flags |= sanitizer_opts[i].flag;
2320 if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
2321 flags |= SANITIZE_UNDEFINED_NONDEFAULT;
2322 break;
2323 }
2324
2325 if (sanitizer_opts[i].name == NULL)
2326 warning (OPT_Wattributes,
2327 "%qs attribute directive ignored", q);
2328
2329 q = strtok (NULL, delim: ",");
2330 }
2331
2332 return flags;
2333}
2334
2335/* Parse -fzero-call-used-regs suboptions from ARG, return the FLAGS. */
2336
2337unsigned int
2338parse_zero_call_used_regs_options (const char *arg)
2339{
2340 unsigned int flags = 0;
2341
2342 /* Check to see if the string matches a sub-option name. */
2343 for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
2344 if (strcmp (s1: arg, s2: zero_call_used_regs_opts[i].name) == 0)
2345 {
2346 flags = zero_call_used_regs_opts[i].flag;
2347 break;
2348 }
2349
2350 if (!flags)
2351 error ("unrecognized argument to %<-fzero-call-used-regs=%>: %qs", arg);
2352
2353 return flags;
2354}
2355
2356/* Parse -falign-NAME format for a FLAG value. Return individual
2357 parsed integer values into RESULT_VALUES array. If REPORT_ERROR is
2358 set, print error message at LOC location. */
2359
2360bool
2361parse_and_check_align_values (const char *flag,
2362 const char *name,
2363 auto_vec<unsigned> &result_values,
2364 bool report_error,
2365 location_t loc)
2366{
2367 char *str = xstrdup (flag);
2368 for (char *p = strtok (s: str, delim: ":"); p; p = strtok (NULL, delim: ":"))
2369 {
2370 char *end;
2371 int v = strtol (nptr: p, endptr: &end, base: 10);
2372 if (*end != '\0' || v < 0)
2373 {
2374 if (report_error)
2375 error_at (loc, "invalid arguments for %<-falign-%s%> option: %qs",
2376 name, flag);
2377
2378 return false;
2379 }
2380
2381 result_values.safe_push (obj: (unsigned)v);
2382 }
2383
2384 free (ptr: str);
2385
2386 /* Check that we have a correct number of values. */
2387 if (result_values.is_empty () || result_values.length () > 4)
2388 {
2389 if (report_error)
2390 error_at (loc, "invalid number of arguments for %<-falign-%s%> "
2391 "option: %qs", name, flag);
2392 return false;
2393 }
2394
2395 for (unsigned i = 0; i < result_values.length (); i++)
2396 if (result_values[i] > MAX_CODE_ALIGN_VALUE)
2397 {
2398 if (report_error)
2399 error_at (loc, "%<-falign-%s%> is not between 0 and %d",
2400 name, MAX_CODE_ALIGN_VALUE);
2401 return false;
2402 }
2403
2404 return true;
2405}
2406
2407/* Check that alignment value FLAG for -falign-NAME is valid at a given
2408 location LOC. OPT_STR points to the stored -falign-NAME=argument and
2409 OPT_FLAG points to the associated -falign-NAME on/off flag. */
2410
2411static void
2412check_alignment_argument (location_t loc, const char *flag, const char *name,
2413 int *opt_flag, const char **opt_str)
2414{
2415 auto_vec<unsigned> align_result;
2416 parse_and_check_align_values (flag, name, result_values&: align_result, report_error: true, loc);
2417
2418 if (align_result.length() >= 1 && align_result[0] == 0)
2419 {
2420 *opt_flag = 1;
2421 *opt_str = NULL;
2422 }
2423}
2424
2425/* Parse argument of -fpatchable-function-entry option ARG and store
2426 corresponding values to PATCH_AREA_SIZE and PATCH_AREA_START.
2427 If REPORT_ERROR is set to true, generate error for a problematic
2428 option arguments. */
2429
2430void
2431parse_and_check_patch_area (const char *arg, bool report_error,
2432 HOST_WIDE_INT *patch_area_size,
2433 HOST_WIDE_INT *patch_area_start)
2434{
2435 *patch_area_size = 0;
2436 *patch_area_start = 0;
2437
2438 if (arg == NULL)
2439 return;
2440
2441 char *patch_area_arg = xstrdup (arg);
2442 char *comma = strchr (s: patch_area_arg, c: ',');
2443 if (comma)
2444 {
2445 *comma = '\0';
2446 *patch_area_size = integral_argument (arg: patch_area_arg);
2447 *patch_area_start = integral_argument (arg: comma + 1);
2448 }
2449 else
2450 *patch_area_size = integral_argument (arg: patch_area_arg);
2451
2452 if (*patch_area_size < 0
2453 || *patch_area_size > USHRT_MAX
2454 || *patch_area_start < 0
2455 || *patch_area_start > USHRT_MAX
2456 || *patch_area_size < *patch_area_start)
2457 if (report_error)
2458 error ("invalid arguments for %<-fpatchable-function-entry%>");
2459
2460 free (ptr: patch_area_arg);
2461}
2462
2463/* Print help when OPT__help_ is set. */
2464
2465void
2466print_help (struct gcc_options *opts, unsigned int lang_mask,
2467 const char *help_option_argument)
2468{
2469 const char *a = help_option_argument;
2470 unsigned int include_flags = 0;
2471 /* Note - by default we include undocumented options when listing
2472 specific classes. If you only want to see documented options
2473 then add ",^undocumented" to the --help= option. E.g.:
2474
2475 --help=target,^undocumented */
2476 unsigned int exclude_flags = 0;
2477
2478 if (lang_mask == CL_DRIVER)
2479 return;
2480
2481 /* Walk along the argument string, parsing each word in turn.
2482 The format is:
2483 arg = [^]{word}[,{arg}]
2484 word = {optimizers|target|warnings|undocumented|
2485 params|common|<language>} */
2486 while (*a != 0)
2487 {
2488 static const struct
2489 {
2490 const char *string;
2491 unsigned int flag;
2492 }
2493 specifics[] =
2494 {
2495 { .string: "optimizers", CL_OPTIMIZATION },
2496 { .string: "target", CL_TARGET },
2497 { .string: "warnings", CL_WARNING },
2498 { .string: "undocumented", CL_UNDOCUMENTED },
2499 { .string: "params", CL_PARAMS },
2500 { .string: "joined", CL_JOINED },
2501 { .string: "separate", CL_SEPARATE },
2502 { .string: "common", CL_COMMON },
2503 { NULL, .flag: 0 }
2504 };
2505 unsigned int *pflags;
2506 const char *comma;
2507 unsigned int lang_flag, specific_flag;
2508 unsigned int len;
2509 unsigned int i;
2510
2511 if (*a == '^')
2512 {
2513 ++a;
2514 if (*a == '\0')
2515 {
2516 error ("missing argument to %qs", "--help=^");
2517 break;
2518 }
2519 pflags = &exclude_flags;
2520 }
2521 else
2522 pflags = &include_flags;
2523
2524 comma = strchr (s: a, c: ',');
2525 if (comma == NULL)
2526 len = strlen (s: a);
2527 else
2528 len = comma - a;
2529 if (len == 0)
2530 {
2531 a = comma + 1;
2532 continue;
2533 }
2534
2535 /* Check to see if the string matches an option class name. */
2536 for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++)
2537 if (strncasecmp (s1: a, s2: specifics[i].string, n: len) == 0)
2538 {
2539 specific_flag = specifics[i].flag;
2540 break;
2541 }
2542
2543 /* Check to see if the string matches a language name.
2544 Note - we rely upon the alpha-sorted nature of the entries in
2545 the lang_names array, specifically that shorter names appear
2546 before their longer variants. (i.e. C before C++). That way
2547 when we are attempting to match --help=c for example we will
2548 match with C first and not C++. */
2549 for (i = 0, lang_flag = 0; i < cl_lang_count; i++)
2550 if (strncasecmp (s1: a, s2: lang_names[i], n: len) == 0)
2551 {
2552 lang_flag = 1U << i;
2553 break;
2554 }
2555
2556 if (specific_flag != 0)
2557 {
2558 if (lang_flag == 0)
2559 *pflags |= specific_flag;
2560 else
2561 {
2562 /* The option's argument matches both the start of a
2563 language name and the start of an option class name.
2564 We have a special case for when the user has
2565 specified "--help=c", but otherwise we have to issue
2566 a warning. */
2567 if (strncasecmp (s1: a, s2: "c", n: len) == 0)
2568 *pflags |= lang_flag;
2569 else
2570 warning (0,
2571 "%<--help%> argument %q.*s is ambiguous, "
2572 "please be more specific",
2573 len, a);
2574 }
2575 }
2576 else if (lang_flag != 0)
2577 *pflags |= lang_flag;
2578 else
2579 warning (0,
2580 "unrecognized argument to %<--help=%> option: %q.*s",
2581 len, a);
2582
2583 if (comma == NULL)
2584 break;
2585 a = comma + 1;
2586 }
2587
2588 /* We started using PerFunction/Optimization for parameters and
2589 a warning. We should exclude these from optimization options. */
2590 if (include_flags & CL_OPTIMIZATION)
2591 exclude_flags |= CL_WARNING;
2592 if (!(include_flags & CL_PARAMS))
2593 exclude_flags |= CL_PARAMS;
2594
2595 if (include_flags)
2596 print_specific_help (include_flags, exclude_flags, any_flags: 0, opts,
2597 lang_mask);
2598}
2599
2600/* Handle target- and language-independent options. Return zero to
2601 generate an "unknown option" message. Only options that need
2602 extra handling need to be listed here; if you simply want
2603 DECODED->value assigned to a variable, it happens automatically. */
2604
2605bool
2606common_handle_option (struct gcc_options *opts,
2607 struct gcc_options *opts_set,
2608 const struct cl_decoded_option *decoded,
2609 unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
2610 location_t loc,
2611 const struct cl_option_handlers *handlers,
2612 diagnostic_context *dc,
2613 void (*target_option_override_hook) (void))
2614{
2615 size_t scode = decoded->opt_index;
2616 const char *arg = decoded->arg;
2617 HOST_WIDE_INT value = decoded->value;
2618 enum opt_code code = (enum opt_code) scode;
2619
2620 gcc_assert (decoded->canonical_option_num_elements <= 2);
2621
2622 switch (code)
2623 {
2624 case OPT__help:
2625 {
2626 unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
2627 unsigned int undoc_mask;
2628 unsigned int i;
2629
2630 if (lang_mask == CL_DRIVER)
2631 break;
2632
2633 undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings)
2634 ? 0
2635 : CL_UNDOCUMENTED);
2636 target_option_override_hook ();
2637 /* First display any single language specific options. */
2638 for (i = 0; i < cl_lang_count; i++)
2639 print_specific_help
2640 (include_flags: 1U << i, exclude_flags: (all_langs_mask & (~ (1U << i))) | undoc_mask, any_flags: 0, opts,
2641 lang_mask);
2642 /* Next display any multi language specific options. */
2643 print_specific_help (include_flags: 0, exclude_flags: undoc_mask, any_flags: all_langs_mask, opts, lang_mask);
2644 /* Then display any remaining, non-language options. */
2645 for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
2646 if (i != CL_DRIVER)
2647 print_specific_help (include_flags: i, exclude_flags: undoc_mask, any_flags: 0, opts, lang_mask);
2648 opts->x_exit_after_options = true;
2649 break;
2650 }
2651
2652 case OPT__target_help:
2653 if (lang_mask == CL_DRIVER)
2654 break;
2655
2656 target_option_override_hook ();
2657 print_specific_help (CL_TARGET, exclude_flags: 0, any_flags: 0, opts, lang_mask);
2658 opts->x_exit_after_options = true;
2659 break;
2660
2661 case OPT__help_:
2662 {
2663 help_option_arguments.safe_push (obj: arg);
2664 opts->x_exit_after_options = true;
2665 break;
2666 }
2667
2668 case OPT__version:
2669 if (lang_mask == CL_DRIVER)
2670 break;
2671
2672 opts->x_exit_after_options = true;
2673 break;
2674
2675 case OPT__completion_:
2676 break;
2677
2678 case OPT_fsanitize_:
2679 opts_set->x_flag_sanitize = true;
2680 opts->x_flag_sanitize
2681 = parse_sanitizer_options (p: arg, loc, scode: code,
2682 flags: opts->x_flag_sanitize, value, complain: true);
2683
2684 /* Kernel ASan implies normal ASan but does not yet support
2685 all features. */
2686 if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
2687 {
2688 SET_OPTION_IF_UNSET (opts, opts_set,
2689 param_asan_instrumentation_with_call_threshold,
2690 0);
2691 SET_OPTION_IF_UNSET (opts, opts_set, param_asan_globals, 0);
2692 SET_OPTION_IF_UNSET (opts, opts_set, param_asan_stack, 0);
2693 SET_OPTION_IF_UNSET (opts, opts_set, param_asan_protect_allocas, 0);
2694 SET_OPTION_IF_UNSET (opts, opts_set, param_asan_use_after_return, 0);
2695 }
2696 if (opts->x_flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
2697 {
2698 SET_OPTION_IF_UNSET (opts, opts_set,
2699 param_hwasan_instrument_stack, 0);
2700 SET_OPTION_IF_UNSET (opts, opts_set,
2701 param_hwasan_random_frame_tag, 0);
2702 SET_OPTION_IF_UNSET (opts, opts_set,
2703 param_hwasan_instrument_allocas, 0);
2704 }
2705 break;
2706
2707 case OPT_fsanitize_recover_:
2708 opts->x_flag_sanitize_recover
2709 = parse_sanitizer_options (p: arg, loc, scode: code,
2710 flags: opts->x_flag_sanitize_recover, value, complain: true);
2711 break;
2712
2713 case OPT_fsanitize_trap_:
2714 opts->x_flag_sanitize_trap
2715 = parse_sanitizer_options (p: arg, loc, scode: code,
2716 flags: opts->x_flag_sanitize_trap, value, complain: true);
2717 break;
2718
2719 case OPT_fasan_shadow_offset_:
2720 /* Deferred. */
2721 break;
2722
2723 case OPT_fsanitize_address_use_after_scope:
2724 opts->x_flag_sanitize_address_use_after_scope = value;
2725 break;
2726
2727 case OPT_fsanitize_recover:
2728 if (value)
2729 opts->x_flag_sanitize_recover
2730 |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)
2731 & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN);
2732 else
2733 opts->x_flag_sanitize_recover
2734 &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
2735 break;
2736
2737 case OPT_fsanitize_trap:
2738 if (value)
2739 opts->x_flag_sanitize_trap
2740 |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
2741 else
2742 opts->x_flag_sanitize_trap
2743 &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
2744 break;
2745
2746 case OPT_O:
2747 case OPT_Os:
2748 case OPT_Ofast:
2749 case OPT_Og:
2750 case OPT_Oz:
2751 /* Currently handled in a prescan. */
2752 break;
2753
2754 case OPT_Wattributes_:
2755 if (lang_mask == CL_DRIVER)
2756 break;
2757
2758 if (value)
2759 {
2760 error_at (loc, "arguments ignored for %<-Wattributes=%>; use "
2761 "%<-Wno-attributes=%> instead");
2762 break;
2763 }
2764 else if (arg[strlen (s: arg) - 1] == ',')
2765 {
2766 error_at (loc, "trailing %<,%> in arguments for "
2767 "%<-Wno-attributes=%>");
2768 break;
2769 }
2770
2771 add_comma_separated_to_vector (pvec: &opts->x_flag_ignored_attributes, arg);
2772 break;
2773
2774 case OPT_Werror:
2775 dc->set_warning_as_error_requested (value);
2776 break;
2777
2778 case OPT_Werror_:
2779 if (lang_mask == CL_DRIVER)
2780 break;
2781
2782 enable_warning_as_error (arg, value, lang_mask, handlers,
2783 opts, opts_set, loc, dc);
2784 break;
2785
2786 case OPT_Wfatal_errors:
2787 dc->m_fatal_errors = value;
2788 break;
2789
2790 case OPT_Wstack_usage_:
2791 opts->x_flag_stack_usage_info = value != -1;
2792 break;
2793
2794 case OPT_Wstrict_aliasing:
2795 set_Wstrict_aliasing (opts, onoff: value);
2796 break;
2797
2798 case OPT_Wstrict_overflow:
2799 opts->x_warn_strict_overflow = (value
2800 ? (int) WARN_STRICT_OVERFLOW_CONDITIONAL
2801 : 0);
2802 break;
2803
2804 case OPT_Wsystem_headers:
2805 dc->m_warn_system_headers = value;
2806 break;
2807
2808 case OPT_aux_info:
2809 opts->x_flag_gen_aux_info = 1;
2810 break;
2811
2812 case OPT_d:
2813 decode_d_option (arg, opts, loc, dc);
2814 break;
2815
2816 case OPT_fcall_used_:
2817 case OPT_fcall_saved_:
2818 /* Deferred. */
2819 break;
2820
2821 case OPT_fdbg_cnt_:
2822 /* Deferred. */
2823 break;
2824
2825 case OPT_fdebug_prefix_map_:
2826 case OPT_ffile_prefix_map_:
2827 case OPT_fprofile_prefix_map_:
2828 /* Deferred. */
2829 break;
2830
2831 case OPT_fcanon_prefix_map:
2832 flag_canon_prefix_map = value;
2833 break;
2834
2835 case OPT_fcallgraph_info:
2836 opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
2837 break;
2838
2839 case OPT_fcallgraph_info_:
2840 {
2841 char *my_arg, *p;
2842 my_arg = xstrdup (arg);
2843 p = strtok (s: my_arg, delim: ",");
2844 while (p)
2845 {
2846 if (strcmp (s1: p, s2: "su") == 0)
2847 {
2848 opts->x_flag_callgraph_info |= CALLGRAPH_INFO_STACK_USAGE;
2849 opts->x_flag_stack_usage_info = true;
2850 }
2851 else if (strcmp (s1: p, s2: "da") == 0)
2852 opts->x_flag_callgraph_info |= CALLGRAPH_INFO_DYNAMIC_ALLOC;
2853 else
2854 return 0;
2855 p = strtok (NULL, delim: ",");
2856 }
2857 free (ptr: my_arg);
2858 }
2859 break;
2860
2861 case OPT_fdiagnostics_show_location_:
2862 diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
2863 break;
2864
2865 case OPT_fdiagnostics_show_caret:
2866 dc->m_source_printing.enabled = value;
2867 break;
2868
2869 case OPT_fdiagnostics_show_labels:
2870 dc->m_source_printing.show_labels_p = value;
2871 break;
2872
2873 case OPT_fdiagnostics_show_line_numbers:
2874 dc->m_source_printing.show_line_numbers_p = value;
2875 break;
2876
2877 case OPT_fdiagnostics_color_:
2878 diagnostic_color_init (context: dc, value);
2879 break;
2880
2881 case OPT_fdiagnostics_urls_:
2882 diagnostic_urls_init (context: dc, value);
2883 break;
2884
2885 case OPT_fdiagnostics_format_:
2886 {
2887 const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name
2888 : opts->x_main_input_basename);
2889 diagnostic_output_format_init (dc, base_file_name: basename,
2890 (enum diagnostics_output_format)value);
2891 break;
2892 }
2893
2894 case OPT_fdiagnostics_text_art_charset_:
2895 dc->set_text_art_charset ((enum diagnostic_text_art_charset)value);
2896 break;
2897
2898 case OPT_fdiagnostics_parseable_fixits:
2899 dc->set_extra_output_kind (value
2900 ? EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
2901 : EXTRA_DIAGNOSTIC_OUTPUT_none);
2902 break;
2903
2904 case OPT_fdiagnostics_column_unit_:
2905 dc->m_column_unit = (enum diagnostics_column_unit)value;
2906 break;
2907
2908 case OPT_fdiagnostics_column_origin_:
2909 dc->m_column_origin = value;
2910 break;
2911
2912 case OPT_fdiagnostics_escape_format_:
2913 dc->set_escape_format ((enum diagnostics_escape_format)value);
2914 break;
2915
2916 case OPT_fdiagnostics_show_cwe:
2917 dc->set_show_cwe (value);
2918 break;
2919
2920 case OPT_fdiagnostics_show_rules:
2921 dc->set_show_rules (value);
2922 break;
2923
2924 case OPT_fdiagnostics_path_format_:
2925 dc->set_path_format ((enum diagnostic_path_format)value);
2926 break;
2927
2928 case OPT_fdiagnostics_show_path_depths:
2929 dc->set_show_path_depths (value);
2930 break;
2931
2932 case OPT_fdiagnostics_show_option:
2933 dc->set_show_option_requested (value);
2934 break;
2935
2936 case OPT_fdiagnostics_minimum_margin_width_:
2937 dc->m_source_printing.min_margin_width = value;
2938 break;
2939
2940 case OPT_fdump_:
2941 /* Deferred. */
2942 break;
2943
2944 case OPT_ffast_math:
2945 set_fast_math_flags (opts, set: value);
2946 break;
2947
2948 case OPT_funsafe_math_optimizations:
2949 set_unsafe_math_optimizations_flags (opts, set: value);
2950 break;
2951
2952 case OPT_ffixed_:
2953 /* Deferred. */
2954 break;
2955
2956 case OPT_finline_limit_:
2957 SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_single,
2958 value / 2);
2959 SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto,
2960 value / 2);
2961 break;
2962
2963 case OPT_finstrument_functions_exclude_function_list_:
2964 add_comma_separated_to_vector
2965 (pvec: &opts->x_flag_instrument_functions_exclude_functions, arg);
2966 break;
2967
2968 case OPT_finstrument_functions_exclude_file_list_:
2969 add_comma_separated_to_vector
2970 (pvec: &opts->x_flag_instrument_functions_exclude_files, arg);
2971 break;
2972
2973 case OPT_fmessage_length_:
2974 pp_set_line_maximum_length (dc->printer, value);
2975 diagnostic_set_caret_max_width (context: dc, value);
2976 break;
2977
2978 case OPT_fopt_info:
2979 case OPT_fopt_info_:
2980 /* Deferred. */
2981 break;
2982
2983 case OPT_foffload_options_:
2984 /* Deferred. */
2985 break;
2986
2987 case OPT_foffload_abi_:
2988#ifdef ACCEL_COMPILER
2989 /* Handled in the 'mkoffload's. */
2990#else
2991 error_at (loc, "%<-foffload-abi%> option can be specified only for "
2992 "offload compiler");
2993#endif
2994 break;
2995
2996 case OPT_fpack_struct_:
2997 if (value <= 0 || (value & (value - 1)) || value > 16)
2998 error_at (loc,
2999 "structure alignment must be a small power of two, not %wu",
3000 value);
3001 else
3002 opts->x_initial_max_fld_align = value;
3003 break;
3004
3005 case OPT_fplugin_:
3006 case OPT_fplugin_arg_:
3007 /* Deferred. */
3008 break;
3009
3010 case OPT_fprofile_use_:
3011 opts->x_profile_data_prefix = xstrdup (arg);
3012 opts->x_flag_profile_use = true;
3013 value = true;
3014 /* No break here - do -fprofile-use processing. */
3015 /* FALLTHRU */
3016 case OPT_fprofile_use:
3017 enable_fdo_optimizations (opts, opts_set, value);
3018 SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_reorder_functions,
3019 value);
3020 /* Indirect call profiling should do all useful transformations
3021 speculative devirtualization does. */
3022 if (opts->x_flag_value_profile_transformations)
3023 SET_OPTION_IF_UNSET (opts, opts_set, flag_devirtualize_speculatively,
3024 false);
3025 break;
3026
3027 case OPT_fauto_profile_:
3028 opts->x_auto_profile_file = xstrdup (arg);
3029 opts->x_flag_auto_profile = true;
3030 value = true;
3031 /* No break here - do -fauto-profile processing. */
3032 /* FALLTHRU */
3033 case OPT_fauto_profile:
3034 enable_fdo_optimizations (opts, opts_set, value);
3035 SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value);
3036 break;
3037
3038 case OPT_fprofile_generate_:
3039 opts->x_profile_data_prefix = xstrdup (arg);
3040 value = true;
3041 /* No break here - do -fprofile-generate processing. */
3042 /* FALLTHRU */
3043 case OPT_fprofile_generate:
3044 SET_OPTION_IF_UNSET (opts, opts_set, profile_arc_flag, value);
3045 SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value);
3046 SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value);
3047 SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
3048 break;
3049
3050 case OPT_fprofile_info_section:
3051 opts->x_profile_info_section = ".gcov_info";
3052 break;
3053
3054 case OPT_fpatchable_function_entry_:
3055 {
3056 HOST_WIDE_INT patch_area_size, patch_area_start;
3057 parse_and_check_patch_area (arg, report_error: true, patch_area_size: &patch_area_size,
3058 patch_area_start: &patch_area_start);
3059 }
3060 break;
3061
3062 case OPT_ftree_vectorize:
3063 /* Automatically sets -ftree-loop-vectorize and
3064 -ftree-slp-vectorize. Nothing more to do here. */
3065 break;
3066 case OPT_fzero_call_used_regs_:
3067 opts->x_flag_zero_call_used_regs
3068 = parse_zero_call_used_regs_options (arg);
3069 break;
3070
3071 case OPT_fshow_column:
3072 dc->m_show_column = value;
3073 break;
3074
3075 case OPT_frandom_seed:
3076 /* The real switch is -fno-random-seed. */
3077 if (value)
3078 return false;
3079 /* Deferred. */
3080 break;
3081
3082 case OPT_frandom_seed_:
3083 /* Deferred. */
3084 break;
3085
3086 case OPT_fsched_verbose_:
3087#ifdef INSN_SCHEDULING
3088 /* Handled with Var in common.opt. */
3089 break;
3090#else
3091 return false;
3092#endif
3093
3094 case OPT_fsched_stalled_insns_:
3095 opts->x_flag_sched_stalled_insns = value;
3096 if (opts->x_flag_sched_stalled_insns == 0)
3097 opts->x_flag_sched_stalled_insns = -1;
3098 break;
3099
3100 case OPT_fsched_stalled_insns_dep_:
3101 opts->x_flag_sched_stalled_insns_dep = value;
3102 break;
3103
3104 case OPT_fstack_check_:
3105 if (!strcmp (s1: arg, s2: "no"))
3106 opts->x_flag_stack_check = NO_STACK_CHECK;
3107 else if (!strcmp (s1: arg, s2: "generic"))
3108 /* This is the old stack checking method. */
3109 opts->x_flag_stack_check = STACK_CHECK_BUILTIN
3110 ? FULL_BUILTIN_STACK_CHECK
3111 : GENERIC_STACK_CHECK;
3112 else if (!strcmp (s1: arg, s2: "specific"))
3113 /* This is the new stack checking method. */
3114 opts->x_flag_stack_check = STACK_CHECK_BUILTIN
3115 ? FULL_BUILTIN_STACK_CHECK
3116 : STACK_CHECK_STATIC_BUILTIN
3117 ? STATIC_BUILTIN_STACK_CHECK
3118 : GENERIC_STACK_CHECK;
3119 else
3120 warning_at (loc, 0, "unknown stack check parameter %qs", arg);
3121 break;
3122
3123 case OPT_fstack_limit:
3124 /* The real switch is -fno-stack-limit. */
3125 if (value)
3126 return false;
3127 /* Deferred. */
3128 break;
3129
3130 case OPT_fstack_limit_register_:
3131 case OPT_fstack_limit_symbol_:
3132 /* Deferred. */
3133 break;
3134
3135 case OPT_fstack_usage:
3136 opts->x_flag_stack_usage = value;
3137 opts->x_flag_stack_usage_info = value != 0;
3138 break;
3139
3140 case OPT_g:
3141 set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
3142 loc);
3143 break;
3144
3145 case OPT_gcodeview:
3146 break;
3147
3148 case OPT_gbtf:
3149 set_debug_level (BTF_DEBUG, extended: false, arg, opts, opts_set, loc);
3150 /* set the debug level to level 2, but if already at level 3,
3151 don't lower it. */
3152 if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
3153 opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
3154 break;
3155
3156 case OPT_gctf:
3157 set_debug_level (CTF_DEBUG, extended: false, arg, opts, opts_set, loc);
3158 /* CTF generation feeds off DWARF dies. For optimal CTF, switch debug
3159 info level to 2. If off or at level 1, set it to level 2, but if
3160 already at level 3, don't lower it. */
3161 if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL
3162 && opts->x_ctf_debug_info_level > CTFINFO_LEVEL_NONE)
3163 opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
3164 break;
3165
3166 case OPT_gdwarf:
3167 if (arg && strlen (s: arg) != 0)
3168 {
3169 error_at (loc, "%<-gdwarf%s%> is ambiguous; "
3170 "use %<-gdwarf-%s%> for DWARF version "
3171 "or %<-gdwarf%> %<-g%s%> for debug level", arg, arg, arg);
3172 break;
3173 }
3174 else
3175 value = opts->x_dwarf_version;
3176
3177 /* FALLTHRU */
3178 case OPT_gdwarf_:
3179 if (value < 2 || value > 5)
3180 error_at (loc, "dwarf version %wu is not supported", value);
3181 else
3182 opts->x_dwarf_version = value;
3183 set_debug_level (DWARF2_DEBUG, extended: false, arg: "", opts, opts_set, loc);
3184 break;
3185
3186 case OPT_ggdb:
3187 set_debug_level (NO_DEBUG, extended: 2, arg, opts, opts_set, loc);
3188 break;
3189
3190 case OPT_gvms:
3191 set_debug_level (VMS_DEBUG, extended: false, arg, opts, opts_set, loc);
3192 break;
3193
3194 case OPT_gz:
3195 case OPT_gz_:
3196 /* Handled completely via specs. */
3197 break;
3198
3199 case OPT_pedantic_errors:
3200 dc->m_pedantic_errors = 1;
3201 control_warning_option (opt_index: OPT_Wpedantic, kind: DK_ERROR, NULL, imply: value,
3202 loc, lang_mask,
3203 handlers, opts, opts_set,
3204 dc);
3205 break;
3206
3207 case OPT_flto:
3208 opts->x_flag_lto = value ? "" : NULL;
3209 break;
3210
3211 case OPT_flto_:
3212 if (strcmp (s1: arg, s2: "none") != 0
3213 && strcmp (s1: arg, s2: "jobserver") != 0
3214 && strcmp (s1: arg, s2: "auto") != 0
3215 && atoi (nptr: arg) == 0)
3216 error_at (loc,
3217 "unrecognized argument to %<-flto=%> option: %qs", arg);
3218 break;
3219
3220 case OPT_w:
3221 dc->m_inhibit_warnings = true;
3222 break;
3223
3224 case OPT_fmax_errors_:
3225 dc->set_max_errors (value);
3226 break;
3227
3228 case OPT_fuse_ld_bfd:
3229 case OPT_fuse_ld_gold:
3230 case OPT_fuse_ld_lld:
3231 case OPT_fuse_ld_mold:
3232 case OPT_fuse_linker_plugin:
3233 /* No-op. Used by the driver and passed to us because it starts with f.*/
3234 break;
3235
3236 case OPT_fwrapv:
3237 if (value)
3238 opts->x_flag_trapv = 0;
3239 break;
3240
3241 case OPT_ftrapv:
3242 if (value)
3243 opts->x_flag_wrapv = 0;
3244 break;
3245
3246 case OPT_fstrict_overflow:
3247 opts->x_flag_wrapv = !value;
3248 opts->x_flag_wrapv_pointer = !value;
3249 if (!value)
3250 opts->x_flag_trapv = 0;
3251 break;
3252
3253 case OPT_fipa_icf:
3254 opts->x_flag_ipa_icf_functions = value;
3255 opts->x_flag_ipa_icf_variables = value;
3256 break;
3257
3258 case OPT_falign_loops_:
3259 check_alignment_argument (loc, flag: arg, name: "loops",
3260 opt_flag: &opts->x_flag_align_loops,
3261 opt_str: &opts->x_str_align_loops);
3262 break;
3263
3264 case OPT_falign_jumps_:
3265 check_alignment_argument (loc, flag: arg, name: "jumps",
3266 opt_flag: &opts->x_flag_align_jumps,
3267 opt_str: &opts->x_str_align_jumps);
3268 break;
3269
3270 case OPT_falign_labels_:
3271 check_alignment_argument (loc, flag: arg, name: "labels",
3272 opt_flag: &opts->x_flag_align_labels,
3273 opt_str: &opts->x_str_align_labels);
3274 break;
3275
3276 case OPT_falign_functions_:
3277 check_alignment_argument (loc, flag: arg, name: "functions",
3278 opt_flag: &opts->x_flag_align_functions,
3279 opt_str: &opts->x_str_align_functions);
3280 break;
3281
3282 case OPT_ftabstop_:
3283 /* It is documented that we silently ignore silly values. */
3284 if (value >= 1 && value <= 100)
3285 dc->m_tabstop = value;
3286 break;
3287
3288 case OPT_freport_bug:
3289 dc->set_report_bug (value);
3290 break;
3291
3292 case OPT_fmultiflags:
3293 gcc_checking_assert (lang_mask == CL_DRIVER);
3294 break;
3295
3296 default:
3297 /* If the flag was handled in a standard way, assume the lack of
3298 processing here is intentional. */
3299 gcc_assert (option_flag_var (scode, opts));
3300 break;
3301 }
3302
3303 common_handle_option_auto (opts, opts_set, decoded, lang_mask, kind,
3304 loc, handlers, dc);
3305 return true;
3306}
3307
3308/* Used to set the level of strict aliasing warnings in OPTS,
3309 when no level is specified (i.e., when -Wstrict-aliasing, and not
3310 -Wstrict-aliasing=level was given).
3311 ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified,
3312 and 0 otherwise. After calling this function, wstrict_aliasing will be
3313 set to the default value of -Wstrict_aliasing=level, currently 3. */
3314static void
3315set_Wstrict_aliasing (struct gcc_options *opts, int onoff)
3316{
3317 gcc_assert (onoff == 0 || onoff == 1);
3318 if (onoff != 0)
3319 opts->x_warn_strict_aliasing = 3;
3320 else
3321 opts->x_warn_strict_aliasing = 0;
3322}
3323
3324/* The following routines are useful in setting all the flags that
3325 -ffast-math and -fno-fast-math imply. */
3326static void
3327set_fast_math_flags (struct gcc_options *opts, int set)
3328{
3329 if (!opts->frontend_set_flag_unsafe_math_optimizations)
3330 {
3331 opts->x_flag_unsafe_math_optimizations = set;
3332 set_unsafe_math_optimizations_flags (opts, set);
3333 }
3334 if (!opts->frontend_set_flag_finite_math_only)
3335 opts->x_flag_finite_math_only = set;
3336 if (!opts->frontend_set_flag_errno_math)
3337 opts->x_flag_errno_math = !set;
3338 if (set)
3339 {
3340 if (opts->frontend_set_flag_excess_precision == EXCESS_PRECISION_DEFAULT)
3341 opts->x_flag_excess_precision
3342 = set ? EXCESS_PRECISION_FAST : EXCESS_PRECISION_DEFAULT;
3343 if (!opts->frontend_set_flag_signaling_nans)
3344 opts->x_flag_signaling_nans = 0;
3345 if (!opts->frontend_set_flag_rounding_math)
3346 opts->x_flag_rounding_math = 0;
3347 if (!opts->frontend_set_flag_cx_limited_range)
3348 opts->x_flag_cx_limited_range = 1;
3349 }
3350}
3351
3352/* When -funsafe-math-optimizations is set the following
3353 flags are set as well. */
3354static void
3355set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set)
3356{
3357 if (!opts->frontend_set_flag_trapping_math)
3358 opts->x_flag_trapping_math = !set;
3359 if (!opts->frontend_set_flag_signed_zeros)
3360 opts->x_flag_signed_zeros = !set;
3361 if (!opts->frontend_set_flag_associative_math)
3362 opts->x_flag_associative_math = set;
3363 if (!opts->frontend_set_flag_reciprocal_math)
3364 opts->x_flag_reciprocal_math = set;
3365}
3366
3367/* Return true iff flags in OPTS are set as if -ffast-math. */
3368bool
3369fast_math_flags_set_p (const struct gcc_options *opts)
3370{
3371 return (!opts->x_flag_trapping_math
3372 && opts->x_flag_unsafe_math_optimizations
3373 && opts->x_flag_finite_math_only
3374 && !opts->x_flag_signed_zeros
3375 && !opts->x_flag_errno_math
3376 && opts->x_flag_excess_precision == EXCESS_PRECISION_FAST);
3377}
3378
3379/* Return true iff flags are set as if -ffast-math but using the flags stored
3380 in the struct cl_optimization structure. */
3381bool
3382fast_math_flags_struct_set_p (struct cl_optimization *opt)
3383{
3384 return (!opt->x_flag_trapping_math
3385 && opt->x_flag_unsafe_math_optimizations
3386 && opt->x_flag_finite_math_only
3387 && !opt->x_flag_signed_zeros
3388 && !opt->x_flag_errno_math);
3389}
3390
3391/* Handle a debug output -g switch for options OPTS
3392 (OPTS_SET->x_write_symbols storing whether a debug format was passed
3393 explicitly), location LOC. EXTENDED is true or false to support
3394 extended output (2 is special and means "-ggdb" was given). */
3395static void
3396set_debug_level (uint32_t dinfo, int extended, const char *arg,
3397 struct gcc_options *opts, struct gcc_options *opts_set,
3398 location_t loc)
3399{
3400 if (dinfo == NO_DEBUG)
3401 {
3402 if (opts->x_write_symbols == NO_DEBUG)
3403 {
3404 opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE;
3405
3406 if (extended == 2)
3407 {
3408#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
3409 if (opts->x_write_symbols & CTF_DEBUG)
3410 opts->x_write_symbols |= DWARF2_DEBUG;
3411 else
3412 opts->x_write_symbols = DWARF2_DEBUG;
3413#endif
3414 }
3415
3416 if (opts->x_write_symbols == NO_DEBUG)
3417 warning_at (loc, 0, "target system does not support debug output");
3418 }
3419 else if ((opts->x_write_symbols & CTF_DEBUG)
3420 || (opts->x_write_symbols & BTF_DEBUG))
3421 {
3422 opts->x_write_symbols |= DWARF2_DEBUG;
3423 opts_set->x_write_symbols |= DWARF2_DEBUG;
3424 }
3425 }
3426 else
3427 {
3428 /* Make and retain the choice if both CTF and DWARF debug info are to
3429 be generated. */
3430 if (((dinfo == DWARF2_DEBUG) || (dinfo == CTF_DEBUG))
3431 && ((opts->x_write_symbols == (DWARF2_DEBUG|CTF_DEBUG))
3432 || (opts->x_write_symbols == DWARF2_DEBUG)
3433 || (opts->x_write_symbols == CTF_DEBUG)))
3434 {
3435 opts->x_write_symbols |= dinfo;
3436 opts_set->x_write_symbols |= dinfo;
3437 }
3438 /* However, CTF and BTF are not allowed together at this time. */
3439 else if (((dinfo == DWARF2_DEBUG) || (dinfo == BTF_DEBUG))
3440 && ((opts->x_write_symbols == (DWARF2_DEBUG|BTF_DEBUG))
3441 || (opts->x_write_symbols == DWARF2_DEBUG)
3442 || (opts->x_write_symbols == BTF_DEBUG)))
3443 {
3444 opts->x_write_symbols |= dinfo;
3445 opts_set->x_write_symbols |= dinfo;
3446 }
3447 else
3448 {
3449 /* Does it conflict with an already selected debug format? */
3450 if (opts_set->x_write_symbols != NO_DEBUG
3451 && opts->x_write_symbols != NO_DEBUG
3452 && dinfo != opts->x_write_symbols)
3453 {
3454 gcc_assert (debug_set_count (dinfo) <= 1);
3455 error_at (loc, "debug format %qs conflicts with prior selection",
3456 debug_type_names[debug_set_to_format (debug_info_set: dinfo)]);
3457 }
3458 opts->x_write_symbols = dinfo;
3459 opts_set->x_write_symbols = dinfo;
3460 }
3461 }
3462
3463 if (dinfo != BTF_DEBUG)
3464 {
3465 /* A debug flag without a level defaults to level 2.
3466 If off or at level 1, set it to level 2, but if already
3467 at level 3, don't lower it. */
3468 if (*arg == '\0')
3469 {
3470 if (dinfo == CTF_DEBUG)
3471 opts->x_ctf_debug_info_level = CTFINFO_LEVEL_NORMAL;
3472 else if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
3473 opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
3474 }
3475 else
3476 {
3477 int argval = integral_argument (arg);
3478 if (argval == -1)
3479 error_at (loc, "unrecognized debug output level %qs", arg);
3480 else if (argval > 3)
3481 error_at (loc, "debug output level %qs is too high", arg);
3482 else
3483 {
3484 if (dinfo == CTF_DEBUG)
3485 opts->x_ctf_debug_info_level
3486 = (enum ctf_debug_info_levels) argval;
3487 else
3488 opts->x_debug_info_level = (enum debug_info_levels) argval;
3489 }
3490 }
3491 }
3492 else if (*arg != '\0')
3493 error_at (loc, "unrecognized btf debug output level %qs", arg);
3494}
3495
3496/* Arrange to dump core on error for diagnostic context DC. (The
3497 regular error message is still printed first, except in the case of
3498 abort ().) */
3499
3500static void
3501setup_core_dumping (diagnostic_context *dc)
3502{
3503#ifdef SIGABRT
3504 signal (SIGABRT, SIG_DFL);
3505#endif
3506#if defined(HAVE_SETRLIMIT)
3507 {
3508 struct rlimit rlim;
3509 if (getrlimit (RLIMIT_CORE, rlimits: &rlim) != 0)
3510 fatal_error (input_location, "getting core file size maximum limit: %m");
3511 rlim.rlim_cur = rlim.rlim_max;
3512 if (setrlimit (RLIMIT_CORE, rlimits: &rlim) != 0)
3513 fatal_error (input_location,
3514 "setting core file size limit to maximum: %m");
3515 }
3516#endif
3517 diagnostic_abort_on_error (context: dc);
3518}
3519
3520/* Parse a -d<ARG> command line switch for OPTS, location LOC,
3521 diagnostic context DC. */
3522
3523static void
3524decode_d_option (const char *arg, struct gcc_options *opts,
3525 location_t loc, diagnostic_context *dc)
3526{
3527 int c;
3528
3529 while (*arg)
3530 switch (c = *arg++)
3531 {
3532 case 'A':
3533 opts->x_flag_debug_asm = 1;
3534 break;
3535 case 'p':
3536 opts->x_flag_print_asm_name = 1;
3537 break;
3538 case 'P':
3539 opts->x_flag_dump_rtl_in_asm = 1;
3540 opts->x_flag_print_asm_name = 1;
3541 break;
3542 case 'x':
3543 opts->x_rtl_dump_and_exit = 1;
3544 break;
3545 case 'D': /* These are handled by the preprocessor. */
3546 case 'I':
3547 case 'M':
3548 case 'N':
3549 case 'U':
3550 break;
3551 case 'H':
3552 setup_core_dumping (dc);
3553 break;
3554 case 'a':
3555 opts->x_flag_dump_all_passed = true;
3556 break;
3557
3558 default:
3559 warning_at (loc, 0, "unrecognized gcc debugging option: %c", c);
3560 break;
3561 }
3562}
3563
3564/* Enable (or disable if VALUE is 0) a warning option ARG (language
3565 mask LANG_MASK, option handlers HANDLERS) as an error for option
3566 structures OPTS and OPTS_SET, diagnostic context DC (possibly
3567 NULL), location LOC. This is used by -Werror=. */
3568
3569static void
3570enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
3571 const struct cl_option_handlers *handlers,
3572 struct gcc_options *opts,
3573 struct gcc_options *opts_set,
3574 location_t loc, diagnostic_context *dc)
3575{
3576 char *new_option;
3577 int option_index;
3578
3579 new_option = XNEWVEC (char, strlen (arg) + 2);
3580 new_option[0] = 'W';
3581 strcpy (dest: new_option + 1, src: arg);
3582 option_index = find_opt (input: new_option, lang_mask);
3583 if (option_index == OPT_SPECIAL_unknown)
3584 {
3585 option_proposer op;
3586 const char *hint = op.suggest_option (bad_opt: new_option);
3587 if (hint)
3588 error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>;"
3589 " did you mean %<-%s%>?", value ? "" : "no-",
3590 arg, new_option, hint);
3591 else
3592 error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>",
3593 value ? "" : "no-", arg, new_option);
3594 }
3595 else if (!(cl_options[option_index].flags & CL_WARNING))
3596 error_at (loc, "%<-Werror=%s%>: %<-%s%> is not an option that "
3597 "controls warnings", arg, new_option);
3598 else
3599 {
3600 const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
3601 const char *arg = NULL;
3602
3603 if (cl_options[option_index].flags & CL_JOINED)
3604 arg = new_option + cl_options[option_index].opt_len;
3605 control_warning_option (opt_index: option_index, kind: (int) kind, arg, imply: value,
3606 loc, lang_mask,
3607 handlers, opts, opts_set, dc);
3608 }
3609 free (ptr: new_option);
3610}
3611
3612/* Return malloced memory for the name of the option OPTION_INDEX
3613 which enabled a diagnostic (context CONTEXT), originally of type
3614 ORIG_DIAG_KIND but possibly converted to DIAG_KIND by options such
3615 as -Werror. */
3616
3617char *
3618option_name (diagnostic_context *context, int option_index,
3619 diagnostic_t orig_diag_kind, diagnostic_t diag_kind)
3620{
3621 if (option_index)
3622 {
3623 /* A warning classified as an error. */
3624 if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN)
3625 && diag_kind == DK_ERROR)
3626 return concat (cl_options[OPT_Werror_].opt_text,
3627 /* Skip over "-W". */
3628 cl_options[option_index].opt_text + 2,
3629 NULL);
3630 /* A warning with option. */
3631 else
3632 return xstrdup (cl_options[option_index].opt_text);
3633 }
3634 /* A warning without option classified as an error. */
3635 else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
3636 || diag_kind == DK_WARNING)
3637 && context->warning_as_error_requested_p ())
3638 return xstrdup (cl_options[OPT_Werror].opt_text);
3639 else
3640 return NULL;
3641}
3642
3643/* Get the page within the documentation for this option. */
3644
3645static const char *
3646get_option_html_page (int option_index)
3647{
3648 const cl_option *cl_opt = &cl_options[option_index];
3649
3650 /* Analyzer options are on their own page. */
3651 if (strstr (haystack: cl_opt->opt_text, needle: "analyzer-"))
3652 return "gcc/Static-Analyzer-Options.html";
3653
3654 /* Handle -flto= option. */
3655 if (strstr (haystack: cl_opt->opt_text, needle: "flto"))
3656 return "gcc/Optimize-Options.html";
3657
3658#ifdef CL_Fortran
3659 if ((cl_opt->flags & CL_Fortran) != 0
3660 /* If it is option common to both C/C++ and Fortran, it is documented
3661 in gcc/ rather than gfortran/ docs. */
3662 && (cl_opt->flags & CL_C) == 0
3663#ifdef CL_CXX
3664 && (cl_opt->flags & CL_CXX) == 0
3665#endif
3666 )
3667 return "gfortran/Error-and-Warning-Options.html";
3668#endif
3669
3670 return "gcc/Warning-Options.html";
3671}
3672
3673/* Return malloced memory for a URL describing the option OPTION_INDEX
3674 which enabled a diagnostic (context CONTEXT). */
3675
3676char *
3677get_option_url (diagnostic_context *, int option_index)
3678{
3679 if (option_index)
3680 return concat (/* DOCUMENTATION_ROOT_URL should be supplied via
3681 #include "config.h" (see --with-documentation-root-url),
3682 and should have a trailing slash. */
3683 DOCUMENTATION_ROOT_URL,
3684
3685 /* get_option_html_page will return something like
3686 "gcc/Warning-Options.html". */
3687 get_option_html_page (option_index),
3688
3689 /* Expect an anchor of the form "index-Wfoo" e.g.
3690 <a name="index-Wformat"></a>, and thus an id within
3691 the URL of "#index-Wformat". */
3692 "#index", cl_options[option_index].opt_text,
3693 NULL);
3694 else
3695 return NULL;
3696}
3697
3698/* Return a heap allocated producer with command line options. */
3699
3700char *
3701gen_command_line_string (cl_decoded_option *options,
3702 unsigned int options_count)
3703{
3704 auto_vec<const char *> switches;
3705 char *options_string, *tail;
3706 const char *p;
3707 size_t len = 0;
3708
3709 for (unsigned i = 0; i < options_count; i++)
3710 switch (options[i].opt_index)
3711 {
3712 case OPT_o:
3713 case OPT_d:
3714 case OPT_dumpbase:
3715 case OPT_dumpbase_ext:
3716 case OPT_dumpdir:
3717 case OPT_quiet:
3718 case OPT_version:
3719 case OPT_v:
3720 case OPT_w:
3721 case OPT_L:
3722 case OPT_D:
3723 case OPT_I:
3724 case OPT_U:
3725 case OPT_SPECIAL_unknown:
3726 case OPT_SPECIAL_ignore:
3727 case OPT_SPECIAL_warn_removed:
3728 case OPT_SPECIAL_program_name:
3729 case OPT_SPECIAL_input_file:
3730 case OPT_grecord_gcc_switches:
3731 case OPT_frecord_gcc_switches:
3732 case OPT__output_pch:
3733 case OPT_fdiagnostics_show_location_:
3734 case OPT_fdiagnostics_show_option:
3735 case OPT_fdiagnostics_show_caret:
3736 case OPT_fdiagnostics_show_labels:
3737 case OPT_fdiagnostics_show_line_numbers:
3738 case OPT_fdiagnostics_color_:
3739 case OPT_fdiagnostics_format_:
3740 case OPT_fverbose_asm:
3741 case OPT____:
3742 case OPT__sysroot_:
3743 case OPT_nostdinc:
3744 case OPT_nostdinc__:
3745 case OPT_fpreprocessed:
3746 case OPT_fltrans_output_list_:
3747 case OPT_fresolution_:
3748 case OPT_fdebug_prefix_map_:
3749 case OPT_fmacro_prefix_map_:
3750 case OPT_ffile_prefix_map_:
3751 case OPT_fprofile_prefix_map_:
3752 case OPT_fcanon_prefix_map:
3753 case OPT_fcompare_debug:
3754 case OPT_fchecking:
3755 case OPT_fchecking_:
3756 /* Ignore these. */
3757 continue;
3758 case OPT_flto_:
3759 {
3760 const char *lto_canonical = "-flto";
3761 switches.safe_push (obj: lto_canonical);
3762 len += strlen (s: lto_canonical) + 1;
3763 break;
3764 }
3765 default:
3766 if (cl_options[options[i].opt_index].flags
3767 & CL_NO_DWARF_RECORD)
3768 continue;
3769 gcc_checking_assert (options[i].canonical_option[0][0] == '-');
3770 switch (options[i].canonical_option[0][1])
3771 {
3772 case 'M':
3773 case 'i':
3774 case 'W':
3775 continue;
3776 case 'f':
3777 if (strncmp (s1: options[i].canonical_option[0] + 2,
3778 s2: "dump", n: 4) == 0)
3779 continue;
3780 break;
3781 default:
3782 break;
3783 }
3784 switches.safe_push (obj: options[i].orig_option_with_args_text);
3785 len += strlen (s: options[i].orig_option_with_args_text) + 1;
3786 break;
3787 }
3788
3789 options_string = XNEWVEC (char, len + 1);
3790 tail = options_string;
3791
3792 unsigned i;
3793 FOR_EACH_VEC_ELT (switches, i, p)
3794 {
3795 len = strlen (s: p);
3796 memcpy (dest: tail, src: p, n: len);
3797 tail += len;
3798 if (i != switches.length () - 1)
3799 {
3800 *tail = ' ';
3801 ++tail;
3802 }
3803 }
3804
3805 *tail = '\0';
3806 return options_string;
3807}
3808
3809/* Return a heap allocated producer string including command line options. */
3810
3811char *
3812gen_producer_string (const char *language_string, cl_decoded_option *options,
3813 unsigned int options_count)
3814{
3815 char *cmdline = gen_command_line_string (options, options_count);
3816 char *combined = concat (language_string, " ", version_string, " ",
3817 cmdline, NULL);
3818 free (ptr: cmdline);
3819 return combined;
3820}
3821
3822#if CHECKING_P
3823
3824namespace selftest {
3825
3826/* Verify that get_option_html_page works as expected. */
3827
3828static void
3829test_get_option_html_page ()
3830{
3831 ASSERT_STREQ (get_option_html_page (OPT_Wcpp), "gcc/Warning-Options.html");
3832 ASSERT_STREQ (get_option_html_page (OPT_Wanalyzer_double_free),
3833 "gcc/Static-Analyzer-Options.html");
3834#ifdef CL_Fortran
3835 ASSERT_STREQ (get_option_html_page (OPT_Wline_truncation),
3836 "gfortran/Error-and-Warning-Options.html");
3837#endif
3838}
3839
3840/* Verify EnumSet and EnumBitSet requirements. */
3841
3842static void
3843test_enum_sets ()
3844{
3845 for (unsigned i = 0; i < cl_options_count; ++i)
3846 if (cl_options[i].var_type == CLVC_ENUM
3847 && cl_options[i].var_value != CLEV_NORMAL)
3848 {
3849 const struct cl_enum *e = &cl_enums[cl_options[i].var_enum];
3850 unsigned HOST_WIDE_INT used_sets = 0;
3851 unsigned HOST_WIDE_INT mask = 0;
3852 unsigned highest_set = 0;
3853 for (unsigned j = 0; e->values[j].arg; ++j)
3854 {
3855 unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
3856 if (cl_options[i].var_value == CLEV_BITSET)
3857 {
3858 /* For EnumBitSet Set shouldn't be used and Value should
3859 be a power of two. */
3860 ASSERT_TRUE (set == 0);
3861 ASSERT_TRUE (pow2p_hwi (e->values[j].value));
3862 continue;
3863 }
3864 /* Test that enumerators referenced in EnumSet have all
3865 Set(n) on them within the valid range. */
3866 ASSERT_TRUE (set >= 1 && set <= HOST_BITS_PER_WIDE_INT);
3867 highest_set = MAX (set, highest_set);
3868 used_sets |= HOST_WIDE_INT_1U << (set - 1);
3869 }
3870 if (cl_options[i].var_value == CLEV_BITSET)
3871 continue;
3872 /* If there is just one set, no point to using EnumSet. */
3873 ASSERT_TRUE (highest_set >= 2);
3874 /* Test that there are no gaps in between the sets. */
3875 if (highest_set == HOST_BITS_PER_WIDE_INT)
3876 ASSERT_TRUE (used_sets == HOST_WIDE_INT_M1U);
3877 else
3878 ASSERT_TRUE (used_sets == (HOST_WIDE_INT_1U << highest_set) - 1);
3879 for (unsigned int j = 1; j <= highest_set; ++j)
3880 {
3881 unsigned HOST_WIDE_INT this_mask = 0;
3882 for (unsigned k = 0; e->values[k].arg; ++k)
3883 {
3884 unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
3885 if (set == j)
3886 this_mask |= e->values[j].value;
3887 }
3888 ASSERT_TRUE ((mask & this_mask) == 0);
3889 mask |= this_mask;
3890 }
3891 }
3892}
3893
3894/* Run all of the selftests within this file. */
3895
3896void
3897opts_cc_tests ()
3898{
3899 test_get_option_html_page ();
3900 test_enum_sets ();
3901}
3902
3903} // namespace selftest
3904
3905#endif /* #if CHECKING_P */
3906

source code of gcc/opts.cc