138fd1498Szrj /* Command line option handling.
238fd1498Szrj Copyright (C) 2002-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Neil Booth.
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3. If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>. */
2038fd1498Szrj
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "intl.h"
2438fd1498Szrj #include "coretypes.h"
2538fd1498Szrj #include "opts.h"
2638fd1498Szrj #include "tm.h"
2738fd1498Szrj #include "flags.h"
2838fd1498Szrj #include "params.h"
2938fd1498Szrj #include "diagnostic.h"
3038fd1498Szrj #include "opts-diagnostic.h"
3138fd1498Szrj #include "insn-attr-common.h"
3238fd1498Szrj #include "common/common-target.h"
3338fd1498Szrj #include "spellcheck.h"
3438fd1498Szrj
3538fd1498Szrj static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
3638fd1498Szrj
3738fd1498Szrj /* Indexed by enum debug_info_type. */
3838fd1498Szrj const char *const debug_type_names[] =
3938fd1498Szrj {
4038fd1498Szrj "none", "stabs", "dwarf-2", "xcoff", "vms"
4138fd1498Szrj };
4238fd1498Szrj
4338fd1498Szrj /* Parse the -femit-struct-debug-detailed option value
4438fd1498Szrj and set the flag variables. */
4538fd1498Szrj
4638fd1498Szrj #define MATCH( prefix, string ) \
4738fd1498Szrj ((strncmp (prefix, string, sizeof prefix - 1) == 0) \
4838fd1498Szrj ? ((string += sizeof prefix - 1), 1) : 0)
4938fd1498Szrj
5038fd1498Szrj void
set_struct_debug_option(struct gcc_options * opts,location_t loc,const char * spec)5138fd1498Szrj set_struct_debug_option (struct gcc_options *opts, location_t loc,
5238fd1498Szrj const char *spec)
5338fd1498Szrj {
5438fd1498Szrj /* various labels for comparison */
5538fd1498Szrj static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
5638fd1498Szrj static const char ord_lbl[] = "ord:", gen_lbl[] = "gen:";
5738fd1498Szrj static const char none_lbl[] = "none", any_lbl[] = "any";
5838fd1498Szrj static const char base_lbl[] = "base", sys_lbl[] = "sys";
5938fd1498Szrj
6038fd1498Szrj enum debug_struct_file files = DINFO_STRUCT_FILE_ANY;
6138fd1498Szrj /* Default is to apply to as much as possible. */
6238fd1498Szrj enum debug_info_usage usage = DINFO_USAGE_NUM_ENUMS;
6338fd1498Szrj int ord = 1, gen = 1;
6438fd1498Szrj
6538fd1498Szrj /* What usage? */
6638fd1498Szrj if (MATCH (dfn_lbl, spec))
6738fd1498Szrj usage = DINFO_USAGE_DFN;
6838fd1498Szrj else if (MATCH (dir_lbl, spec))
6938fd1498Szrj usage = DINFO_USAGE_DIR_USE;
7038fd1498Szrj else if (MATCH (ind_lbl, spec))
7138fd1498Szrj usage = DINFO_USAGE_IND_USE;
7238fd1498Szrj
7338fd1498Szrj /* Generics or not? */
7438fd1498Szrj if (MATCH (ord_lbl, spec))
7538fd1498Szrj gen = 0;
7638fd1498Szrj else if (MATCH (gen_lbl, spec))
7738fd1498Szrj ord = 0;
7838fd1498Szrj
7938fd1498Szrj /* What allowable environment? */
8038fd1498Szrj if (MATCH (none_lbl, spec))
8138fd1498Szrj files = DINFO_STRUCT_FILE_NONE;
8238fd1498Szrj else if (MATCH (any_lbl, spec))
8338fd1498Szrj files = DINFO_STRUCT_FILE_ANY;
8438fd1498Szrj else if (MATCH (sys_lbl, spec))
8538fd1498Szrj files = DINFO_STRUCT_FILE_SYS;
8638fd1498Szrj else if (MATCH (base_lbl, spec))
8738fd1498Szrj files = DINFO_STRUCT_FILE_BASE;
8838fd1498Szrj else
8938fd1498Szrj error_at (loc,
9038fd1498Szrj "argument %qs to %<-femit-struct-debug-detailed%> "
9138fd1498Szrj "not recognized",
9238fd1498Szrj spec);
9338fd1498Szrj
9438fd1498Szrj /* Effect the specification. */
9538fd1498Szrj if (usage == DINFO_USAGE_NUM_ENUMS)
9638fd1498Szrj {
9738fd1498Szrj if (ord)
9838fd1498Szrj {
9938fd1498Szrj opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files;
10038fd1498Szrj opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files;
10138fd1498Szrj opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files;
10238fd1498Szrj }
10338fd1498Szrj if (gen)
10438fd1498Szrj {
10538fd1498Szrj opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files;
10638fd1498Szrj opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files;
10738fd1498Szrj opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files;
10838fd1498Szrj }
10938fd1498Szrj }
11038fd1498Szrj else
11138fd1498Szrj {
11238fd1498Szrj if (ord)
11338fd1498Szrj opts->x_debug_struct_ordinary[usage] = files;
11438fd1498Szrj if (gen)
11538fd1498Szrj opts->x_debug_struct_generic[usage] = files;
11638fd1498Szrj }
11738fd1498Szrj
11838fd1498Szrj if (*spec == ',')
11938fd1498Szrj set_struct_debug_option (opts, loc, spec+1);
12038fd1498Szrj else
12138fd1498Szrj {
12238fd1498Szrj /* No more -femit-struct-debug-detailed specifications.
12338fd1498Szrj Do final checks. */
12438fd1498Szrj if (*spec != '\0')
12538fd1498Szrj error_at (loc,
12638fd1498Szrj "argument %qs to %<-femit-struct-debug-detailed%> unknown",
12738fd1498Szrj spec);
12838fd1498Szrj if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE]
12938fd1498Szrj < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE]
13038fd1498Szrj || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE]
13138fd1498Szrj < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE])
13238fd1498Szrj error_at (loc,
13338fd1498Szrj "%<-femit-struct-debug-detailed=dir:...%> must allow "
13438fd1498Szrj "at least as much as "
13538fd1498Szrj "%<-femit-struct-debug-detailed=ind:...%>");
13638fd1498Szrj }
13738fd1498Szrj }
13838fd1498Szrj
13938fd1498Szrj /* Strip off a legitimate source ending from the input string NAME of
14038fd1498Szrj length LEN. Rather than having to know the names used by all of
14138fd1498Szrj our front ends, we strip off an ending of a period followed by
14238fd1498Szrj up to fource characters. (C++ uses ".cpp".) */
14338fd1498Szrj
14438fd1498Szrj void
strip_off_ending(char * name,int len)14538fd1498Szrj strip_off_ending (char *name, int len)
14638fd1498Szrj {
14738fd1498Szrj int i;
14838fd1498Szrj for (i = 2; i < 5 && len > i; i++)
14938fd1498Szrj {
15038fd1498Szrj if (name[len - i] == '.')
15138fd1498Szrj {
15238fd1498Szrj name[len - i] = '\0';
15338fd1498Szrj break;
15438fd1498Szrj }
15538fd1498Szrj }
15638fd1498Szrj }
15738fd1498Szrj
15838fd1498Szrj /* Find the base name of a path, stripping off both directories and
15938fd1498Szrj a single final extension. */
16038fd1498Szrj int
base_of_path(const char * path,const char ** base_out)16138fd1498Szrj base_of_path (const char *path, const char **base_out)
16238fd1498Szrj {
16338fd1498Szrj const char *base = path;
16438fd1498Szrj const char *dot = 0;
16538fd1498Szrj const char *p = path;
16638fd1498Szrj char c = *p;
16738fd1498Szrj while (c)
16838fd1498Szrj {
16938fd1498Szrj if (IS_DIR_SEPARATOR (c))
17038fd1498Szrj {
17138fd1498Szrj base = p + 1;
17238fd1498Szrj dot = 0;
17338fd1498Szrj }
17438fd1498Szrj else if (c == '.')
17538fd1498Szrj dot = p;
17638fd1498Szrj c = *++p;
17738fd1498Szrj }
17838fd1498Szrj if (!dot)
17938fd1498Szrj dot = p;
18038fd1498Szrj *base_out = base;
18138fd1498Szrj return dot - base;
18238fd1498Szrj }
18338fd1498Szrj
18438fd1498Szrj /* What to print when a switch has no documentation. */
18538fd1498Szrj static const char undocumented_msg[] = N_("This option lacks documentation.");
18638fd1498Szrj static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed.");
18738fd1498Szrj
18838fd1498Szrj typedef char *char_p; /* For DEF_VEC_P. */
18938fd1498Szrj
19038fd1498Szrj static void handle_param (struct gcc_options *opts,
19138fd1498Szrj struct gcc_options *opts_set, location_t loc,
19238fd1498Szrj const char *carg);
19338fd1498Szrj static void set_debug_level (enum debug_info_type type, int extended,
19438fd1498Szrj const char *arg, struct gcc_options *opts,
19538fd1498Szrj struct gcc_options *opts_set,
19638fd1498Szrj location_t loc);
19738fd1498Szrj static void set_fast_math_flags (struct gcc_options *opts, int set);
19838fd1498Szrj static void decode_d_option (const char *arg, struct gcc_options *opts,
19938fd1498Szrj location_t loc, diagnostic_context *dc);
20038fd1498Szrj static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
20138fd1498Szrj int set);
20238fd1498Szrj static void enable_warning_as_error (const char *arg, int value,
20338fd1498Szrj unsigned int lang_mask,
20438fd1498Szrj const struct cl_option_handlers *handlers,
20538fd1498Szrj struct gcc_options *opts,
20638fd1498Szrj struct gcc_options *opts_set,
20738fd1498Szrj location_t loc,
20838fd1498Szrj diagnostic_context *dc);
20938fd1498Szrj
21038fd1498Szrj /* Handle a back-end option; arguments and return value as for
21138fd1498Szrj handle_option. */
21238fd1498Szrj
21338fd1498Szrj bool
target_handle_option(struct gcc_options * opts,struct gcc_options * opts_set,const struct cl_decoded_option * decoded,unsigned int lang_mask ATTRIBUTE_UNUSED,int kind,location_t loc,const struct cl_option_handlers * handlers ATTRIBUTE_UNUSED,diagnostic_context * dc,void (*)(void))21438fd1498Szrj target_handle_option (struct gcc_options *opts,
21538fd1498Szrj struct gcc_options *opts_set,
21638fd1498Szrj const struct cl_decoded_option *decoded,
21738fd1498Szrj unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
21838fd1498Szrj location_t loc,
21938fd1498Szrj const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
22038fd1498Szrj diagnostic_context *dc, void (*) (void))
22138fd1498Szrj {
22238fd1498Szrj gcc_assert (dc == global_dc);
22338fd1498Szrj gcc_assert (kind == DK_UNSPECIFIED);
22438fd1498Szrj return targetm_common.handle_option (opts, opts_set, decoded, loc);
22538fd1498Szrj }
22638fd1498Szrj
22738fd1498Szrj /* Add comma-separated strings to a char_p vector. */
22838fd1498Szrj
22938fd1498Szrj static void
add_comma_separated_to_vector(void ** pvec,const char * arg)23038fd1498Szrj add_comma_separated_to_vector (void **pvec, const char *arg)
23138fd1498Szrj {
23238fd1498Szrj char *tmp;
23338fd1498Szrj char *r;
23438fd1498Szrj char *w;
23538fd1498Szrj char *token_start;
23638fd1498Szrj vec<char_p> *v = (vec<char_p> *) *pvec;
23738fd1498Szrj
23838fd1498Szrj vec_check_alloc (v, 1);
23938fd1498Szrj
24038fd1498Szrj /* We never free this string. */
24138fd1498Szrj tmp = xstrdup (arg);
24238fd1498Szrj
24338fd1498Szrj r = tmp;
24438fd1498Szrj w = tmp;
24538fd1498Szrj token_start = tmp;
24638fd1498Szrj
24738fd1498Szrj while (*r != '\0')
24838fd1498Szrj {
24938fd1498Szrj if (*r == ',')
25038fd1498Szrj {
25138fd1498Szrj *w++ = '\0';
25238fd1498Szrj ++r;
25338fd1498Szrj v->safe_push (token_start);
25438fd1498Szrj token_start = w;
25538fd1498Szrj }
25638fd1498Szrj if (*r == '\\' && r[1] == ',')
25738fd1498Szrj {
25838fd1498Szrj *w++ = ',';
25938fd1498Szrj r += 2;
26038fd1498Szrj }
26138fd1498Szrj else
26238fd1498Szrj *w++ = *r++;
26338fd1498Szrj }
26438fd1498Szrj if (*token_start != '\0')
26538fd1498Szrj v->safe_push (token_start);
26638fd1498Szrj
26738fd1498Szrj *pvec = v;
26838fd1498Szrj }
26938fd1498Szrj
27038fd1498Szrj /* Initialize opts_obstack. */
27138fd1498Szrj
27238fd1498Szrj void
init_opts_obstack(void)27338fd1498Szrj init_opts_obstack (void)
27438fd1498Szrj {
27538fd1498Szrj gcc_obstack_init (&opts_obstack);
27638fd1498Szrj }
27738fd1498Szrj
27838fd1498Szrj /* Initialize OPTS and OPTS_SET before using them in parsing options. */
27938fd1498Szrj
28038fd1498Szrj void
init_options_struct(struct gcc_options * opts,struct gcc_options * opts_set)28138fd1498Szrj init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
28238fd1498Szrj {
28338fd1498Szrj size_t num_params = get_num_compiler_params ();
28438fd1498Szrj
28538fd1498Szrj /* Ensure that opts_obstack has already been initialized by the time
28638fd1498Szrj that we initialize any gcc_options instances (PR jit/68446). */
28738fd1498Szrj gcc_assert (opts_obstack.chunk_size > 0);
28838fd1498Szrj
28938fd1498Szrj *opts = global_options_init;
29038fd1498Szrj
29138fd1498Szrj if (opts_set)
29238fd1498Szrj memset (opts_set, 0, sizeof (*opts_set));
29338fd1498Szrj
29438fd1498Szrj opts->x_param_values = XNEWVEC (int, num_params);
29538fd1498Szrj
29638fd1498Szrj if (opts_set)
29738fd1498Szrj opts_set->x_param_values = XCNEWVEC (int, num_params);
29838fd1498Szrj
29938fd1498Szrj init_param_values (opts->x_param_values);
30038fd1498Szrj
30138fd1498Szrj /* Initialize whether `char' is signed. */
30238fd1498Szrj opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
30338fd1498Szrj /* Set this to a special "uninitialized" value. The actual default
30438fd1498Szrj is set after target options have been processed. */
30538fd1498Szrj opts->x_flag_short_enums = 2;
30638fd1498Szrj
30738fd1498Szrj /* Initialize target_flags before default_options_optimization
30838fd1498Szrj so the latter can modify it. */
30938fd1498Szrj opts->x_target_flags = targetm_common.default_target_flags;
31038fd1498Szrj
31138fd1498Szrj /* Some targets have ABI-specified unwind tables. */
31238fd1498Szrj opts->x_flag_unwind_tables = targetm_common.unwind_tables_default;
31338fd1498Szrj
31438fd1498Szrj /* Some targets have other target-specific initialization. */
31538fd1498Szrj targetm_common.option_init_struct (opts);
31638fd1498Szrj }
31738fd1498Szrj
31838fd1498Szrj /* Release any allocations owned by OPTS. */
31938fd1498Szrj
32038fd1498Szrj void
finalize_options_struct(struct gcc_options * opts)32138fd1498Szrj finalize_options_struct (struct gcc_options *opts)
32238fd1498Szrj {
32338fd1498Szrj XDELETEVEC (opts->x_param_values);
32438fd1498Szrj }
32538fd1498Szrj
32638fd1498Szrj /* If indicated by the optimization level LEVEL (-Os if SIZE is set,
32738fd1498Szrj -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT
32838fd1498Szrj to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language
32938fd1498Szrj mask LANG_MASK and option handlers HANDLERS. */
33038fd1498Szrj
33138fd1498Szrj static void
maybe_default_option(struct gcc_options * opts,struct gcc_options * opts_set,const struct default_options * default_opt,int level,bool size,bool fast,bool debug,unsigned int lang_mask,const struct cl_option_handlers * handlers,location_t loc,diagnostic_context * dc)33238fd1498Szrj maybe_default_option (struct gcc_options *opts,
33338fd1498Szrj struct gcc_options *opts_set,
33438fd1498Szrj const struct default_options *default_opt,
33538fd1498Szrj int level, bool size, bool fast, bool debug,
33638fd1498Szrj unsigned int lang_mask,
33738fd1498Szrj const struct cl_option_handlers *handlers,
33838fd1498Szrj location_t loc,
33938fd1498Szrj diagnostic_context *dc)
34038fd1498Szrj {
34138fd1498Szrj const struct cl_option *option = &cl_options[default_opt->opt_index];
34238fd1498Szrj bool enabled;
34338fd1498Szrj
34438fd1498Szrj if (size)
34538fd1498Szrj gcc_assert (level == 2);
34638fd1498Szrj if (fast)
34738fd1498Szrj gcc_assert (level == 3);
34838fd1498Szrj if (debug)
34938fd1498Szrj gcc_assert (level == 1);
35038fd1498Szrj
35138fd1498Szrj switch (default_opt->levels)
35238fd1498Szrj {
35338fd1498Szrj case OPT_LEVELS_ALL:
35438fd1498Szrj enabled = true;
35538fd1498Szrj break;
35638fd1498Szrj
35738fd1498Szrj case OPT_LEVELS_0_ONLY:
35838fd1498Szrj enabled = (level == 0);
35938fd1498Szrj break;
36038fd1498Szrj
36138fd1498Szrj case OPT_LEVELS_1_PLUS:
36238fd1498Szrj enabled = (level >= 1);
36338fd1498Szrj break;
36438fd1498Szrj
36538fd1498Szrj case OPT_LEVELS_1_PLUS_SPEED_ONLY:
36638fd1498Szrj enabled = (level >= 1 && !size && !debug);
36738fd1498Szrj break;
36838fd1498Szrj
36938fd1498Szrj case OPT_LEVELS_1_PLUS_NOT_DEBUG:
37038fd1498Szrj enabled = (level >= 1 && !debug);
37138fd1498Szrj break;
37238fd1498Szrj
37338fd1498Szrj case OPT_LEVELS_2_PLUS:
37438fd1498Szrj enabled = (level >= 2);
37538fd1498Szrj break;
37638fd1498Szrj
37738fd1498Szrj case OPT_LEVELS_2_PLUS_SPEED_ONLY:
37838fd1498Szrj enabled = (level >= 2 && !size && !debug);
37938fd1498Szrj break;
38038fd1498Szrj
38138fd1498Szrj case OPT_LEVELS_3_PLUS:
38238fd1498Szrj enabled = (level >= 3);
38338fd1498Szrj break;
38438fd1498Szrj
38538fd1498Szrj case OPT_LEVELS_3_PLUS_AND_SIZE:
38638fd1498Szrj enabled = (level >= 3 || size);
38738fd1498Szrj break;
38838fd1498Szrj
38938fd1498Szrj case OPT_LEVELS_SIZE:
39038fd1498Szrj enabled = size;
39138fd1498Szrj break;
39238fd1498Szrj
39338fd1498Szrj case OPT_LEVELS_FAST:
39438fd1498Szrj enabled = fast;
39538fd1498Szrj break;
39638fd1498Szrj
39738fd1498Szrj case OPT_LEVELS_NONE:
39838fd1498Szrj default:
39938fd1498Szrj gcc_unreachable ();
40038fd1498Szrj }
40138fd1498Szrj
40238fd1498Szrj if (enabled)
40338fd1498Szrj handle_generated_option (opts, opts_set, default_opt->opt_index,
40438fd1498Szrj default_opt->arg, default_opt->value,
40538fd1498Szrj lang_mask, DK_UNSPECIFIED, loc,
40638fd1498Szrj handlers, true, dc);
40738fd1498Szrj else if (default_opt->arg == NULL
40838fd1498Szrj && !option->cl_reject_negative)
40938fd1498Szrj handle_generated_option (opts, opts_set, default_opt->opt_index,
41038fd1498Szrj default_opt->arg, !default_opt->value,
41138fd1498Szrj lang_mask, DK_UNSPECIFIED, loc,
41238fd1498Szrj handlers, true, dc);
41338fd1498Szrj }
41438fd1498Szrj
41538fd1498Szrj /* As indicated by the optimization level LEVEL (-Os if SIZE is set,
41638fd1498Szrj -Ofast if FAST is set), apply the options in array DEFAULT_OPTS to
41738fd1498Szrj OPTS and OPTS_SET, diagnostic context DC, location LOC, with
41838fd1498Szrj language mask LANG_MASK and option handlers HANDLERS. */
41938fd1498Szrj
42038fd1498Szrj static void
maybe_default_options(struct gcc_options * opts,struct gcc_options * opts_set,const struct default_options * default_opts,int level,bool size,bool fast,bool debug,unsigned int lang_mask,const struct cl_option_handlers * handlers,location_t loc,diagnostic_context * dc)42138fd1498Szrj maybe_default_options (struct gcc_options *opts,
42238fd1498Szrj struct gcc_options *opts_set,
42338fd1498Szrj const struct default_options *default_opts,
42438fd1498Szrj int level, bool size, bool fast, bool debug,
42538fd1498Szrj unsigned int lang_mask,
42638fd1498Szrj const struct cl_option_handlers *handlers,
42738fd1498Szrj location_t loc,
42838fd1498Szrj diagnostic_context *dc)
42938fd1498Szrj {
43038fd1498Szrj size_t i;
43138fd1498Szrj
43238fd1498Szrj for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
43338fd1498Szrj maybe_default_option (opts, opts_set, &default_opts[i],
43438fd1498Szrj level, size, fast, debug,
43538fd1498Szrj lang_mask, handlers, loc, dc);
43638fd1498Szrj }
43738fd1498Szrj
43838fd1498Szrj /* Table of options enabled by default at different levels. */
43938fd1498Szrj
44038fd1498Szrj static const struct default_options default_options_table[] =
44138fd1498Szrj {
44238fd1498Szrj /* -O1 optimizations. */
44338fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
44438fd1498Szrj #if DELAY_SLOTS
44538fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fdelayed_branch, NULL, 1 },
44638fd1498Szrj #endif
44738fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fguess_branch_probability, NULL, 1 },
44838fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fcprop_registers, NULL, 1 },
44938fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fforward_propagate, NULL, 1 },
45038fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion, NULL, 1 },
45138fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 },
45238fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 },
45338fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },
45438fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },
45538fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },
45638fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 },
45738fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
45838fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
45938fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
46038fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 },
46138fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_coalesce_vars, NULL, 1 },
46238fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_dce, NULL, 1 },
46338fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },
46438fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_dse, NULL, 1 },
46538fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
46638fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
46738fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
46838fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
46938fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
47038fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },
47138fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 },
47238fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 },
47338fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 },
47438fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 },
47538fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 },
47638fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 },
47738fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 },
47838fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
47938fd1498Szrj { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
48038fd1498Szrj
48138fd1498Szrj /* -O2 optimizations. */
48238fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },
48338fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },
48438fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fpartial_inlining, NULL, 1 },
48538fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fthread_jumps, NULL, 1 },
48638fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fcrossjumping, NULL, 1 },
48738fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_foptimize_sibling_calls, NULL, 1 },
48838fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fcse_follow_jumps, NULL, 1 },
48938fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },
49038fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },
49138fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_frerun_cse_after_loop, NULL, 1 },
49238fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fcaller_saves, NULL, 1 },
49338fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fpeephole2, NULL, 1 },
49438fd1498Szrj #ifdef INSN_SCHEDULING
49538fd1498Szrj /* Only run the pre-regalloc scheduling pass if optimizing for speed. */
49638fd1498Szrj { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
49738fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
49838fd1498Szrj #endif
49938fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
50038fd1498Szrj { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL,
50138fd1498Szrj REORDER_BLOCKS_ALGORITHM_STC },
50238fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },
50338fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
50438fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fcode_hoisting, NULL, 1 },
50538fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
50638fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
50738fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
50838fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 },
50938fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_vrp, NULL, 1 },
51038fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
51138fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
51238fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
51338fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_falign_loops, NULL, 1 },
51438fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_falign_jumps, NULL, 1 },
51538fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },
51638fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
51738fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
51838fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
51938fd1498Szrj { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
52038fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
52138fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 },
52238fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
52338fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 },
52438fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },
52538fd1498Szrj { OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 },
52638fd1498Szrj
52738fd1498Szrj /* -O3 optimizations. */
52838fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
52938fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 },
53038fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_floop_interchange, NULL, 1 },
53138fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
53238fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },
53338fd1498Szrj /* Inlining of functions reducing size is a good idea with -Os
53438fd1498Szrj regardless of them being declared inline. */
53538fd1498Szrj { OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
53638fd1498Szrj { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 },
53738fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 },
53838fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
53938fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_floop_unroll_and_jam, NULL, 1 },
54038fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
54138fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },
54238fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 },
54338fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },
54438fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },
54538fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
54638fd1498Szrj { OPT_LEVELS_3_PLUS, OPT_fpeel_loops, NULL, 1 },
54738fd1498Szrj
54838fd1498Szrj /* -Ofast adds optimizations to -O3. */
54938fd1498Szrj { OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },
55038fd1498Szrj
55138fd1498Szrj { OPT_LEVELS_NONE, 0, NULL, 0 }
55238fd1498Szrj };
55338fd1498Szrj
55438fd1498Szrj /* Default the options in OPTS and OPTS_SET based on the optimization
55538fd1498Szrj settings in DECODED_OPTIONS and DECODED_OPTIONS_COUNT. */
55638fd1498Szrj void
default_options_optimization(struct gcc_options * opts,struct gcc_options * opts_set,struct cl_decoded_option * decoded_options,unsigned int decoded_options_count,location_t loc,unsigned int lang_mask,const struct cl_option_handlers * handlers,diagnostic_context * dc)55738fd1498Szrj default_options_optimization (struct gcc_options *opts,
55838fd1498Szrj struct gcc_options *opts_set,
55938fd1498Szrj struct cl_decoded_option *decoded_options,
56038fd1498Szrj unsigned int decoded_options_count,
56138fd1498Szrj location_t loc,
56238fd1498Szrj unsigned int lang_mask,
56338fd1498Szrj const struct cl_option_handlers *handlers,
56438fd1498Szrj diagnostic_context *dc)
56538fd1498Szrj {
56638fd1498Szrj unsigned int i;
56738fd1498Szrj int opt2;
56838fd1498Szrj bool openacc_mode = false;
56938fd1498Szrj
57038fd1498Szrj /* Scan to see what optimization level has been specified. That will
57138fd1498Szrj determine the default value of many flags. */
57238fd1498Szrj for (i = 1; i < decoded_options_count; i++)
57338fd1498Szrj {
57438fd1498Szrj struct cl_decoded_option *opt = &decoded_options[i];
57538fd1498Szrj switch (opt->opt_index)
57638fd1498Szrj {
57738fd1498Szrj case OPT_O:
57838fd1498Szrj if (*opt->arg == '\0')
57938fd1498Szrj {
58038fd1498Szrj opts->x_optimize = 1;
58138fd1498Szrj opts->x_optimize_size = 0;
58238fd1498Szrj opts->x_optimize_fast = 0;
58338fd1498Szrj opts->x_optimize_debug = 0;
58438fd1498Szrj }
58538fd1498Szrj else
58638fd1498Szrj {
58738fd1498Szrj const int optimize_val = integral_argument (opt->arg);
58838fd1498Szrj if (optimize_val == -1)
58938fd1498Szrj error_at (loc, "argument to %<-O%> should be a non-negative "
59038fd1498Szrj "integer, %<g%>, %<s%> or %<fast%>");
59138fd1498Szrj else
59238fd1498Szrj {
59338fd1498Szrj opts->x_optimize = optimize_val;
59438fd1498Szrj if ((unsigned int) opts->x_optimize > 255)
59538fd1498Szrj opts->x_optimize = 255;
59638fd1498Szrj opts->x_optimize_size = 0;
59738fd1498Szrj opts->x_optimize_fast = 0;
59838fd1498Szrj opts->x_optimize_debug = 0;
59938fd1498Szrj }
60038fd1498Szrj }
60138fd1498Szrj break;
60238fd1498Szrj
60338fd1498Szrj case OPT_Os:
60438fd1498Szrj opts->x_optimize_size = 1;
60538fd1498Szrj
60638fd1498Szrj /* Optimizing for size forces optimize to be 2. */
60738fd1498Szrj opts->x_optimize = 2;
60838fd1498Szrj opts->x_optimize_fast = 0;
60938fd1498Szrj opts->x_optimize_debug = 0;
61038fd1498Szrj break;
61138fd1498Szrj
61238fd1498Szrj case OPT_Ofast:
61338fd1498Szrj /* -Ofast only adds flags to -O3. */
61438fd1498Szrj opts->x_optimize_size = 0;
61538fd1498Szrj opts->x_optimize = 3;
61638fd1498Szrj opts->x_optimize_fast = 1;
61738fd1498Szrj opts->x_optimize_debug = 0;
61838fd1498Szrj break;
61938fd1498Szrj
62038fd1498Szrj case OPT_Og:
62138fd1498Szrj /* -Og selects optimization level 1. */
62238fd1498Szrj opts->x_optimize_size = 0;
62338fd1498Szrj opts->x_optimize = 1;
62438fd1498Szrj opts->x_optimize_fast = 0;
62538fd1498Szrj opts->x_optimize_debug = 1;
62638fd1498Szrj break;
62738fd1498Szrj
62838fd1498Szrj case OPT_fopenacc:
62938fd1498Szrj if (opt->value)
63038fd1498Szrj openacc_mode = true;
63138fd1498Szrj break;
63238fd1498Szrj
63338fd1498Szrj default:
63438fd1498Szrj /* Ignore other options in this prescan. */
63538fd1498Szrj break;
63638fd1498Szrj }
63738fd1498Szrj }
63838fd1498Szrj
63938fd1498Szrj maybe_default_options (opts, opts_set, default_options_table,
64038fd1498Szrj opts->x_optimize, opts->x_optimize_size,
64138fd1498Szrj opts->x_optimize_fast, opts->x_optimize_debug,
64238fd1498Szrj lang_mask, handlers, loc, dc);
64338fd1498Szrj
64438fd1498Szrj /* -O2 param settings. */
64538fd1498Szrj opt2 = (opts->x_optimize >= 2);
64638fd1498Szrj
64738fd1498Szrj if (openacc_mode
64838fd1498Szrj && !opts_set->x_flag_ipa_pta)
64938fd1498Szrj opts->x_flag_ipa_pta = true;
65038fd1498Szrj
65138fd1498Szrj /* Track fields in field-sensitive alias analysis. */
65238fd1498Szrj maybe_set_param_value
65338fd1498Szrj (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE,
65438fd1498Szrj opt2 ? 100 : default_param_value (PARAM_MAX_FIELDS_FOR_FIELD_SENSITIVE),
65538fd1498Szrj opts->x_param_values, opts_set->x_param_values);
65638fd1498Szrj
65738fd1498Szrj /* For -O1 only do loop invariant motion for very small loops. */
65838fd1498Szrj maybe_set_param_value
65938fd1498Szrj (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
66058e805e6Szrj opt2 ? default_param_value (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP)
66158e805e6Szrj : default_param_value (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP) / 10,
66258e805e6Szrj opts->x_param_values, opts_set->x_param_values);
66358e805e6Szrj
66458e805e6Szrj /* For -O1 reduce the maximum number of active local stores for RTL DSE
66558e805e6Szrj since this can consume huge amounts of memory (PR89115). */
66658e805e6Szrj maybe_set_param_value
66758e805e6Szrj (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES,
66858e805e6Szrj opt2 ? default_param_value (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES)
66958e805e6Szrj : default_param_value (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES) / 10,
67038fd1498Szrj opts->x_param_values, opts_set->x_param_values);
67138fd1498Szrj
67238fd1498Szrj /* At -Ofast, allow store motion to introduce potential race conditions. */
67338fd1498Szrj maybe_set_param_value
67438fd1498Szrj (PARAM_ALLOW_STORE_DATA_RACES,
67538fd1498Szrj opts->x_optimize_fast ? 1
67638fd1498Szrj : default_param_value (PARAM_ALLOW_STORE_DATA_RACES),
67738fd1498Szrj opts->x_param_values, opts_set->x_param_values);
67838fd1498Szrj
67938fd1498Szrj if (opts->x_optimize_size)
68038fd1498Szrj /* We want to crossjump as much as possible. */
68138fd1498Szrj maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS, 1,
68238fd1498Szrj opts->x_param_values, opts_set->x_param_values);
68338fd1498Szrj else
68438fd1498Szrj maybe_set_param_value (PARAM_MIN_CROSSJUMP_INSNS,
68538fd1498Szrj default_param_value (PARAM_MIN_CROSSJUMP_INSNS),
68638fd1498Szrj opts->x_param_values, opts_set->x_param_values);
68738fd1498Szrj
68838fd1498Szrj /* Restrict the amount of work combine does at -Og while retaining
68938fd1498Szrj most of its useful transforms. */
69038fd1498Szrj if (opts->x_optimize_debug)
69138fd1498Szrj maybe_set_param_value (PARAM_MAX_COMBINE_INSNS, 2,
69238fd1498Szrj opts->x_param_values, opts_set->x_param_values);
69338fd1498Szrj
69438fd1498Szrj /* Allow default optimizations to be specified on a per-machine basis. */
69538fd1498Szrj maybe_default_options (opts, opts_set,
69638fd1498Szrj targetm_common.option_optimization_table,
69738fd1498Szrj opts->x_optimize, opts->x_optimize_size,
69838fd1498Szrj opts->x_optimize_fast, opts->x_optimize_debug,
69938fd1498Szrj lang_mask, handlers, loc, dc);
70038fd1498Szrj }
70138fd1498Szrj
70238fd1498Szrj /* After all options at LOC have been read into OPTS and OPTS_SET,
70338fd1498Szrj finalize settings of those options and diagnose incompatible
70438fd1498Szrj combinations. */
70538fd1498Szrj void
finish_options(struct gcc_options * opts,struct gcc_options * opts_set,location_t loc)70638fd1498Szrj finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
70738fd1498Szrj location_t loc)
70838fd1498Szrj {
70938fd1498Szrj enum unwind_info_type ui_except;
71038fd1498Szrj
71138fd1498Szrj if (opts->x_dump_base_name
71238fd1498Szrj && ! opts->x_dump_base_name_prefixed)
71338fd1498Szrj {
71438fd1498Szrj const char *sep = opts->x_dump_base_name;
71538fd1498Szrj
71638fd1498Szrj for (; *sep; sep++)
71738fd1498Szrj if (IS_DIR_SEPARATOR (*sep))
71838fd1498Szrj break;
71938fd1498Szrj
72038fd1498Szrj if (*sep)
72138fd1498Szrj /* If dump_base_path contains subdirectories, don't prepend
72238fd1498Szrj anything. */;
72338fd1498Szrj else if (opts->x_dump_dir_name)
72438fd1498Szrj /* We have a DUMP_DIR_NAME, prepend that. */
72538fd1498Szrj opts->x_dump_base_name = opts_concat (opts->x_dump_dir_name,
72638fd1498Szrj opts->x_dump_base_name, NULL);
72738fd1498Szrj else if (opts->x_aux_base_name
72838fd1498Szrj && strcmp (opts->x_aux_base_name, HOST_BIT_BUCKET) != 0)
72938fd1498Szrj /* AUX_BASE_NAME is set and is not the bit bucket. If it
73038fd1498Szrj contains a directory component, prepend those directories.
73138fd1498Szrj Typically this places things in the same directory as the
73238fd1498Szrj object file. */
73338fd1498Szrj {
73438fd1498Szrj const char *aux_base;
73538fd1498Szrj
73638fd1498Szrj base_of_path (opts->x_aux_base_name, &aux_base);
73738fd1498Szrj if (opts->x_aux_base_name != aux_base)
73838fd1498Szrj {
73938fd1498Szrj int dir_len = aux_base - opts->x_aux_base_name;
74038fd1498Szrj char *new_dump_base_name
74138fd1498Szrj = XOBNEWVEC (&opts_obstack, char,
74238fd1498Szrj strlen (opts->x_dump_base_name) + dir_len + 1);
74338fd1498Szrj
74438fd1498Szrj /* Copy directory component from OPTS->X_AUX_BASE_NAME. */
74538fd1498Szrj memcpy (new_dump_base_name, opts->x_aux_base_name, dir_len);
74638fd1498Szrj /* Append existing OPTS->X_DUMP_BASE_NAME. */
74738fd1498Szrj strcpy (new_dump_base_name + dir_len, opts->x_dump_base_name);
74838fd1498Szrj opts->x_dump_base_name = new_dump_base_name;
74938fd1498Szrj }
75038fd1498Szrj }
75138fd1498Szrj
75238fd1498Szrj /* It is definitely prefixed now. */
75338fd1498Szrj opts->x_dump_base_name_prefixed = true;
75438fd1498Szrj }
75538fd1498Szrj
75638fd1498Szrj /* Handle related options for unit-at-a-time, toplevel-reorder, and
75738fd1498Szrj section-anchors. */
75838fd1498Szrj if (!opts->x_flag_unit_at_a_time)
75938fd1498Szrj {
76038fd1498Szrj if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
76138fd1498Szrj error_at (loc, "section anchors must be disabled when unit-at-a-time "
76238fd1498Szrj "is disabled");
76338fd1498Szrj opts->x_flag_section_anchors = 0;
76438fd1498Szrj if (opts->x_flag_toplevel_reorder == 1)
76538fd1498Szrj error_at (loc, "toplevel reorder must be disabled when unit-at-a-time "
76638fd1498Szrj "is disabled");
76738fd1498Szrj opts->x_flag_toplevel_reorder = 0;
76838fd1498Szrj }
76938fd1498Szrj
77038fd1498Szrj /* -fself-test depends on the state of the compiler prior to
77138fd1498Szrj compiling anything. Ideally it should be run on an empty source
77238fd1498Szrj file. However, in case we get run with actual source, assume
77338fd1498Szrj -fsyntax-only which will inhibit any compiler initialization
77438fd1498Szrj which may confuse the self tests. */
77538fd1498Szrj if (opts->x_flag_self_test)
77638fd1498Szrj opts->x_flag_syntax_only = 1;
77738fd1498Szrj
77838fd1498Szrj if (opts->x_flag_tm && opts->x_flag_non_call_exceptions)
77938fd1498Szrj sorry ("transactional memory is not supported with non-call exceptions");
78038fd1498Szrj
78138fd1498Szrj /* Unless the user has asked for section anchors, we disable toplevel
78238fd1498Szrj reordering at -O0 to disable transformations that might be surprising
78338fd1498Szrj to end users and to get -fno-toplevel-reorder tested. */
78438fd1498Szrj if (!opts->x_optimize
78538fd1498Szrj && opts->x_flag_toplevel_reorder == 2
78638fd1498Szrj && !(opts->x_flag_section_anchors && opts_set->x_flag_section_anchors))
78738fd1498Szrj {
78838fd1498Szrj opts->x_flag_toplevel_reorder = 0;
78938fd1498Szrj opts->x_flag_section_anchors = 0;
79038fd1498Szrj }
79138fd1498Szrj if (!opts->x_flag_toplevel_reorder)
79238fd1498Szrj {
79338fd1498Szrj if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
79438fd1498Szrj error_at (loc, "section anchors must be disabled when toplevel reorder"
79538fd1498Szrj " is disabled");
79638fd1498Szrj opts->x_flag_section_anchors = 0;
79738fd1498Szrj }
79838fd1498Szrj
79938fd1498Szrj if (!opts->x_flag_opts_finished)
80038fd1498Szrj {
80138fd1498Szrj /* We initialize opts->x_flag_pie to -1 so that targets can set a
80238fd1498Szrj default value. */
80338fd1498Szrj if (opts->x_flag_pie == -1)
80438fd1498Szrj {
80538fd1498Szrj /* We initialize opts->x_flag_pic to -1 so that we can tell if
80638fd1498Szrj -fpic, -fPIC, -fno-pic or -fno-PIC is used. */
80738fd1498Szrj if (opts->x_flag_pic == -1)
80838fd1498Szrj opts->x_flag_pie = DEFAULT_FLAG_PIE;
80938fd1498Szrj else
81038fd1498Szrj opts->x_flag_pie = 0;
81138fd1498Szrj }
81238fd1498Szrj /* If -fPIE or -fpie is used, turn on PIC. */
81338fd1498Szrj if (opts->x_flag_pie)
81438fd1498Szrj opts->x_flag_pic = opts->x_flag_pie;
81538fd1498Szrj else if (opts->x_flag_pic == -1)
81638fd1498Szrj opts->x_flag_pic = 0;
81738fd1498Szrj if (opts->x_flag_pic && !opts->x_flag_pie)
81838fd1498Szrj opts->x_flag_shlib = 1;
81938fd1498Szrj opts->x_flag_opts_finished = true;
82038fd1498Szrj }
82138fd1498Szrj
82238fd1498Szrj /* We initialize opts->x_flag_stack_protect to -1 so that targets
82338fd1498Szrj can set a default value. */
82438fd1498Szrj if (opts->x_flag_stack_protect == -1)
82538fd1498Szrj opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
82638fd1498Szrj
82738fd1498Szrj if (opts->x_optimize == 0)
82838fd1498Szrj {
82938fd1498Szrj /* Inlining does not work if not optimizing,
83038fd1498Szrj so force it not to be done. */
83138fd1498Szrj opts->x_warn_inline = 0;
83238fd1498Szrj opts->x_flag_no_inline = 1;
83338fd1498Szrj }
83438fd1498Szrj
83538fd1498Szrj /* The optimization to partition hot and cold basic blocks into separate
83638fd1498Szrj sections of the .o and executable files does not work (currently)
83738fd1498Szrj with exception handling. This is because there is no support for
83838fd1498Szrj generating unwind info. If opts->x_flag_exceptions is turned on
83938fd1498Szrj we need to turn off the partitioning optimization. */
84038fd1498Szrj
84138fd1498Szrj ui_except = targetm_common.except_unwind_info (opts);
84238fd1498Szrj
84338fd1498Szrj if (opts->x_flag_exceptions
84438fd1498Szrj && opts->x_flag_reorder_blocks_and_partition
84538fd1498Szrj && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
84638fd1498Szrj {
84738fd1498Szrj if (opts_set->x_flag_reorder_blocks_and_partition)
84838fd1498Szrj inform (loc,
84938fd1498Szrj "%<-freorder-blocks-and-partition%> does not work "
85038fd1498Szrj "with exceptions on this architecture");
85138fd1498Szrj opts->x_flag_reorder_blocks_and_partition = 0;
85238fd1498Szrj opts->x_flag_reorder_blocks = 1;
85338fd1498Szrj }
85438fd1498Szrj
85538fd1498Szrj /* If user requested unwind info, then turn off the partitioning
85638fd1498Szrj optimization. */
85738fd1498Szrj
85838fd1498Szrj if (opts->x_flag_unwind_tables
85938fd1498Szrj && !targetm_common.unwind_tables_default
86038fd1498Szrj && opts->x_flag_reorder_blocks_and_partition
86138fd1498Szrj && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
86238fd1498Szrj {
86338fd1498Szrj if (opts_set->x_flag_reorder_blocks_and_partition)
86438fd1498Szrj inform (loc,
86538fd1498Szrj "%<-freorder-blocks-and-partition%> does not support "
86638fd1498Szrj "unwind info on this architecture");
86738fd1498Szrj opts->x_flag_reorder_blocks_and_partition = 0;
86838fd1498Szrj opts->x_flag_reorder_blocks = 1;
86938fd1498Szrj }
87038fd1498Szrj
87138fd1498Szrj /* If the target requested unwind info, then turn off the partitioning
87238fd1498Szrj optimization with a different message. Likewise, if the target does not
87338fd1498Szrj support named sections. */
87438fd1498Szrj
87538fd1498Szrj if (opts->x_flag_reorder_blocks_and_partition
87638fd1498Szrj && (!targetm_common.have_named_sections
87738fd1498Szrj || (opts->x_flag_unwind_tables
87838fd1498Szrj && targetm_common.unwind_tables_default
87938fd1498Szrj && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))))
88038fd1498Szrj {
88138fd1498Szrj if (opts_set->x_flag_reorder_blocks_and_partition)
88238fd1498Szrj inform (loc,
88338fd1498Szrj "%<-freorder-blocks-and-partition%> does not work "
88438fd1498Szrj "on this architecture");
88538fd1498Szrj opts->x_flag_reorder_blocks_and_partition = 0;
88638fd1498Szrj opts->x_flag_reorder_blocks = 1;
88738fd1498Szrj }
88838fd1498Szrj
88938fd1498Szrj
89038fd1498Szrj /* Pipelining of outer loops is only possible when general pipelining
89138fd1498Szrj capabilities are requested. */
89238fd1498Szrj if (!opts->x_flag_sel_sched_pipelining)
89338fd1498Szrj opts->x_flag_sel_sched_pipelining_outer_loops = 0;
89438fd1498Szrj
89538fd1498Szrj if (opts->x_flag_conserve_stack)
89638fd1498Szrj {
89738fd1498Szrj maybe_set_param_value (PARAM_LARGE_STACK_FRAME, 100,
89838fd1498Szrj opts->x_param_values, opts_set->x_param_values);
89938fd1498Szrj maybe_set_param_value (PARAM_STACK_FRAME_GROWTH, 40,
90038fd1498Szrj opts->x_param_values, opts_set->x_param_values);
90138fd1498Szrj }
90238fd1498Szrj
90338fd1498Szrj if (opts->x_flag_lto)
90438fd1498Szrj {
90538fd1498Szrj #ifdef ENABLE_LTO
90638fd1498Szrj opts->x_flag_generate_lto = 1;
90738fd1498Szrj
90838fd1498Szrj /* When generating IL, do not operate in whole-program mode.
90938fd1498Szrj Otherwise, symbols will be privatized too early, causing link
91038fd1498Szrj errors later. */
91138fd1498Szrj opts->x_flag_whole_program = 0;
91238fd1498Szrj #else
91338fd1498Szrj error_at (loc, "LTO support has not been enabled in this configuration");
91438fd1498Szrj #endif
91538fd1498Szrj if (!opts->x_flag_fat_lto_objects
91638fd1498Szrj && (!HAVE_LTO_PLUGIN
91738fd1498Szrj || (opts_set->x_flag_use_linker_plugin
91838fd1498Szrj && !opts->x_flag_use_linker_plugin)))
91938fd1498Szrj {
92038fd1498Szrj if (opts_set->x_flag_fat_lto_objects)
92138fd1498Szrj error_at (loc, "%<-fno-fat-lto-objects%> are supported only with "
92238fd1498Szrj "linker plugin");
92338fd1498Szrj opts->x_flag_fat_lto_objects = 1;
92438fd1498Szrj }
925*e215fc28Szrj
926*e215fc28Szrj /* -gsplit-dwarf isn't compatible with LTO, see PR88389. */
927*e215fc28Szrj if (opts->x_dwarf_split_debug_info)
928*e215fc28Szrj {
929*e215fc28Szrj inform (loc, "%<-gsplit-dwarf%> is not supported with LTO,"
930*e215fc28Szrj " disabling");
931*e215fc28Szrj opts->x_dwarf_split_debug_info = 0;
932*e215fc28Szrj }
93338fd1498Szrj }
93438fd1498Szrj
93538fd1498Szrj /* We initialize opts->x_flag_split_stack to -1 so that targets can set a
93638fd1498Szrj default value if they choose based on other options. */
93738fd1498Szrj if (opts->x_flag_split_stack == -1)
93838fd1498Szrj opts->x_flag_split_stack = 0;
93938fd1498Szrj else if (opts->x_flag_split_stack)
94038fd1498Szrj {
94138fd1498Szrj if (!targetm_common.supports_split_stack (true, opts))
94238fd1498Szrj {
94338fd1498Szrj error_at (loc, "%<-fsplit-stack%> is not supported by "
94438fd1498Szrj "this compiler configuration");
94538fd1498Szrj opts->x_flag_split_stack = 0;
94638fd1498Szrj }
94738fd1498Szrj }
94838fd1498Szrj
94938fd1498Szrj /* If stack splitting is turned on, and the user did not explicitly
95038fd1498Szrj request function partitioning, turn off partitioning, as it
95138fd1498Szrj confuses the linker when trying to handle partitioned split-stack
95238fd1498Szrj code that calls a non-split-stack functions. But if partitioning
95338fd1498Szrj was turned on explicitly just hope for the best. */
95438fd1498Szrj if (opts->x_flag_split_stack
95538fd1498Szrj && opts->x_flag_reorder_blocks_and_partition
95638fd1498Szrj && !opts_set->x_flag_reorder_blocks_and_partition)
95738fd1498Szrj opts->x_flag_reorder_blocks_and_partition = 0;
95838fd1498Szrj
95938fd1498Szrj if (opts->x_flag_reorder_blocks_and_partition
96038fd1498Szrj && !opts_set->x_flag_reorder_functions)
96138fd1498Szrj opts->x_flag_reorder_functions = 1;
96238fd1498Szrj
96338fd1498Szrj /* Tune vectorization related parametees according to cost model. */
96438fd1498Szrj if (opts->x_flag_vect_cost_model == VECT_COST_MODEL_CHEAP)
96538fd1498Szrj {
96638fd1498Szrj maybe_set_param_value (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS,
96738fd1498Szrj 6, opts->x_param_values, opts_set->x_param_values);
96838fd1498Szrj maybe_set_param_value (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS,
96938fd1498Szrj 0, opts->x_param_values, opts_set->x_param_values);
97038fd1498Szrj maybe_set_param_value (PARAM_VECT_MAX_PEELING_FOR_ALIGNMENT,
97138fd1498Szrj 0, opts->x_param_values, opts_set->x_param_values);
97238fd1498Szrj }
97338fd1498Szrj
97438fd1498Szrj /* Set PARAM_MAX_STORES_TO_SINK to 0 if either vectorization or if-conversion
97538fd1498Szrj is disabled. */
97638fd1498Szrj if ((!opts->x_flag_tree_loop_vectorize && !opts->x_flag_tree_slp_vectorize)
97738fd1498Szrj || !opts->x_flag_tree_loop_if_convert)
97838fd1498Szrj maybe_set_param_value (PARAM_MAX_STORES_TO_SINK, 0,
97938fd1498Szrj opts->x_param_values, opts_set->x_param_values);
98038fd1498Szrj
98138fd1498Szrj /* The -gsplit-dwarf option requires -ggnu-pubnames. */
98238fd1498Szrj if (opts->x_dwarf_split_debug_info)
98338fd1498Szrj opts->x_debug_generate_pub_sections = 2;
98438fd1498Szrj
98538fd1498Szrj if ((opts->x_flag_sanitize
98638fd1498Szrj & (SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS)) == 0)
98738fd1498Szrj {
98838fd1498Szrj if (opts->x_flag_sanitize & SANITIZE_POINTER_COMPARE)
98938fd1498Szrj error_at (loc,
99038fd1498Szrj "%<-fsanitize=pointer-compare%> must be combined with "
99138fd1498Szrj "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
99238fd1498Szrj if (opts->x_flag_sanitize & SANITIZE_POINTER_SUBTRACT)
99338fd1498Szrj error_at (loc,
99438fd1498Szrj "%<-fsanitize=pointer-subtract%> must be combined with "
99538fd1498Szrj "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
99638fd1498Szrj }
99738fd1498Szrj
99838fd1498Szrj /* Userspace and kernel ASan conflict with each other. */
99938fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
100038fd1498Szrj && (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS))
100138fd1498Szrj error_at (loc,
100238fd1498Szrj "%<-fsanitize=address%> is incompatible with "
100338fd1498Szrj "%<-fsanitize=kernel-address%>");
100438fd1498Szrj
100538fd1498Szrj /* And with TSan. */
100638fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_ADDRESS)
100738fd1498Szrj && (opts->x_flag_sanitize & SANITIZE_THREAD))
100838fd1498Szrj error_at (loc,
100938fd1498Szrj "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> "
101038fd1498Szrj "are incompatible with %<-fsanitize=thread%>");
101138fd1498Szrj
101238fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_LEAK)
101338fd1498Szrj && (opts->x_flag_sanitize & SANITIZE_THREAD))
101438fd1498Szrj error_at (loc,
101538fd1498Szrj "%<-fsanitize=leak%> is incompatible with %<-fsanitize=thread%>");
101638fd1498Szrj
101738fd1498Szrj /* Check error recovery for -fsanitize-recover option. */
101838fd1498Szrj for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
101938fd1498Szrj if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
102038fd1498Szrj && !sanitizer_opts[i].can_recover)
102138fd1498Szrj error_at (loc, "%<-fsanitize-recover=%s%> is not supported",
102238fd1498Szrj sanitizer_opts[i].name);
102338fd1498Szrj
102438fd1498Szrj /* When instrumenting the pointers, we don't want to remove
102538fd1498Szrj the null pointer checks. */
102638fd1498Szrj if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
102738fd1498Szrj | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
102838fd1498Szrj opts->x_flag_delete_null_pointer_checks = 0;
102938fd1498Szrj
103038fd1498Szrj /* Aggressive compiler optimizations may cause false negatives. */
103138fd1498Szrj if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE))
103238fd1498Szrj opts->x_flag_aggressive_loop_optimizations = 0;
103338fd1498Szrj
103438fd1498Szrj /* Enable -fsanitize-address-use-after-scope if address sanitizer is
103538fd1498Szrj enabled. */
103638fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS)
103738fd1498Szrj && !opts_set->x_flag_sanitize_address_use_after_scope)
103838fd1498Szrj opts->x_flag_sanitize_address_use_after_scope = true;
103938fd1498Szrj
104038fd1498Szrj /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope
104138fd1498Szrj is enabled. */
104238fd1498Szrj if (opts->x_flag_sanitize_address_use_after_scope)
104338fd1498Szrj {
104438fd1498Szrj if (opts->x_flag_stack_reuse != SR_NONE
104538fd1498Szrj && opts_set->x_flag_stack_reuse != SR_NONE)
104638fd1498Szrj error_at (loc,
104738fd1498Szrj "%<-fsanitize-address-use-after-scope%> requires "
104838fd1498Szrj "%<-fstack-reuse=none%> option");
104938fd1498Szrj
105038fd1498Szrj opts->x_flag_stack_reuse = SR_NONE;
105138fd1498Szrj }
105238fd1498Szrj
105338fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && opts->x_flag_tm)
105438fd1498Szrj sorry ("transactional memory is not supported with %<-fsanitize=address%>");
105538fd1498Szrj
105638fd1498Szrj if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm)
105738fd1498Szrj sorry ("transactional memory is not supported with "
105838fd1498Szrj "%<-fsanitize=kernel-address%>");
105938fd1498Szrj
106038fd1498Szrj /* Comes from final.c -- no real reason to change it. */
106138fd1498Szrj #define MAX_CODE_ALIGN 16
106238fd1498Szrj #define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
106338fd1498Szrj
106438fd1498Szrj if (opts->x_align_loops > MAX_CODE_ALIGN_VALUE)
106538fd1498Szrj error_at (loc, "-falign-loops=%d is not between 0 and %d",
106638fd1498Szrj opts->x_align_loops, MAX_CODE_ALIGN_VALUE);
106738fd1498Szrj
106838fd1498Szrj if (opts->x_align_jumps > MAX_CODE_ALIGN_VALUE)
106938fd1498Szrj error_at (loc, "-falign-jumps=%d is not between 0 and %d",
107038fd1498Szrj opts->x_align_jumps, MAX_CODE_ALIGN_VALUE);
107138fd1498Szrj
107238fd1498Szrj if (opts->x_align_functions > MAX_CODE_ALIGN_VALUE)
107338fd1498Szrj error_at (loc, "-falign-functions=%d is not between 0 and %d",
107438fd1498Szrj opts->x_align_functions, MAX_CODE_ALIGN_VALUE);
107538fd1498Szrj
107638fd1498Szrj if (opts->x_align_labels > MAX_CODE_ALIGN_VALUE)
107738fd1498Szrj error_at (loc, "-falign-labels=%d is not between 0 and %d",
107838fd1498Szrj opts->x_align_labels, MAX_CODE_ALIGN_VALUE);
107938fd1498Szrj }
108038fd1498Szrj
108138fd1498Szrj #define LEFT_COLUMN 27
108238fd1498Szrj
108338fd1498Szrj /* Output ITEM, of length ITEM_WIDTH, in the left column,
108438fd1498Szrj followed by word-wrapped HELP in a second column. */
108538fd1498Szrj static void
wrap_help(const char * help,const char * item,unsigned int item_width,unsigned int columns)108638fd1498Szrj wrap_help (const char *help,
108738fd1498Szrj const char *item,
108838fd1498Szrj unsigned int item_width,
108938fd1498Szrj unsigned int columns)
109038fd1498Szrj {
109138fd1498Szrj unsigned int col_width = LEFT_COLUMN;
109238fd1498Szrj unsigned int remaining, room, len;
109338fd1498Szrj
109438fd1498Szrj remaining = strlen (help);
109538fd1498Szrj
109638fd1498Szrj do
109738fd1498Szrj {
109838fd1498Szrj room = columns - 3 - MAX (col_width, item_width);
109938fd1498Szrj if (room > columns)
110038fd1498Szrj room = 0;
110138fd1498Szrj len = remaining;
110238fd1498Szrj
110338fd1498Szrj if (room < len)
110438fd1498Szrj {
110538fd1498Szrj unsigned int i;
110638fd1498Szrj
110738fd1498Szrj for (i = 0; help[i]; i++)
110838fd1498Szrj {
110938fd1498Szrj if (i >= room && len != remaining)
111038fd1498Szrj break;
111138fd1498Szrj if (help[i] == ' ')
111238fd1498Szrj len = i;
111338fd1498Szrj else if ((help[i] == '-' || help[i] == '/')
111438fd1498Szrj && help[i + 1] != ' '
111538fd1498Szrj && i > 0 && ISALPHA (help[i - 1]))
111638fd1498Szrj len = i + 1;
111738fd1498Szrj }
111838fd1498Szrj }
111938fd1498Szrj
112038fd1498Szrj printf (" %-*.*s %.*s\n", col_width, item_width, item, len, help);
112138fd1498Szrj item_width = 0;
112238fd1498Szrj while (help[len] == ' ')
112338fd1498Szrj len++;
112438fd1498Szrj help += len;
112538fd1498Szrj remaining -= len;
112638fd1498Szrj }
112738fd1498Szrj while (remaining);
112838fd1498Szrj }
112938fd1498Szrj
113038fd1498Szrj /* Print help for a specific front-end, etc. */
113138fd1498Szrj static void
print_filtered_help(unsigned int include_flags,unsigned int exclude_flags,unsigned int any_flags,unsigned int columns,struct gcc_options * opts,unsigned int lang_mask)113238fd1498Szrj print_filtered_help (unsigned int include_flags,
113338fd1498Szrj unsigned int exclude_flags,
113438fd1498Szrj unsigned int any_flags,
113538fd1498Szrj unsigned int columns,
113638fd1498Szrj struct gcc_options *opts,
113738fd1498Szrj unsigned int lang_mask)
113838fd1498Szrj {
113938fd1498Szrj unsigned int i;
114038fd1498Szrj const char *help;
114138fd1498Szrj bool found = false;
114238fd1498Szrj bool displayed = false;
114338fd1498Szrj char new_help[256];
114438fd1498Szrj
114538fd1498Szrj if (include_flags == CL_PARAMS)
114638fd1498Szrj {
114738fd1498Szrj for (i = 0; i < LAST_PARAM; i++)
114838fd1498Szrj {
114938fd1498Szrj const char *param = compiler_params[i].option;
115038fd1498Szrj
115138fd1498Szrj help = compiler_params[i].help;
115238fd1498Szrj if (help == NULL || *help == '\0')
115338fd1498Szrj {
115438fd1498Szrj if (exclude_flags & CL_UNDOCUMENTED)
115538fd1498Szrj continue;
115638fd1498Szrj help = undocumented_msg;
115738fd1498Szrj }
115838fd1498Szrj
115938fd1498Szrj /* Get the translation. */
116038fd1498Szrj help = _(help);
116138fd1498Szrj
116238fd1498Szrj if (!opts->x_quiet_flag)
116338fd1498Szrj {
116438fd1498Szrj snprintf (new_help, sizeof (new_help),
116538fd1498Szrj _("default %d minimum %d maximum %d"),
116638fd1498Szrj compiler_params[i].default_value,
116738fd1498Szrj compiler_params[i].min_value,
116838fd1498Szrj compiler_params[i].max_value);
116938fd1498Szrj help = new_help;
117038fd1498Szrj }
117138fd1498Szrj wrap_help (help, param, strlen (param), columns);
117238fd1498Szrj }
117338fd1498Szrj putchar ('\n');
117438fd1498Szrj return;
117538fd1498Szrj }
117638fd1498Szrj
117738fd1498Szrj if (!opts->x_help_printed)
117838fd1498Szrj opts->x_help_printed = XCNEWVAR (char, cl_options_count);
117938fd1498Szrj
118038fd1498Szrj if (!opts->x_help_enum_printed)
118138fd1498Szrj opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
118238fd1498Szrj
118338fd1498Szrj for (i = 0; i < cl_options_count; i++)
118438fd1498Szrj {
118538fd1498Szrj const struct cl_option *option = cl_options + i;
118638fd1498Szrj unsigned int len;
118738fd1498Szrj const char *opt;
118838fd1498Szrj const char *tab;
118938fd1498Szrj
119038fd1498Szrj if (include_flags == 0
119138fd1498Szrj || ((option->flags & include_flags) != include_flags))
119238fd1498Szrj {
119338fd1498Szrj if ((option->flags & any_flags) == 0)
119438fd1498Szrj continue;
119538fd1498Szrj }
119638fd1498Szrj
119738fd1498Szrj /* Skip unwanted switches. */
119838fd1498Szrj if ((option->flags & exclude_flags) != 0)
119938fd1498Szrj continue;
120038fd1498Szrj
120138fd1498Szrj /* The driver currently prints its own help text. */
120238fd1498Szrj if ((option->flags & CL_DRIVER) != 0
120338fd1498Szrj && (option->flags & (((1U << cl_lang_count) - 1)
120438fd1498Szrj | CL_COMMON | CL_TARGET)) == 0)
120538fd1498Szrj continue;
120638fd1498Szrj
120738fd1498Szrj found = true;
120838fd1498Szrj /* Skip switches that have already been printed. */
120938fd1498Szrj if (opts->x_help_printed[i])
121038fd1498Szrj continue;
121138fd1498Szrj
121238fd1498Szrj opts->x_help_printed[i] = true;
121338fd1498Szrj
121438fd1498Szrj help = option->help;
121538fd1498Szrj if (help == NULL)
121638fd1498Szrj {
121738fd1498Szrj if (exclude_flags & CL_UNDOCUMENTED)
121838fd1498Szrj continue;
121938fd1498Szrj
122038fd1498Szrj help = undocumented_msg;
122138fd1498Szrj }
122238fd1498Szrj
122338fd1498Szrj if (option->alias_target < N_OPTS
122438fd1498Szrj && cl_options [option->alias_target].help)
122538fd1498Szrj {
122638fd1498Szrj if (help == undocumented_msg)
122738fd1498Szrj {
122838fd1498Szrj /* For undocumented options that are aliases for other options
122938fd1498Szrj that are documented, point the reader to the other option in
123038fd1498Szrj preference of the former. */
123138fd1498Szrj snprintf (new_help, sizeof new_help,
123238fd1498Szrj _("Same as %s. Use the latter option instead."),
123338fd1498Szrj cl_options [option->alias_target].opt_text);
123438fd1498Szrj }
123538fd1498Szrj else
123638fd1498Szrj {
123738fd1498Szrj /* For documented options with aliases, mention the aliased
123838fd1498Szrj option's name for reference. */
123938fd1498Szrj snprintf (new_help, sizeof new_help,
124038fd1498Szrj _("%s Same as %s."),
124138fd1498Szrj help, cl_options [option->alias_target].opt_text);
124238fd1498Szrj }
124338fd1498Szrj
124438fd1498Szrj help = new_help;
124538fd1498Szrj }
124638fd1498Szrj
124738fd1498Szrj if (option->warn_message)
124838fd1498Szrj {
124938fd1498Szrj /* Mention that the use of the option will trigger a warning. */
125038fd1498Szrj if (help == new_help)
125138fd1498Szrj snprintf (new_help + strlen (new_help),
125238fd1498Szrj sizeof new_help - strlen (new_help),
125338fd1498Szrj " %s", _(use_diagnosed_msg));
125438fd1498Szrj else
125538fd1498Szrj snprintf (new_help, sizeof new_help,
125638fd1498Szrj "%s %s", help, _(use_diagnosed_msg));
125738fd1498Szrj
125838fd1498Szrj help = new_help;
125938fd1498Szrj }
126038fd1498Szrj
126138fd1498Szrj /* Get the translation. */
126238fd1498Szrj help = _(help);
126338fd1498Szrj
126438fd1498Szrj /* Find the gap between the name of the
126538fd1498Szrj option and its descriptive text. */
126638fd1498Szrj tab = strchr (help, '\t');
126738fd1498Szrj if (tab)
126838fd1498Szrj {
126938fd1498Szrj len = tab - help;
127038fd1498Szrj opt = help;
127138fd1498Szrj help = tab + 1;
127238fd1498Szrj }
127338fd1498Szrj else
127438fd1498Szrj {
127538fd1498Szrj opt = option->opt_text;
127638fd1498Szrj len = strlen (opt);
127738fd1498Szrj }
127838fd1498Szrj
127938fd1498Szrj /* With the -Q option enabled we change the descriptive text associated
128038fd1498Szrj with an option to be an indication of its current setting. */
128138fd1498Szrj if (!opts->x_quiet_flag)
128238fd1498Szrj {
128338fd1498Szrj void *flag_var = option_flag_var (i, opts);
128438fd1498Szrj
128538fd1498Szrj if (len < (LEFT_COLUMN + 2))
128638fd1498Szrj strcpy (new_help, "\t\t");
128738fd1498Szrj else
128838fd1498Szrj strcpy (new_help, "\t");
128938fd1498Szrj
129038fd1498Szrj if (flag_var != NULL
129138fd1498Szrj && option->var_type != CLVC_DEFER)
129238fd1498Szrj {
129338fd1498Szrj if (option->flags & CL_JOINED)
129438fd1498Szrj {
129538fd1498Szrj if (option->var_type == CLVC_STRING)
129638fd1498Szrj {
129738fd1498Szrj if (* (const char **) flag_var != NULL)
129838fd1498Szrj snprintf (new_help + strlen (new_help),
129938fd1498Szrj sizeof (new_help) - strlen (new_help),
130038fd1498Szrj "%s", * (const char **) flag_var);
130138fd1498Szrj }
130238fd1498Szrj else if (option->var_type == CLVC_ENUM)
130338fd1498Szrj {
130438fd1498Szrj const struct cl_enum *e = &cl_enums[option->var_enum];
130538fd1498Szrj int value;
130638fd1498Szrj const char *arg = NULL;
130738fd1498Szrj
130838fd1498Szrj value = e->get (flag_var);
130938fd1498Szrj enum_value_to_arg (e->values, &arg, value, lang_mask);
131038fd1498Szrj if (arg == NULL)
131138fd1498Szrj arg = _("[default]");
131238fd1498Szrj snprintf (new_help + strlen (new_help),
131338fd1498Szrj sizeof (new_help) - strlen (new_help),
131438fd1498Szrj "%s", arg);
131538fd1498Szrj }
131638fd1498Szrj else
131738fd1498Szrj sprintf (new_help + strlen (new_help),
131838fd1498Szrj "%d", * (int *) flag_var);
131938fd1498Szrj }
132038fd1498Szrj else
132138fd1498Szrj strcat (new_help, option_enabled (i, opts)
132238fd1498Szrj ? _("[enabled]") : _("[disabled]"));
132338fd1498Szrj }
132438fd1498Szrj
132538fd1498Szrj help = new_help;
132638fd1498Szrj }
132738fd1498Szrj
132838fd1498Szrj if (option->range_max != -1)
132938fd1498Szrj {
133038fd1498Szrj char b[128];
133138fd1498Szrj snprintf (b, sizeof (b), "<%d,%d>", option->range_min,
133238fd1498Szrj option->range_max);
133338fd1498Szrj opt = concat (opt, b, NULL);
133438fd1498Szrj len += strlen (b);
133538fd1498Szrj }
133638fd1498Szrj
133738fd1498Szrj wrap_help (help, opt, len, columns);
133838fd1498Szrj displayed = true;
133938fd1498Szrj
134038fd1498Szrj if (option->var_type == CLVC_ENUM
134138fd1498Szrj && opts->x_help_enum_printed[option->var_enum] != 2)
134238fd1498Szrj opts->x_help_enum_printed[option->var_enum] = 1;
134338fd1498Szrj }
134438fd1498Szrj
134538fd1498Szrj if (! found)
134638fd1498Szrj {
134738fd1498Szrj unsigned int langs = include_flags & CL_LANG_ALL;
134838fd1498Szrj
134938fd1498Szrj if (langs == 0)
135038fd1498Szrj printf (_(" No options with the desired characteristics were found\n"));
135138fd1498Szrj else
135238fd1498Szrj {
135338fd1498Szrj unsigned int i;
135438fd1498Szrj
135538fd1498Szrj /* PR 31349: Tell the user how to see all of the
135638fd1498Szrj options supported by a specific front end. */
135738fd1498Szrj for (i = 0; (1U << i) < CL_LANG_ALL; i ++)
135838fd1498Szrj if ((1U << i) & langs)
135938fd1498Szrj printf (_(" None found. Use --help=%s to show *all* the options supported by the %s front-end.\n"),
136038fd1498Szrj lang_names[i], lang_names[i]);
136138fd1498Szrj }
136238fd1498Szrj
136338fd1498Szrj }
136438fd1498Szrj else if (! displayed)
136538fd1498Szrj printf (_(" All options with the desired characteristics have already been displayed\n"));
136638fd1498Szrj
136738fd1498Szrj putchar ('\n');
136838fd1498Szrj
136938fd1498Szrj /* Print details of enumerated option arguments, if those
137038fd1498Szrj enumerations have help text headings provided. If no help text
137138fd1498Szrj is provided, presume that the possible values are listed in the
137238fd1498Szrj help text for the relevant options. */
137338fd1498Szrj for (i = 0; i < cl_enums_count; i++)
137438fd1498Szrj {
137538fd1498Szrj unsigned int j, pos;
137638fd1498Szrj
137738fd1498Szrj if (opts->x_help_enum_printed[i] != 1)
137838fd1498Szrj continue;
137938fd1498Szrj if (cl_enums[i].help == NULL)
138038fd1498Szrj continue;
138138fd1498Szrj printf (" %s\n ", _(cl_enums[i].help));
138238fd1498Szrj pos = 4;
138338fd1498Szrj for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
138438fd1498Szrj {
138538fd1498Szrj unsigned int len = strlen (cl_enums[i].values[j].arg);
138638fd1498Szrj
138738fd1498Szrj if (pos > 4 && pos + 1 + len <= columns)
138838fd1498Szrj {
138938fd1498Szrj printf (" %s", cl_enums[i].values[j].arg);
139038fd1498Szrj pos += 1 + len;
139138fd1498Szrj }
139238fd1498Szrj else
139338fd1498Szrj {
139438fd1498Szrj if (pos > 4)
139538fd1498Szrj {
139638fd1498Szrj printf ("\n ");
139738fd1498Szrj pos = 4;
139838fd1498Szrj }
139938fd1498Szrj printf ("%s", cl_enums[i].values[j].arg);
140038fd1498Szrj pos += len;
140138fd1498Szrj }
140238fd1498Szrj }
140338fd1498Szrj printf ("\n\n");
140438fd1498Szrj opts->x_help_enum_printed[i] = 2;
140538fd1498Szrj }
140638fd1498Szrj }
140738fd1498Szrj
140838fd1498Szrj /* Display help for a specified type of option.
140938fd1498Szrj The options must have ALL of the INCLUDE_FLAGS set
141038fd1498Szrj ANY of the flags in the ANY_FLAGS set
141138fd1498Szrj and NONE of the EXCLUDE_FLAGS set. The current option state is in
141238fd1498Szrj OPTS; LANG_MASK is used for interpreting enumerated option state. */
141338fd1498Szrj static void
print_specific_help(unsigned int include_flags,unsigned int exclude_flags,unsigned int any_flags,struct gcc_options * opts,unsigned int lang_mask)141438fd1498Szrj print_specific_help (unsigned int include_flags,
141538fd1498Szrj unsigned int exclude_flags,
141638fd1498Szrj unsigned int any_flags,
141738fd1498Szrj struct gcc_options *opts,
141838fd1498Szrj unsigned int lang_mask)
141938fd1498Szrj {
142038fd1498Szrj unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
142138fd1498Szrj const char * description = NULL;
142238fd1498Szrj const char * descrip_extra = "";
142338fd1498Szrj size_t i;
142438fd1498Szrj unsigned int flag;
142538fd1498Szrj
142638fd1498Szrj /* Sanity check: Make sure that we do not have more
142738fd1498Szrj languages than we have bits available to enumerate them. */
142838fd1498Szrj gcc_assert ((1U << cl_lang_count) <= CL_MIN_OPTION_CLASS);
142938fd1498Szrj
143038fd1498Szrj /* If we have not done so already, obtain
143138fd1498Szrj the desired maximum width of the output. */
143238fd1498Szrj if (opts->x_help_columns == 0)
143338fd1498Szrj {
143438fd1498Szrj opts->x_help_columns = get_terminal_width ();
143538fd1498Szrj if (opts->x_help_columns == INT_MAX)
143638fd1498Szrj /* Use a reasonable default. */
143738fd1498Szrj opts->x_help_columns = 80;
143838fd1498Szrj }
143938fd1498Szrj
144038fd1498Szrj /* Decide upon the title for the options that we are going to display. */
144138fd1498Szrj for (i = 0, flag = 1; flag <= CL_MAX_OPTION_CLASS; flag <<= 1, i ++)
144238fd1498Szrj {
144338fd1498Szrj switch (flag & include_flags)
144438fd1498Szrj {
144538fd1498Szrj case 0:
144638fd1498Szrj case CL_DRIVER:
144738fd1498Szrj break;
144838fd1498Szrj
144938fd1498Szrj case CL_TARGET:
145038fd1498Szrj description = _("The following options are target specific");
145138fd1498Szrj break;
145238fd1498Szrj case CL_WARNING:
145338fd1498Szrj description = _("The following options control compiler warning messages");
145438fd1498Szrj break;
145538fd1498Szrj case CL_OPTIMIZATION:
145638fd1498Szrj description = _("The following options control optimizations");
145738fd1498Szrj break;
145838fd1498Szrj case CL_COMMON:
145938fd1498Szrj description = _("The following options are language-independent");
146038fd1498Szrj break;
146138fd1498Szrj case CL_PARAMS:
146238fd1498Szrj description = _("The --param option recognizes the following as parameters");
146338fd1498Szrj break;
146438fd1498Szrj default:
146538fd1498Szrj if (i >= cl_lang_count)
146638fd1498Szrj break;
146738fd1498Szrj if (exclude_flags & all_langs_mask)
146838fd1498Szrj description = _("The following options are specific to just the language ");
146938fd1498Szrj else
147038fd1498Szrj description = _("The following options are supported by the language ");
147138fd1498Szrj descrip_extra = lang_names [i];
147238fd1498Szrj break;
147338fd1498Szrj }
147438fd1498Szrj }
147538fd1498Szrj
147638fd1498Szrj if (description == NULL)
147738fd1498Szrj {
147838fd1498Szrj if (any_flags == 0)
147938fd1498Szrj {
148038fd1498Szrj if (include_flags & CL_UNDOCUMENTED)
148138fd1498Szrj description = _("The following options are not documented");
148238fd1498Szrj else if (include_flags & CL_SEPARATE)
148338fd1498Szrj description = _("The following options take separate arguments");
148438fd1498Szrj else if (include_flags & CL_JOINED)
148538fd1498Szrj description = _("The following options take joined arguments");
148638fd1498Szrj else
148738fd1498Szrj {
148838fd1498Szrj internal_error ("unrecognized include_flags 0x%x passed to print_specific_help",
148938fd1498Szrj include_flags);
149038fd1498Szrj return;
149138fd1498Szrj }
149238fd1498Szrj }
149338fd1498Szrj else
149438fd1498Szrj {
149538fd1498Szrj if (any_flags & all_langs_mask)
149638fd1498Szrj description = _("The following options are language-related");
149738fd1498Szrj else
149838fd1498Szrj description = _("The following options are language-independent");
149938fd1498Szrj }
150038fd1498Szrj }
150138fd1498Szrj
150238fd1498Szrj printf ("%s%s:\n", description, descrip_extra);
150338fd1498Szrj print_filtered_help (include_flags, exclude_flags, any_flags,
150438fd1498Szrj opts->x_help_columns, opts, lang_mask);
150538fd1498Szrj }
150638fd1498Szrj
150738fd1498Szrj /* Enable FDO-related flags. */
150838fd1498Szrj
150938fd1498Szrj static void
enable_fdo_optimizations(struct gcc_options * opts,struct gcc_options * opts_set,int value)151038fd1498Szrj enable_fdo_optimizations (struct gcc_options *opts,
151138fd1498Szrj struct gcc_options *opts_set,
151238fd1498Szrj int value)
151338fd1498Szrj {
151438fd1498Szrj if (!opts_set->x_flag_branch_probabilities)
151538fd1498Szrj opts->x_flag_branch_probabilities = value;
151638fd1498Szrj if (!opts_set->x_flag_profile_values)
151738fd1498Szrj opts->x_flag_profile_values = value;
151838fd1498Szrj if (!opts_set->x_flag_unroll_loops)
151938fd1498Szrj opts->x_flag_unroll_loops = value;
152038fd1498Szrj if (!opts_set->x_flag_peel_loops)
152138fd1498Szrj opts->x_flag_peel_loops = value;
152238fd1498Szrj if (!opts_set->x_flag_tracer)
152338fd1498Szrj opts->x_flag_tracer = value;
152438fd1498Szrj if (!opts_set->x_flag_value_profile_transformations)
152538fd1498Szrj opts->x_flag_value_profile_transformations = value;
152638fd1498Szrj if (!opts_set->x_flag_inline_functions)
152738fd1498Szrj opts->x_flag_inline_functions = value;
152838fd1498Szrj if (!opts_set->x_flag_ipa_cp)
152938fd1498Szrj opts->x_flag_ipa_cp = value;
153038fd1498Szrj if (!opts_set->x_flag_ipa_cp_clone
153138fd1498Szrj && value && opts->x_flag_ipa_cp)
153238fd1498Szrj opts->x_flag_ipa_cp_clone = value;
153338fd1498Szrj if (!opts_set->x_flag_ipa_bit_cp
153438fd1498Szrj && value && opts->x_flag_ipa_cp)
153538fd1498Szrj opts->x_flag_ipa_bit_cp = value;
153638fd1498Szrj if (!opts_set->x_flag_predictive_commoning)
153738fd1498Szrj opts->x_flag_predictive_commoning = value;
153838fd1498Szrj if (!opts_set->x_flag_split_loops)
153938fd1498Szrj opts->x_flag_split_loops = value;
154038fd1498Szrj if (!opts_set->x_flag_unswitch_loops)
154138fd1498Szrj opts->x_flag_unswitch_loops = value;
154238fd1498Szrj if (!opts_set->x_flag_gcse_after_reload)
154338fd1498Szrj opts->x_flag_gcse_after_reload = value;
154438fd1498Szrj if (!opts_set->x_flag_tree_loop_vectorize)
154538fd1498Szrj opts->x_flag_tree_loop_vectorize = value;
154638fd1498Szrj if (!opts_set->x_flag_tree_slp_vectorize)
154738fd1498Szrj opts->x_flag_tree_slp_vectorize = value;
154838fd1498Szrj if (!opts_set->x_flag_vect_cost_model)
154938fd1498Szrj opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
155038fd1498Szrj if (!opts_set->x_flag_tree_loop_distribute_patterns)
155138fd1498Szrj opts->x_flag_tree_loop_distribute_patterns = value;
155238fd1498Szrj }
155338fd1498Szrj
155438fd1498Szrj /* -f{,no-}sanitize{,-recover}= suboptions. */
155538fd1498Szrj const struct sanitizer_opts_s sanitizer_opts[] =
155638fd1498Szrj {
155738fd1498Szrj #define SANITIZER_OPT(name, flags, recover) \
155838fd1498Szrj { #name, flags, sizeof #name - 1, recover }
155938fd1498Szrj SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
156038fd1498Szrj SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
156138fd1498Szrj true),
156238fd1498Szrj SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true),
156338fd1498Szrj SANITIZER_OPT (pointer-subtract, SANITIZE_POINTER_SUBTRACT, true),
156438fd1498Szrj SANITIZER_OPT (thread, SANITIZE_THREAD, false),
156538fd1498Szrj SANITIZER_OPT (leak, SANITIZE_LEAK, false),
156638fd1498Szrj SANITIZER_OPT (shift, SANITIZE_SHIFT, true),
156738fd1498Szrj SANITIZER_OPT (shift-base, SANITIZE_SHIFT_BASE, true),
156838fd1498Szrj SANITIZER_OPT (shift-exponent, SANITIZE_SHIFT_EXPONENT, true),
156938fd1498Szrj SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true),
157038fd1498Szrj SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true),
157138fd1498Szrj SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false),
157238fd1498Szrj SANITIZER_OPT (vla-bound, SANITIZE_VLA, true),
157338fd1498Szrj SANITIZER_OPT (return, SANITIZE_RETURN, false),
157438fd1498Szrj SANITIZER_OPT (null, SANITIZE_NULL, true),
157538fd1498Szrj SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true),
157638fd1498Szrj SANITIZER_OPT (bool, SANITIZE_BOOL, true),
157738fd1498Szrj SANITIZER_OPT (enum, SANITIZE_ENUM, true),
157838fd1498Szrj SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true),
157938fd1498Szrj SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true),
158038fd1498Szrj SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true),
158138fd1498Szrj SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true),
158238fd1498Szrj SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true),
158338fd1498Szrj SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true),
158438fd1498Szrj SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
158538fd1498Szrj true),
158638fd1498Szrj SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true),
158738fd1498Szrj SANITIZER_OPT (vptr, SANITIZE_VPTR, true),
158838fd1498Szrj SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true),
158938fd1498Szrj SANITIZER_OPT (builtin, SANITIZE_BUILTIN, true),
159038fd1498Szrj SANITIZER_OPT (all, ~0U, true),
159138fd1498Szrj #undef SANITIZER_OPT
159238fd1498Szrj { NULL, 0U, 0UL, false }
159338fd1498Szrj };
159438fd1498Szrj
159538fd1498Szrj /* -f{,no-}sanitize-coverage= suboptions. */
159638fd1498Szrj const struct sanitizer_opts_s coverage_sanitizer_opts[] =
159738fd1498Szrj {
159838fd1498Szrj #define COVERAGE_SANITIZER_OPT(name, flags) \
159938fd1498Szrj { #name, flags, sizeof #name - 1, true }
160038fd1498Szrj COVERAGE_SANITIZER_OPT (trace-pc, SANITIZE_COV_TRACE_PC),
160138fd1498Szrj COVERAGE_SANITIZER_OPT (trace-cmp, SANITIZE_COV_TRACE_CMP),
160238fd1498Szrj #undef COVERAGE_SANITIZER_OPT
160338fd1498Szrj { NULL, 0U, 0UL, false }
160438fd1498Szrj };
160538fd1498Szrj
160638fd1498Szrj /* A struct for describing a run of chars within a string. */
160738fd1498Szrj
160838fd1498Szrj struct string_fragment
160938fd1498Szrj {
string_fragmentstring_fragment161038fd1498Szrj string_fragment (const char *start, size_t len)
161138fd1498Szrj : m_start (start), m_len (len) {}
161238fd1498Szrj
161338fd1498Szrj const char *m_start;
161438fd1498Szrj size_t m_len;
161538fd1498Szrj };
161638fd1498Szrj
161738fd1498Szrj /* Specialization of edit_distance_traits for string_fragment,
161838fd1498Szrj for use by get_closest_sanitizer_option. */
161938fd1498Szrj
162038fd1498Szrj template <>
162138fd1498Szrj struct edit_distance_traits<const string_fragment &>
162238fd1498Szrj {
162338fd1498Szrj static size_t get_length (const string_fragment &fragment)
162438fd1498Szrj {
162538fd1498Szrj return fragment.m_len;
162638fd1498Szrj }
162738fd1498Szrj
162838fd1498Szrj static const char *get_string (const string_fragment &fragment)
162938fd1498Szrj {
163038fd1498Szrj return fragment.m_start;
163138fd1498Szrj }
163238fd1498Szrj };
163338fd1498Szrj
163438fd1498Szrj /* Given ARG, an unrecognized sanitizer option, return the best
163538fd1498Szrj matching sanitizer option, or NULL if there isn't one.
163638fd1498Szrj OPTS is array of candidate sanitizer options.
163738fd1498Szrj CODE is OPT_fsanitize_, OPT_fsanitize_recover_ or
163838fd1498Szrj OPT_fsanitize_coverage_.
163938fd1498Szrj VALUE is non-zero for the regular form of the option, zero
164038fd1498Szrj for the "no-" form (e.g. "-fno-sanitize-recover="). */
164138fd1498Szrj
164238fd1498Szrj static const char *
164338fd1498Szrj get_closest_sanitizer_option (const string_fragment &arg,
164438fd1498Szrj const struct sanitizer_opts_s *opts,
164538fd1498Szrj enum opt_code code, int value)
164638fd1498Szrj {
164738fd1498Szrj best_match <const string_fragment &, const char*> bm (arg);
164838fd1498Szrj for (int i = 0; opts[i].name != NULL; ++i)
164938fd1498Szrj {
165038fd1498Szrj /* -fsanitize=all is not valid, so don't offer it. */
165138fd1498Szrj if (code == OPT_fsanitize_
165238fd1498Szrj && opts[i].flag == ~0U
165338fd1498Szrj && value)
165438fd1498Szrj continue;
165538fd1498Szrj
165638fd1498Szrj /* For -fsanitize-recover= (and not -fno-sanitize-recover=),
165738fd1498Szrj don't offer the non-recoverable options. */
165838fd1498Szrj if (code == OPT_fsanitize_recover_
165938fd1498Szrj && !opts[i].can_recover
166038fd1498Szrj && value)
166138fd1498Szrj continue;
166238fd1498Szrj
166338fd1498Szrj bm.consider (opts[i].name);
166438fd1498Szrj }
166538fd1498Szrj return bm.get_best_meaningful_candidate ();
166638fd1498Szrj }
166738fd1498Szrj
166838fd1498Szrj /* Parse comma separated sanitizer suboptions from P for option SCODE,
166938fd1498Szrj adjust previous FLAGS and return new ones. If COMPLAIN is false,
167038fd1498Szrj don't issue diagnostics. */
167138fd1498Szrj
167238fd1498Szrj unsigned int
167338fd1498Szrj parse_sanitizer_options (const char *p, location_t loc, int scode,
167438fd1498Szrj unsigned int flags, int value, bool complain)
167538fd1498Szrj {
167638fd1498Szrj enum opt_code code = (enum opt_code) scode;
167738fd1498Szrj
167838fd1498Szrj const struct sanitizer_opts_s *opts;
167938fd1498Szrj if (code == OPT_fsanitize_coverage_)
168038fd1498Szrj opts = coverage_sanitizer_opts;
168138fd1498Szrj else
168238fd1498Szrj opts = sanitizer_opts;
168338fd1498Szrj
168438fd1498Szrj while (*p != 0)
168538fd1498Szrj {
168638fd1498Szrj size_t len, i;
168738fd1498Szrj bool found = false;
168838fd1498Szrj const char *comma = strchr (p, ',');
168938fd1498Szrj
169038fd1498Szrj if (comma == NULL)
169138fd1498Szrj len = strlen (p);
169238fd1498Szrj else
169338fd1498Szrj len = comma - p;
169438fd1498Szrj if (len == 0)
169538fd1498Szrj {
169638fd1498Szrj p = comma + 1;
169738fd1498Szrj continue;
169838fd1498Szrj }
169938fd1498Szrj
170038fd1498Szrj /* Check to see if the string matches an option class name. */
170138fd1498Szrj for (i = 0; opts[i].name != NULL; ++i)
170238fd1498Szrj if (len == opts[i].len && memcmp (p, opts[i].name, len) == 0)
170338fd1498Szrj {
170438fd1498Szrj /* Handle both -fsanitize and -fno-sanitize cases. */
170538fd1498Szrj if (value && opts[i].flag == ~0U)
170638fd1498Szrj {
170738fd1498Szrj if (code == OPT_fsanitize_)
170838fd1498Szrj {
170938fd1498Szrj if (complain)
171038fd1498Szrj error_at (loc, "%<-fsanitize=all%> option is not valid");
171138fd1498Szrj }
171238fd1498Szrj else
171338fd1498Szrj flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK
171438fd1498Szrj | SANITIZE_UNREACHABLE | SANITIZE_RETURN);
171538fd1498Szrj }
171638fd1498Szrj else if (value)
171738fd1498Szrj {
171838fd1498Szrj /* Do not enable -fsanitize-recover=unreachable and
171938fd1498Szrj -fsanitize-recover=return if -fsanitize-recover=undefined
172038fd1498Szrj is selected. */
172138fd1498Szrj if (code == OPT_fsanitize_recover_
172238fd1498Szrj && opts[i].flag == SANITIZE_UNDEFINED)
172338fd1498Szrj flags |= (SANITIZE_UNDEFINED
172438fd1498Szrj & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN));
172538fd1498Szrj else
172638fd1498Szrj flags |= opts[i].flag;
172738fd1498Szrj }
172838fd1498Szrj else
172938fd1498Szrj flags &= ~opts[i].flag;
173038fd1498Szrj found = true;
173138fd1498Szrj break;
173238fd1498Szrj }
173338fd1498Szrj
173438fd1498Szrj if (! found && complain)
173538fd1498Szrj {
173638fd1498Szrj const char *hint
173738fd1498Szrj = get_closest_sanitizer_option (string_fragment (p, len),
173838fd1498Szrj opts, code, value);
173938fd1498Szrj
174038fd1498Szrj const char *suffix;
174138fd1498Szrj if (code == OPT_fsanitize_recover_)
174238fd1498Szrj suffix = "-recover";
174338fd1498Szrj else if (code == OPT_fsanitize_coverage_)
174438fd1498Szrj suffix = "-coverage";
174538fd1498Szrj else
174638fd1498Szrj suffix = "";
174738fd1498Szrj
174838fd1498Szrj if (hint)
174938fd1498Szrj error_at (loc,
175038fd1498Szrj "unrecognized argument to -f%ssanitize%s= option: %q.*s;"
175138fd1498Szrj " did you mean %qs?",
175238fd1498Szrj value ? "" : "no-",
175338fd1498Szrj suffix, (int) len, p, hint);
175438fd1498Szrj else
175538fd1498Szrj error_at (loc,
175638fd1498Szrj "unrecognized argument to -f%ssanitize%s= option: %q.*s",
175738fd1498Szrj value ? "" : "no-",
175838fd1498Szrj suffix, (int) len, p);
175938fd1498Szrj }
176038fd1498Szrj
176138fd1498Szrj if (comma == NULL)
176238fd1498Szrj break;
176338fd1498Szrj p = comma + 1;
176438fd1498Szrj }
176538fd1498Szrj return flags;
176638fd1498Szrj }
176738fd1498Szrj
176838fd1498Szrj /* Parse string values of no_sanitize attribute passed in VALUE.
176938fd1498Szrj Values are separated with comma. */
177038fd1498Szrj
177138fd1498Szrj unsigned int
177238fd1498Szrj parse_no_sanitize_attribute (char *value)
177338fd1498Szrj {
177438fd1498Szrj unsigned int flags = 0;
177538fd1498Szrj unsigned int i;
177638fd1498Szrj char *q = strtok (value, ",");
177738fd1498Szrj
177838fd1498Szrj while (q != NULL)
177938fd1498Szrj {
178038fd1498Szrj for (i = 0; sanitizer_opts[i].name != NULL; ++i)
178138fd1498Szrj if (strcmp (sanitizer_opts[i].name, q) == 0)
178238fd1498Szrj {
178338fd1498Szrj flags |= sanitizer_opts[i].flag;
178438fd1498Szrj if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
178538fd1498Szrj flags |= SANITIZE_UNDEFINED_NONDEFAULT;
178638fd1498Szrj break;
178738fd1498Szrj }
178838fd1498Szrj
178938fd1498Szrj if (sanitizer_opts[i].name == NULL)
179038fd1498Szrj warning (OPT_Wattributes,
179138fd1498Szrj "%<%s%> attribute directive ignored", q);
179238fd1498Szrj
179338fd1498Szrj q = strtok (NULL, ",");
179438fd1498Szrj }
179538fd1498Szrj
179638fd1498Szrj return flags;
179738fd1498Szrj }
179838fd1498Szrj
179938fd1498Szrj /* Handle target- and language-independent options. Return zero to
180038fd1498Szrj generate an "unknown option" message. Only options that need
180138fd1498Szrj extra handling need to be listed here; if you simply want
180238fd1498Szrj DECODED->value assigned to a variable, it happens automatically. */
180338fd1498Szrj
180438fd1498Szrj bool
180538fd1498Szrj common_handle_option (struct gcc_options *opts,
180638fd1498Szrj struct gcc_options *opts_set,
180738fd1498Szrj const struct cl_decoded_option *decoded,
180838fd1498Szrj unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
180938fd1498Szrj location_t loc,
181038fd1498Szrj const struct cl_option_handlers *handlers,
181138fd1498Szrj diagnostic_context *dc,
181238fd1498Szrj void (*target_option_override_hook) (void))
181338fd1498Szrj {
181438fd1498Szrj size_t scode = decoded->opt_index;
181538fd1498Szrj const char *arg = decoded->arg;
181638fd1498Szrj int value = decoded->value;
181738fd1498Szrj enum opt_code code = (enum opt_code) scode;
181838fd1498Szrj
181938fd1498Szrj gcc_assert (decoded->canonical_option_num_elements <= 2);
182038fd1498Szrj
182138fd1498Szrj switch (code)
182238fd1498Szrj {
182338fd1498Szrj case OPT__param:
182438fd1498Szrj handle_param (opts, opts_set, loc, arg);
182538fd1498Szrj break;
182638fd1498Szrj
182738fd1498Szrj case OPT__help:
182838fd1498Szrj {
182938fd1498Szrj unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
183038fd1498Szrj unsigned int undoc_mask;
183138fd1498Szrj unsigned int i;
183238fd1498Szrj
183338fd1498Szrj if (lang_mask == CL_DRIVER)
183438fd1498Szrj break;
183538fd1498Szrj
183638fd1498Szrj undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings)
183738fd1498Szrj ? 0
183838fd1498Szrj : CL_UNDOCUMENTED);
183938fd1498Szrj target_option_override_hook ();
184038fd1498Szrj /* First display any single language specific options. */
184138fd1498Szrj for (i = 0; i < cl_lang_count; i++)
184238fd1498Szrj print_specific_help
184338fd1498Szrj (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts,
184438fd1498Szrj lang_mask);
184538fd1498Szrj /* Next display any multi language specific options. */
184638fd1498Szrj print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask);
184738fd1498Szrj /* Then display any remaining, non-language options. */
184838fd1498Szrj for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
184938fd1498Szrj if (i != CL_DRIVER)
185038fd1498Szrj print_specific_help (i, undoc_mask, 0, opts, lang_mask);
185138fd1498Szrj opts->x_exit_after_options = true;
185238fd1498Szrj break;
185338fd1498Szrj }
185438fd1498Szrj
185538fd1498Szrj case OPT__target_help:
185638fd1498Szrj if (lang_mask == CL_DRIVER)
185738fd1498Szrj break;
185838fd1498Szrj
185938fd1498Szrj target_option_override_hook ();
186038fd1498Szrj print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts, lang_mask);
186138fd1498Szrj opts->x_exit_after_options = true;
186238fd1498Szrj break;
186338fd1498Szrj
186438fd1498Szrj case OPT__help_:
186538fd1498Szrj {
186638fd1498Szrj const char *a = arg;
186738fd1498Szrj unsigned int include_flags = 0;
186838fd1498Szrj /* Note - by default we include undocumented options when listing
186938fd1498Szrj specific classes. If you only want to see documented options
187038fd1498Szrj then add ",^undocumented" to the --help= option. E.g.:
187138fd1498Szrj
187238fd1498Szrj --help=target,^undocumented */
187338fd1498Szrj unsigned int exclude_flags = 0;
187438fd1498Szrj
187538fd1498Szrj if (lang_mask == CL_DRIVER)
187638fd1498Szrj break;
187738fd1498Szrj
187838fd1498Szrj /* Walk along the argument string, parsing each word in turn.
187938fd1498Szrj The format is:
188038fd1498Szrj arg = [^]{word}[,{arg}]
188138fd1498Szrj word = {optimizers|target|warnings|undocumented|
188238fd1498Szrj params|common|<language>} */
188338fd1498Szrj while (*a != 0)
188438fd1498Szrj {
188538fd1498Szrj static const struct
188638fd1498Szrj {
188738fd1498Szrj const char *string;
188838fd1498Szrj unsigned int flag;
188938fd1498Szrj }
189038fd1498Szrj specifics[] =
189138fd1498Szrj {
189238fd1498Szrj { "optimizers", CL_OPTIMIZATION },
189338fd1498Szrj { "target", CL_TARGET },
189438fd1498Szrj { "warnings", CL_WARNING },
189538fd1498Szrj { "undocumented", CL_UNDOCUMENTED },
189638fd1498Szrj { "params", CL_PARAMS },
189738fd1498Szrj { "joined", CL_JOINED },
189838fd1498Szrj { "separate", CL_SEPARATE },
189938fd1498Szrj { "common", CL_COMMON },
190038fd1498Szrj { NULL, 0 }
190138fd1498Szrj };
190238fd1498Szrj unsigned int *pflags;
190338fd1498Szrj const char *comma;
190438fd1498Szrj unsigned int lang_flag, specific_flag;
190538fd1498Szrj unsigned int len;
190638fd1498Szrj unsigned int i;
190738fd1498Szrj
190838fd1498Szrj if (*a == '^')
190938fd1498Szrj {
191038fd1498Szrj ++a;
191138fd1498Szrj if (*a == '\0')
191238fd1498Szrj {
191338fd1498Szrj error_at (loc, "missing argument to %qs", "--help=^");
191438fd1498Szrj break;
191538fd1498Szrj }
191638fd1498Szrj pflags = &exclude_flags;
191738fd1498Szrj }
191838fd1498Szrj else
191938fd1498Szrj pflags = &include_flags;
192038fd1498Szrj
192138fd1498Szrj comma = strchr (a, ',');
192238fd1498Szrj if (comma == NULL)
192338fd1498Szrj len = strlen (a);
192438fd1498Szrj else
192538fd1498Szrj len = comma - a;
192638fd1498Szrj if (len == 0)
192738fd1498Szrj {
192838fd1498Szrj a = comma + 1;
192938fd1498Szrj continue;
193038fd1498Szrj }
193138fd1498Szrj
193238fd1498Szrj /* Check to see if the string matches an option class name. */
193338fd1498Szrj for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++)
193438fd1498Szrj if (strncasecmp (a, specifics[i].string, len) == 0)
193538fd1498Szrj {
193638fd1498Szrj specific_flag = specifics[i].flag;
193738fd1498Szrj break;
193838fd1498Szrj }
193938fd1498Szrj
194038fd1498Szrj /* Check to see if the string matches a language name.
194138fd1498Szrj Note - we rely upon the alpha-sorted nature of the entries in
194238fd1498Szrj the lang_names array, specifically that shorter names appear
194338fd1498Szrj before their longer variants. (i.e. C before C++). That way
194438fd1498Szrj when we are attempting to match --help=c for example we will
194538fd1498Szrj match with C first and not C++. */
194638fd1498Szrj for (i = 0, lang_flag = 0; i < cl_lang_count; i++)
194738fd1498Szrj if (strncasecmp (a, lang_names[i], len) == 0)
194838fd1498Szrj {
194938fd1498Szrj lang_flag = 1U << i;
195038fd1498Szrj break;
195138fd1498Szrj }
195238fd1498Szrj
195338fd1498Szrj if (specific_flag != 0)
195438fd1498Szrj {
195538fd1498Szrj if (lang_flag == 0)
195638fd1498Szrj *pflags |= specific_flag;
195738fd1498Szrj else
195838fd1498Szrj {
195938fd1498Szrj /* The option's argument matches both the start of a
196038fd1498Szrj language name and the start of an option class name.
196138fd1498Szrj We have a special case for when the user has
196238fd1498Szrj specified "--help=c", but otherwise we have to issue
196338fd1498Szrj a warning. */
196438fd1498Szrj if (strncasecmp (a, "c", len) == 0)
196538fd1498Szrj *pflags |= lang_flag;
196638fd1498Szrj else
196738fd1498Szrj warning_at (loc, 0,
196838fd1498Szrj "--help argument %q.*s is ambiguous, "
196938fd1498Szrj "please be more specific",
197038fd1498Szrj len, a);
197138fd1498Szrj }
197238fd1498Szrj }
197338fd1498Szrj else if (lang_flag != 0)
197438fd1498Szrj *pflags |= lang_flag;
197538fd1498Szrj else
197638fd1498Szrj warning_at (loc, 0,
197738fd1498Szrj "unrecognized argument to --help= option: %q.*s",
197838fd1498Szrj len, a);
197938fd1498Szrj
198038fd1498Szrj if (comma == NULL)
198138fd1498Szrj break;
198238fd1498Szrj a = comma + 1;
198338fd1498Szrj }
198438fd1498Szrj
198538fd1498Szrj if (include_flags)
198638fd1498Szrj {
198738fd1498Szrj target_option_override_hook ();
198838fd1498Szrj print_specific_help (include_flags, exclude_flags, 0, opts,
198938fd1498Szrj lang_mask);
199038fd1498Szrj }
199138fd1498Szrj opts->x_exit_after_options = true;
199238fd1498Szrj break;
199338fd1498Szrj }
199438fd1498Szrj
199538fd1498Szrj case OPT__version:
199638fd1498Szrj if (lang_mask == CL_DRIVER)
199738fd1498Szrj break;
199838fd1498Szrj
199938fd1498Szrj opts->x_exit_after_options = true;
200038fd1498Szrj break;
200138fd1498Szrj
200238fd1498Szrj case OPT_fsanitize_:
200338fd1498Szrj opts->x_flag_sanitize
200438fd1498Szrj = parse_sanitizer_options (arg, loc, code,
200538fd1498Szrj opts->x_flag_sanitize, value, true);
200638fd1498Szrj
200738fd1498Szrj /* Kernel ASan implies normal ASan but does not yet support
200838fd1498Szrj all features. */
200938fd1498Szrj if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
201038fd1498Szrj {
201138fd1498Szrj maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
201238fd1498Szrj 0, opts->x_param_values,
201338fd1498Szrj opts_set->x_param_values);
201438fd1498Szrj maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, opts->x_param_values,
201538fd1498Szrj opts_set->x_param_values);
201638fd1498Szrj maybe_set_param_value (PARAM_ASAN_STACK, 0, opts->x_param_values,
201738fd1498Szrj opts_set->x_param_values);
201838fd1498Szrj maybe_set_param_value (PARAM_ASAN_PROTECT_ALLOCAS, 0,
201938fd1498Szrj opts->x_param_values,
202038fd1498Szrj opts_set->x_param_values);
202138fd1498Szrj maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
202238fd1498Szrj opts->x_param_values,
202338fd1498Szrj opts_set->x_param_values);
202438fd1498Szrj }
202538fd1498Szrj break;
202638fd1498Szrj
202738fd1498Szrj case OPT_fsanitize_recover_:
202838fd1498Szrj opts->x_flag_sanitize_recover
202938fd1498Szrj = parse_sanitizer_options (arg, loc, code,
203038fd1498Szrj opts->x_flag_sanitize_recover, value, true);
203138fd1498Szrj break;
203238fd1498Szrj
203338fd1498Szrj case OPT_fasan_shadow_offset_:
203438fd1498Szrj /* Deferred. */
203538fd1498Szrj break;
203638fd1498Szrj
203738fd1498Szrj case OPT_fsanitize_address_use_after_scope:
203838fd1498Szrj opts->x_flag_sanitize_address_use_after_scope = value;
203938fd1498Szrj break;
204038fd1498Szrj
204138fd1498Szrj case OPT_fsanitize_recover:
204238fd1498Szrj if (value)
204338fd1498Szrj opts->x_flag_sanitize_recover
204438fd1498Szrj |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)
204538fd1498Szrj & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN);
204638fd1498Szrj else
204738fd1498Szrj opts->x_flag_sanitize_recover
204838fd1498Szrj &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
204938fd1498Szrj break;
205038fd1498Szrj
205138fd1498Szrj case OPT_fsanitize_coverage_:
205238fd1498Szrj opts->x_flag_sanitize_coverage
205338fd1498Szrj = parse_sanitizer_options (arg, loc, code,
205438fd1498Szrj opts->x_flag_sanitize_coverage, value, true);
205538fd1498Szrj break;
205638fd1498Szrj
205738fd1498Szrj case OPT_O:
205838fd1498Szrj case OPT_Os:
205938fd1498Szrj case OPT_Ofast:
206038fd1498Szrj case OPT_Og:
206138fd1498Szrj /* Currently handled in a prescan. */
206238fd1498Szrj break;
206338fd1498Szrj
206438fd1498Szrj case OPT_Werror:
206538fd1498Szrj dc->warning_as_error_requested = value;
206638fd1498Szrj break;
206738fd1498Szrj
206838fd1498Szrj case OPT_Werror_:
206938fd1498Szrj if (lang_mask == CL_DRIVER)
207038fd1498Szrj break;
207138fd1498Szrj
207238fd1498Szrj enable_warning_as_error (arg, value, lang_mask, handlers,
207338fd1498Szrj opts, opts_set, loc, dc);
207438fd1498Szrj break;
207538fd1498Szrj
207638fd1498Szrj case OPT_Wlarger_than_:
207738fd1498Szrj opts->x_larger_than_size = value;
207838fd1498Szrj opts->x_warn_larger_than = value != -1;
207938fd1498Szrj break;
208038fd1498Szrj
208138fd1498Szrj case OPT_Wfatal_errors:
208238fd1498Szrj dc->fatal_errors = value;
208338fd1498Szrj break;
208438fd1498Szrj
208538fd1498Szrj case OPT_Wframe_larger_than_:
208638fd1498Szrj opts->x_frame_larger_than_size = value;
208738fd1498Szrj opts->x_warn_frame_larger_than = value != -1;
208838fd1498Szrj break;
208938fd1498Szrj
209038fd1498Szrj case OPT_Wstack_usage_:
209138fd1498Szrj opts->x_warn_stack_usage = value;
209238fd1498Szrj opts->x_flag_stack_usage_info = value != -1;
209338fd1498Szrj break;
209438fd1498Szrj
209538fd1498Szrj case OPT_Wstrict_aliasing:
209638fd1498Szrj set_Wstrict_aliasing (opts, value);
209738fd1498Szrj break;
209838fd1498Szrj
209938fd1498Szrj case OPT_Wstrict_overflow:
210038fd1498Szrj opts->x_warn_strict_overflow = (value
210138fd1498Szrj ? (int) WARN_STRICT_OVERFLOW_CONDITIONAL
210238fd1498Szrj : 0);
210338fd1498Szrj break;
210438fd1498Szrj
210538fd1498Szrj case OPT_Wsystem_headers:
210638fd1498Szrj dc->dc_warn_system_headers = value;
210738fd1498Szrj break;
210838fd1498Szrj
210938fd1498Szrj case OPT_aux_info:
211038fd1498Szrj opts->x_flag_gen_aux_info = 1;
211138fd1498Szrj break;
211238fd1498Szrj
211338fd1498Szrj case OPT_auxbase_strip:
211438fd1498Szrj {
211538fd1498Szrj char *tmp = xstrdup (arg);
211638fd1498Szrj strip_off_ending (tmp, strlen (tmp));
211738fd1498Szrj if (tmp[0])
211838fd1498Szrj opts->x_aux_base_name = tmp;
211938fd1498Szrj else
212038fd1498Szrj free (tmp);
212138fd1498Szrj }
212238fd1498Szrj break;
212338fd1498Szrj
212438fd1498Szrj case OPT_d:
212538fd1498Szrj decode_d_option (arg, opts, loc, dc);
212638fd1498Szrj break;
212738fd1498Szrj
212838fd1498Szrj case OPT_fcall_used_:
212938fd1498Szrj case OPT_fcall_saved_:
213038fd1498Szrj /* Deferred. */
213138fd1498Szrj break;
213238fd1498Szrj
213338fd1498Szrj case OPT_fdbg_cnt_:
213438fd1498Szrj /* Deferred. */
213538fd1498Szrj break;
213638fd1498Szrj
213738fd1498Szrj case OPT_fdbg_cnt_list:
213838fd1498Szrj /* Deferred. */
213938fd1498Szrj opts->x_exit_after_options = true;
214038fd1498Szrj break;
214138fd1498Szrj
214238fd1498Szrj case OPT_fdebug_prefix_map_:
214338fd1498Szrj case OPT_ffile_prefix_map_:
214438fd1498Szrj /* Deferred. */
214538fd1498Szrj break;
214638fd1498Szrj
214738fd1498Szrj case OPT_fdiagnostics_show_location_:
214838fd1498Szrj diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
214938fd1498Szrj break;
215038fd1498Szrj
215138fd1498Szrj case OPT_fdiagnostics_show_caret:
215238fd1498Szrj dc->show_caret = value;
215338fd1498Szrj break;
215438fd1498Szrj
215538fd1498Szrj case OPT_fdiagnostics_color_:
215638fd1498Szrj diagnostic_color_init (dc, value);
215738fd1498Szrj break;
215838fd1498Szrj
215938fd1498Szrj case OPT_fdiagnostics_parseable_fixits:
216038fd1498Szrj dc->parseable_fixits_p = value;
216138fd1498Szrj break;
216238fd1498Szrj
216338fd1498Szrj case OPT_fdiagnostics_show_option:
216438fd1498Szrj dc->show_option_requested = value;
216538fd1498Szrj break;
216638fd1498Szrj
216738fd1498Szrj case OPT_fdump_:
216838fd1498Szrj /* Deferred. */
216938fd1498Szrj break;
217038fd1498Szrj
217138fd1498Szrj case OPT_ffast_math:
217238fd1498Szrj set_fast_math_flags (opts, value);
217338fd1498Szrj break;
217438fd1498Szrj
217538fd1498Szrj case OPT_funsafe_math_optimizations:
217638fd1498Szrj set_unsafe_math_optimizations_flags (opts, value);
217738fd1498Szrj break;
217838fd1498Szrj
217938fd1498Szrj case OPT_ffixed_:
218038fd1498Szrj /* Deferred. */
218138fd1498Szrj break;
218238fd1498Szrj
218338fd1498Szrj case OPT_finline_limit_:
218438fd1498Szrj set_param_value ("max-inline-insns-single", value / 2,
218538fd1498Szrj opts->x_param_values, opts_set->x_param_values);
218638fd1498Szrj set_param_value ("max-inline-insns-auto", value / 2,
218738fd1498Szrj opts->x_param_values, opts_set->x_param_values);
218838fd1498Szrj break;
218938fd1498Szrj
219038fd1498Szrj case OPT_finstrument_functions_exclude_function_list_:
219138fd1498Szrj add_comma_separated_to_vector
219238fd1498Szrj (&opts->x_flag_instrument_functions_exclude_functions, arg);
219338fd1498Szrj break;
219438fd1498Szrj
219538fd1498Szrj case OPT_finstrument_functions_exclude_file_list_:
219638fd1498Szrj add_comma_separated_to_vector
219738fd1498Szrj (&opts->x_flag_instrument_functions_exclude_files, arg);
219838fd1498Szrj break;
219938fd1498Szrj
220038fd1498Szrj case OPT_fmessage_length_:
220138fd1498Szrj pp_set_line_maximum_length (dc->printer, value);
220238fd1498Szrj diagnostic_set_caret_max_width (dc, value);
220338fd1498Szrj break;
220438fd1498Szrj
220538fd1498Szrj case OPT_fopt_info:
220638fd1498Szrj case OPT_fopt_info_:
220738fd1498Szrj /* Deferred. */
220838fd1498Szrj break;
220938fd1498Szrj
221038fd1498Szrj case OPT_foffload_:
221138fd1498Szrj {
221238fd1498Szrj const char *p = arg;
221338fd1498Szrj opts->x_flag_disable_hsa = true;
221438fd1498Szrj while (*p != 0)
221538fd1498Szrj {
221638fd1498Szrj const char *comma = strchr (p, ',');
221738fd1498Szrj
221838fd1498Szrj if ((strncmp (p, "disable", 7) == 0)
221938fd1498Szrj && (p[7] == ',' || p[7] == '\0'))
222038fd1498Szrj {
222138fd1498Szrj opts->x_flag_disable_hsa = true;
222238fd1498Szrj break;
222338fd1498Szrj }
222438fd1498Szrj
222538fd1498Szrj if ((strncmp (p, "hsa", 3) == 0)
222638fd1498Szrj && (p[3] == ',' || p[3] == '\0'))
222738fd1498Szrj {
222838fd1498Szrj #ifdef ENABLE_HSA
222938fd1498Szrj opts->x_flag_disable_hsa = false;
223038fd1498Szrj #else
223138fd1498Szrj sorry ("HSA has not been enabled during configuration");
223238fd1498Szrj #endif
223338fd1498Szrj }
223438fd1498Szrj if (!comma)
223538fd1498Szrj break;
223638fd1498Szrj p = comma + 1;
223738fd1498Szrj }
223838fd1498Szrj break;
223938fd1498Szrj }
224038fd1498Szrj
224138fd1498Szrj #ifndef ACCEL_COMPILER
224238fd1498Szrj case OPT_foffload_abi_:
224338fd1498Szrj error_at (loc, "%<-foffload-abi%> option can be specified only for "
224438fd1498Szrj "offload compiler");
224538fd1498Szrj break;
224638fd1498Szrj #endif
224738fd1498Szrj
224838fd1498Szrj case OPT_fpack_struct_:
224938fd1498Szrj if (value <= 0 || (value & (value - 1)) || value > 16)
225038fd1498Szrj error_at (loc,
225138fd1498Szrj "structure alignment must be a small power of two, not %d",
225238fd1498Szrj value);
225338fd1498Szrj else
225438fd1498Szrj opts->x_initial_max_fld_align = value;
225538fd1498Szrj break;
225638fd1498Szrj
225738fd1498Szrj case OPT_fplugin_:
225838fd1498Szrj case OPT_fplugin_arg_:
225938fd1498Szrj /* Deferred. */
226038fd1498Szrj break;
226138fd1498Szrj
226238fd1498Szrj case OPT_fprofile_use_:
226338fd1498Szrj opts->x_profile_data_prefix = xstrdup (arg);
226438fd1498Szrj opts->x_flag_profile_use = true;
226538fd1498Szrj value = true;
226638fd1498Szrj /* No break here - do -fprofile-use processing. */
226738fd1498Szrj /* FALLTHRU */
226838fd1498Szrj case OPT_fprofile_use:
226938fd1498Szrj enable_fdo_optimizations (opts, opts_set, value);
227038fd1498Szrj if (!opts_set->x_flag_profile_reorder_functions)
227138fd1498Szrj opts->x_flag_profile_reorder_functions = value;
227238fd1498Szrj /* Indirect call profiling should do all useful transformations
227338fd1498Szrj speculative devirtualization does. */
227438fd1498Szrj if (!opts_set->x_flag_devirtualize_speculatively
227538fd1498Szrj && opts->x_flag_value_profile_transformations)
227638fd1498Szrj opts->x_flag_devirtualize_speculatively = false;
227738fd1498Szrj break;
227838fd1498Szrj
227938fd1498Szrj case OPT_fauto_profile_:
228038fd1498Szrj opts->x_auto_profile_file = xstrdup (arg);
228138fd1498Szrj opts->x_flag_auto_profile = true;
228238fd1498Szrj value = true;
228338fd1498Szrj /* No break here - do -fauto-profile processing. */
228438fd1498Szrj /* FALLTHRU */
228538fd1498Szrj case OPT_fauto_profile:
228638fd1498Szrj enable_fdo_optimizations (opts, opts_set, value);
228738fd1498Szrj if (!opts_set->x_flag_profile_correction)
228838fd1498Szrj opts->x_flag_profile_correction = value;
228938fd1498Szrj maybe_set_param_value (
229038fd1498Szrj PARAM_EARLY_INLINER_MAX_ITERATIONS, 10,
229138fd1498Szrj opts->x_param_values, opts_set->x_param_values);
229238fd1498Szrj break;
229338fd1498Szrj
229438fd1498Szrj case OPT_fprofile_generate_:
229538fd1498Szrj opts->x_profile_data_prefix = xstrdup (arg);
229638fd1498Szrj value = true;
229738fd1498Szrj /* No break here - do -fprofile-generate processing. */
229838fd1498Szrj /* FALLTHRU */
229938fd1498Szrj case OPT_fprofile_generate:
230038fd1498Szrj if (!opts_set->x_profile_arc_flag)
230138fd1498Szrj opts->x_profile_arc_flag = value;
230238fd1498Szrj if (!opts_set->x_flag_profile_values)
230338fd1498Szrj opts->x_flag_profile_values = value;
230438fd1498Szrj if (!opts_set->x_flag_inline_functions)
230538fd1498Szrj opts->x_flag_inline_functions = value;
230638fd1498Szrj if (!opts_set->x_flag_ipa_bit_cp)
230738fd1498Szrj opts->x_flag_ipa_bit_cp = value;
230838fd1498Szrj /* FIXME: Instrumentation we insert makes ipa-reference bitmaps
230938fd1498Szrj quadratic. Disable the pass until better memory representation
231038fd1498Szrj is done. */
231138fd1498Szrj if (!opts_set->x_flag_ipa_reference)
231238fd1498Szrj opts->x_flag_ipa_reference = false;
231338fd1498Szrj break;
231438fd1498Szrj
231538fd1498Szrj case OPT_fpatchable_function_entry_:
231638fd1498Szrj {
231738fd1498Szrj char *patch_area_arg = xstrdup (arg);
231838fd1498Szrj char *comma = strchr (patch_area_arg, ',');
231938fd1498Szrj if (comma)
232038fd1498Szrj {
232138fd1498Szrj *comma = '\0';
232238fd1498Szrj function_entry_patch_area_size =
232338fd1498Szrj integral_argument (patch_area_arg);
232438fd1498Szrj function_entry_patch_area_start =
232538fd1498Szrj integral_argument (comma + 1);
232638fd1498Szrj }
232738fd1498Szrj else
232838fd1498Szrj {
232938fd1498Szrj function_entry_patch_area_size =
233038fd1498Szrj integral_argument (patch_area_arg);
233138fd1498Szrj function_entry_patch_area_start = 0;
233238fd1498Szrj }
233338fd1498Szrj if (function_entry_patch_area_size < 0
233438fd1498Szrj || function_entry_patch_area_start < 0
233538fd1498Szrj || function_entry_patch_area_size
233638fd1498Szrj < function_entry_patch_area_start)
233738fd1498Szrj error ("invalid arguments for %<-fpatchable_function_entry%>");
233838fd1498Szrj free (patch_area_arg);
233938fd1498Szrj }
234038fd1498Szrj break;
234138fd1498Szrj
234238fd1498Szrj case OPT_ftree_vectorize:
234338fd1498Szrj /* Automatically sets -ftree-loop-vectorize and
234438fd1498Szrj -ftree-slp-vectorize. Nothing more to do here. */
234538fd1498Szrj break;
234638fd1498Szrj case OPT_fshow_column:
234738fd1498Szrj dc->show_column = value;
234838fd1498Szrj break;
234938fd1498Szrj
235038fd1498Szrj case OPT_frandom_seed:
235138fd1498Szrj /* The real switch is -fno-random-seed. */
235238fd1498Szrj if (value)
235338fd1498Szrj return false;
235438fd1498Szrj /* Deferred. */
235538fd1498Szrj break;
235638fd1498Szrj
235738fd1498Szrj case OPT_frandom_seed_:
235838fd1498Szrj /* Deferred. */
235938fd1498Szrj break;
236038fd1498Szrj
236138fd1498Szrj case OPT_fsched_verbose_:
236238fd1498Szrj #ifdef INSN_SCHEDULING
236338fd1498Szrj /* Handled with Var in common.opt. */
236438fd1498Szrj break;
236538fd1498Szrj #else
236638fd1498Szrj return false;
236738fd1498Szrj #endif
236838fd1498Szrj
236938fd1498Szrj case OPT_fsched_stalled_insns_:
237038fd1498Szrj opts->x_flag_sched_stalled_insns = value;
237138fd1498Szrj if (opts->x_flag_sched_stalled_insns == 0)
237238fd1498Szrj opts->x_flag_sched_stalled_insns = -1;
237338fd1498Szrj break;
237438fd1498Szrj
237538fd1498Szrj case OPT_fsched_stalled_insns_dep_:
237638fd1498Szrj opts->x_flag_sched_stalled_insns_dep = value;
237738fd1498Szrj break;
237838fd1498Szrj
237938fd1498Szrj case OPT_fstack_check_:
238038fd1498Szrj if (!strcmp (arg, "no"))
238138fd1498Szrj opts->x_flag_stack_check = NO_STACK_CHECK;
238238fd1498Szrj else if (!strcmp (arg, "generic"))
238338fd1498Szrj /* This is the old stack checking method. */
238438fd1498Szrj opts->x_flag_stack_check = STACK_CHECK_BUILTIN
238538fd1498Szrj ? FULL_BUILTIN_STACK_CHECK
238638fd1498Szrj : GENERIC_STACK_CHECK;
238738fd1498Szrj else if (!strcmp (arg, "specific"))
238838fd1498Szrj /* This is the new stack checking method. */
238938fd1498Szrj opts->x_flag_stack_check = STACK_CHECK_BUILTIN
239038fd1498Szrj ? FULL_BUILTIN_STACK_CHECK
239138fd1498Szrj : STACK_CHECK_STATIC_BUILTIN
239238fd1498Szrj ? STATIC_BUILTIN_STACK_CHECK
239338fd1498Szrj : GENERIC_STACK_CHECK;
239438fd1498Szrj else
239538fd1498Szrj warning_at (loc, 0, "unknown stack check parameter %qs", arg);
239638fd1498Szrj break;
239738fd1498Szrj
239838fd1498Szrj case OPT_fstack_limit:
239938fd1498Szrj /* The real switch is -fno-stack-limit. */
240038fd1498Szrj if (value)
240138fd1498Szrj return false;
240238fd1498Szrj /* Deferred. */
240338fd1498Szrj break;
240438fd1498Szrj
240538fd1498Szrj case OPT_fstack_limit_register_:
240638fd1498Szrj case OPT_fstack_limit_symbol_:
240738fd1498Szrj /* Deferred. */
240838fd1498Szrj break;
240938fd1498Szrj
241038fd1498Szrj case OPT_fstack_usage:
241138fd1498Szrj opts->x_flag_stack_usage = value;
241238fd1498Szrj opts->x_flag_stack_usage_info = value != 0;
241338fd1498Szrj break;
241438fd1498Szrj
241538fd1498Szrj case OPT_g:
241638fd1498Szrj set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
241738fd1498Szrj loc);
241838fd1498Szrj break;
241938fd1498Szrj
242038fd1498Szrj case OPT_gdwarf:
242138fd1498Szrj if (arg && strlen (arg) != 0)
242238fd1498Szrj {
242338fd1498Szrj error_at (loc, "%<-gdwarf%s%> is ambiguous; "
242438fd1498Szrj "use %<-gdwarf-%s%> for DWARF version "
242538fd1498Szrj "or %<-gdwarf -g%s%> for debug level", arg, arg, arg);
242638fd1498Szrj break;
242738fd1498Szrj }
242838fd1498Szrj else
242938fd1498Szrj value = opts->x_dwarf_version;
243038fd1498Szrj
243138fd1498Szrj /* FALLTHRU */
243238fd1498Szrj case OPT_gdwarf_:
243338fd1498Szrj if (value < 2 || value > 5)
243438fd1498Szrj error_at (loc, "dwarf version %d is not supported", value);
243538fd1498Szrj else
243638fd1498Szrj opts->x_dwarf_version = value;
243738fd1498Szrj set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc);
243838fd1498Szrj break;
243938fd1498Szrj
244038fd1498Szrj case OPT_gsplit_dwarf:
244138fd1498Szrj set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "", opts, opts_set,
244238fd1498Szrj loc);
244338fd1498Szrj break;
244438fd1498Szrj
244538fd1498Szrj case OPT_ggdb:
244638fd1498Szrj set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc);
244738fd1498Szrj break;
244838fd1498Szrj
244938fd1498Szrj case OPT_gstabs:
245038fd1498Szrj case OPT_gstabs_:
245138fd1498Szrj set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
245238fd1498Szrj loc);
245338fd1498Szrj break;
245438fd1498Szrj
245538fd1498Szrj case OPT_gvms:
245638fd1498Szrj set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc);
245738fd1498Szrj break;
245838fd1498Szrj
245938fd1498Szrj case OPT_gxcoff:
246038fd1498Szrj case OPT_gxcoff_:
246138fd1498Szrj set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set,
246238fd1498Szrj loc);
246338fd1498Szrj break;
246438fd1498Szrj
246538fd1498Szrj case OPT_gz:
246638fd1498Szrj case OPT_gz_:
246738fd1498Szrj /* Handled completely via specs. */
246838fd1498Szrj break;
246938fd1498Szrj
247038fd1498Szrj case OPT_pedantic_errors:
247138fd1498Szrj dc->pedantic_errors = 1;
247238fd1498Szrj control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
247338fd1498Szrj loc, lang_mask,
247438fd1498Szrj handlers, opts, opts_set,
247538fd1498Szrj dc);
247638fd1498Szrj break;
247738fd1498Szrj
247838fd1498Szrj case OPT_flto:
247938fd1498Szrj opts->x_flag_lto = value ? "" : NULL;
248038fd1498Szrj break;
248138fd1498Szrj
248238fd1498Szrj case OPT_w:
248338fd1498Szrj dc->dc_inhibit_warnings = true;
248438fd1498Szrj break;
248538fd1498Szrj
248638fd1498Szrj case OPT_fmax_errors_:
248738fd1498Szrj dc->max_errors = value;
248838fd1498Szrj break;
248938fd1498Szrj
249038fd1498Szrj case OPT_fuse_ld_bfd:
249138fd1498Szrj case OPT_fuse_ld_gold:
249238fd1498Szrj case OPT_fuse_linker_plugin:
249338fd1498Szrj /* No-op. Used by the driver and passed to us because it starts with f.*/
249438fd1498Szrj break;
249538fd1498Szrj
249638fd1498Szrj case OPT_fwrapv:
249738fd1498Szrj if (value)
249838fd1498Szrj opts->x_flag_trapv = 0;
249938fd1498Szrj break;
250038fd1498Szrj
250138fd1498Szrj case OPT_ftrapv:
250238fd1498Szrj if (value)
250338fd1498Szrj opts->x_flag_wrapv = 0;
250438fd1498Szrj break;
250538fd1498Szrj
250638fd1498Szrj case OPT_fstrict_overflow:
250738fd1498Szrj opts->x_flag_wrapv = !value;
250838fd1498Szrj opts->x_flag_wrapv_pointer = !value;
250938fd1498Szrj if (!value)
251038fd1498Szrj opts->x_flag_trapv = 0;
251138fd1498Szrj break;
251238fd1498Szrj
251338fd1498Szrj case OPT_fipa_icf:
251438fd1498Szrj opts->x_flag_ipa_icf_functions = value;
251538fd1498Szrj opts->x_flag_ipa_icf_variables = value;
251638fd1498Szrj break;
251738fd1498Szrj
251838fd1498Szrj default:
251938fd1498Szrj /* If the flag was handled in a standard way, assume the lack of
252038fd1498Szrj processing here is intentional. */
252138fd1498Szrj gcc_assert (option_flag_var (scode, opts));
252238fd1498Szrj break;
252338fd1498Szrj }
252438fd1498Szrj
252538fd1498Szrj common_handle_option_auto (opts, opts_set, decoded, lang_mask, kind,
252638fd1498Szrj loc, handlers, dc);
252738fd1498Szrj return true;
252838fd1498Szrj }
252938fd1498Szrj
253038fd1498Szrj /* Handle --param NAME=VALUE. */
253138fd1498Szrj static void
253238fd1498Szrj handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
253338fd1498Szrj location_t loc, const char *carg)
253438fd1498Szrj {
253538fd1498Szrj char *equal, *arg;
253638fd1498Szrj int value;
253738fd1498Szrj
253838fd1498Szrj arg = xstrdup (carg);
253938fd1498Szrj equal = strchr (arg, '=');
254038fd1498Szrj if (!equal)
254138fd1498Szrj error_at (loc, "%s: --param arguments should be of the form NAME=VALUE",
254238fd1498Szrj arg);
254338fd1498Szrj else
254438fd1498Szrj {
254538fd1498Szrj *equal = '\0';
254638fd1498Szrj
254738fd1498Szrj enum compiler_param index;
254838fd1498Szrj if (!find_param (arg, &index))
254938fd1498Szrj {
255038fd1498Szrj const char *suggestion = find_param_fuzzy (arg);
255138fd1498Szrj if (suggestion)
255238fd1498Szrj error_at (loc, "invalid --param name %qs; did you mean %qs?",
255338fd1498Szrj arg, suggestion);
255438fd1498Szrj else
255538fd1498Szrj error_at (loc, "invalid --param name %qs", arg);
255638fd1498Szrj }
255738fd1498Szrj else
255838fd1498Szrj {
255938fd1498Szrj if (!param_string_value_p (index, equal + 1, &value))
256038fd1498Szrj value = integral_argument (equal + 1);
256138fd1498Szrj
256238fd1498Szrj if (value == -1)
256338fd1498Szrj error_at (loc, "invalid --param value %qs", equal + 1);
256438fd1498Szrj else
256538fd1498Szrj set_param_value (arg, value,
256638fd1498Szrj opts->x_param_values, opts_set->x_param_values);
256738fd1498Szrj }
256838fd1498Szrj }
256938fd1498Szrj
257038fd1498Szrj free (arg);
257138fd1498Szrj }
257238fd1498Szrj
257338fd1498Szrj /* Used to set the level of strict aliasing warnings in OPTS,
257438fd1498Szrj when no level is specified (i.e., when -Wstrict-aliasing, and not
257538fd1498Szrj -Wstrict-aliasing=level was given).
257638fd1498Szrj ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified,
257738fd1498Szrj and 0 otherwise. After calling this function, wstrict_aliasing will be
257838fd1498Szrj set to the default value of -Wstrict_aliasing=level, currently 3. */
257938fd1498Szrj static void
258038fd1498Szrj set_Wstrict_aliasing (struct gcc_options *opts, int onoff)
258138fd1498Szrj {
258238fd1498Szrj gcc_assert (onoff == 0 || onoff == 1);
258338fd1498Szrj if (onoff != 0)
258438fd1498Szrj opts->x_warn_strict_aliasing = 3;
258538fd1498Szrj else
258638fd1498Szrj opts->x_warn_strict_aliasing = 0;
258738fd1498Szrj }
258838fd1498Szrj
258938fd1498Szrj /* The following routines are useful in setting all the flags that
259038fd1498Szrj -ffast-math and -fno-fast-math imply. */
259138fd1498Szrj static void
259238fd1498Szrj set_fast_math_flags (struct gcc_options *opts, int set)
259338fd1498Szrj {
259438fd1498Szrj if (!opts->frontend_set_flag_unsafe_math_optimizations)
259538fd1498Szrj {
259638fd1498Szrj opts->x_flag_unsafe_math_optimizations = set;
259738fd1498Szrj set_unsafe_math_optimizations_flags (opts, set);
259838fd1498Szrj }
259938fd1498Szrj if (!opts->frontend_set_flag_finite_math_only)
260038fd1498Szrj opts->x_flag_finite_math_only = set;
260138fd1498Szrj if (!opts->frontend_set_flag_errno_math)
260238fd1498Szrj opts->x_flag_errno_math = !set;
260338fd1498Szrj if (set)
260438fd1498Szrj {
260538fd1498Szrj if (opts->frontend_set_flag_excess_precision_cmdline
260638fd1498Szrj == EXCESS_PRECISION_DEFAULT)
260738fd1498Szrj opts->x_flag_excess_precision_cmdline
260838fd1498Szrj = set ? EXCESS_PRECISION_FAST : EXCESS_PRECISION_DEFAULT;
260938fd1498Szrj if (!opts->frontend_set_flag_signaling_nans)
261038fd1498Szrj opts->x_flag_signaling_nans = 0;
261138fd1498Szrj if (!opts->frontend_set_flag_rounding_math)
261238fd1498Szrj opts->x_flag_rounding_math = 0;
261338fd1498Szrj if (!opts->frontend_set_flag_cx_limited_range)
261438fd1498Szrj opts->x_flag_cx_limited_range = 1;
261538fd1498Szrj }
261638fd1498Szrj }
261738fd1498Szrj
261838fd1498Szrj /* When -funsafe-math-optimizations is set the following
261938fd1498Szrj flags are set as well. */
262038fd1498Szrj static void
262138fd1498Szrj set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set)
262238fd1498Szrj {
262338fd1498Szrj if (!opts->frontend_set_flag_trapping_math)
262438fd1498Szrj opts->x_flag_trapping_math = !set;
262538fd1498Szrj if (!opts->frontend_set_flag_signed_zeros)
262638fd1498Szrj opts->x_flag_signed_zeros = !set;
262738fd1498Szrj if (!opts->frontend_set_flag_associative_math)
262838fd1498Szrj opts->x_flag_associative_math = set;
262938fd1498Szrj if (!opts->frontend_set_flag_reciprocal_math)
263038fd1498Szrj opts->x_flag_reciprocal_math = set;
263138fd1498Szrj }
263238fd1498Szrj
263338fd1498Szrj /* Return true iff flags in OPTS are set as if -ffast-math. */
263438fd1498Szrj bool
263538fd1498Szrj fast_math_flags_set_p (const struct gcc_options *opts)
263638fd1498Szrj {
263738fd1498Szrj return (!opts->x_flag_trapping_math
263838fd1498Szrj && opts->x_flag_unsafe_math_optimizations
263938fd1498Szrj && opts->x_flag_finite_math_only
264038fd1498Szrj && !opts->x_flag_signed_zeros
264138fd1498Szrj && !opts->x_flag_errno_math
264238fd1498Szrj && opts->x_flag_excess_precision_cmdline
264338fd1498Szrj == EXCESS_PRECISION_FAST);
264438fd1498Szrj }
264538fd1498Szrj
264638fd1498Szrj /* Return true iff flags are set as if -ffast-math but using the flags stored
264738fd1498Szrj in the struct cl_optimization structure. */
264838fd1498Szrj bool
264938fd1498Szrj fast_math_flags_struct_set_p (struct cl_optimization *opt)
265038fd1498Szrj {
265138fd1498Szrj return (!opt->x_flag_trapping_math
265238fd1498Szrj && opt->x_flag_unsafe_math_optimizations
265338fd1498Szrj && opt->x_flag_finite_math_only
265438fd1498Szrj && !opt->x_flag_signed_zeros
265538fd1498Szrj && !opt->x_flag_errno_math);
265638fd1498Szrj }
265738fd1498Szrj
265838fd1498Szrj /* Handle a debug output -g switch for options OPTS
265938fd1498Szrj (OPTS_SET->x_write_symbols storing whether a debug type was passed
266038fd1498Szrj explicitly), location LOC. EXTENDED is true or false to support
266138fd1498Szrj extended output (2 is special and means "-ggdb" was given). */
266238fd1498Szrj static void
266338fd1498Szrj set_debug_level (enum debug_info_type type, int extended, const char *arg,
266438fd1498Szrj struct gcc_options *opts, struct gcc_options *opts_set,
266538fd1498Szrj location_t loc)
266638fd1498Szrj {
266738fd1498Szrj opts->x_use_gnu_debug_info_extensions = extended;
266838fd1498Szrj
266938fd1498Szrj if (type == NO_DEBUG)
267038fd1498Szrj {
267138fd1498Szrj if (opts->x_write_symbols == NO_DEBUG)
267238fd1498Szrj {
267338fd1498Szrj opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE;
267438fd1498Szrj
267538fd1498Szrj if (extended == 2)
267638fd1498Szrj {
267738fd1498Szrj #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
267838fd1498Szrj opts->x_write_symbols = DWARF2_DEBUG;
267938fd1498Szrj #elif defined DBX_DEBUGGING_INFO
268038fd1498Szrj opts->x_write_symbols = DBX_DEBUG;
268138fd1498Szrj #endif
268238fd1498Szrj }
268338fd1498Szrj
268438fd1498Szrj if (opts->x_write_symbols == NO_DEBUG)
268538fd1498Szrj warning_at (loc, 0, "target system does not support debug output");
268638fd1498Szrj }
268738fd1498Szrj }
268838fd1498Szrj else
268938fd1498Szrj {
269038fd1498Szrj /* Does it conflict with an already selected type? */
269138fd1498Szrj if (opts_set->x_write_symbols != NO_DEBUG
269238fd1498Szrj && opts->x_write_symbols != NO_DEBUG
269338fd1498Szrj && type != opts->x_write_symbols)
269438fd1498Szrj error_at (loc, "debug format %qs conflicts with prior selection",
269538fd1498Szrj debug_type_names[type]);
269638fd1498Szrj opts->x_write_symbols = type;
269738fd1498Szrj opts_set->x_write_symbols = type;
269838fd1498Szrj }
269938fd1498Szrj
270038fd1498Szrj /* A debug flag without a level defaults to level 2.
270138fd1498Szrj If off or at level 1, set it to level 2, but if already
270238fd1498Szrj at level 3, don't lower it. */
270338fd1498Szrj if (*arg == '\0')
270438fd1498Szrj {
270538fd1498Szrj if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
270638fd1498Szrj opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
270738fd1498Szrj }
270838fd1498Szrj else
270938fd1498Szrj {
271038fd1498Szrj int argval = integral_argument (arg);
271138fd1498Szrj if (argval == -1)
271238fd1498Szrj error_at (loc, "unrecognized debug output level %qs", arg);
271338fd1498Szrj else if (argval > 3)
271438fd1498Szrj error_at (loc, "debug output level %qs is too high", arg);
271538fd1498Szrj else
271638fd1498Szrj opts->x_debug_info_level = (enum debug_info_levels) argval;
271738fd1498Szrj }
271838fd1498Szrj }
271938fd1498Szrj
272038fd1498Szrj /* Arrange to dump core on error for diagnostic context DC. (The
272138fd1498Szrj regular error message is still printed first, except in the case of
272238fd1498Szrj abort ().) */
272338fd1498Szrj
272438fd1498Szrj static void
272538fd1498Szrj setup_core_dumping (diagnostic_context *dc)
272638fd1498Szrj {
272738fd1498Szrj #ifdef SIGABRT
272838fd1498Szrj signal (SIGABRT, SIG_DFL);
272938fd1498Szrj #endif
273038fd1498Szrj #if defined(HAVE_SETRLIMIT)
273138fd1498Szrj {
273238fd1498Szrj struct rlimit rlim;
273338fd1498Szrj if (getrlimit (RLIMIT_CORE, &rlim) != 0)
273438fd1498Szrj fatal_error (input_location, "getting core file size maximum limit: %m");
273538fd1498Szrj rlim.rlim_cur = rlim.rlim_max;
273638fd1498Szrj if (setrlimit (RLIMIT_CORE, &rlim) != 0)
273738fd1498Szrj fatal_error (input_location,
273838fd1498Szrj "setting core file size limit to maximum: %m");
273938fd1498Szrj }
274038fd1498Szrj #endif
274138fd1498Szrj diagnostic_abort_on_error (dc);
274238fd1498Szrj }
274338fd1498Szrj
274438fd1498Szrj /* Parse a -d<ARG> command line switch for OPTS, location LOC,
274538fd1498Szrj diagnostic context DC. */
274638fd1498Szrj
274738fd1498Szrj static void
274838fd1498Szrj decode_d_option (const char *arg, struct gcc_options *opts,
274938fd1498Szrj location_t loc, diagnostic_context *dc)
275038fd1498Szrj {
275138fd1498Szrj int c;
275238fd1498Szrj
275338fd1498Szrj while (*arg)
275438fd1498Szrj switch (c = *arg++)
275538fd1498Szrj {
275638fd1498Szrj case 'A':
275738fd1498Szrj opts->x_flag_debug_asm = 1;
275838fd1498Szrj break;
275938fd1498Szrj case 'p':
276038fd1498Szrj opts->x_flag_print_asm_name = 1;
276138fd1498Szrj break;
276238fd1498Szrj case 'P':
276338fd1498Szrj opts->x_flag_dump_rtl_in_asm = 1;
276438fd1498Szrj opts->x_flag_print_asm_name = 1;
276538fd1498Szrj break;
276638fd1498Szrj case 'x':
276738fd1498Szrj opts->x_rtl_dump_and_exit = 1;
276838fd1498Szrj break;
276938fd1498Szrj case 'D': /* These are handled by the preprocessor. */
277038fd1498Szrj case 'I':
277138fd1498Szrj case 'M':
277238fd1498Szrj case 'N':
277338fd1498Szrj case 'U':
277438fd1498Szrj break;
277538fd1498Szrj case 'H':
277638fd1498Szrj setup_core_dumping (dc);
277738fd1498Szrj break;
277838fd1498Szrj case 'a':
277938fd1498Szrj opts->x_flag_dump_all_passed = true;
278038fd1498Szrj break;
278138fd1498Szrj
278238fd1498Szrj default:
278338fd1498Szrj warning_at (loc, 0, "unrecognized gcc debugging option: %c", c);
278438fd1498Szrj break;
278538fd1498Szrj }
278638fd1498Szrj }
278738fd1498Szrj
278838fd1498Szrj /* Enable (or disable if VALUE is 0) a warning option ARG (language
278938fd1498Szrj mask LANG_MASK, option handlers HANDLERS) as an error for option
279038fd1498Szrj structures OPTS and OPTS_SET, diagnostic context DC (possibly
279138fd1498Szrj NULL), location LOC. This is used by -Werror=. */
279238fd1498Szrj
279338fd1498Szrj static void
279438fd1498Szrj enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
279538fd1498Szrj const struct cl_option_handlers *handlers,
279638fd1498Szrj struct gcc_options *opts,
279738fd1498Szrj struct gcc_options *opts_set,
279838fd1498Szrj location_t loc, diagnostic_context *dc)
279938fd1498Szrj {
280038fd1498Szrj char *new_option;
280138fd1498Szrj int option_index;
280238fd1498Szrj
280338fd1498Szrj new_option = XNEWVEC (char, strlen (arg) + 2);
280438fd1498Szrj new_option[0] = 'W';
280538fd1498Szrj strcpy (new_option + 1, arg);
280638fd1498Szrj option_index = find_opt (new_option, lang_mask);
280738fd1498Szrj if (option_index == OPT_SPECIAL_unknown)
280838fd1498Szrj error_at (loc, "-Werror=%s: no option -%s", arg, new_option);
280938fd1498Szrj else if (!(cl_options[option_index].flags & CL_WARNING))
281038fd1498Szrj error_at (loc, "-Werror=%s: -%s is not an option that controls warnings",
281138fd1498Szrj arg, new_option);
281238fd1498Szrj else
281338fd1498Szrj {
281438fd1498Szrj const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
281538fd1498Szrj const char *arg = NULL;
281638fd1498Szrj
281738fd1498Szrj if (cl_options[option_index].flags & CL_JOINED)
281838fd1498Szrj arg = new_option + cl_options[option_index].opt_len;
281938fd1498Szrj control_warning_option (option_index, (int) kind, arg, value,
282038fd1498Szrj loc, lang_mask,
282138fd1498Szrj handlers, opts, opts_set, dc);
282238fd1498Szrj }
282338fd1498Szrj free (new_option);
282438fd1498Szrj }
282538fd1498Szrj
282638fd1498Szrj /* Return malloced memory for the name of the option OPTION_INDEX
282738fd1498Szrj which enabled a diagnostic (context CONTEXT), originally of type
282838fd1498Szrj ORIG_DIAG_KIND but possibly converted to DIAG_KIND by options such
282938fd1498Szrj as -Werror. */
283038fd1498Szrj
283138fd1498Szrj char *
283238fd1498Szrj option_name (diagnostic_context *context, int option_index,
283338fd1498Szrj diagnostic_t orig_diag_kind, diagnostic_t diag_kind)
283438fd1498Szrj {
283538fd1498Szrj if (option_index)
283638fd1498Szrj {
283738fd1498Szrj /* A warning classified as an error. */
283838fd1498Szrj if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN)
283938fd1498Szrj && diag_kind == DK_ERROR)
284038fd1498Szrj return concat (cl_options[OPT_Werror_].opt_text,
284138fd1498Szrj /* Skip over "-W". */
284238fd1498Szrj cl_options[option_index].opt_text + 2,
284338fd1498Szrj NULL);
284438fd1498Szrj /* A warning with option. */
284538fd1498Szrj else
284638fd1498Szrj return xstrdup (cl_options[option_index].opt_text);
284738fd1498Szrj }
284838fd1498Szrj /* A warning without option classified as an error. */
284938fd1498Szrj else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
285038fd1498Szrj || diag_kind == DK_WARNING)
285138fd1498Szrj && context->warning_as_error_requested)
285238fd1498Szrj return xstrdup (cl_options[OPT_Werror].opt_text);
285338fd1498Szrj else
285438fd1498Szrj return NULL;
285538fd1498Szrj }
2856