The very large option argument enhancement committed last week
inadvertently introduced an assumption about the LP64 data model
that makes the -Wxxx-larger-than options have a different effect
at their default documented setting of PTRDIFF_MAX between ILP32
and LP64.  As a result, the options are treated as suppressed in
ILP32 while triggering the expected warnings for allocations or
sizes in excess of the limit in ILP64.

To remove this I considered making it possible to use symbolic
constants like PTRDIFF_MAX as the option arguments so that
then defaults in the .opt files could be set to that.  Sadly,
options in GCC are processed before the values of constants
like PTRDIFF_MAX for the target are known, and deferring
the handling of just the -Wxxx-larger-than= options until
the constants have been computed would be too involved to
make it worth the effort.

To keep things simple I decided to have the code that handles
each of the affected options treat the HOST_WIDE_INT_MAX default
as a special request to substitute the value of PTRDIFF_MAX at
the time.

The attached patch implements this.

Tested on x86_64-linux with -m32/-m64.

Martin
PR middle-end/86631 - missing -Walloc-size-larger-than on ILP32 hosts

gcc/ChangeLog:

	PR middle-end/86631
	* calls.c (alloc_max_size): Treat HOST_WIDE_INT special.
	* gimple-ssa-warn-alloca.c (adjusted_warn_limit): New function.
	(pass_walloca::gate): Use it.
	(alloca_call_type): Same.
	(pass_walloca::execute): Same.
	* stor-layout.c (layout_decl): Treat HOST_WIDE_INT special.

gcc/testsuite/ChangeLog:

	PR middle-end/86631
	* g++.dg/Walloca1.C: Adjust.

Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(revision 262951)
+++ gcc/calls.c	(working copy)
@@ -1222,9 +1222,12 @@ alloc_max_size (void)
   if (alloc_object_size_limit)
     return alloc_object_size_limit;
 
-  alloc_object_size_limit
-    = build_int_cst (size_type_node, warn_alloc_size_limit);
+  HOST_WIDE_INT limit = warn_alloc_size_limit;
+  if (limit == HOST_WIDE_INT_MAX)
+    limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
 
+  alloc_object_size_limit = build_int_cst (size_type_node, limit);
+
   return alloc_object_size_limit;
 }
 
Index: gcc/gimple-ssa-warn-alloca.c
===================================================================
--- gcc/gimple-ssa-warn-alloca.c	(revision 262951)
+++ gcc/gimple-ssa-warn-alloca.c	(working copy)
@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "intl.h"
 
+static unsigned HOST_WIDE_INT adjusted_warn_limit (bool);
+
 const pass_data pass_data_walloca = {
   GIMPLE_PASS,
   "walloca",
@@ -82,7 +84,9 @@ pass_walloca::gate (function *fun ATTRIBUTE_UNUSED
   // 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;
+  unsigned HOST_WIDE_INT max = tree_to_uhwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+  return (adjusted_warn_limit (false) <= max
+	  || adjusted_warn_limit (true) <= max);
 }
 
 // Possible problematic uses of alloca.
@@ -127,6 +131,30 @@ struct alloca_type_and_limit {
   alloca_type_and_limit (enum alloca_type type) : type(type) { }
 };
 
+/* Return the value of the argument N to -Walloca-larger-than= or
+   -Wvla-larger-than= adjusted for the target data model so that
+   when N == HOST_WIDE_INT_MAX, the adjusted value is set to
+   PTRDIFF_MAX on the target.  This is done to prevent warnings
+   for unknown/unbounded allocations in the "permissive mode"
+   while still diagnosing excessive and necessarily invalid
+   allocations.  */
+
+static unsigned HOST_WIDE_INT
+adjusted_warn_limit (bool idx)
+{
+  static HOST_WIDE_INT limits[2];
+  if (limits[idx])
+    return limits[idx];
+
+  limits[idx] = idx ? warn_vla_limit : warn_alloca_limit;
+  if (limits[idx] != HOST_WIDE_INT_MAX)
+    return limits[idx];
+
+  limits[idx] = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+  return limits[idx];
+}
+
+
 // NOTE: When we get better range info, this entire function becomes
 // irrelevant, as it should be possible to get range info for an SSA
 // name at any point in the program.
@@ -309,11 +337,7 @@ alloca_call_type (gimple *stmt, bool is_vla, tree
 
   // 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 = warn_vla_limit;
-  else
-    max_size = warn_alloca_limit;
+  unsigned HOST_WIDE_INT max_size = adjusted_warn_limit (is_vla);
 
   // Check for the obviously bounded case.
   if (TREE_CODE (len) == INTEGER_CST)
@@ -510,6 +534,8 @@ pass_walloca::execute (function *fun)
 	  struct alloca_type_and_limit t
 	    = alloca_call_type (stmt, is_vla, &invalid_casted_type);
 
+	  unsigned HOST_WIDE_INT adjusted_alloca_limit
+	    = adjusted_warn_limit (false);
 	  // Even if we think the alloca call is OK, make sure it's not in a
 	  // loop, except for a VLA, since VLAs are guaranteed to be cleaned
 	  // up when they go out of scope, including in a loop.
@@ -519,8 +545,7 @@ pass_walloca::execute (function *fun)
 		 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 ())
+	      if (adjusted_alloca_limit < maxobjsize.to_uhwi ())
 		t = alloca_type_and_limit (ALLOCA_IN_LOOP);
 	    }
 
@@ -541,7 +566,7 @@ pass_walloca::execute (function *fun)
 		  print_decu (t.limit, buff);
 		  inform (loc, G_("limit is %wu bytes, but argument "
 				  "may be as large as %s"),
-			  is_vla ? warn_vla_limit : warn_alloca_limit, buff);
+			  is_vla ? warn_vla_limit : adjusted_alloca_limit, buff);
 		}
 	      break;
 	    case ALLOCA_BOUND_DEFINITELY_LARGE:
@@ -553,7 +578,7 @@ pass_walloca::execute (function *fun)
 		{
 		  print_decu (t.limit, buff);
 		  inform (loc, G_("limit is %wu bytes, but argument is %s"),
-			  is_vla ? warn_vla_limit : warn_alloca_limit, buff);
+			  is_vla ? warn_vla_limit : adjusted_alloca_limit, buff);
 		}
 	      break;
 	    case ALLOCA_BOUND_UNKNOWN:
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 262951)
+++ gcc/stor-layout.c	(working copy)
@@ -761,14 +761,19 @@ layout_decl (tree decl, unsigned int known_align)
     {
       tree size = DECL_SIZE_UNIT (decl);
 
-      if (size != 0 && TREE_CODE (size) == INTEGER_CST
-	  && compare_tree_int (size, warn_larger_than_size) > 0)
+      if (size != 0 && TREE_CODE (size) == INTEGER_CST)
 	{
-	  unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size);
+	  /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated
+	     as if PTRDIFF_MAX had been specified, with the value
+	     being that on the target rather than the host.  */
+	  unsigned HOST_WIDE_INT max_size = warn_larger_than_size;
+	  if (max_size == HOST_WIDE_INT_MAX)
+	    max_size = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
 
-	  warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds "
-		   "maximum object size %wu",
-		   decl, uhwisize, warn_larger_than_size);
+	  if (compare_tree_int (size, max_size) > 0)
+	    warning (OPT_Wlarger_than_, "size of %q+D %E bytes exceeds "
+		     "maximum object size %wu",
+		     decl, size, max_size);
 	}
     }
 
Index: gcc/testsuite/g++.dg/Walloca1.C
===================================================================
--- gcc/testsuite/g++.dg/Walloca1.C	(revision 262951)
+++ gcc/testsuite/g++.dg/Walloca1.C	(working copy)
@@ -1,7 +1,9 @@
-/* PR middle-end/79809 */
+/* PR middle-end/79809 - ICE in alloca_call_type, at gimple-ssa-warn-alloca.c */
 /* { dg-do compile } */
 /* { dg-options "-Walloca-larger-than=4207115063 -Wvla-larger-than=1233877270 -O2" } */
 /* { dg-require-effective-target alloca } */
 
 int a;
-char *b = static_cast<char *>(__builtin_alloca (a)); // { dg-warning "argument to .alloca. may be too large|unbounded use of" }
+char *b = static_cast<char *>(__builtin_alloca (a));
+
+// { dg-prune-output "argument to .alloca." }

Reply via email to