xref: /llvm-project/clang/test/CodeGen/nrvo-tracking.cpp (revision 61d418f97154805100dc19ff2ef1338e9de2f27d)
1 // RUN: %clang_cc1 -std=c++20 -fblocks -Wno-return-stack-address -triple x86_64-unknown-unknown-gnu -emit-llvm -O1 -o - %s | FileCheck %s
2 
3 struct alignas(4) X {
4   X();
5   X(const X &);
6   X(X &&);
7 };
8 
9 #define L(A, B, C) void l##A() {    \
10   auto t = []<class T = X>() -> C { \
11     T t;                            \
12     return B;                       \
13   }();                              \
14 }
15 
16 // CHECK-LABEL: define{{.*}} void @_Z2l1v
17 // CHECK:       call {{.*}} @_ZN1XC1Ev
18 // CHECK-NEXT:  call void @llvm.lifetime.end
19 // CHECK-NEXT:  ret void
20 L(1, t, X);
21 
22 // CHECK-LABEL: define{{.*}} void @_Z2l2v
23 // CHECK:       call {{.*}} @_ZN1XC1Ev
24 // CHECK-NEXT:  call void @llvm.lifetime.end
25 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
26 // CHECK-NEXT:  call void @llvm.lifetime.end
27 // CHECK-NEXT:  ret void
28 L(2, t, X&);
29 
30 // CHECK-LABEL: define{{.*}} void @_Z2l3v
31 // CHECK:       call {{.*}} @_ZN1XC1Ev
32 // CHECK-NEXT:  call void @llvm.lifetime.end
33 // CHECK-NEXT:  ret void
34 L(3, t, T);
35 
36 // CHECK-LABEL: define{{.*}} void @_Z2l4v
37 // CHECK:       call {{.*}} @_ZN1XC1Ev
38 // CHECK-NEXT:  call void @llvm.lifetime.end
39 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
40 // CHECK-NEXT:  call void @llvm.lifetime.end
41 // CHECK-NEXT:  ret void
42 L(4, t, T&);
43 
44 // CHECK-LABEL: define{{.*}} void @_Z2l5v
45 // CHECK:       call {{.*}} @_ZN1XC1Ev
46 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
47 // CHECK-NEXT:  call void @llvm.lifetime.end
48 // CHECK-NEXT:  call void @llvm.lifetime.end
49 // CHECK-NEXT:  ret void
50 L(5, t, auto);
51 
52 // CHECK-LABEL: define{{.*}} void @_Z2l6v
53 // CHECK:       call {{.*}} @_ZN1XC1Ev
54 // CHECK-NEXT:  call void @llvm.lifetime.end
55 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
56 // CHECK-NEXT:  call void @llvm.lifetime.end
57 // CHECK-NEXT:  ret void
58 L(6, t, auto&);
59 
60 // CHECK-LABEL: define{{.*}} void @_Z2l7v
61 // CHECK:       call {{.*}} @_ZN1XC1Ev
62 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
63 // CHECK-NEXT:  call void @llvm.lifetime.end
64 // CHECK-NEXT:  call void @llvm.lifetime.end
65 // CHECK-NEXT:  ret void
66 L(7, t, decltype(auto));
67 
68 // CHECK-LABEL: define{{.*}} void @_Z2l8v
69 // CHECK:       call {{.*}} @_ZN1XC1Ev
70 // CHECK-NEXT:  call void @llvm.lifetime.end
71 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
72 // CHECK-NEXT:  call void @llvm.lifetime.end
73 // CHECK-NEXT:  ret void
74 L(8, (t), decltype(auto));
75 
76 #undef L
77 
78 #define F(A, B, C) template<class T = X> static inline auto tf##A() -> C { \
79     T t;                                                                   \
80     return B;                                                              \
81 }                                                                          \
82 void f##A() { auto t = tf##A(); }                                          \
83 
84 // CHECK-LABEL: define{{.*}} void @_Z2f1v
85 // CHECK:       call {{.*}} @_ZN1XC1Ev
86 // CHECK-NEXT:  call void @llvm.lifetime.end
87 // CHECK-NEXT:  ret void
88 F(1, t, X);
89 
90 // CHECK-LABEL: define{{.*}} void @_Z2f2v
91 // CHECK:       call {{.*}} @_ZN1XC1Ev
92 // CHECK-NEXT:  call void @llvm.lifetime.end
93 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
94 // CHECK-NEXT:  call void @llvm.lifetime.end
95 // CHECK-NEXT:  ret void
96 F(2, t, X&);
97 
98 // CHECK-LABEL: define{{.*}} void @_Z2f3v
99 // CHECK:       call {{.*}} @_ZN1XC1Ev
100 // CHECK-NEXT:  call void @llvm.lifetime.end
101 // CHECK-NEXT:  ret void
102 F(3, t, T);
103 
104 // CHECK-LABEL: define{{.*}} void @_Z2f4v
105 // CHECK:       call {{.*}} @_ZN1XC1Ev
106 // CHECK-NEXT:  call void @llvm.lifetime.end
107 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
108 // CHECK-NEXT:  call void @llvm.lifetime.end
109 // CHECK-NEXT:  ret void
110 F(4, t, T&);
111 
112 // CHECK-LABEL: define{{.*}} void @_Z2f5v
113 // CHECK:       call {{.*}} @_ZN1XC1Ev
114 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
115 // CHECK-NEXT:  call void @llvm.lifetime.end
116 // CHECK-NEXT:  call void @llvm.lifetime.end
117 // CHECK-NEXT:  ret void
118 F(5, t, auto);
119 
120 // CHECK-LABEL: define{{.*}} void @_Z2f6v
121 // CHECK:       call {{.*}} @_ZN1XC1Ev
122 // CHECK-NEXT:  call void @llvm.lifetime.end
123 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
124 // CHECK-NEXT:  call void @llvm.lifetime.end
125 // CHECK-NEXT:  ret void
126 F(6, t, auto&);
127 
128 // CHECK-LABEL: define{{.*}} void @_Z2f7v
129 // CHECK:       call {{.*}} @_ZN1XC1Ev
130 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
131 // CHECK-NEXT:  call void @llvm.lifetime.end
132 // CHECK-NEXT:  call void @llvm.lifetime.end
133 // CHECK-NEXT:  ret void
134 F(7, t, decltype(auto));
135 
136 // CHECK-LABEL: define{{.*}} void @_Z2f8v
137 // CHECK:       call {{.*}} @_ZN1XC1Ev
138 // CHECK-NEXT:  call void @llvm.lifetime.end
139 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
140 // CHECK-NEXT:  call void @llvm.lifetime.end
141 // CHECK-NEXT:  ret void
142 F(8, (t), decltype(auto));
143 
144 #undef F
145 
146 #define B(A, B) void b##A() { \
147   auto t = []<class T = X>() { return ^ B () { \
148       T t;                                     \
149       return t;                                \
150   }; }()();                                    \
151 }
152 
153 // CHECK-LABEL: define{{.*}} void @_Z2b1v
154 // CHECK:       call {{.*}} @_ZN1XC1Ev
155 // CHECK-NEXT:  call void @llvm.lifetime.end
156 // CHECK-NEXT:  ret void
157 B(1, X);
158 
159 // CHECK-LABEL: define{{.*}} void @_Z2b2v
160 // CHECK:       call {{.*}} @_ZN1XC1Ev
161 // CHECK-NEXT:  call void @llvm.lifetime.end
162 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
163 // CHECK-NEXT:  call void @llvm.lifetime.end
164 // CHECK-NEXT:  ret void
165 B(2, X&);
166 
167 // CHECK-LABEL: define{{.*}} void @_Z2b3v
168 // CHECK:       call {{.*}} @_ZN1XC1Ev
169 // CHECK-NEXT:  call void @llvm.lifetime.end
170 // CHECK-NEXT:  ret void
171 B(3, T);
172 
173 // CHECK-LABEL: define{{.*}} void @_Z2b4v
174 // CHECK:       call {{.*}} @_ZN1XC1Ev
175 // CHECK-NEXT:  call void @llvm.lifetime.end
176 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
177 // CHECK-NEXT:  call void @llvm.lifetime.end
178 // CHECK-NEXT:  ret void
179 B(4, T&);
180 
181 // CHECK-LABEL: define{{.*}} void @_Z2b5v
182 // CHECK:       call {{.*}} @_ZN1XC1Ev
183 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
184 // CHECK-NEXT:  call void @llvm.lifetime.end
185 // CHECK-NEXT:  call void @llvm.lifetime.end
186 // CHECK-NEXT:  ret void
187 B(5, );
188 
189 #undef B
190 
191 // CHECK-LABEL: define{{.*}} void @_Z6f_attrv
192 // CHECK:       call {{.*}} @_ZN1XC1Ev
193 // CHECK-NEXT:  call void @llvm.lifetime.end
194 // CHECK-NEXT:  ret void
tf_attr()195 template<class T = X> [[gnu::cdecl]] static inline auto tf_attr() -> X {
196   T t;
197   return t;
198 }
f_attr()199 void f_attr() { auto t = tf_attr(); }
200 
201 // CHECK-LABEL: define{{.*}} void @_Z6b_attrv
202 // CHECK:       call {{.*}} @_ZN1XC1Ev
203 // CHECK-NEXT:  call void @llvm.lifetime.end
204 // CHECK-NEXT:  ret void
b_attr()205 void b_attr() {
206   auto t = []<class T = X>() {
207     return ^X() [[clang::vectorcall]] {
208       T t;
209       return t;
210     };
211   }()();
212 }
213 
214 namespace test_alignas {
215 
t1()216 template <int A> X t1() {
217   X a [[gnu::aligned(A)]];
218   return a;
219 }
220 
221 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi1EEE1Xv
222 // CHECK:       call {{.*}} @_ZN1XC1Ev
223 // CHECK-NEXT:  ret void
224 template X t1<1>();
225 
226 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi4EEE1Xv
227 // CHECK:       call {{.*}} @_ZN1XC1Ev
228 // CHECK-NEXT:  ret void
229 template X t1<4>();
230 
231 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi8EEE1Xv
232 // CHECK:       call {{.*}} @_ZN1XC1Ev
233 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
234 // CHECK-NEXT:  call void @llvm.lifetime.end
235 template X t1<8>();
236 
t2()237 template <int A> X t2() {
238   X a [[gnu::aligned(1)]] [[gnu::aligned(A)]] [[gnu::aligned(2)]];
239   return a;
240 }
241 
242 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi1EEE1Xv
243 // CHECK:       call {{.*}} @_ZN1XC1Ev
244 // CHECK-NEXT:  ret void
245 template X t2<1>();
246 
247 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi4EEE1Xv
248 // CHECK:       call {{.*}} @_ZN1XC1Ev
249 // CHECK-NEXT:  ret void
250 template X t2<4>();
251 
252 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi8EEE1Xv
253 // CHECK:       call {{.*}} @_ZN1XC1Ev
254 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
255 // CHECK-NEXT:  call void @llvm.lifetime.end
256 template X t2<8>();
257 
258 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t3Ev
259 // CHECK:       call {{.*}} @_ZN1XC1Ev
260 // CHECK-NEXT:  ret void
t3()261 X t3() {
262   X a [[gnu::aligned(1)]];
263   return a;
264 }
265 
266 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t4Ev
267 // CHECK:       call {{.*}} @_ZN1XC1Ev
268 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
269 // CHECK-NEXT:  call void @llvm.lifetime.end
t4()270 X t4() {
271   X a [[gnu::aligned(8)]];
272   return a;
273 }
274 
275 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t5Ev
276 // CHECK:       call {{.*}} @_ZN1XC1Ev
277 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
278 // CHECK-NEXT:  call void @llvm.lifetime.end
t5()279 X t5() {
280   X a [[gnu::aligned(1)]] [[gnu::aligned(8)]];
281   return a;
282 }
283 
284 } // namespace test_alignas
285 
286 namespace PR51862 {
287 
test()288 template <class T> T test() {
289   T a;
290   T b;
291   if (0)
292     return a;
293   return b;
294 }
295 
296 struct A {
297   A();
298   A(A &);
299   A(int);
300   operator int();
301 };
302 
303 // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1AEEET_v
304 // CHECK:       call noundef i32 @_ZN7PR518621AcviEv
305 // CHECK-NEXT:  call void @_ZN7PR518621AC1Ei
306 // CHECK-NEXT:  call void @llvm.lifetime.end
307 template A test<A>();
308 
309 struct BSub {};
310 struct B : BSub {
311   B();
312   B(B &);
313   B(const BSub &);
314 };
315 
316 // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1BEEET_v
317 // CHECK:       call void @_ZN7PR518621BC1ERKNS_4BSubE
318 // CHECK-NEXT:  call void @llvm.lifetime.end
319 template B test<B>();
320 
321 } // namespace PR51862
322