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" } */