aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-03-22 08:39:40 +0100
committerJakub Jelinek <jakub@redhat.com>2022-03-22 08:39:40 +0100
commit6adbb51eaa85f5bfed1ee06327daca306d48986d (patch)
tree5f42d2003f8bf77116b99993e27321345c95c02e
parentc6bc4835659d24edc2bf5de13bfe8f59ae409ff3 (diff)
downloadgcc-6adbb51eaa85f5bfed1ee06327daca306d48986d.zip
gcc-6adbb51eaa85f5bfed1ee06327daca306d48986d.tar.gz
gcc-6adbb51eaa85f5bfed1ee06327daca306d48986d.tar.bz2
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.
-rw-r--r--gcc/calls.cc9
-rw-r--r--gcc/testsuite/g++.dg/other/pr104989.C9
2 files changed, 17 insertions, 1 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc
index 50fa7b8..e13469c 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -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,
diff --git a/gcc/testsuite/g++.dg/other/pr104989.C b/gcc/testsuite/g++.dg/other/pr104989.C
new file mode 100644
index 0000000..8b1f79b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr104989.C
@@ -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 "" }