blob: 196c4bbfbdda19ff40030e1283cb02b75d3e2b06 [file] [log] [blame]
/* 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" } } */