aboutsummaryrefslogtreecommitdiff
path: root/gcc/opts-common.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-07-20 20:51:20 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-07-20 14:51:20 -0600
commit00abf86c47606f8220d6508654ef52ef11d76e3d (patch)
tree9fa355c5a990f19e6fa77fffaa11f37da0124134 /gcc/opts-common.c
parent20e8ceae67be4186c4f20b4fb96f7cfade9853a7 (diff)
downloadgcc-00abf86c47606f8220d6508654ef52ef11d76e3d.zip
gcc-00abf86c47606f8220d6508654ef52ef11d76e3d.tar.gz
gcc-00abf86c47606f8220d6508654ef52ef11d76e3d.tar.bz2
PR middle-end/82063 - issues with arguments enabled by -Wall
gcc/ada/ChangeLog: PR middle-end/82063 * gcc-interface/misc.c (gnat_handle_option): Change function argument to HOST_WIDE_INT. gcc/brig/ChangeLog: PR middle-end/82063 * brig/brig-lang.c (brig_langhook_handle_option): Change function argument to HOST_WIDE_INT. gcc/c-family/ChangeLog: PR middle-end/82063 * c-common.h (c_common_handle_option): Change function argument to HOST_WIDE_INT. * c-opts.c (c_common_init_options): Same. (c_common_handle_option): Same. Remove special handling of OPT_Walloca_larger_than_ and OPT_Wvla_larger_than_. * c.opt (-Walloc-size-larger-than, -Walloca-larger-than): Change options to take a HOST_WIDE_INT argument and accept a byte-size suffix. Initialize. (-Wvla-larger-than): Same. (-Wno-alloc-size-larger-than, -Wno-alloca-larger-than): New. (-Wno-vla-larger-than): Same. gcc/fortran/ChangeLog: PR middle-end/82063 * gfortran.h (gfc_handle_option): Change function argument to HOST_WIDE_INT. * options.c (gfc_handle_option): Same. gcc/go/ChangeLog: PR middle-end/82063 * go-lang.c (go_langhook_handle_option): Change function argument to HOST_WIDE_INT. gcc/lto/ChangeLog: PR middle-end/82063 * lto-lang.c (lto_handle_option): Change function argument to HOST_WIDE_INT. gcc/testsuite/ChangeLog: PR middle-end/82063 * gcc/testsuite/c-c++-common/pr68657-1.c: Adjust. * gcc/testsuite/c-c++-common/pr68657-2.c: Same. * gcc/testsuite/c-c++-common/pr68657-3.c: Same. * gcc.dg/Walloc-size-larger-than-16.c: Same. * gcc.dg/Walloca-larger-than.c: New test. * gcc.dg/Walloca-larger-than-2.c: New test. * gcc.dg/Wframe-larger-than-2.c: New test. * gcc.dg/Wlarger-than3.c: New test. * gcc.dg/Wvla-larger-than-3.c: New test. * gcc.dg/pr42611.c: Adjust. * gnat.dg/frame_overflow.adb: Same. gcc/ChangeLog: PR middle-end/82063 * builtins.c (expand_builtin_alloca): Adjust. * calls.c (alloc_max_size): Simplify. * cgraphunit.c (cgraph_node::expand): Adjust. * common.opt (larger_than_size, warn_frame_larger_than): Remove variables. (frame_larger_than_size): Same. (-Wframe-larger-than, -Wlarger-than, -Wstack-usage): Change options to take a HOST_WIDE_INT argument and accept a byte-size suffix. Initialize. * doc/invoke.texi (GCC Command Options): Document option arguments. Explain byte-size arguments and suffixes. (-Wvla-larger-than, -Wno-alloc-size-larger-than): Update. (-Wno-alloca-larger-than, -Wno-vla-larger-than): Same. (-Wframe-larger-than, -Wlarger-than, -Wstack-usage): Same. * doc/options.texi (UInteger): Expand. (Host_Wide_Int, ByteSize): Document new properties. * final.c (final_start_function_1): Include sizes in an error message. * function.c (frame_offset_overflow): Same. * gimple-ssa-warn-alloca.c (pass_walloca::gate): Adjust. (alloca_call_type_by_arg): Change function argument to HOST_WIDE_INT. Diagnose unbounded alloca calls only for limits of less than PTRDIFF_MAX. (alloca_call_type): Adjust. Diagnose possibly out-of-bounds alloca calls and VLA size only for limits of less than PTRDIFF_MAX. Same for alloca(0). (pass_walloca::execute): Adjust. Diagnose alloca calls in loops only for limits of less than PTRDIFF_MAX. * langhooks-def.h (lhd_handle_option): Change function argument to HOST_WIDE_INT. * langhooks.c (lhd_handle_option): Same. * langhooks.h (handle_option): Same. * opt-functions.awk (switch_bit_fields): Handle Host_Wide_Int and ByteSize flags. (var_type, var_type_struct): Same. (var_set): Handle ByteSize flag. * optc-gen.awk: Add comments to output to ease debugging. Make use of HOST_WIDE_INT where appropriate. * opts-gen-save.awk: Use %lx to format unsigned long. * opth-gen.awk: Change function argument to HOST_WIDE_INT. * opts-common.c (integral_argument): Return HOST_WIDE_INT and add arguments. Parse bytes-size suffixes. (enum_arg_to_value): Change function argument to HOST_WIDE_INT. (enum_value_to_arg): Same. (decode_cmdline_option): Handle cl_host_wide_int. Adjust. (handle_option): Adjust. (generate_option): Change function argument to HOST_WIDE_INT. (cmdline_handle_error): Adjust. (read_cmdline_option): Change function argument to HOST_WIDE_INT. (set_option): Change function argument to HOST_WIDE_INT. (option_enabled): Handle cl_host_wide_int. (get_option_state): Handle CLVC_SIZE. (control_warning_option): Same. * opts.c (common_handle_option): Change function argument to HOST_WIDE_INT. Remove handling of OPT_Walloca_larger_than_ and OPT_Wvla_larger_than_. * opts.h (enum cl_var_type): Add an enumerator. * stor-layout.c (layout_decl): Print a more meaningful warning. * toplev.c (output_stack_usage): Adjust. From-SVN: r262910
Diffstat (limited to 'gcc/opts-common.c')
-rw-r--r--gcc/opts-common.c235
1 files changed, 182 insertions, 53 deletions
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 004da73..1135644 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -169,32 +169,95 @@ find_opt (const char *input, unsigned int lang_mask)
return match_wrong_lang;
}
-/* If ARG is a non-negative decimal or hexadecimal integer, return its
- value, otherwise return -1. */
+/* 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. */
-int
-integral_argument (const char *arg)
+HOST_WIDE_INT
+integral_argument (const char *arg, int *err, bool byte_size_suffix)
{
- const char *p = arg;
+ if (!err)
+ err = &errno;
+
+ if (!ISDIGIT (*arg))
+ {
+ *err = EINVAL;
+ return -1;
+ }
+
+ *err = 0;
+ errno = 0;
- while (*p && ISDIGIT (*p))
- p++;
+ char *end = NULL;
+ unsigned HOST_WIDE_INT unit = 1;
+ unsigned HOST_WIDE_INT value = strtoull (arg, &end, 10);
- if (*p == '\0')
- return atoi (arg);
+ /* If the value is too large to be represented use the maximum
+ representable value that strtoull sets VALUE to (setting
+ errno to ERANGE). */
- /* It wasn't a decimal number - try hexadecimal. */
- if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X'))
+ if (end && *end)
{
- p = arg + 2;
- while (*p && ISXDIGIT (*p))
- p++;
+ 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 (p != arg + 2 && *p == '\0')
- return strtol (arg, NULL, 16);
+ if (unit)
+ {
+ unsigned HOST_WIDE_INT prod = value * unit;
+ value = prod < value ? HOST_WIDE_INT_M1U : prod;
}
- return -1;
+ return value;
}
/* Return whether OPTION is OK for the language given by
@@ -230,7 +293,8 @@ enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg,
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 @@ enum_arg_to_value (const struct cl_enum_arg *enum_args,
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 @@ enum_value_to_arg (const struct cl_enum_arg *enum_args,
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 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
{
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 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
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;
@@ -684,11 +761,12 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask,
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. */
@@ -1008,7 +1086,7 @@ handle_option (struct gcc_options *opts,
{
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;
@@ -1038,7 +1116,7 @@ handle_option (struct gcc_options *opts,
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)
@@ -1055,7 +1133,7 @@ handle_generated_option (struct gcc_options *opts,
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];
@@ -1167,8 +1245,13 @@ cmdline_handle_error (location_t loc, const struct cl_option *option,
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;
}
@@ -1274,7 +1357,7 @@ read_cmdline_option (struct gcc_options *opts,
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];
@@ -1293,22 +1376,54 @@ set_option (struct gcc_options *opts, struct gcc_options *opts_set,
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:
@@ -1395,7 +1510,10 @@ option_enabled (int opt_idx, void *opts)
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)
@@ -1415,6 +1533,12 @@ option_enabled (int opt_idx, void *opts)
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:
@@ -1439,6 +1563,7 @@ get_option_state (struct gcc_options *opts, int option,
{
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)
@@ -1503,9 +1628,11 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
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;
@@ -1517,11 +1644,13 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
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);