calls: Fix error recovery after sorry differently [PR104989]
On Mon, Feb 28, 2022 at 07:52:56AM -0000, Roger Sayle wrote: > This patch resolves PR c++/84964 which is an ICE in the middle-end after > emitting a "sorry, unimplemented" message, and is a regression from > earlier releases of GCC. This issue is that after encountering a > function call requiring an unreasonable amount of stack space, the > code continues and falls foul of an assert checking that stack pointer > has been correctly updated. The fix is to (locally) consider aborted > function calls as "no return", which skips this downstream sanity check. As can be seen on PR104989, just setting ECF_NORETURN after sorry is quite risky and leads to other ICEs. The problem is that ECF_NORETURN calls better should be at the end of basic blocks that don't have any fallthru successor edges, otherwise we can ICE later. This patch instead sets sibcall_failure if in pass == 0 (sibcall_failure means that the tail call sequence is not useful/not desirable and throws it away) and otherwise sets a new bool variable that will let us pass the assertion and also throws away the whole call sequence, I think that is best for error recovery. 2022-03-22 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/104989 * calls.cc (expand_call): Don't set ECF_NORETURN in flags after sorry for passing too large argument, instead set sibcall_failure for pass == 0, or a new normal_failure flag otherwise. If normal_failure is set, don't assert all stack has been deallocated at the end and throw away the whole insn sequence. * g++.dg/other/pr104989.C: New test.
This commit is contained in:
parent
c6bc483565
commit
6adbb51eaa
@ -3068,6 +3068,7 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
for (pass = try_tail_call ? 0 : 1; pass < 2; pass++)
|
||||
{
|
||||
int sibcall_failure = 0;
|
||||
bool normal_failure = false;
|
||||
/* We want to emit any pending stack adjustments before the tail
|
||||
recursion "call". That way we know any adjustment after the tail
|
||||
recursion call can be ignored if we indeed use the tail
|
||||
@ -3448,7 +3449,10 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
{
|
||||
sorry ("passing too large argument on stack");
|
||||
/* Don't worry about stack clean-up. */
|
||||
flags |= ECF_NORETURN;
|
||||
if (pass == 0)
|
||||
sibcall_failure = 1;
|
||||
else
|
||||
normal_failure = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3905,9 +3909,12 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
|
||||
/* Verify that we've deallocated all the stack we used. */
|
||||
gcc_assert ((flags & ECF_NORETURN)
|
||||
|| normal_failure
|
||||
|| known_eq (old_stack_allocated,
|
||||
stack_pointer_delta
|
||||
- pending_stack_adjust));
|
||||
if (normal_failure)
|
||||
normal_call_insns = NULL;
|
||||
}
|
||||
|
||||
/* If something prevents making this a sibling call,
|
||||
|
9
gcc/testsuite/g++.dg/other/pr104989.C
Normal file
9
gcc/testsuite/g++.dg/other/pr104989.C
Normal file
@ -0,0 +1,9 @@
|
||||
// PR rtl-optimization/104989
|
||||
// { dg-do compile }
|
||||
// { dg-options "-fnon-call-exceptions" }
|
||||
|
||||
struct a {
|
||||
short b : -1ULL;
|
||||
};
|
||||
void c(...) { c(a()); }
|
||||
// { dg-excess-errors "" }
|
Loading…
x
Reference in New Issue
Block a user