This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] specify large command line option arguments (PR 82063)


Storing integer command line option arguments in type int
limits options such as -Wlarger-than= or -Walloca-larger-than
to at most INT_MAX (see bug 71905).  Larger values wrap around
zero.  The value zero is considered to disable the option,
making it impossible to specify a zero limit.

To get around these limitations, the -Walloc-size-larger-than=
option accepts a string argument that it then parses itself
and interprets as HOST_WIDE_INT.  The option also accepts byte
size suffixes like KB, MB, GiB, etc. to make it convenient to
specify very large limits.

The int limitation is obviously less than ideal in a 64-bit
world.  The treatment of zero as a toggle is just a minor wart.
The special treatment to make it work for just a single option
makes option handling inconsistent.  It should be possible for
any option that takes an integer argument to use the same logic.

The attached patch enhances GCC option processing to do that.
It changes the storage type of option arguments from int to
HOST_WIDE_INT and extends the existing (although undocumented)
option property Host_Wide_Int to specify wide option arguments.
It also introduces the ByteSize property for options for which
specifying the byte-size suffix makes sense.

To make it possible to consider zero as a meaningful argument
value rather than a flag indicating that an option is disabled
the patch also adds a CLVC_SIZE enumerator to the cl_var_type
enumeration, and modifies how options of the kind are handled.

Warning options that take large byte-size arguments can be
disabled by specifying a value equal to or greater than
HOST_WIDE_INT_M1U.  For convenience, aliases in the form of
-Wno-xxx-larger-than have been provided for all the affected
options.

In the patch all the existing -larger-than options are set
to PTRDIFF_MAX.  This makes them effectively enabled, but
because the setting is exceedingly permissive, and because
some of the existing warnings are already set to the same
value and some other checks detect and reject such exceedingly
large values with errors, this change shouldn't noticeably
affect what constructs are diagnosed.

Although all the options are set to PTRDIFF_MAX, I think it
would make sense to consider setting some of them lower, say
to PTRDIFF_MAX / 2.  I'd like to propose that in a followup
patch.

To minimize observable changes the -Walloca-larger-than and
-Wvla-larger-than warnings required more extensive work to
make of the new mechanism because of the "unbounded" argument
handling (the warnings trigger for arguments that are not
visibly constrained), and because of the zero handling
(the warnings also trigger


Martin

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:
	* 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.dg/Walloc-size-larger-than-16.c: Adjust.
	* gcc.dg/Walloca-larger-than.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/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.

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index e4efa21..e7f1716 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -138,8 +138,9 @@ gnat_option_lang_mask (void)
    are marked as Ada-specific.  Return true on success or false on failure.  */
 
 static bool
-gnat_handle_option (size_t scode, const char *arg, int value, int kind,
-		    location_t loc, const struct cl_option_handlers *handlers)
+gnat_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
+		    int kind, location_t loc,
+		    const struct cl_option_handlers *handlers)
 {
   enum opt_code code = (enum opt_code) scode;
 
diff --git a/gcc/brig/brig-lang.c b/gcc/brig/brig-lang.c
index 3c4d4bd..862ea69 100644
--- a/gcc/brig/brig-lang.c
+++ b/gcc/brig/brig-lang.c
@@ -145,7 +145,7 @@ brig_langhook_init_options_struct (struct gcc_options *opts)
 static bool
 brig_langhook_handle_option
   (size_t scode, const char *arg ATTRIBUTE_UNUSED,
-  int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+  HOST_WIDE_INT value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
   location_t loc ATTRIBUTE_UNUSED,
   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 91658e8..400bc45 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5057,13 +5057,20 @@ expand_builtin_alloca (tree exp)
   if (!valid_arglist)
     return NULL_RTX;
 
-  if ((alloca_for_var && !warn_vla_limit)
-      || (!alloca_for_var && !warn_alloca_limit))
-    {
-      /* -Walloca-larger-than and -Wvla-larger-than settings override
-	 the more general -Walloc-size-larger-than so unless either of
-	 the former options is specified check the alloca arguments for
-	 overflow.  */
+  if ((alloca_for_var
+       && warn_vla_limit >= HOST_WIDE_INT_MAX
+       && warn_alloc_size_limit < warn_vla_limit)
+      || (!alloca_for_var
+	  && warn_alloca_limit >= HOST_WIDE_INT_MAX
+	  && warn_alloc_size_limit < warn_alloca_limit
+	  ))
+    {
+      /* -Walloca-larger-than and -Wvla-larger-than settings of
+	 less than HOST_WIDE_INT_MAX override the more general
+	 -Walloc-size-larger-than so unless either of the former
+	 options is smaller than the last one (wchich would imply
+	 that the call was already checked), check the alloca
+	 arguments for overflow.  */
       tree args[] = { CALL_EXPR_ARG (exp, 0), NULL_TREE };
       int idx[] = { 0, -1 };
       maybe_warn_alloc_args_overflow (fndecl, exp, args, idx);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index c266fee..fcec95b 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -808,7 +808,8 @@ extern void check_function_format (tree, int, tree *, vec<location_t> *);
 extern bool attribute_fallthrough_p (tree);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
-extern bool c_common_handle_option (size_t, const char *, int, int, location_t,
+extern bool c_common_handle_option (size_t, const char *, HOST_WIDE_INT, int,
+				    location_t,
 				    const struct cl_option_handlers *);
 extern bool default_handle_c_option (size_t, const char *, int);
 extern tree c_common_type_for_mode (machine_mode, int);
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index bbcb1bb..cb69fb3 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -262,7 +262,7 @@ c_common_init_options (unsigned int decoded_options_count,
    form of an -f or -W option was given.  Returns false if the switch was
    invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
 bool
-c_common_handle_option (size_t scode, const char *arg, int value,
+c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 			int kind, location_t loc,
 			const struct cl_option_handlers *handlers)
 {
@@ -381,16 +381,6 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       cpp_opts->warn_num_sign_change = value;
       break;
 
-    case OPT_Walloca_larger_than_:
-      if (!value)
-	inform (loc, "-Walloca-larger-than=0 is meaningless");
-      break;
-
-    case OPT_Wvla_larger_than_:
-      if (!value)
-	inform (loc, "-Wvla-larger-than=0 is meaningless");
-      break;
-
     case OPT_Wunknown_pragmas:
       /* Set to greater than 1, so that even unknown pragmas in
 	 system headers will be warned about.  */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index b4aefd8..bb4f603 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -304,12 +304,12 @@ C ObjC C++ ObjC++ Var(warn_alloca) Warning
 Warn on any use of alloca.
 
 Walloc-size-larger-than=
-C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Warning Joined LangEnabledBy(C ObjC C++ LTO ObjC++,Wall)
+C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Joined Host_Wide_Int ByteSize Warning Init(HOST_WIDE_INT_MAX)
 -Walloc-size-larger-than=<bytes> Warn for calls to allocation functions that
 attempt to allocate objects larger than the specified number of bytes.
 
 Wno-alloc-size-larger-than
-C ObjC C++ LTO ObjC++ Alias(Walloc-size-larger-than=, 18446744073709551615EiB,none) Warning
+C ObjC C++ LTO ObjC++ Alias(Walloc-size-larger-than=,18446744073709551615EiB,none) Warning
 -Wno-alloc-size-larger-than Disable Walloc-size-larger-than= warning.  Equivalent to Walloc-size-larger-than=<SIZE_MAX> or larger.
 
 Walloc-zero
@@ -317,11 +317,15 @@ C ObjC C++ ObjC++ Var(warn_alloc_zero) Warning
 -Walloc-zero Warn for calls to allocation functions that specify zero bytes.
 
 Walloca-larger-than=
-C ObjC C++ LTO ObjC++ Var(warn_alloca_limit) Warning Joined RejectNegative UInteger
+C ObjC C++ LTO ObjC++ Var(warn_alloca_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX)
 -Walloca-larger-than=<number>	Warn on unbounded uses of
 alloca, and on bounded uses of alloca whose bound can be larger than
 <number> bytes.
 
+Wno-alloca-larger-than
+C ObjC C++ LTO ObjC++ Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning
+-Wno-alloca-larger-than Disable Walloca-larger-than= warning.  Equivalent to Walloca-larger-than=<SIZE_MAX> or larger.
+
 Warray-bounds
 LangEnabledBy(C ObjC C++ LTO ObjC++,Wall)
 ; in common.opt
@@ -1158,10 +1162,15 @@ C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
 Warn if a variable length array is used.
 
 Wvla-larger-than=
-C ObjC C++ ObjC++ Var(warn_vla_limit) Warning Joined RejectNegative UInteger
--Wvla-larger-than=<number>	Warn on unbounded uses of variable-length arrays, and
-on bounded uses of variable-length arrays whose bound can be
+C ObjC C++ LTO ObjC++ Var(warn_vla_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX)
+-Wvla-larger-than=<number>	Warn on unbounded uses of variable-length
+arrays, and on bounded uses of variable-length arrays whose bound can be
 larger than <number> bytes.
+<number> bytes.
+
+Wno-vla-larger-than
+C ObjC C++ LTO ObjC++ Alias(Wvla-larger-than=,18446744073709551615EiB,none) Warning
+-Wno-vla-larger-than Disable Wvla-larger-than= warning.  Equivalent to Wvla-larger-than=<SIZE_MAX> or larger.
 
 Wvolatile-register-var
 C ObjC C++ ObjC++ Var(warn_volatile_register_var) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
diff --git a/gcc/calls.c b/gcc/calls.c
index 1970f1c..e1dcacc 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1222,77 +1222,8 @@ alloc_max_size (void)
   if (alloc_object_size_limit)
     return alloc_object_size_limit;
 
-  alloc_object_size_limit = max_object_size ();
-
-  if (!warn_alloc_size_limit)
-    return alloc_object_size_limit;
-
-  const char *optname = "-Walloc-size-larger-than=";
-
-  char *end = NULL;
-  errno = 0;
-  unsigned HOST_WIDE_INT unit = 1;
-  unsigned HOST_WIDE_INT limit
-    = strtoull (warn_alloc_size_limit, &end, 10);
-
-  /* If the value is too large to be represented use the maximum
-     representable value that strtoull sets limit to (setting
-     errno to ERANGE).  */
-
-  if (end && *end)
-    {
-      /* 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".  */
-	  warning_at (UNKNOWN_LOCATION, 0,
-		      "invalid argument %qs to %qs",
-		      warn_alloc_size_limit, optname);
-
-	  /* Ignore the limit extracted by strtoull.  */
-	  unit = 0;
-	}
-    }
-
-  if (unit)
-    {
-      widest_int w = wi::mul (limit, unit);
-      if (w < wi::to_widest (alloc_object_size_limit))
-	alloc_object_size_limit
-	  = wide_int_to_tree (ptrdiff_type_node, w);
-      else
-	alloc_object_size_limit = build_all_ones_cst (size_type_node);
-    }
-
+  alloc_object_size_limit
+    = build_int_cst (size_type_node, warn_alloc_size_limit);
 
   return alloc_object_size_limit;
 }
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 04b6919..73b922a 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2129,24 +2129,26 @@ cgraph_node::expand (void)
   /* If requested, warn about function definitions where the function will
      return a value (usually of some struct or union type) which itself will
      take up a lot of stack space.  */
-  if (warn_larger_than && !DECL_EXTERNAL (decl) && TREE_TYPE (decl))
+  if (!DECL_EXTERNAL (decl) && TREE_TYPE (decl))
     {
       tree ret_type = TREE_TYPE (TREE_TYPE (decl));
 
       if (ret_type && TYPE_SIZE_UNIT (ret_type)
 	  && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
 	  && compare_tree_int (TYPE_SIZE_UNIT (ret_type),
-			       larger_than_size) > 0)
+			       warn_larger_than_size) > 0)
 	{
 	  unsigned int size_as_int
 	    = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
 	  if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
-	    warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
+	    warning (OPT_Wlarger_than_,
+		     "size of return value of %q+D is %u bytes",
                      decl, size_as_int);
 	  else
-	    warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
-                     decl, larger_than_size);
+	    warning (OPT_Wlarger_than_,
+		     "size of return value of %q+D is larger than %wu bytes",
+                     decl, warn_larger_than_size);
 	}
     }
 
diff --git a/gcc/common.opt b/gcc/common.opt
index 0d1445b..435055e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -74,23 +74,6 @@ int flag_generate_lto
 Variable
 int flag_generate_offload = 0
 
-; True to warn about any objects definitions whose size is larger
-; than N bytes.  Also want about function definitions whose returned
-; values are larger than N bytes, where N is 'larger_than_size'.
-Variable
-bool warn_larger_than
-
-Variable
-HOST_WIDE_INT larger_than_size
-
-; True to warn about any function whose frame size is larger
-; than N bytes.
-Variable
-bool warn_frame_larger_than
-
-Variable
-HOST_WIDE_INT frame_larger_than_size
-
 ; Nonzero means we should be saving declaration info into a .X file.
 Variable
 int flag_gen_aux_info = 0
@@ -604,8 +587,8 @@ Common Var(flag_fatal_errors)
 Exit on the first error occurred.
 
 Wframe-larger-than=
-Common RejectNegative Joined UInteger Warning
--Wframe-larger-than=<number>	Warn if a function's stack frame requires more than <number> bytes.
+Common RejectNegative Joined Host_Wide_Int ByteSize Warning Var(warn_frame_larger_than_size) Init(HOST_WIDE_INT_MAX)
+-Wframe-larger-than=<byte-size>	Warn if a function's stack frame requires in excess of <byte-size>.
 
 Wfree-nonheap-object
 Common Var(warn_free_nonheap_object) Init(1) Warning
@@ -634,8 +617,8 @@ Wlarger-than-
 Common RejectNegative Joined Warning Undocumented Alias(Wlarger-than=)
 
 Wlarger-than=
-Common RejectNegative Joined UInteger Warning
--Wlarger-than=<number>	Warn if an object is larger than <number> bytes.
+Common RejectNegative Joined Host_Wide_Int ByteSize Warning Var(warn_larger_than_size) Init(HOST_WIDE_INT_MAX)
+-Wlarger-than=<byte-size>	Warn if an object's size exceeds <byte-size>.
 
 Wnonnull-compare
 Var(warn_nonnull_compare) Warning
@@ -707,8 +690,8 @@ Common Var(warn_stack_protect) Warning
 Warn when not issuing stack smashing protection for some reason.
 
 Wstack-usage=
-Common Joined RejectNegative UInteger Var(warn_stack_usage) Warning
--Wstack-usage=<number>	Warn if stack usage might be larger than specified amount.
+Common Joined RejectNegative Host_Wide_Int ByteSize Var(warn_stack_usage) Warning Init(HOST_WIDE_INT_MAX)
+-Wstack-usage=<byte-size>	Warn if stack usage might exceed <byte-size>.
 
 Wstrict-aliasing
 Common Warning
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9bb1a49..0b824e8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -121,6 +121,21 @@ these have both positive and negative forms; the negative form of
 @option{-ffoo} is @option{-fno-foo}.  This manual documents
 only one of these two forms, whichever one is not the default.
 
+Some options take one or more arguments typically separated either
+by a space or by the equals sign (@samp{=}) from the option name.
+Unless documented otherwise, an argument can be either numeric or
+a string.  Numeric arguments must typically be small unsigned decimal
+or hexadecimal integers.  Hexadecimal arguments must begin with
+the @samp{0x} prefix.  Arguments to options that specify a size
+threshold of some sort may be arbitrarily large decimal or hexadecimal
+integers followed by a byte size suffix designating a multiple of bytes
+such as @code{kB} and @code{KiB} for kilobyte and kibibyte, respectively,
+@code{MB} and @code{MiB} for megabyte and mebibyte, @code{GB} and
+@code{GiB} for gigabyte and gigibyte, and so on.  Such arguments are
+designated by @var{byte-size} in the following text.  Refer to the NIST,
+IEC, and other relevant national and international standards for the full
+listing and explanation of the binary and decimal byte size prefixes.
+
 @c man end
 
 @xref{Option Index}, for an index to GCC's options.
@@ -261,8 +276,8 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-fsyntax-only  -fmax-errors=@var{n}  -Wpedantic @gol
 -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waddress  -Waggregate-return  @gol
--Walloc-zero  -Walloc-size-larger-than=@var{n}
--Walloca  -Walloca-larger-than=@var{n} @gol
+-Walloc-zero  -Walloc-size-larger-than=@var{byte-size}
+-Walloca  -Walloca-larger-than=@var{byte-size} @gol
 -Wno-aggressive-loop-optimizations  -Warray-bounds  -Warray-bounds=@var{n} @gol
 -Wno-attributes  -Wbool-compare  -Wbool-operation @gol
 -Wno-builtin-declaration-mismatch @gol
@@ -285,14 +300,15 @@ Objective-C and Objective-C++ Dialects}.
 -Wformat-nonliteral -Wformat-overflow=@var{n} @gol
 -Wformat-security  -Wformat-signedness  -Wformat-truncation=@var{n} @gol
 -Wformat-y2k  -Wframe-address @gol
--Wframe-larger-than=@var{len}  -Wno-free-nonheap-object  -Wjump-misses-init @gol
+-Wframe-larger-than=@var{byte-size}  -Wno-free-nonheap-object @gol
+-Wjump-misses-init @gol
 -Wif-not-aligned @gol
 -Wignored-qualifiers  -Wignored-attributes  -Wincompatible-pointer-types @gol
 -Wimplicit  -Wimplicit-fallthrough  -Wimplicit-fallthrough=@var{n} @gol
 -Wimplicit-function-declaration  -Wimplicit-int @gol
 -Winit-self  -Winline  -Wno-int-conversion  -Wint-in-bool-context @gol
 -Wno-int-to-pointer-cast  -Winvalid-memory-model  -Wno-invalid-offsetof @gol
--Winvalid-pch  -Wlarger-than=@var{len} @gol
+-Winvalid-pch  -Wlarger-than=@var{byte-size} @gol
 -Wlogical-op  -Wlogical-not-parentheses  -Wlong-long @gol
 -Wmain  -Wmaybe-uninitialized  -Wmemset-elt-size  -Wmemset-transposed-args @gol
 -Wmisleading-indentation  -Wmissing-attributes -Wmissing-braces @gol
@@ -313,7 +329,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wsign-compare  -Wsign-conversion  -Wfloat-conversion @gol
 -Wno-scalar-storage-order  -Wsizeof-pointer-div @gol
 -Wsizeof-pointer-memaccess  -Wsizeof-array-argument @gol
--Wstack-protector  -Wstack-usage=@var{len}  -Wstrict-aliasing @gol
+-Wstack-protector  -Wstack-usage=@var{byte-size}  -Wstrict-aliasing @gol
 -Wstrict-aliasing=n  -Wstrict-overflow  -Wstrict-overflow=@var{n} @gol
 -Wstringop-overflow=@var{n} -Wstringop-truncation @gol
 -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}malloc@r{]} @gol
@@ -331,7 +347,8 @@ Objective-C and Objective-C++ Dialects}.
 -Wunused-const-variable  -Wunused-const-variable=@var{n} @gol
 -Wunused-but-set-parameter  -Wunused-but-set-variable @gol
 -Wuseless-cast  -Wvariadic-macros  -Wvector-operation-performance @gol
--Wvla  -Wvla-larger-than=@var{n}  -Wvolatile-register-var  -Wwrite-strings @gol
+-Wvla  -Wvla-larger-than=@var{byte-size}  -Wvolatile-register-var @gol
+-Wwrite-strings @gol
 -Wzero-as-null-pointer-constant  -Whsa}
 
 @item C and Objective-C-only Warning Options
@@ -5521,33 +5538,39 @@ when called with a zero size differs among implementations (and in the case
 of @code{realloc} has been deprecated) relying on it may result in subtle
 portability bugs and should be avoided.
 
-@item -Walloc-size-larger-than=@var{n}
-@opindex Walloc-size-larger-than=@var{n}
+@item -Walloc-size-larger-than=@var{byte-size}
+@opindex Walloc-size-larger-than=
 @opindex Wno-alloc-size-larger-than
 Warn about calls to functions decorated with attribute @code{alloc_size}
 that attempt to allocate objects larger than the specified number of bytes,
 or where the result of the size computation in an integer type with infinite
-precision would exceed @code{SIZE_MAX / 2}.  The option argument @var{n} is
-treated as an integer with infinite precision and may end in one of
-the standard suffixes designating a multiple of bytes such as @code{kB} and
-@code{KiB} for kilobyte and kibibyte, respectively, @code{MB} and @code{MiB}
-for megabyte and mebibyte, and so on.
-@option{-Walloc-size-larger-than=}@var{PTRDIFF_MAX} is enabled by default.
+precision would exceed the value of @samp{PTRDIFF_MAX} on the target.
+@option{-Walloc-size-larger-than=}@samp{PTRDIFF_MAX} is enabled by default.
 Warnings controlled by the option can be disabled either by specifying
-@var{n} of @var{SIZE_MAX} or more or by @option{-Wno-alloc-size-larger-than}.
+@var{byte-size} of @samp{SIZE_MAX} or more or by
+@option{-Wno-alloc-size-larger-than}.
 @xref{Function Attributes}.
 
+@item -Wno-alloc-size-larger-than
+@opindex Wno-alloc-size-larger-than
+Disable @option{-Walloc-size-larger-than=} warnings.  The option is
+equivalent to @option{-Walloc-size-larger-than=}@samp{SIZE_MAX} or
+larger.
+
 @item -Walloca
 @opindex Wno-alloca
 @opindex Walloca
 This option warns on all uses of @code{alloca} in the source.
 
-@item -Walloca-larger-than=@var{n}
-This option warns on calls to @code{alloca} that are not bounded by a
-controlling predicate limiting its argument of integer type to at most
-@var{n} bytes, or calls to @code{alloca} where the bound is unknown.
-Arguments of non-integer types are considered unbounded even if they
-appear to be constrained to the expected range.
+@item -Walloca-larger-than=@var{byte-size}
+@opindex -Walloca-larger-than=
+@opindex -Wno-alloca-larger-than
+This option warns on calls to @code{alloca} with an integer argument whose
+value is either zero, or that is not bounded by a controlling predicate
+that limits its value to at most @var{byte-size}.  It also warns for calls
+to @code{alloca} where the bound value is unknown.  Arguments of non-integer
+types are considered unbounded even if they appear to be constrained to
+the expected range.
 
 For example, a bounded case of @code{alloca} could be:
 
@@ -5601,10 +5624,16 @@ expected argument to be implicitly cast into the @code{alloca} call.
 
 This option also warns when @code{alloca} is used in a loop.
 
-This warning is not enabled by @option{-Wall}, and is only active when
-@option{-ftree-vrp} is active (default for @option{-O2} and above).
+@option{-Walloca-larger-than=}@samp{PTRDIFF_MAX} is enabled by default
+but is usually only effective  when @option{-ftree-vrp} is active (default
+for @option{-O2} and above).
 
-See also @option{-Wvla-larger-than=@var{n}}.
+See also @option{-Wvla-larger-than=}@samp{byte-size}.
+
+@item -Wno-alloca-larger-than
+@opindex Wno-alloca-larger-than
+Disable @option{-Walloca-larger-than=} warnings.  The option is
+equivalent to @option{-Walloca-larger-than=}@samp{SIZE_MAX} or larger.
 
 @item -Warray-bounds
 @itemx -Warray-bounds=@var{n}
@@ -5952,22 +5981,40 @@ possibly reduce the number of warnings triggered by intentional shadowing.
 
 This warning is enabled by @option{-Wshadow=local}.
 
-@item -Wlarger-than=@var{len}
-@opindex Wlarger-than=@var{len}
-@opindex Wlarger-than-@var{len}
-Warn whenever an object of larger than @var{len} bytes is defined.
-
-@item -Wframe-larger-than=@var{len}
-@opindex Wframe-larger-than=@var{len}
-@opindex Wframe-larger-than
-Warn if the size of a function frame is larger than @var{len} bytes.
+@item -Wlarger-than=@var{byte-size}
+@opindex Wlarger-than=
+@opindex Wlarger-than-@var{byte-size}
+Warn whenever an object is defined whose size exceeds @var{byte-size}.
+@option{-Wlarger-than=}@samp{PTRDIFF_MAX} is enabled by default.
+Warnings controlled by the option can be disabled either by specifying
+@var{byte-size} of @samp{SIZE_MAX} or more or by
+@option{-Wno-larger-than}.
+
+@item -Wno-larger-than
+@opindex Wno-larger-than
+Disable @option{-Wlarger-than=} warnings.  The option is equivalent
+to @option{-Wlarger-than=}@samp{SIZE_MAX} or larger.
+
+@item -Wframe-larger-than=@var{byte-size}
+@opindex Wframe-larger-than=
+@opindex Wno-frame-larger-than
+Warn if the size of a function frame exceeds @var{byte-size}.
 The computation done to determine the stack frame size is approximate
 and not conservative.
-The actual requirements may be somewhat greater than @var{len}
+The actual requirements may be somewhat greater than @var{byte-size}
 even if you do not get a warning.  In addition, any space allocated
 via @code{alloca}, variable-length arrays, or related constructs
 is not included by the compiler when determining
 whether or not to issue a warning.
+@option{-Wframe-larger-than=}@samp{PTRDIFF_MAX} is enabled by default.
+Warnings controlled by the option can be disabled either by specifying
+@var{byte-size} of @samp{SIZE_MAX} or more or by
+@option{-Wno-frame-larger-than}.
+
+@item -Wno-frame-larger-than
+@opindex Wno-frame-larger-than
+Disable @option{-Wframe-larger-than=} warnings.  The option is equivalent
+to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
 
 @item -Wno-free-nonheap-object
 @opindex Wno-free-nonheap-object
@@ -5975,10 +6022,10 @@ whether or not to issue a warning.
 Do not warn when attempting to free an object that was not allocated
 on the heap.
 
-@item -Wstack-usage=@var{len}
+@item -Wstack-usage=@var{byte-size}
 @opindex Wstack-usage
 @opindex Wno-stack-usage
-Warn if the stack usage of a function might be larger than @var{len} bytes.
+Warn if the stack usage of a function might exceed @var{byte-size}.
 The computation done to determine the stack usage is conservative.
 Any space allocated via @code{alloca}, variable-length arrays, or related
 constructs is included by the compiler when determining whether or not to
@@ -6007,6 +6054,24 @@ If the stack usage is (partly) dynamic and not bounded, it's:
 @end smallexample
 @end itemize
 
+@option{-Wstack-usage=}@samp{PTRDIFF_MAX} is enabled by default.
+Warnings controlled by the option can be disabled either by specifying
+@var{byte-size} of @samp{SIZE_MAX} or more or by
+@option{-Wno-stack-usage}.
+
+@item -Wno-stack-usage
+@opindex Wno-stack-usage
+Disable @option{-Wstack-usage=} warnings.  The option is equivalent
+to @option{-Wstack-usage=}@samp{SIZE_MAX} or larger.
+
+@item -Wunsafe-loop-optimizations
+@opindex Wunsafe-loop-optimizations
+@opindex Wno-unsafe-loop-optimizations
+Warn if the loop cannot be optimized because the compiler cannot
+assume anything on the bounds of the loop indices.  With
+@option{-funsafe-loop-optimizations} warn if the compiler makes
+such assumptions.
+
 @item -Wno-pedantic-ms-format @r{(MinGW targets only)}
 @opindex Wno-pedantic-ms-format
 @opindex Wpedantic-ms-format
@@ -7009,21 +7074,29 @@ Warn if a variable-length array is used in the code.
 @option{-Wno-vla} prevents the @option{-Wpedantic} warning of
 the variable-length array.
 
-@item -Wvla-larger-than=@var{n}
-If this option is used, the compiler will warn on uses of
-variable-length arrays where the size is either unbounded, or bounded
-by an argument that can be larger than @var{n} bytes.  This is similar
-to how @option{-Walloca-larger-than=@var{n}} works, but with
-variable-length arrays.
+@item -Wvla-larger-than=@var{byte-size}
+@opindex -Wvla-larger-than=
+@opindex -Wno-vla-larger-than
+If this option is used, the compiler will warn for declarations of
+variable-length arrays whose size is either unbounded, or bounded
+by an argument that allows the array size to exceed @var{byte-size}
+bytes.  This is similar to how @option{-Walloca-larger-than=}@var{byte-size}
+works, but with variable-length arrays.
 
 Note that GCC may optimize small variable-length arrays of a known
 value into plain arrays, so this warning may not get triggered for
 such arrays.
 
-This warning is not enabled by @option{-Wall}, and is only active when
-@option{-ftree-vrp} is active (default for @option{-O2} and above).
+@option{-Wvla-larger-than=}@samp{PTRDIFF_MAX} is enabled by default but
+is typically only effective when @option{-ftree-vrp} is active (default
+for @option{-O2} and above).
+
+See also @option{-Walloca-larger-than=@var{byte-size}}.
 
-See also @option{-Walloca-larger-than=@var{n}}.
+@item -Wno-vla-larger-than
+@opindex Wno-vla-larger-than
+Disable @option{-Wvla-larger-than=} warnings.  The option is equivalent
+to @option{-Wvla-larger-than=}@samp{SIZE_MAX} or larger.
 
 @item -Wvolatile-register-var
 @opindex Wvolatile-register-var
diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi
index b3ca9f6..f887d16 100644
--- a/gcc/doc/options.texi
+++ b/gcc/doc/options.texi
@@ -257,17 +257,42 @@ For an option marked @code{Separate}, indicate that it takes @var{n}
 arguments.  The default is 1.
 
 @item UInteger
-The option's argument is a non-negative integer.  The option parser
-will check and convert the argument before passing it to the relevant
-option handler.  @code{UInteger} should also be used on options like
-@code{-falign-loops} where both @code{-falign-loops} and
-@code{-falign-loops}=@var{n} are supported to make sure the saved
-options are given a full integer.
+The option's argument is a non-negative integer consisting of either
+decimal or hexadecimal digits interpreted as @code{int}.  Hexadecimal
+integers may optionally start with the @code{0x} or @code{0X} prefix.
+The option parser validates and converts the argument before passing
+it to the relevant option handler.  @code{UInteger} should also be used
+with options like @code{-falign-loops} where both @code{-falign-loops}
+and @code{-falign-loops}=@var{n} are supported to make sure the saved
+options are given a full integer.  Positive values of the argument in
+excess of @code{INT_MAX} wrap around zero.
+
+@item Host_Wide_Int
+The option's argument is a non-negative integer consisting of either
+decimal or hexadecimal digits interpreted as the widest integer type
+on the host.  As with an @code{UInteger} argument, hexadecimal integers
+may optionally start with the @code{0x} or @code{0X} prefix.  The option
+parser validates and converts the argument before passing it to
+the relevant option handler.  @code{Host_Wide_Int} should be used with
+options that need to accept very large values.  Positive values of
+the argument in excess of @code{HOST_WIDE_INT_M1U} are assigned
+@code{HOST_WIDE_INT_M1U}.
 
 @item IntegerRange(@var{n}, @var{m})
-The options's arguments are integer numbers.  The option's parser
-will check that value of an option is inclusively within the
-range [@var{n}, @var{m}].
+The options's arguments are integers of type @code{int}.  The option's
+parser validates that the value of an option integer argument is within
+the closed range [@var{n}, @var{m}].
+
+@item ByteSize
+A property applicable only to @code{UInteger} or @code{Host_Wide_Int}
+arguments.  The option's integer argument is interpreted as if in infinite
+precision using saturation arithmetic in the corresponding type.  The argument
+may be followed by a @samp{byte-size} suffix designating a multiple of bytes
+such as @code{kB} and @code{KiB} for kilobyte and kibibyte, respectively,
+@code{MB} and @code{MiB} for megabyte and mebibyte, @code{GB} and @code{GiB}
+for gigabyte and gigibyte, and so on.  @code{ByteSize} should be used for
+with options that take a very large argument representing a size in bytes,
+such as @option{-Wlarger-than=}.
 
 @item ToLower
 The option's argument should be converted to lowercase as part of
diff --git a/gcc/final.c b/gcc/final.c
index a17a3a6..77b76e8 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1859,14 +1859,14 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
       TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
     }
 
-  HOST_WIDE_INT min_frame_size = constant_lower_bound (get_frame_size ());
-  if (warn_frame_larger_than
-      && min_frame_size > frame_larger_than_size)
+  unsigned HOST_WIDE_INT min_frame_size
+    = constant_lower_bound (get_frame_size ());
+  if (min_frame_size > (unsigned HOST_WIDE_INT) warn_frame_larger_than_size)
     {
       /* Issue a warning */
       warning (OPT_Wframe_larger_than_,
-	       "the frame size of %wd bytes is larger than %wd bytes",
-	       min_frame_size, frame_larger_than_size);
+	       "the frame size of %wu bytes is larger than %wu bytes",
+	       min_frame_size, warn_frame_larger_than_size);
     }
 
   /* First output the function prologue: code to set up the stack frame.  */
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 0b89f8d..9d35041 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2837,7 +2837,7 @@ unsigned int gfc_option_lang_mask (void);
 void gfc_init_options_struct (struct gcc_options *);
 void gfc_init_options (unsigned int,
 		       struct cl_decoded_option *);
-bool gfc_handle_option (size_t, const char *, int, int, location_t,
+bool gfc_handle_option (size_t, const char *, HOST_WIDE_INT, int, location_t,
 			const struct cl_option_handlers *);
 bool gfc_post_options (const char **);
 char *gfc_get_option_string (void);
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 85f699e..af93751 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -585,7 +585,7 @@ gfc_handle_runtime_check_option (const char *arg)
    recognized and handled.  */
 
 bool
-gfc_handle_option (size_t scode, const char *arg, int value,
+gfc_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 		   int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED,
 		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/function.c b/gcc/function.c
index 47232a2..32dc0e0 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -242,8 +242,15 @@ frame_offset_overflow (poly_int64 offset, tree func)
 
   if (!coeffs_in_range_p (size, 0U, limit))
     {
-      error_at (DECL_SOURCE_LOCATION (func),
-		"total size of local objects too large");
+      unsigned HOST_WIDE_INT hwisize;
+      if (size.is_constant (&hwisize))
+	error_at (DECL_SOURCE_LOCATION (func),
+		  "total size of local objects %wu exceeds maximum %wu",
+		  hwisize, limit);
+      else
+	error_at (DECL_SOURCE_LOCATION (func),
+		  "total size of local objects exceeds maximum %wu",
+		  limit);
       return true;
     }
 
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 327c806..a3367aa 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa.h"
 #include "params.h"
 #include "tree-cfg.h"
+#include "builtins.h"
 #include "calls.h"
 #include "cfgloop.h"
 #include "intl.h"
@@ -78,8 +79,10 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED)
   if (first_time_p)
     return warn_alloca != 0;
 
-  return ((unsigned HOST_WIDE_INT) warn_alloca_limit > 0
-	  || (unsigned HOST_WIDE_INT) warn_vla_limit > 0);
+  // Warning is disabled when its size limit is greater than PTRDIFF_MAX
+  // for the target maximum, which makes the limit negative since when
+  // represented in signed HOST_WIDE_INT.
+  return warn_alloca_limit >= 0 || warn_vla_limit >= 0;
 }
 
 // Possible problematic uses of alloca.
@@ -150,13 +153,25 @@ struct alloca_type_and_limit {
 // in bytes we allow for arg.
 
 static struct alloca_type_and_limit
-alloca_call_type_by_arg (tree arg, tree arg_casted, edge e, unsigned max_size)
+alloca_call_type_by_arg (tree arg, tree arg_casted, edge e,
+			 unsigned HOST_WIDE_INT max_size)
 {
   basic_block bb = e->src;
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
   gimple *last = gsi_stmt (gsi);
+
+  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
+
+  /* When MAX_SIZE is greater than or equal to PTRDIFF_MAX treat
+     allocations that aren't visibly constrained as OK, otherwise
+     report them as (potentially) unbonded.  */
+  alloca_type unbounded_result = (max_size < maxobjsize.to_uhwi ()
+				  ? ALLOCA_UNBOUNDED : ALLOCA_OK);
+
   if (!last || gimple_code (last) != GIMPLE_COND)
-    return alloca_type_and_limit (ALLOCA_UNBOUNDED);
+    {
+      return alloca_type_and_limit (unbounded_result);
+    }
 
   enum tree_code cond_code = gimple_cond_code (last);
   if (e->flags & EDGE_TRUE_VALUE)
@@ -164,7 +179,7 @@ alloca_call_type_by_arg (tree arg, tree arg_casted, edge e, unsigned max_size)
   else if (e->flags & EDGE_FALSE_VALUE)
     cond_code = invert_tree_comparison (cond_code, false);
   else
-    return alloca_type_and_limit (ALLOCA_UNBOUNDED);
+      return alloca_type_and_limit (unbounded_result);
 
   // Check for:
   //   if (ARG .COND. N)
@@ -229,10 +244,10 @@ alloca_call_type_by_arg (tree arg, tree arg_casted, edge e, unsigned max_size)
       //
       // If this ever triggers, we should probably figure out why and
       // handle it, though it is likely to be just an ALLOCA_UNBOUNDED.
-      return alloca_type_and_limit (ALLOCA_UNBOUNDED);
+      return alloca_type_and_limit (unbounded_result);
     }
 
-  return alloca_type_and_limit (ALLOCA_UNBOUNDED);
+  return alloca_type_and_limit (unbounded_result);
 }
 
 // Return TRUE if SSA's definition is a cast from a signed type.
@@ -281,16 +296,16 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
   edge_iterator ei;
   edge e;
 
-  gcc_assert (!is_vla || (unsigned HOST_WIDE_INT) warn_vla_limit > 0);
-  gcc_assert (is_vla || (unsigned HOST_WIDE_INT) warn_alloca_limit > 0);
+  gcc_assert (!is_vla || warn_vla_limit >= 0);
+  gcc_assert (is_vla || warn_alloca_limit >= 0);
 
   // Adjust warn_alloca_max_size for VLAs, by taking the underlying
   // type into account.
   unsigned HOST_WIDE_INT max_size;
   if (is_vla)
-    max_size = (unsigned HOST_WIDE_INT) warn_vla_limit;
+    max_size = warn_vla_limit;
   else
-    max_size = (unsigned HOST_WIDE_INT) warn_alloca_limit;
+    max_size = warn_alloca_limit;
 
   // Check for the obviously bounded case.
   if (TREE_CODE (len) == INTEGER_CST)
@@ -299,7 +314,13 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
 	return alloca_type_and_limit (ALLOCA_BOUND_DEFINITELY_LARGE,
 				      wi::to_wide (len));
       if (integer_zerop (len))
-	return alloca_type_and_limit (ALLOCA_ARG_IS_ZERO);
+	{
+	  const offset_int maxobjsize
+	    = wi::to_offset (max_object_size ());
+	  alloca_type result = (max_size < maxobjsize
+				? ALLOCA_ARG_IS_ZERO : ALLOCA_OK);
+	  return alloca_type_and_limit (result);
+	}
 
       return alloca_type_and_limit (ALLOCA_OK);
     }
@@ -357,8 +378,15 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
 		}
 	      else if (range_type == VR_ANTI_RANGE)
 		return alloca_type_and_limit (ALLOCA_UNBOUNDED);
-	      else if (range_type != VR_VARYING)
-		return alloca_type_and_limit (ALLOCA_BOUND_MAYBE_LARGE, max);
+
+	      if (range_type != VR_VARYING)
+		{
+		  const offset_int maxobjsize
+		    = wi::to_offset (max_object_size ());
+		  alloca_type result = (max_size < maxobjsize
+					? ALLOCA_BOUND_MAYBE_LARGE : ALLOCA_OK);
+		  return alloca_type_and_limit (result, max);
+		}
 	    }
 	}
       else if (range_type == VR_ANTI_RANGE)
@@ -414,8 +442,13 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type)
       if (compare_tree_int (arg, max_size) <= 0)
 	ret = alloca_type_and_limit (ALLOCA_OK);
       else
-	ret = alloca_type_and_limit (ALLOCA_BOUND_MAYBE_LARGE,
-				     wi::to_wide (arg));
+	{
+	  const offset_int maxobjsize
+	    = wi::to_offset (max_object_size ());
+	  alloca_type result = (max_size < maxobjsize
+				? ALLOCA_BOUND_MAYBE_LARGE : ALLOCA_OK);
+	  ret = alloca_type_and_limit (result, wi::to_wide (arg));
+	}
     }
 
   return ret;
@@ -452,16 +485,18 @@ pass_walloca::execute (function *fun)
 	  // Strict mode whining for VLAs is handled by the front-end,
 	  // so we can safely ignore this case.  Also, ignore VLAs if
 	  // the user doesn't care about them.
-	  if (is_vla
-	      && (warn_vla > 0 || !warn_vla_limit))
-	    continue;
-
-	  if (!is_vla && (warn_alloca || !warn_alloca_limit))
+	  if (is_vla)
 	    {
-	      if (warn_alloca)
-		warning_at (loc, OPT_Walloca, G_("use of %<alloca%>"));
+	      if (warn_vla > 0 || warn_vla_limit < 0)
+		continue;
+	    }
+	  else if (warn_alloca)
+	    {
+	      warning_at (loc, OPT_Walloca, G_("use of %<alloca%>"));
 	      continue;
 	    }
+	  else if (warn_alloca_limit < 0)
+	    continue;
 
 	  tree invalid_casted_type = NULL;
 	  struct alloca_type_and_limit t
@@ -471,7 +506,15 @@ pass_walloca::execute (function *fun)
 	  // loop, except for a VLA, since VLAs are guaranteed to be cleaned
 	  // up when they go out of scope, including in a loop.
 	  if (t.type == ALLOCA_OK && !is_vla && in_loop_p (stmt))
-	    t = alloca_type_and_limit (ALLOCA_IN_LOOP);
+	    {
+	      /* As in other instances, only diagnose this when the limit
+		 is less than the maximum valid object size.  */
+	      const offset_int maxobjsize
+		= wi::to_offset (max_object_size ());
+	      if ((unsigned HOST_WIDE_INT) warn_alloca_limit
+		  < maxobjsize.to_uhwi ())
+		t = alloca_type_and_limit (ALLOCA_IN_LOOP);
+	    }
 
 	  enum opt_code wcode
 	    = is_vla ? OPT_Wvla_larger_than_ : OPT_Walloca_larger_than_;
@@ -488,7 +531,7 @@ pass_walloca::execute (function *fun)
 		  && t.limit != 0)
 		{
 		  print_decu (t.limit, buff);
-		  inform (loc, G_("limit is %u bytes, but argument "
+		  inform (loc, G_("limit is %wu bytes, but argument "
 				  "may be as large as %s"),
 			  is_vla ? warn_vla_limit : warn_alloca_limit, buff);
 		}
@@ -501,7 +544,7 @@ pass_walloca::execute (function *fun)
 		  && t.limit != 0)
 		{
 		  print_decu (t.limit, buff);
-		  inform (loc, G_("limit is %u bytes, but argument is %s"),
+		  inform (loc, G_("limit is %wu bytes, but argument is %s"),
 			  is_vla ? warn_vla_limit : warn_alloca_limit, buff);
 		}
 	      break;
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 45dee88..e76e1fc 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -194,7 +194,7 @@ static bool
 go_langhook_handle_option (
     size_t scode,
     const char *arg,
-    int value,
+    HOST_WIDE_INT value,
     int kind ATTRIBUTE_UNUSED,
     location_t loc ATTRIBUTE_UNUSED,
     const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index fd20dfd..27b8273 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -70,8 +70,8 @@ extern void lhd_initialize_diagnostics (diagnostic_context *);
 extern void lhd_init_options (unsigned int,
 			      struct cl_decoded_option *);
 extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
-extern bool lhd_handle_option (size_t, const char *, int, int, location_t,
-			       const struct cl_option_handlers *);
+extern bool lhd_handle_option (size_t, const char *, HOST_WIDE_INT, int,
+			       location_t, const struct cl_option_handlers *);
 
 
 /* Declarations for tree gimplification hooks.  */
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 3cd7901..c7b5cf9 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -353,7 +353,8 @@ lhd_complain_wrong_lang_p (const struct cl_option *option ATTRIBUTE_UNUSED)
 bool
 lhd_handle_option (size_t code ATTRIBUTE_UNUSED,
 		   const char *arg ATTRIBUTE_UNUSED,
-		   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+		   HOST_WIDE_INT value ATTRIBUTE_UNUSED,
+		   int kind ATTRIBUTE_UNUSED,
 		   location_t loc ATTRIBUTE_UNUSED,
 		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 94bb39f..8ad2ec7 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -348,8 +348,8 @@ struct lang_hooks
      location of the option.
 
      Return true if the switch is valid, false if invalid.  */
-  bool (*handle_option) (size_t code, const char *arg, int value, int kind,
-			 location_t loc,
+  bool (*handle_option) (size_t code, const char *arg, HOST_WIDE_INT value,
+			 int kind, location_t loc,
 			 const struct cl_option_handlers *handlers);
 
   /* Called when all command line options have been parsed to allow
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index a1a41bc..de6ec1c 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -827,7 +827,8 @@ lto_init_options_struct (struct gcc_options *opts)
 const char *resolution_file_name;
 static bool
 lto_handle_option (size_t scode, const char *arg,
-		   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+		   HOST_WIDE_INT value ATTRIBUTE_UNUSED,
+		   int kind ATTRIBUTE_UNUSED,
 		   location_t loc ATTRIBUTE_UNUSED,
 		   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index 2c371e5..6611bf3 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -113,9 +113,14 @@ function switch_flags (flags)
 # Return bit-field initializers for option flags FLAGS.
 function switch_bit_fields (flags)
 {
+	uinteger_flag = ""
 	vn = var_name(flags);
 	if (host_wide_int[vn] == "yes")
 		hwi = "Host_Wide_Int"
+	else if (flag_set_p("Host_Wide_Int", flags)) {
+		hwi = "Host_Wide_Int"
+		uinteger_flag = flag_init("UInteger", flags)
+	}
 	else
 		hwi = ""
 	result = ""
@@ -126,6 +131,20 @@ function switch_bit_fields (flags)
 		sep_args--
 	result = result sep_args ", "
 
+	if (uinteger_flag == "")
+		uinteger_flag = flag_init("UInteger", flags)
+
+	hwi_flag = flag_init("Host_Wide_Int", hwi)
+	byte_size_flag = flag_init("ByteSize", flags)
+
+	if (substr(byte_size_flag, 1, 1) != "0"	\
+	    && substr(uinteger_flag, 1, 1) == "0" \
+	    && substr(hwi_flag, 1, 1) == "0")
+	  print "#error only UInteger amd Host_Wide_Int options can specify a ByteSize suffix"
+
+	# The following flags need to be in the same order as
+	# the corresponding members of struct cl_option defined
+	# in gcc/opts.h.
 	result = result \
 	  flag_init("SeparateAlias", flags) \
 	  flag_init("NegativeAlias", flags) \
@@ -133,11 +152,12 @@ function switch_bit_fields (flags)
 	  flag_init("RejectDriver", flags) \
 	  flag_init("RejectNegative", flags) \
 	  flag_init("JoinedOrMissing", flags) \
-	  flag_init("UInteger", flags) \
-	  flag_init("Host_Wide_Int", hwi) \
+	  uinteger_flag \
+	  hwi_flag \
 	  flag_init("ToLower", flags) \
 	  flag_init("Report", flags) \
-	  flag_init("Deprecated", flags)
+	  flag_init("Deprecated", flags) \
+	  byte_size_flag
 
 	sub(", $", "", result)
 	return result
@@ -200,6 +220,8 @@ function var_type(flags)
 	}
 	else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
 		return "int "
+	else if (flag_set_p("Host_Wide_Int", flags))
+		return "HOST_WIDE_INT "
 	else if (flag_set_p("UInteger", flags))
 		return "int "
 	else
@@ -211,8 +233,13 @@ function var_type(flags)
 # type instead of int to save space.
 function var_type_struct(flags)
 {
-	if (flag_set_p("UInteger", flags))
-		return "int "
+	if (flag_set_p("UInteger", flags)) {
+		if (host_wide_int[var_name(flags)] == "yes")
+			return "HOST_WIDE_INT ";
+		if (flag_set_p("ByteSize", flags))
+			return "HOST_WIDE_INT "
+	  return "int "
+	}
 	else if (flag_set_p("Enum.*", flags)) {
 		en = opt_args("Enum", flags);
 		return enum_type[en] " "
@@ -222,7 +249,7 @@ function var_type_struct(flags)
 			if (host_wide_int[var_name(flags)] == "yes")
 				return "HOST_WIDE_INT "
 			else
-				return "int "
+				return "/* - */ int "
 		}
 		else
 			return "signed char "
@@ -262,6 +289,8 @@ function var_set(flags)
 	}
 	if (var_type(flags) == "const char *")
 		return "0, CLVC_STRING, 0"
+	if (flag_set_p("ByteSize", flags))
+		return "0, CLVC_SIZE, 0"
 	return "0, CLVC_BOOLEAN, 0"
 }
 
diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk
index bf177e8..7eaca62 100644
--- a/gcc/optc-gen.awk
+++ b/gcc/optc-gen.awk
@@ -274,6 +274,7 @@ for (i = 0; i < n_opts; i++) {
 	j++;
 }
 
+optindex = 0
 for (i = 0; i < n_opts; i++) {
 	# With identical flags, pick only the last one.  The
 	# earlier loop ensured that it has all flags merged,
@@ -303,20 +304,20 @@ for (i = 0; i < n_opts; i++) {
 		comma = ""
 
 	if (help[i] == "")
-		hlp = "0"
+		hlp = "NULL"
 	else
 		hlp = quote help[i] quote;
 
 	missing_arg_error = opt_args("MissingArgError", flags[i])
 	if (missing_arg_error == "")
-		missing_arg_error = "0"
+		missing_arg_error = "NULL"
 	else
 		missing_arg_error = quote missing_arg_error quote
 
 
 	warn_message = opt_args("Warn", flags[i])
 	if (warn_message == "")
-		warn_message = "0"
+		warn_message = "NULL"
 	else
 		warn_message = quote warn_message quote
 
@@ -378,10 +379,11 @@ for (i = 0; i < n_opts; i++) {
 	}
 	# Split the printf after %u to work around an ia64-hp-hpux11.23
 	# awk bug.
-	printf("  { %c-%s%c,\n    %s,\n    %s,\n    %s,\n    %s, %s, %u,",
+	printf(" /* [%i] = */ {\n", optindex)
+	printf("    %c-%s%c,\n    %s,\n    %s,\n    %s,\n    %s, %s, %u,",
 	       quote, opts[i], quote, hlp, missing_arg_error, warn_message,
 	       alias_data, back_chain[i], len)
-	printf(" %d,\n", idx)
+	printf(" /* .neg_idx = */ %d,\n", idx)
 	condition = opt_args("Condition", flags[i])
 	cl_flags = switch_flags(flags[i])
 	cl_bit_fields = switch_bit_fields(flags[i])
@@ -402,7 +404,10 @@ for (i = 0; i < n_opts; i++) {
 	printf("    %s, %s, %s }%s\n", var_ref(opts[i], flags[i]),
 	       var_set(flags[i]), integer_range_info(opt_args("IntegerRange", flags[i]),
 		    opt_args("Init", flags[i]), opts[i]), comma)
-}
+
+	# Bump up the informational option index.
+	++optindex
+ }
 
 print "};"
 
@@ -417,7 +422,7 @@ print "                           const struct cl_option_handlers *handlers, "
 print "                           diagnostic_context *dc)                    "
 print "{                                                                     "
 print "  size_t scode = decoded->opt_index;                                  "
-print "  int value = decoded->value;                                         "
+print "  HOST_WIDE_INT value = decoded->value;                               "
 print "  enum opt_code code = (enum opt_code) scode;                         "
 print "                                                                      "
 print "  gcc_assert (decoded->canonical_option_num_elements <= 2);           "
@@ -467,7 +472,7 @@ for (i = 0; i < n_langs; i++) {
     print "bool                                                                  "
     print lang_name "_handle_option_auto (struct gcc_options *opts" mark_unused ",              "
     print "                           struct gcc_options *opts_set" mark_unused ",              "
-    print "                           size_t scode" mark_unused ", const char *arg" mark_unused ", int value" mark_unused ",  "
+    print "                           size_t scode" mark_unused ", const char *arg" mark_unused ", HOST_WIDE_INT value" mark_unused ",  "
     print "                           unsigned int lang_mask" mark_unused ", int kind" mark_unused ",          "
     print "                           location_t loc" mark_unused ",                            "
     print "                           const struct cl_option_handlers *handlers" mark_unused ", "
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index 1a365fc..c4fd454 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -445,13 +445,14 @@ print "{";
 print "  fputs (\"\\n\", file);";
 for (i = 0; i < n_target_other; i++) {
 	print "  if (ptr->x_" var_target_other[i] ")";
-	if (host_wide_int[var_target_other[i]] == "yes")
+	hwi = host_wide_int[var_target_other[i]]
+	if (hwi == "yes")
 		print "    fprintf (file, \"%*s%s (%#\" HOST_WIDE_INT_PRINT \"x)\\n\",";
 	else
-		print "    fprintf (file, \"%*s%s (%#x)\\n\",";
+		print "    fprintf (file, \"%*s%s (%#lx)\\n\",";
 	print "             indent, \"\",";
 	print "             \"" var_target_other[i] "\",";
-	if (host_wide_int[var_target_other[i]] == "yes")
+	if (hwi == "yes")
 		print "             ptr->x_" var_target_other[i] ");";
 	else
 		print "             (unsigned long)ptr->x_" var_target_other[i] ");";
@@ -511,13 +512,14 @@ print "{";
 print "  fputs (\"\\n\", file);";
 for (i = 0; i < n_target_other; i++) {
 	print "  if (ptr1->x_" var_target_other[i] " != ptr2->x_" var_target_other[i] ")";
-	if (host_wide_int[var_target_other[i]] == "yes")
+	hwi = host_wide_int[var_target_other[i]]
+	if (hwi == "yes")
 		print "    fprintf (file, \"%*s%s (%#\" HOST_WIDE_INT_PRINT \"x/%#\" HOST_WIDE_INT_PRINT \"x)\\n\",";
 	else
-		print "    fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+		print "    fprintf (file, \"%*s%s (%#lx/%#lx)\\n\",";
 	print "             indent, \"\",";
 	print "             \"" var_target_other[i] "\",";
-	if (host_wide_int[var_target_other[i]] == "yes") {
+	if (hwi == "yes") {
 		print "             ptr1->x_" var_target_other[i] ",";
 		print "             ptr2->x_" var_target_other[i] ");";
 	}
diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
index fecd4b8..4e0c0ea 100644
--- a/gcc/opth-gen.awk
+++ b/gcc/opth-gen.awk
@@ -320,14 +320,15 @@ print "                           const struct cl_option_handlers *handlers, "
 print "                           diagnostic_context *dc);                   "
 for (i = 0; i < n_langs; i++) {
     lang_name = lang_sanitized_name(langs[i]);
-    print "bool                                                                  "
-    print lang_name "_handle_option_auto (struct gcc_options *opts,              "
-    print "                           struct gcc_options *opts_set,              "
-    print "                           size_t scode, const char *arg, int value,  "
-    print "                           unsigned int lang_mask, int kind,          "
-    print "                           location_t loc,                            "
-    print "                           const struct cl_option_handlers *handlers, "
-    print "                           diagnostic_context *dc);                   "
+    print "bool"
+    print lang_name "_handle_option_auto (struct gcc_options *opts,"
+    print "                           struct gcc_options *opts_set,"
+    print "                           size_t scode, const char *arg,"
+    print "                           HOST_WIDE_INT value,"
+    print "                           unsigned int lang_mask, int kind,"
+    print "                           location_t loc,"
+    print "                           const struct cl_option_handlers *handlers,"
+    print "                           diagnostic_context *dc);"
 }
 print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
 print "                             struct cpp_options * cpp_opts);"
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 004da73..eef461f 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 = integral_argument (arg, &error, option->cl_byte_size);
+      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;
@@ -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;
@@ -1520,8 +1647,9 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg,
 	  /* If the switch takes an integer, convert it.  */
 	  if (arg && option->cl_uinteger)
 	    {
-	      value = integral_argument (arg);
-	      if (value == -1)
+	      int error = 0;
+	      value = integral_argument (arg, &error, option->cl_byte_size);
+	      if (error)
 		{
 		  cmdline_handle_error (loc, option, option->opt_text, arg,
 					CL_ERR_UINT_ARG, lang_mask);
diff --git a/gcc/opts.c b/gcc/opts.c
index 33efcc0..5310a01 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1796,7 +1796,7 @@ common_handle_option (struct gcc_options *opts,
 {
   size_t scode = decoded->opt_index;
   const char *arg = decoded->arg;
-  int value = decoded->value;
+  HOST_WIDE_INT value = decoded->value;
   enum opt_code code = (enum opt_code) scode;
 
   gcc_assert (decoded->canonical_option_num_elements <= 2);
@@ -2056,22 +2056,11 @@ common_handle_option (struct gcc_options *opts,
 			       opts, opts_set, loc, dc);
       break;
 
-    case OPT_Wlarger_than_:
-      opts->x_larger_than_size = value;
-      opts->x_warn_larger_than = value != -1;
-      break;
-
     case OPT_Wfatal_errors:
       dc->fatal_errors = value;
       break;
 
-    case OPT_Wframe_larger_than_:
-      opts->x_frame_larger_than_size = value;
-      opts->x_warn_frame_larger_than = value != -1;
-      break;
-
     case OPT_Wstack_usage_:
-      opts->x_warn_stack_usage = value;
       opts->x_flag_stack_usage_info = value != -1;
       break;
 
@@ -2231,7 +2220,7 @@ common_handle_option (struct gcc_options *opts,
     case OPT_fpack_struct_:
       if (value <= 0 || (value & (value - 1)) || value > 16)
 	error_at (loc,
-		  "structure alignment must be a small power of two, not %d",
+		  "structure alignment must be a small power of two, not %wu",
 		  value);
       else
 	opts->x_initial_max_fld_align = value;
@@ -2414,7 +2403,7 @@ common_handle_option (struct gcc_options *opts,
       /* FALLTHRU */
     case OPT_gdwarf_:
       if (value < 2 || value > 5)
-	error_at (loc, "dwarf version %d is not supported", value);
+	error_at (loc, "dwarf version %wu is not supported", value);
       else
 	opts->x_dwarf_version = value;
       set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc);
diff --git a/gcc/opts.h b/gcc/opts.h
index 3c4065ea..fb169b4 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -36,6 +36,9 @@ enum cl_var_type {
   /* The switch is enabled when VAR_VALUE is set in FLAG_VAR.  */
   CLVC_BIT_SET,
 
+  /* The switch is enabled when FLAG_VAR is less than HOST_WIDE_INT_M1U.  */
+  CLVC_SIZE,
+
   /* The switch takes a string argument and FLAG_VAR points to that
      argument.  */
   CLVC_STRING,
@@ -70,7 +73,10 @@ struct cl_option
   unsigned short back_chain;
   /* Option length, not including initial '-'.  */
   unsigned char opt_len;
-  /* Next option in a sequence marked with Negative, or -1 if none.  */
+  /* Next option in a sequence marked with Negative, or -1 if none.
+     For a single option with both a negative and a positve form
+     (such as -Wall and -Wno-all), NEG_IDX is equal to the option's
+     own index (i.e., cl_options[IDX].neg_idx == IDX holds).  */
   int neg_index;
   /* CL_* flags for this option.  */
   unsigned int flags;
@@ -102,6 +108,8 @@ struct cl_option
   BOOL_BITFIELD cl_report : 1;
   /* Deprecated option  */
   BOOL_BITFIELD cl_deprecated: 1;
+  /* Argument is an unsigned integer with an optional byte suffix.  */
+  BOOL_BITFIELD cl_byte_size: 1;
   /* Offset of field for this option in struct gcc_options, or
      (unsigned short) -1 if none.  */
   unsigned short flag_var_offset;
@@ -247,7 +255,7 @@ struct cl_decoded_option
   /* For a boolean option, 1 for the true case and 0 for the "no-"
      case.  For an unsigned integer option, the value of the
      argument.  1 in all other cases.  */
-  int value;
+  HOST_WIDE_INT value;
 
   /* Any flags describing errors detected in this option.  */
   int errors;
@@ -327,7 +335,7 @@ extern char *opts_concat (const char *first, ...);
 extern struct obstack opts_obstack;
 
 size_t find_opt (const char *input, unsigned int lang_mask);
-extern int integral_argument (const char *arg);
+extern HOST_WIDE_INT integral_argument (const char *arg, int * = NULL, bool = false);
 extern bool enum_value_to_arg (const struct cl_enum_arg *enum_args,
 			       const char **argp, int value,
 			       unsigned int lang_mask);
@@ -359,8 +367,8 @@ extern bool get_option_state (struct gcc_options *, int,
 			      struct cl_option_state *);
 extern void set_option (struct gcc_options *opts,
 			struct gcc_options *opts_set,
-			int opt_index, int value, const char *arg, int kind,
-			location_t loc, diagnostic_context *dc);
+			int opt_index, HOST_WIDE_INT value, const char *arg,
+			int kind, location_t loc, diagnostic_context *dc);
 extern void *option_flag_var (int opt_index, struct gcc_options *opts);
 bool handle_generated_option (struct gcc_options *opts,
 			      struct gcc_options *opts_set,
@@ -368,7 +376,7 @@ bool handle_generated_option (struct gcc_options *opts,
 			      unsigned int lang_mask, int kind, location_t loc,
 			      const struct cl_option_handlers *handlers,
 			      bool generated_p, diagnostic_context *dc);
-void generate_option (size_t opt_index, const char *arg, int value,
+void generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
 		      unsigned int lang_mask,
 		      struct cl_decoded_option *decoded);
 void generate_option_input_file (const char *file,
@@ -425,7 +433,8 @@ extern void set_struct_debug_option (struct gcc_options *opts,
 				     location_t loc,
 				     const char *value);
 extern bool opt_enum_arg_to_value (size_t opt_index, const char *arg,
-				   int *value, unsigned int lang_mask);
+				   int *value,
+				   unsigned int lang_mask);
 
 extern const struct sanitizer_opts_s
 {
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index ad97001..cb377ca 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -756,22 +756,19 @@ layout_decl (tree decl, unsigned int known_align)
     DECL_SIZE_UNIT (decl) = variable_size (DECL_SIZE_UNIT (decl));
 
   /* If requested, warn about definitions of large data objects.  */
-  if (warn_larger_than
-      && (code == VAR_DECL || code == PARM_DECL)
+  if ((code == VAR_DECL || code == PARM_DECL)
       && ! DECL_EXTERNAL (decl))
     {
       tree size = DECL_SIZE_UNIT (decl);
 
       if (size != 0 && TREE_CODE (size) == INTEGER_CST
-	  && compare_tree_int (size, larger_than_size) > 0)
+	  && compare_tree_int (size, warn_larger_than_size) > 0)
 	{
-	  int size_as_int = TREE_INT_CST_LOW (size);
+	  unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size);
 
-	  if (compare_tree_int (size, size_as_int) == 0)
-	    warning (OPT_Wlarger_than_, "size of %q+D is %d bytes", decl, size_as_int);
-	  else
-	    warning (OPT_Wlarger_than_, "size of %q+D is larger than %wd bytes",
-                     decl, larger_than_size);
+	  warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds "
+		   "maximum object size %wu",
+		   decl, uhwisize, warn_larger_than_size);
 	}
     }
 
diff --git a/gcc/testsuite/gcc.dg/Walloc-size-larger-than-16.c b/gcc/testsuite/gcc.dg/Walloc-size-larger-than-16.c
index 837b69a..d035cbb 100644
--- a/gcc/testsuite/gcc.dg/Walloc-size-larger-than-16.c
+++ b/gcc/testsuite/gcc.dg/Walloc-size-larger-than-16.c
@@ -1,32 +1,9 @@
 /* PR middle-end/82063 - issues with arguments enabled by -Wall
+   Verify that an invalid argument to -Walloc-size-larger-than is diagnosed.
    { dg-do compile }
-   { dg-options "-O -Walloc-size-larger-than=1zb -ftrack-macro-expansion=0" } */
+   { dg-options "-Walloc-size-larger-than=1zb -Walloca-larger-than=2kbytes -Wvla-larger-than=3MIBZ" } */
 
-typedef __SIZE_TYPE__ size_t;
 
-void sink (void*);
-
-#define T(x) sink (x)
-
-/* Verify that an invalid -Walloc-size-larger-than argument is diagnosed
-   and rejected without changing the default setting of PTRDIFF_MAX.  */
-
-void f (void)
-{
-  size_t n = 0;
-  T (__builtin_malloc (n));
-
-  n = __PTRDIFF_MAX__;
-  T (__builtin_malloc (n));
-
-  n += 1;
-  T (__builtin_malloc (n));   /* { dg-warning "exceeds maximum object size" } */
-
-  n = __SIZE_MAX__ - 1;
-  T (__builtin_malloc (n));   /* { dg-warning "exceeds maximum object size" } */
-
-  n = __SIZE_MAX__;
-  T (__builtin_malloc (n));   /* { dg-warning "exceeds maximum object size" } */
-}
-
-/* { dg-warning "invalid argument .1zb. to .-Walloc-size-larger-than=." "" { target *-*-* } 0 } */
+/* { dg-error "argument to '-Walloc-size-larger-than=' should be a non-negative integer optionally followed by a size unit" "" { target *-*-* } 0 }
+   { dg-error "argument to '-Walloca-larger-than=' should be a non-negative integer optionally followed by a size unit" "" { target *-*-* } 0 }
+   { dg-error "argument to '-Wvla-larger-than=' should be a non-negative integer optionally followed by a size unit" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c b/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c
new file mode 100644
index 0000000..fe003bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c
@@ -0,0 +1,24 @@
+/* PR middle-end/82063 - issues with arguments enabled by -Wall
+   Verify that alloca() calls in loops are not diagnosed by default.
+   { dg-do compile }
+   { dg-options "-O2 -ftrack-macro-expansion=0" } */
+
+extern void* alloca (__SIZE_TYPE__);
+
+void sink (void*);
+
+#define T(x) sink (x)
+
+void test_alloca (unsigned n)
+{
+  /* Verify that alloca(0) is not diagnosed in a loop either.  */
+  for (unsigned i = 0; i < n; ++i)
+    T (alloca (0));
+
+  /* Verify no warnings for the loops below.  */
+  for (unsigned i = 0; i < n; ++i)
+    T (alloca (1));
+
+  for (unsigned i = 1; i < n; ++i)
+    T (alloca (n));
+}
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than.c b/gcc/testsuite/gcc.dg/Walloca-larger-than.c
new file mode 100644
index 0000000..284601d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than.c
@@ -0,0 +1,26 @@
+/* PR middle-end/82063 - issues with arguments enabled by -Wall
+   { dg-do compile }
+   { dg-options "-O2 -Walloca-larger-than=0 -Wvla-larger-than=0 -ftrack-macro-expansion=0" } */
+
+extern void* alloca (__SIZE_TYPE__);
+
+void sink (void*);
+
+#define T(x) sink (x)
+
+void test_alloca (void)
+{
+  /* Verify that alloca(0) is diagnosed even if the limit is zero.  */
+  T (alloca (0));   /* { dg-warning "argument to .alloca. is zero" } */
+  T (alloca (1));   /* { dg-warning "argument to .alloca. is too large" } */
+}
+
+void test_vla (unsigned n)
+{
+  /* VLAs smaller than 32 bytes are optimized into ordinary arrays.  */
+  if (n < 1 || 99 < n)
+    n = 1;
+
+  char a[n];        /* { dg-warning "argument to variable-length array " } */
+  T (a);
+}
diff --git a/gcc/testsuite/gcc.dg/Wframe-larger-than-2.c b/gcc/testsuite/gcc.dg/Wframe-larger-than-2.c
new file mode 100644
index 0000000..1a5402f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wframe-larger-than-2.c
@@ -0,0 +1,19 @@
+/* Exercise -Wframe-larger-than= with a byte-size suffix.
+   { dg-do compile }
+   { dg-options "-O -Wframe-larger-than=1KB" } */
+
+extern void f (void*, ...);
+
+void frame_size_912 (void)
+{
+  char a[512];
+  char b[400];
+  f (a, b);
+}
+
+void frame_size_1025 (void)
+{
+  char a[512];
+  char b[513];
+  f (a, b);
+} /* { dg-warning "frame size of \[0-9\]+ bytes is larger than 1024 bytes" } */
diff --git a/gcc/testsuite/gcc.dg/Wlarger-than3.c b/gcc/testsuite/gcc.dg/Wlarger-than3.c
new file mode 100644
index 0000000..b9eaa56
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wlarger-than3.c
@@ -0,0 +1,12 @@
+/* Exercise -Wlarger-than= with a byte-size suffix.
+   { dg-do compile }
+   { dg-options "-Wlarger-than=1MiB" } */
+
+#define MB (1000 * 1000)    /* MegaByte */
+#define MiB (1024 * 1024)   /* MebiByte */
+
+char megabyte[MB];
+char membibyte[MiB];
+
+char megabyte_plus_1[MB + 1];
+char membibyte_plus_1[MiB + 1];   /* { dg-warning "size of .membibyte_plus_1. 1048577 bytes exceeds maximum object size 1048576" } */
diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-3.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-3.c
new file mode 100644
index 0000000..70011f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-3.c
@@ -0,0 +1,68 @@
+/* Verify that VLA definitions with an unknown upper bound don't trigger
+   -Wvla-larger-than= warnings by default.
+   { dg-do compile }
+   { dg-require-effective-target alloca }
+   { dg-options "-O2 -Wall" } */
+
+void f (void *, ...);
+
+void nowarn_vla_int (int n)
+{
+  char a[n];
+
+  if (n < 1234)
+    n = 1234;
+
+  char b[n];
+  f (a, b);
+}
+
+void nowarn_vla_uint (unsigned n)
+{
+  char a[n];
+  f (a);
+
+  if (n < 2345)
+    n = 2345;
+
+  char b[n];
+  f (a, b);
+}
+
+void nowarn_vla_long (long n)
+{
+  char a[n];
+
+  if (n < 1234)
+    n = 1234;
+
+  char b[n];
+  f (a, b);
+}
+
+void nowarn_vla_ulong (unsigned long n)
+{
+  char a[n];
+  f (a);
+
+  if (n < 2345)
+    n = 2345;
+
+  char b[n];
+  f (a, b);
+}
+
+/* Verify that a VLA whose size is definitely in excess of PTRDIFF_MAX
+   is diagnosed by default.  */
+
+void warn_vla (__PTRDIFF_TYPE__ n)
+{
+  int a[n];
+  f (a);
+
+  if (n <= __PTRDIFF_MAX__)
+    n = __PTRDIFF_MAX__;
+
+  int b[n];   /* { dg-warning "argument to variable-length array is too large" } */
+  f (a, b);
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index d108096..5ad7fe7 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1021,7 +1021,7 @@ output_stack_usage (void)
 	       stack_usage_kind_str[stack_usage_kind]);
     }
 
-  if (warn_stack_usage >= 0)
+  if (warn_stack_usage >= 0 && warn_stack_usage < HOST_WIDE_INT_MAX)
     {
       const location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
 
@@ -1031,10 +1031,10 @@ output_stack_usage (void)
 	{
 	  if (stack_usage_kind == DYNAMIC_BOUNDED)
 	    warning_at (loc,
-			OPT_Wstack_usage_, "stack usage might be %wd bytes",
+			OPT_Wstack_usage_, "stack usage might be %wu bytes",
 			stack_usage);
 	  else
-	    warning_at (loc, OPT_Wstack_usage_, "stack usage is %wd bytes",
+	    warning_at (loc, OPT_Wstack_usage_, "stack usage is %wu bytes",
 			stack_usage);
 	}
     }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]