After the sorry we'd skip storing the argument, but that just creates an
inconsistency later when we try to deallocate the arguments.  This used to
"work" because pending_stack_adjust and stack_pointer_delta were int rather
than HWI, so 1<<33 got truncated to 0.

It's not easy to back out at this point because there's so much global
state floating around.  One option I tried was to put the sorry after:

      unadjusted_args_size
        = compute_argument_block_size (reg_parm_stack_space,
                                       &adjusted_args_size,
                                       fndecl, fntype,
                                       (pass == 0 ? 0
                                        : preferred_stack_boundary));

and then zero the argument sizes and num_actual.  That avoids the
ICE too, but who knows what other problems it creates.

In the end it seemed easier just to stop.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


2018-03-21  Richard Sandiford  <richard.sandif...@linaro.org>

gcc/
        PR error-recovery/84964
        * diagnostic-core.h (fatal_sorry): Declare.
        * diagnostic.c (fatal_sorry): New function.
        * calls.c (expand_call): Use it instead of sorry.

gcc/testsuite/
        PR error-recovery/84964
        * g++.dg/diagnostic/pr84964.C: New test.

Index: gcc/diagnostic-core.h
===================================================================
--- gcc/diagnostic-core.h       2018-03-01 08:20:43.590534306 +0000
+++ gcc/diagnostic-core.h       2018-03-21 08:31:34.635677798 +0000
@@ -87,6 +87,8 @@ extern bool permerror (location_t, const
 extern bool permerror (rich_location *, const char *,
                                   ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void fatal_sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
+    ATTRIBUTE_NORETURN;
 extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern void inform (rich_location *, const char *, ...) 
ATTRIBUTE_GCC_DIAG(2,3);
 extern void inform_n (location_t, unsigned HOST_WIDE_INT, const char *,
Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c    2018-03-01 08:20:43.589534337 +0000
+++ gcc/diagnostic.c    2018-03-21 08:31:34.635677798 +0000
@@ -1407,6 +1407,20 @@ sorry (const char *gmsgid, ...)
   va_end (ap);
 }
 
+/* Same, but stop compilation immediately.  */
+
+void
+fatal_sorry (const char *gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, input_location);
+  diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
+  va_end (ap);
+
+  exit (FATAL_EXIT_CODE);
+}
+
 /* Return true if an error or a "sorry" has been seen.  Various
    processing is disabled after errors.  */
 bool
Index: gcc/calls.c
===================================================================
--- gcc/calls.c 2018-03-17 08:30:20.937100705 +0000
+++ gcc/calls.c 2018-03-21 08:31:34.635677798 +0000
@@ -4052,13 +4052,10 @@ expand_call (tree exp, rtx target, int i
              rtx_insn *before_arg = get_last_insn ();
 
              /* We don't allow passing huge (> 2^30 B) arguments
-                by value.  It would cause an overflow later on.  */
+                by value.  It would cause an overflow later on.  */
              if (constant_lower_bound (adjusted_args_size.constant)
                  >= (1 << (HOST_BITS_PER_INT - 2)))
-               {
-                 sorry ("passing too large argument on stack");
-                 continue;
-               }
+               fatal_sorry ("passing too large argument on stack");
 
              if (store_one_arg (&args[i], argblock, flags,
                                 adjusted_args_size.var != 0,
Index: gcc/testsuite/g++.dg/diagnostic/pr84964.C
===================================================================
--- /dev/null   2018-03-17 08:19:33.716019995 +0000
+++ gcc/testsuite/g++.dg/diagnostic/pr84964.C   2018-03-21 08:31:34.635677798 
+0000
@@ -0,0 +1,6 @@
+/* { dg-do compile { target lp64 } } */
+
+struct a {
+  short b : 1ULL << 33; /* { dg-warning "width of 'a::b' exceeds its type" } */
+};
+void c(...) { c(a()); } /* { dg-message "sorry, unimplemented: passing too 
large argument on stack" } */

Reply via email to