blob: ac8496bf569d044662e87bd819995b01ccdbb50c [file] [log] [blame]
Luca Versari99fddff2022-05-25 10:22:32 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5// Tests involving initializers.
6
7#include "gmock/gmock.h"
8#include "gtest/gtest.h"
9#include "lifetime_analysis/test/lifetime_analysis_test.h"
10
11namespace clang {
12namespace tidy {
13namespace lifetimes {
14namespace {
15
16TEST_F(LifetimeAnalysisTest,
17 ReturnStructFieldFromMultipleInitializersConstructor) {
18 EXPECT_THAT(GetLifetimes(R"(
19 template <typename T>
20 struct S {
21 S(T i) : i(i) {}
22 T i;
23 };
24 int* ConstructorSyntax(int* a, int* b, bool cond) {
25 return (cond ? S<int*>{a} : S<int*>{b}).i;
26 }
27 int* CastSyntax(int* a, int* b, bool cond) {
28 return (cond ? S<int*>(a) : S<int*>(b)).i;
29 }
30 )"),
31 LifetimesAre({
32 {"S<int *>::S", "(a, b): a"},
33 {"ConstructorSyntax", "a, a, () -> a"},
34 {"CastSyntax", "a, a, () -> a"},
35 }));
36}
37
38TEST_F(LifetimeAnalysisTest,
39 ReturnStructFieldFromMultipleInitializersInitList) {
40 EXPECT_THAT(GetLifetimes(R"(
41 template <typename T>
42 struct S {
43 T i;
44 };
45 int* target(int* a, int* b, bool cond) {
46 return (cond ? S<int*>{a} : S<int*>{b}).i;
47 }
48 )"),
49 LifetimesAre({{"target", "a, a, () -> a"}}));
50}
51
52TEST_F(LifetimeAnalysisTest,
53 ReturnStructFromMultipleInitializersConstructSyntax) {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070054 EXPECT_THAT(GetLifetimes(R"(
Luca Versari99fddff2022-05-25 10:22:32 -070055 template <typename T>
56 struct S {
57 S(T i) : i(i) {}
58 T i;
59 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070060 S<int*> target(int* a, int* b, bool cond) {
61 return cond ? S<int*>{a} : S<int*>{b};
Luca Versari99fddff2022-05-25 10:22:32 -070062 }
63 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070064 LifetimesAre(
65 {{"S<int *>::S", "(a, b): a"}, {"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -070066}
67
68TEST_F(LifetimeAnalysisTest, ReturnStructFromMultipleInitializersCastSyntax) {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070069 EXPECT_THAT(GetLifetimes(R"(
Luca Versari99fddff2022-05-25 10:22:32 -070070 template <typename T>
71 struct S {
72 S(T i) : i(i) {}
73 T i;
74 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070075 S<int*> target(int* a, int* b, bool cond) {
76 return cond ? S<int*>(a) : S<int*>(b);
Luca Versari99fddff2022-05-25 10:22:32 -070077 }
78 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070079 LifetimesAre(
80 {{"S<int *>::S", "(a, b): a"}, {"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -070081}
82
83TEST_F(LifetimeAnalysisTest,
84 ReturnStructFromMultipleInitializersInitListSyntax) {
85 EXPECT_THAT(GetLifetimes(R"(
86 template <typename T>
87 struct S {
88 T i;
89 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070090 S<int*> target(int* a, int* b, bool cond) {
91 return cond ? S<int*>{a} : S<int*>{b};
Luca Versari99fddff2022-05-25 10:22:32 -070092 }
93 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070094 LifetimesAre({{"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -070095}
96
97TEST_F(LifetimeAnalysisTest, StructWithMultipleInitializersConstructorSyntax) {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -070098 EXPECT_THAT(GetLifetimes(R"(
Luca Versari99fddff2022-05-25 10:22:32 -070099 template <typename T>
100 struct S {
101 S(T i) : i(i) {}
102 T i;
103 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700104 int* target(int* a, int* b, bool cond) {
105 S<int*> s = cond ? S{a} : S{b};
Luca Versari99fddff2022-05-25 10:22:32 -0700106 return s.i;
107 }
108 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700109 LifetimesAre(
110 {{"S<int *>::S", "(a, b): a"}, {"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -0700111}
112
113TEST_F(LifetimeAnalysisTest, StructWithMultipleInitializersCastSyntax) {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700114 EXPECT_THAT(GetLifetimes(R"(
Luca Versari99fddff2022-05-25 10:22:32 -0700115 template <typename T>
116 struct S {
117 S(T i) : i(i) {}
118 T i;
119 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700120 int* target(int* a, int* b, bool cond) {
121 S<int*> s = cond ? S(a) : S(b);
Luca Versari99fddff2022-05-25 10:22:32 -0700122 return s.i;
123 }
124 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700125 LifetimesAre(
126 {{"S<int *>::S", "(a, b): a"}, {"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -0700127}
128
129TEST_F(LifetimeAnalysisTest, StructWithMultipleInitializersInitListSyntax) {
130 EXPECT_THAT(GetLifetimes(R"(
131 template <typename T>
132 struct S {
133 T i;
134 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700135 int* target(int* a, int* b, bool cond) {
136 S<int*> s = cond ? S<int*>{a} : S<int*>{b};
Luca Versari99fddff2022-05-25 10:22:32 -0700137 return s.i;
138 }
139 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700140 LifetimesAre({{"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -0700141}
142
143TEST_F(LifetimeAnalysisTest,
144 ConstructorInitWithMultipleInitializersConstructorSyntax) {
145 EXPECT_THAT(GetLifetimes(R"(
146 template <typename T>
147 struct R {
148 R(T i) : i(i) {}
149 T i;
150 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700151 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700152 template <typename T>
153 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700154 S(T a, T b) : r(cond() ? R{a} : R{b}) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700155 R<T> r;
156 };
157 int* target(int* a, int* b) {
158 S<int*> s(a, b);
159 return s.r.i;
160 }
161 )"),
162 LifetimesAre({{"R<int *>::R", "(a, b): a"},
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700163 {"cond", ""},
Luca Versari99fddff2022-05-25 10:22:32 -0700164 {"S<int *>::S", "(a, b): a, a"},
165 {"target", "a, a -> a"}}));
166}
167
168TEST_F(LifetimeAnalysisTest,
169 ConstructorInitWithMultipleInitializersCastSyntax) {
170 EXPECT_THAT(GetLifetimes(R"(
171 template <typename T>
172 struct R {
173 R(T i) : i(i) {}
174 T i;
175 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700176 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700177 template <typename T>
178 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700179 S(T a, T b) : r(cond() ? R(a) : R(b)) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700180 R<T> r;
181 };
182 int* target(int* a, int* b) {
183 S<int*> s(a, b);
184 return s.r.i;
185 }
186 )"),
187 LifetimesAre({{"R<int *>::R", "(a, b): a"},
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700188 {"cond", ""},
Luca Versari99fddff2022-05-25 10:22:32 -0700189 {"S<int *>::S", "(a, b): a, a"},
190 {"target", "a, a -> a"}}));
191}
192
193TEST_F(LifetimeAnalysisTest,
194 ConstructorInitWithMultipleInitializersInitListSyntax) {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700195 EXPECT_THAT(GetLifetimes(R"(
Luca Versari99fddff2022-05-25 10:22:32 -0700196 template <typename T>
197 struct R {
198 T i;
199 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700200 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700201 template <typename T>
202 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700203 S(T a, T b) : r(cond() ? R<T>{a} : R<T>{b}) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700204 R<T> r;
205 };
206 int* target(int* a, int* b) {
207 S<int*> s(a, b);
208 return s.r.i;
209 }
210 )"),
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700211 LifetimesAre({{"S<int *>::S", "(a, b): a, a"},
212 {"cond", ""},
213 {"target", "a, a -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -0700214}
215
216TEST_F(LifetimeAnalysisTest,
217 MemberInitWithMultipleInitializersConstructorSyntax) {
218 EXPECT_THAT(GetLifetimes(R"(
219 template <typename T>
220 struct R {
221 R(T i) : i(i) {}
222 T i;
223 };
224 template <typename T>
225 struct S {
226 S(T a, T b) : a(a), b(b) {}
227 T a;
228 T b;
229 R<T> r{true ? R{a} : R{b}};
230 };
231 int* target(int* a, int* b) {
232 S<int*> s(a, b);
233 return s.r.i;
234 }
235 )"),
236 LifetimesAre({{"R<int *>::R", "(a, b): a"},
237 {"S<int *>::S", "(a, b): a, a"},
238 {"target", "a, a -> a"}}));
239}
240
241TEST_F(LifetimeAnalysisTest, MemberInitWithMultipleInitializersCastSyntax) {
242 EXPECT_THAT(GetLifetimes(R"(
243 template <typename T>
244 struct R {
245 R(T i) : i(i) {}
246 T i;
247 };
248 template <typename T>
249 struct S {
250 S(T a, T b) : a(a), b(b) {}
251 T a;
252 T b;
253 R<T> r{true ? R(a) : R(b)};
254 };
255 int* target(int* a, int* b) {
256 S<int*> s(a, b);
257 return s.r.i;
258 }
259 )"),
260 LifetimesAre({{"R<int *>::R", "(a, b): a"},
261 {"S<int *>::S", "(a, b): a, a"},
262 {"target", "a, a -> a"}}));
263}
264
265TEST_F(LifetimeAnalysisTest, ConstructorInitWithMultiplePointers) {
266 EXPECT_THAT(
267 GetLifetimes(R"(
268 template <typename T>
269 struct R {
270 R(T i) : i(i) {}
271 T i;
272 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700273 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700274 template <typename T, typename U, typename V>
275 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700276 S(T a, U b) : r(cond() ? a : b) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700277 R<V> r;
278 };
279 int* target(int* a, int* b) {
280 S<int*, int*, int*> s(a, b);
281 return s.r.i;
282 }
283 )"),
284 LifetimesAre({{"R<int *>::R", "(a, b): a"},
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700285 {"cond", ""},
Luca Versari99fddff2022-05-25 10:22:32 -0700286 {"S<int *, int *, int *>::S", "(<b, c, a>, d): a, a"},
287 {"target", "a, a -> a"}}));
288}
289
290TEST_F(LifetimeAnalysisTest,
291 ConstructorInitWithMultiplePointersAndStoresFields) {
292 EXPECT_THAT(
293 GetLifetimes(R"(
294 template <typename T>
295 struct R {
296 R(T i) : i(i) {}
297 T i;
298 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700299 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700300 template <typename T, typename U, typename V>
301 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700302 S(T a, U b) : a_(a), b_(b), r(cond() ? a : b) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700303 T a_;
304 U b_;
305 R<V> r;
306 };
307 int* target(int* a, int* b) {
308 S<int*, int*, int*> s(a, b);
309 return s.r.i;
310 }
311 )"),
312 LifetimesAre({{"R<int *>::R", "(a, b): a"},
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700313 {"cond", ""},
Luca Versari99fddff2022-05-25 10:22:32 -0700314 {"S<int *, int *, int *>::S", "(<a, a, a>, b): a, a"},
315 {"target", "a, a -> a"}}));
316}
317
318TEST_F(LifetimeAnalysisTest, MemberInitWithMultiplePointers) {
319 EXPECT_THAT(
320 GetLifetimes(R"(
321 template <typename T>
322 struct R {
323 R(T i) : i(i) {}
324 T i;
325 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700326 bool cond();
Luca Versari99fddff2022-05-25 10:22:32 -0700327 template <typename T, typename U, typename V>
328 struct S {
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700329 S(T a, U b, bool cond) : a(a), b(b), cond(cond) {}
Luca Versari99fddff2022-05-25 10:22:32 -0700330 T a;
331 U b;
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700332 bool cond;
333 R<V> r{cond ? a : b};
Luca Versari99fddff2022-05-25 10:22:32 -0700334 };
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700335 int* target(int* a, int* b, bool cond) {
336 S<int*, int*, int*> s(a, b, cond);
Luca Versari99fddff2022-05-25 10:22:32 -0700337 return s.r.i;
338 }
339 )"),
340 LifetimesAre({{"R<int *>::R", "(a, b): a"},
Kinuko Yasuda45fd4be2023-05-03 02:11:57 -0700341 {"S<int *, int *, int *>::S", "(<a, a, a>, b): a, a, ()"},
342 {"target", "a, a, () -> a"}}));
Luca Versari99fddff2022-05-25 10:22:32 -0700343}
344
345TEST_F(LifetimeAnalysisTest, MemberInitWithMultipleInitializersInitListSyntax) {
346 EXPECT_THAT(
347 GetLifetimes(R"(
348 template <typename T>
349 struct R {
350 T i;
351 };
352 template <typename T>
353 struct S {
354 S(T a, T b) : a(a), b(b) {}
355 T a;
356 T b;
357 R<T> r{true ? R<T>{a} : R<T>{b}};
358 };
359 int* target(int* a, int* b) {
360 S<int*> s(a, b);
361 return s.r.i;
362 }
363 )"),
364 LifetimesAre({{"S<int *>::S", "(a, b): a, a"}, {"target", "a, a -> a"}}));
365}
366
367TEST_F(LifetimeAnalysisTest, DeclStructInitializerWithConversionOperator) {
368 EXPECT_THAT(GetLifetimes(R"(
369 template <typename T>
370 struct R {
371 T a;
372 };
373 template <typename T>
374 struct S {
375 T a;
376 operator R<T>() { return {a}; }
377 };
378 int* target(int* a) {
379 R<int*> r = S<int*>{a};
380 return r.a;
381 }
382 )"),
383 LifetimesAre({{"S<int *>::operator R", "(a, b): -> a"},
384 {"target", "a -> a"}}));
385}
386
387TEST_F(LifetimeAnalysisTest, DeclStructInitializerFromCall) {
388 EXPECT_THAT(GetLifetimes(R"(
389 template <typename T>
390 struct R {
391 T a;
392 };
393 template <typename T>
394 struct R<T> f(T a) {
395 return R<T>{a};
396 }
397 int* target(int* a) {
398 R<int*> r = f<int*>(a);
399 return r.a;
400 }
401 )"),
402 LifetimesAre({{"f", "a -> a"}, {"target", "a -> a"}}));
403}
404
405TEST_F(LifetimeAnalysisTest, ReturnStructInitializerWithConversionOperator) {
406 EXPECT_THAT(GetLifetimes(R"(
407 template <typename T>
408 struct R {
409 T a;
410 };
411 template <typename T>
412 struct S {
413 T a;
414 operator R<T>() { return {a}; }
415 };
416 R<int*> target(int* a) {
417 return S<int*>{a};
418 }
419 )"),
420 LifetimesAre({{"S<int *>::operator R", "(a, b): -> a"},
421 {"target", "a -> a"}}));
422}
423
424// TODO(danakj): Crashes due to operator() not being a CXXConstructExpr, but
425// SetExprObjectSetRespectingType only handles CXXConstructExpr for record
426// types.
427TEST_F(LifetimeAnalysisTest,
428 DISABLED_ConstructorInitializerWithConversionOperator) {
429 EXPECT_THAT(GetLifetimes(R"(
430 template <typename T>
431 struct S {
432 T a;
433 };
434 template <typename T>
435 struct R {
436 T a;
437 operator S<T>() { return {a}; }
438 };
439
440 // This initializes the `s` field from a constructor initializer.
441 template <typename T>
442 struct QConstructor {
443 QQConstructor(T a) : s(R<T>{a}) {}
444 S<T> s;
445 };
446 int* constructor(int* a) {
447 return QQConstructor<int*>{a}.s.a;
448 }
449
450 // This initializes the `s` field from a transparent InitListExpr on a
451 // member initializer.
452 template <typename T>
453 struct QMember {
454 QMember(T a) : a(a) {}
455 T a;
456 S<T> s{S<T>(R<T>{a})};
457 };
458 int* member(int* a) {
459 return QMember<int*>{a}.s.a;
460 }
461)"),
462 LifetimesAre({{"QConstructor<int *>::QConstructor", "(a, b): a"},
463 {"QMember<int *>::QMember", "(a, b): a"},
464 {"constructor", "a -> a"},
465 {"member", "a -> a"}}));
466}
467
468TEST_F(LifetimeAnalysisTest, StructInitializerWithCtorCall) {
469 EXPECT_THAT(GetLifetimes(R"(
470 template <typename T>
471 struct S {
472 S(T a) : a(a) {}
473 T a;
474 };
475 int* TransparentInitListExpr(int* a) {
476 S<int*> s{S<int*>(a)};
477 return s.a;
478 }
479 int* CastSyntax(int* a) {
480 S<int*> s((S<int*>(a)));
481 return s.a;
482 }
483 )"),
484 LifetimesAre({{"S<int *>::S", "(a, b): a"},
485 {"TransparentInitListExpr", "a -> a"},
486 {"CastSyntax", "a -> a"}}));
487}
488
489// TODO(danakj): Crashes because the initializer expression is a
490// CXXStaticCastExpr, and operator() is not a CXXConstructExpr, but
491// SetExprObjectSetRespectingType only handles CXXConstructExpr for record
492// types.
493TEST_F(LifetimeAnalysisTest, DISABLED_StaticCastInitializer) {
494 EXPECT_THAT(GetLifetimes(R"(
495 template <typename T>
496 struct S {
497 T a;
498 };
499 template <typename T>
500 struct R {
501 T a;
502 operator S<T>() { return {a}; }
503 };
504 int* target(int* a) {
505 return static_cast<S<int*>>(R<int*>{a}).a;
506 }
507 )"),
508 LifetimesAre({{"target", "a -> a"}}));
509}
510
511} // namespace
512} // namespace lifetimes
513} // namespace tidy
514} // namespace clang