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