/* The goal here is to ensure that we never consider a call to a noreturn function as a potential tail call. Right now GCC discovers potential tail calls by looking at the predecessors of the exit block. A call to a non-return function has no successors and thus can never match that first filter. But that could change one day and we want to catch it. The problem is the compiler could potentially optimize a tail call to a nonreturn function, even if the caller has a frame. That breaks the assumption that calls probe *sp when saving the return address that some targets depend on to elide stack probes. */ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection -fdump-tree-tailc -fdump-tree-optimized" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ extern void foo (void) __attribute__ ((__noreturn__)); void test_direct_1 (void) { foo (); } void test_direct_2 (void) { return foo (); } void (*indirect)(void)__attribute__ ((noreturn)); void test_indirect_1 () { (*indirect)(); } void test_indirect_2 (void) { return (*indirect)();; } typedef void (*pvfn)() __attribute__ ((noreturn)); void (*indirect_casted)(void); void test_indirect_casted_1 () { (*(pvfn)indirect_casted)(); } void test_indirect_casted_2 (void) { return (*(pvfn)indirect_casted)(); } /* { dg-final { scan-tree-dump-not "tail call" "tailc" } } */ /* { dg-final { scan-tree-dump-not "tail call" "optimized" } } */