blob: 5998a6ab600f2d0022f1cb41af1cd52ede6ddde7 [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 for initialization.
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
16// TODO(danakj): Crashes trying to find the initializer expression under
17// MaterializeTemporaryExpr. Should be improved by cl/414032764.
18TEST_F(LifetimeAnalysisTest, DISABLED_VarDeclReferenceToRecordTemporary) {
19 EXPECT_THAT(GetLifetimes(R"(
20 template <typename T>
21 struct S {
22 T a;
23 };
24 int* target(int* a) {
25 const S<int*>& s = S<int*>{a};
26 return s.a;
27 }
28 )"),
29 LifetimesAre({{"target", "a -> a"}}));
30}
31
32TEST_F(LifetimeAnalysisTest, VarDeclReferenceToRecordTemplate) {
33 EXPECT_THAT(GetLifetimes(R"(
34 template <typename T>
35 struct S {
36 T a;
37 };
38 S<int*>* target(S<int*>* a) {
39 S<int*>& b = *a;
40 return &b;
41 }
42 )"),
43 LifetimesAre({{"target", "(a, b) -> (a, b)"}}));
44}
45
46TEST_F(LifetimeAnalysisTest, VarDeclReferenceToRecordNoTemplate) {
47 EXPECT_THAT(GetLifetimes(R"(
48 struct [[clang::annotate("lifetime_params", "a")]] S {
49 [[clang::annotate("member_lifetimes", "a")]]
50 int* a;
51 };
52 S* target(S* a) {
53 S& b = *a;
54 return &b;
55 }
56 )"),
57 LifetimesAre({{"target", "(a, b) -> (a, b)"}}));
58}
59
60TEST_F(LifetimeAnalysisTest, ConstructorInitReferenceToRecord) {
61 EXPECT_THAT(GetLifetimes(R"(
62 struct [[clang::annotate("lifetime_params", "a")]] S {
63 [[clang::annotate("member_lifetimes", "a")]]
64 int* a;
65 };
66 template <class Ref>
67 struct R {
68 R(S& s): s(s) {}
69 Ref s;
70 };
71 int* target(S* a) {
72 R<S&> r(*a);
73 return r.s.a;
74 }
75 )"),
76 LifetimesAre({{"R<S &>::R", "(a, b, c): (a, b)"},
77 {"target", "(a, b) -> a"}}));
78}
79
80// TODO(danakj): Fails because a nested TransferMemberExpr() ends up looking for
81// the field from the outer expr on the object of the inner expr.
82//
83// The code:
84// ObjectSet struct_points_to =
85// points_to_map.GetExprObjectSet(member->getBase());
86//
87// The AST:
88// MemberExpr 0x4027d3f2628 'int *':'int *' lvalue .p 0x4027d3f7338
89// `-MemberExpr 0x4027d3f25f8 'S<int *>':'struct S<int *>' lvalue .s
90// 0x4027d3f74c0
91// `-DeclRefExpr 0x4027d3f25d8 'R<int *>':'struct R<int *>' lvalue Var
92// 0x4027d3f6cd0 'r' 'R<int *>':'struct R<int *>'
93//
94// The p field is on struct S, but the code tries to find it on an object
95// of type R<int *>.
96TEST_F(LifetimeAnalysisTest, MemberInitReferenceToRecord) {
97 EXPECT_THAT(
98 GetLifetimes(R"(
99 template <typename P>
100 struct S {
101 P p;
102 };
103 template<typename P>
104 struct [[clang::annotate("lifetime_params", "a")]] R {
105 R(P p): ss{p} {}
106 S<P> ss;
107 [[clang::annotate("member_lifetimes", "a")]]
108 S<P>& s{ss};
109 };
110 int* target(int* a) {
111 R<int*> r(a);
112 return r.s.p;
113 }
114 )"),
115 LifetimesAre({{"R<int *>::R", "(<a> [b], b): a"}, {"target", "a -> a"}}));
116}
117
118} // namespace
119} // namespace lifetimes
120} // namespace tidy
121} // namespace clang