1 | volatile int x; |
2 | |
3 | void __attribute__((noinline)) tail_call_sink() { |
4 | x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK") |
5 | // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4 |
6 | // TAIL-CALL-SINK-NEXT: func3{{.*}} [artificial] |
7 | // TAIL-CALL-SINK-NEXT: main{{.*}} |
8 | |
9 | // TODO: The backtrace should include inlinable_function_which_tail_calls. |
10 | } |
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 | void __attribute__((always_inline)) inline_sink() { |
21 | x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK") |
22 | // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] inline_sink() at main.cpp:[[@LINE-1]]:4 |
23 | // INLINE-SINK-NEXT: func2{{.*}} |
24 | // INLINE-SINK-NEXT: func1{{.*}} [artificial] |
25 | // INLINE-SINK-NEXT: main{{.*}} |
26 | } |
27 | |
28 | void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ } |
29 | |
30 | void __attribute__((noinline)) func1() { func2(); /* tail */ } |
31 | |
32 | int __attribute__((disable_tail_calls)) main() { |
33 | // First, call a function that tail-calls a function, which itself inlines |
34 | // a third function. |
35 | func1(); |
36 | |
37 | // Next, call a function which contains an inlined tail-call. |
38 | func3(); |
39 | |
40 | return 0; |
41 | } |
42 | |