Mercurial > hg > CbC > CbC_gcc
diff gcc/opts-common.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/opts-common.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/opts-common.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Command line option handling. - Copyright (C) 2006-2017 Free Software Foundation, Inc. + Copyright (C) 2006-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -169,32 +169,95 @@ return match_wrong_lang; } -/* If ARG is a non-negative decimal or hexadecimal integer, return its - value, otherwise return -1. */ - -int -integral_argument (const char *arg) -{ - const char *p = arg; - - while (*p && ISDIGIT (*p)) - p++; +/* If ARG is a non-negative decimal or hexadecimal integer representable + in HOST_WIDE_INT return its value, otherwise return -1. If ERR is not + null set *ERR to zero on success or to EINVAL or to the value of errno + otherwise. */ - if (*p == '\0') - return atoi (arg); +HOST_WIDE_INT +integral_argument (const char *arg, int *err, bool byte_size_suffix) +{ + if (!err) + err = &errno; - /* It wasn't a decimal number - try hexadecimal. */ - if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) + if (!ISDIGIT (*arg)) { - p = arg + 2; - while (*p && ISXDIGIT (*p)) - p++; - - if (p != arg + 2 && *p == '\0') - return strtol (arg, NULL, 16); + *err = EINVAL; + return -1; } - return -1; + *err = 0; + errno = 0; + + char *end = NULL; + unsigned HOST_WIDE_INT unit = 1; + unsigned HOST_WIDE_INT value = strtoull (arg, &end, 10); + + /* If the value is too large to be represented use the maximum + representable value that strtoull sets VALUE to (setting + errno to ERANGE). */ + + if (end && *end) + { + if (!byte_size_suffix) + { + errno = 0; + value = strtoull (arg, &end, 0); + if (*end) + { + /* errno is most likely EINVAL here. */ + *err = errno; + return -1; + } + + return value; + } + + /* Numeric option arguments are at most INT_MAX. Make it + possible to specify a larger value by accepting common + suffixes. */ + if (!strcmp (end, "kB")) + unit = 1000; + else if (!strcasecmp (end, "KiB") || !strcmp (end, "KB")) + unit = 1024; + else if (!strcmp (end, "MB")) + unit = HOST_WIDE_INT_UC (1000) * 1000; + else if (!strcasecmp (end, "MiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024; + else if (!strcasecmp (end, "GB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000; + else if (!strcasecmp (end, "GiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024; + else if (!strcasecmp (end, "TB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "TiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "PB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "PiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "EB")) + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000 + * 1000; + else if (!strcasecmp (end, "EiB")) + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024 + * 1024; + else + { + /* This could mean an unknown suffix or a bad prefix, like + "+-1". */ + *err = EINVAL; + return -1; + } + } + + if (unit) + { + unsigned HOST_WIDE_INT prod = value * unit; + value = prod < value ? HOST_WIDE_INT_M1U : prod; + } + + return value; } /* Return whether OPTION is OK for the language given by @@ -230,7 +293,8 @@ static bool enum_arg_to_value (const struct cl_enum_arg *enum_args, - const char *arg, int *value, unsigned int lang_mask) + const char *arg, HOST_WIDE_INT *value, + unsigned int lang_mask) { unsigned int i; @@ -250,15 +314,22 @@ and returning false without modifying *VALUE if not found. */ bool -opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value, - unsigned int lang_mask) +opt_enum_arg_to_value (size_t opt_index, const char *arg, + int *value, unsigned int lang_mask) { const struct cl_option *option = &cl_options[opt_index]; gcc_assert (option->var_type == CLVC_ENUM); - return enum_arg_to_value (cl_enums[option->var_enum].values, arg, - value, lang_mask); + HOST_WIDE_INT wideval; + if (enum_arg_to_value (cl_enums[option->var_enum].values, arg, + &wideval, lang_mask)) + { + *value = wideval; + return true; + } + + return false; } /* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the @@ -299,7 +370,8 @@ described by OPT_INDEX, ARG and VALUE. */ static void -generate_canonical_option (size_t opt_index, const char *arg, int value, +generate_canonical_option (size_t opt_index, const char *arg, + HOST_WIDE_INT value, struct cl_decoded_option *decoded) { const struct cl_option *option = &cl_options[opt_index]; @@ -449,7 +521,7 @@ { size_t opt_index; const char *arg = 0; - int value = 1; + HOST_WIDE_INT value = 1; unsigned int result = 1, i, extra_args, separate_args = 0; int adjust_len = 0; size_t total_len; @@ -520,6 +592,11 @@ goto done; } + /* Clear the initial value for size options (it will be overwritten + later based on the Init(value) specification in the opt file. */ + if (option->var_type == CLVC_SIZE) + value = 0; + result = extra_args + 1; warn_message = option->warn_message; @@ -586,13 +663,13 @@ { size_t new_opt_index = option->alias_target; - if (new_opt_index == OPT_SPECIAL_ignore) + if (new_opt_index == OPT_SPECIAL_ignore + || new_opt_index == OPT_SPECIAL_deprecated) { gcc_assert (option->alias_arg == NULL); gcc_assert (option->neg_alias_arg == NULL); opt_index = new_opt_index; arg = NULL; - value = 1; } else { @@ -680,11 +757,12 @@ arg = arg_lower; } - /* If the switch takes an integer, convert it. */ - if (arg && option->cl_uinteger) + /* If the switch takes an integer argument, convert it. */ + if (arg && (option->cl_uinteger || option->cl_host_wide_int)) { - value = integral_argument (arg); - if (value == -1) + int error = 0; + value = *arg ? integral_argument (arg, &error, option->cl_byte_size) : 0; + if (error) errors |= CL_ERR_UINT_ARG; /* Reject value out of a range. */ @@ -741,7 +819,8 @@ else decoded->canonical_option[i] = NULL; } - if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore) + if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore + && opt_index != OPT_SPECIAL_deprecated) { generate_canonical_option (opt_index, arg, value, decoded); if (separate_args > 1) @@ -919,6 +998,7 @@ { case OPT_SPECIAL_unknown: case OPT_SPECIAL_ignore: + case OPT_SPECIAL_deprecated: case OPT_SPECIAL_program_name: case OPT_SPECIAL_input_file: goto keep; @@ -1004,7 +1084,7 @@ { size_t opt_index = decoded->opt_index; const char *arg = decoded->arg; - int value = decoded->value; + HOST_WIDE_INT value = decoded->value; const struct cl_option *option = &cl_options[opt_index]; void *flag_var = option_flag_var (opt_index, opts); size_t i; @@ -1034,7 +1114,7 @@ bool handle_generated_option (struct gcc_options *opts, struct gcc_options *opts_set, - size_t opt_index, const char *arg, int value, + size_t opt_index, const char *arg, HOST_WIDE_INT value, unsigned int lang_mask, int kind, location_t loc, const struct cl_option_handlers *handlers, bool generated_p, diagnostic_context *dc) @@ -1051,7 +1131,7 @@ compiler generates options internally. */ void -generate_option (size_t opt_index, const char *arg, int value, +generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value, unsigned int lang_mask, struct cl_decoded_option *decoded) { const struct cl_option *option = &cl_options[opt_index]; @@ -1163,8 +1243,13 @@ if (errors & CL_ERR_UINT_ARG) { - error_at (loc, "argument to %qs should be a non-negative integer", - option->opt_text); + if (option->cl_byte_size) + error_at (loc, "argument to %qs should be a non-negative integer " + "optionally followed by a size unit", + option->opt_text); + else + error_at (loc, "argument to %qs should be a non-negative integer", + option->opt_text); return true; } @@ -1181,6 +1266,7 @@ unsigned int i; char *s; + auto_diagnostic_group d; if (e->unknown_error) error_at (loc, e->unknown_error, arg); else @@ -1237,6 +1323,14 @@ if (decoded->opt_index == OPT_SPECIAL_ignore) return; + if (decoded->opt_index == OPT_SPECIAL_deprecated) + { + /* Warn only about positive ignored options. */ + if (decoded->value) + warning_at (loc, 0, "switch %qs is no longer supported", opt); + return; + } + option = &cl_options[decoded->opt_index]; if (decoded->errors @@ -1264,7 +1358,7 @@ void set_option (struct gcc_options *opts, struct gcc_options *opts_set, - int opt_index, int value, const char *arg, int kind, + int opt_index, HOST_WIDE_INT value, const char *arg, int kind, location_t loc, diagnostic_context *dc) { const struct cl_option *option = &cl_options[opt_index]; @@ -1283,22 +1377,54 @@ switch (option->var_type) { case CLVC_BOOLEAN: - *(int *) flag_var = value; - if (set_flag_var) - *(int *) set_flag_var = 1; + if (option->cl_host_wide_int) + { + *(HOST_WIDE_INT *) flag_var = value; + if (set_flag_var) + *(HOST_WIDE_INT *) set_flag_var = 1; + } + else + { + *(int *) flag_var = value; + if (set_flag_var) + *(int *) set_flag_var = 1; + } + + break; + + case CLVC_SIZE: + if (option->cl_host_wide_int) + { + *(HOST_WIDE_INT *) flag_var = value; + if (set_flag_var) + *(HOST_WIDE_INT *) set_flag_var = value; + } + else + { + *(int *) flag_var = value; + if (set_flag_var) + *(int *) set_flag_var = value; + } + break; case CLVC_EQUAL: - if (option->cl_host_wide_int) - *(HOST_WIDE_INT *) flag_var = (value - ? option->var_value - : !option->var_value); + if (option->cl_host_wide_int) + { + *(HOST_WIDE_INT *) flag_var = (value + ? option->var_value + : !option->var_value); + if (set_flag_var) + *(HOST_WIDE_INT *) set_flag_var = 1; + } else - *(int *) flag_var = (value - ? option->var_value - : !option->var_value); - if (set_flag_var) - *(int *) set_flag_var = 1; + { + *(int *) flag_var = (value + ? option->var_value + : !option->var_value); + if (set_flag_var) + *(int *) set_flag_var = 1; + } break; case CLVC_BIT_CLEAR: @@ -1385,7 +1511,10 @@ switch (option->var_type) { case CLVC_BOOLEAN: - return *(int *) flag_var != 0; + if (option->cl_host_wide_int) + return *(HOST_WIDE_INT *) flag_var != 0; + else + return *(int *) flag_var != 0; case CLVC_EQUAL: if (option->cl_host_wide_int) @@ -1405,6 +1534,12 @@ else return (*(int *) flag_var & option->var_value) != 0; + case CLVC_SIZE: + if (option->cl_host_wide_int) + return *(HOST_WIDE_INT *) flag_var != -1; + else + return *(int *) flag_var != -1; + case CLVC_STRING: case CLVC_ENUM: case CLVC_DEFER: @@ -1429,6 +1564,7 @@ { case CLVC_BOOLEAN: case CLVC_EQUAL: + case CLVC_SIZE: state->data = flag_var; state->size = (cl_options[option].cl_host_wide_int ? sizeof (HOST_WIDE_INT) @@ -1484,7 +1620,7 @@ arg = cl_options[opt_index].alias_arg; opt_index = cl_options[opt_index].alias_target; } - if (opt_index == OPT_SPECIAL_ignore) + if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_deprecated) return; if (dc) diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); @@ -1493,9 +1629,11 @@ const struct cl_option *option = &cl_options[opt_index]; /* -Werror=foo implies -Wfoo. */ - if (option->var_type == CLVC_BOOLEAN || option->var_type == CLVC_ENUM) + if (option->var_type == CLVC_BOOLEAN + || option->var_type == CLVC_ENUM + || option->var_type == CLVC_SIZE) { - int value = 1; + HOST_WIDE_INT value = 1; if (arg && *arg == '\0' && !option->cl_missing_ok) arg = NULL; @@ -1507,11 +1645,13 @@ return; } - /* If the switch takes an integer, convert it. */ - if (arg && option->cl_uinteger) + /* If the switch takes an integer argument, convert it. */ + if (arg && (option->cl_uinteger || option->cl_host_wide_int)) { - value = integral_argument (arg); - if (value == -1) + int error = 0; + value = *arg ? integral_argument (arg, &error, + option->cl_byte_size) : 0; + if (error) { cmdline_handle_error (loc, option, option->opt_text, arg, CL_ERR_UINT_ARG, lang_mask);