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