1 | volatile int x; |
2 | |
3 | // clang-format off |
4 | void __attribute__((noinline)) tail_call_sink() { |
5 | x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK") |
6 | // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4 |
7 | // TAIL-CALL-SINK-NEXT: inlinable_function_which_tail_calls() at main.cpp{{.*}} [artificial] |
8 | // TAIL-CALL-SINK-NEXT: main{{.*}} |
9 | } |
10 | // clang-format on |
11 | |
12 | void __attribute__((always_inline)) inlinable_function_which_tail_calls() { |
13 | tail_call_sink(); |
14 | } |
15 | |
16 | void __attribute__((noinline)) func3() { |
17 | inlinable_function_which_tail_calls(); |
18 | } |
19 | |
20 | // clang-format off |
21 | void __attribute__((always_inline)) inline_sink() { |
22 | x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK") |
23 | // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`inline_sink() at main.cpp:[[@LINE-1]]:4 |
24 | // INLINE-SINK-NEXT: func2{{.*}} |
25 | // INLINE-SINK-NEXT: func1{{.*}} [artificial] |
26 | // INLINE-SINK-NEXT: main{{.*}} |
27 | } |
28 | // clang-format on |
29 | |
30 | void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ } |
31 | |
32 | void __attribute__((noinline)) func1() { func2(); /* tail */ } |
33 | |
34 | int __attribute__((disable_tail_calls)) main() { |
35 | // First, call a function that tail-calls a function, which itself inlines |
36 | // a third function. |
37 | func1(); |
38 | |
39 | // Next, call a function which contains an inlined tail-call. |
40 | func3(); |
41 | |
42 | return 0; |
43 | } |
44 | |