111
|
1 /* The goal here is to ensure that we never consider a call to a noreturn
|
|
2 function as a potential tail call.
|
|
3
|
|
4 Right now GCC discovers potential tail calls by looking at the
|
|
5 predecessors of the exit block. A call to a non-return function
|
|
6 has no successors and thus can never match that first filter.
|
|
7
|
|
8 But that could change one day and we want to catch it. The problem
|
|
9 is the compiler could potentially optimize a tail call to a nonreturn
|
|
10 function, even if the caller has a frame. That breaks the assumption
|
|
11 that calls probe *sp when saving the return address that some targets
|
|
12 depend on to elide stack probes. */
|
|
13
|
|
14 /* { dg-do compile } */
|
|
15 /* { dg-options "-O2 -fstack-clash-protection -fdump-tree-tailc -fdump-tree-optimized" } */
|
|
16 /* { dg-require-effective-target supports_stack_clash_protection } */
|
|
17
|
|
18 extern void foo (void) __attribute__ ((__noreturn__));
|
|
19
|
|
20
|
|
21 void
|
|
22 test_direct_1 (void)
|
|
23 {
|
|
24 foo ();
|
|
25 }
|
|
26
|
|
27 void
|
|
28 test_direct_2 (void)
|
|
29 {
|
|
30 return foo ();
|
|
31 }
|
|
32
|
|
33 void (*indirect)(void)__attribute__ ((noreturn));
|
|
34
|
|
35
|
|
36 void
|
|
37 test_indirect_1 ()
|
|
38 {
|
|
39 (*indirect)();
|
|
40 }
|
|
41
|
|
42 void
|
|
43 test_indirect_2 (void)
|
|
44 {
|
|
45 return (*indirect)();;
|
|
46 }
|
|
47
|
|
48
|
|
49 typedef void (*pvfn)() __attribute__ ((noreturn));
|
|
50
|
|
51 void (*indirect_casted)(void);
|
|
52
|
|
53 void
|
|
54 test_indirect_casted_1 ()
|
|
55 {
|
|
56 (*(pvfn)indirect_casted)();
|
|
57 }
|
|
58
|
|
59 void
|
|
60 test_indirect_casted_2 (void)
|
|
61 {
|
|
62 return (*(pvfn)indirect_casted)();
|
|
63 }
|
|
64 /* { dg-final { scan-tree-dump-not "tail call" "tailc" } } */
|
|
65 /* { dg-final { scan-tree-dump-not "tail call" "optimized" } } */
|
|
66
|