blob: cf4a2a49e670cd5eb9fc37ce94c6dca67b50566c [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 inheritance.
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, StructSimpleInheritance) {
17 EXPECT_THAT(GetLifetimes(R"(
18struct [[clang::annotate("lifetime_params", "a")]] B {
19 [[clang::annotate("member_lifetimes", "a")]]
20 int* a;
21};
22struct S : public B {
23};
24int* target(S* s, int* a) {
25 s->a = a;
26 return s->a;
27}
28 )"),
29 LifetimesAre({{"target", "(a, b), a -> a"}}));
30}
31
32TEST_F(LifetimeAnalysisTest,
33 DISABLED_StructInheritanceCallTrivialDefaultConstructor) {
34 EXPECT_THAT(GetLifetimes(R"(
35 struct T {};
36 struct S: public T {
37 S(): T() {}
38 int* a;
39 };
40 void target() {
41 S s;
42 }
43 )"),
44 LifetimesAre({{"target", ""}}));
45}
46
47TEST_F(LifetimeAnalysisTest, StructInheritanceCallBaseConstructor) {
48 EXPECT_THAT(GetLifetimes(R"(
49 struct [[clang::annotate("lifetime_params", "a")]] T {
50 [[clang::annotate("member_lifetimes", "a")]]
51 int* b;
52 T(int* b): b(b) {}
53 };
54 struct S: public T {
55 S(int* a, int* b): a(a), T(b) {}
56 [[clang::annotate("member_lifetimes", "a")]]
57 int* a;
58 };
59 int* target(int* a, int* b) {
60 S s(a, b);
61 return s.b;
62 }
63 )"),
64 LifetimesContain({{"target", "a, a -> a"}}));
65}
66
67TEST_F(LifetimeAnalysisTest, StructInheritanceCallBaseConstructorTypedef) {
68 EXPECT_THAT(GetLifetimes(R"(
69 struct [[clang::annotate("lifetime_params", "a")]] T {
70 [[clang::annotate("member_lifetimes", "a")]]
71 int* b;
72 T(int* b): b(b) {}
73 };
74 using U = T;
75 struct S: public U {
76 S(int* a, int* b): a(a), T(b) {}
77 [[clang::annotate("member_lifetimes", "a")]]
78 int* a;
79 };
80 int* target(int* a, int* b) {
81 S s(a, b);
82 return s.b;
83 }
84 )"),
85 LifetimesContain({{"target", "a, a -> a"}}));
86}
87
88TEST_F(LifetimeAnalysisTest,
89 StructInheritanceCallBaseConstructorTypedefBaseInit) {
90 EXPECT_THAT(GetLifetimes(R"(
91 struct [[clang::annotate("lifetime_params", "a")]] T {
92 [[clang::annotate("member_lifetimes", "a")]]
93 int* b;
94 T(int* b): b(b) {}
95 };
96 using U = T;
97 struct S: public T {
98 S(int* a, int* b): a(a), U(b) {}
99 [[clang::annotate("member_lifetimes", "a")]]
100 int* a;
101 };
102 int* target(int* a, int* b) {
103 S s(a, b);
104 return s.b;
105 }
106 )"),
107 LifetimesContain({{"target", "a, a -> a"}}));
108}
109
110TEST_F(LifetimeAnalysisTest, StructSimpleInheritanceWithMethod) {
111 EXPECT_THAT(
112 GetLifetimes(R"(
113struct [[clang::annotate("lifetime_params", "a")]] B {
114 [[clang::annotate("member_lifetimes", "a")]]
115 int* a;
116 int* f() { return a; }
117};
118struct S : public B {
119};
120int* target(S* s, int* a) {
121 s->a = a;
122 return s->f();
123}
124 )"),
125 LifetimesAre({{"B::f", "(a, b): -> a"}, {"target", "(a, b), a -> a"}}));
126}
127
128TEST_F(LifetimeAnalysisTest, StructSimpleInheritanceWithMethodInDerived) {
129 EXPECT_THAT(
130 GetLifetimes(R"(
131struct [[clang::annotate("lifetime_params", "a")]] B {
132 [[clang::annotate("member_lifetimes", "a")]]
133 int* a;
134};
135struct S : public B {
136 int* f() { return a; }
137};
138int* target(S* s, int* a) {
139 s->a = a;
140 return s->f();
141}
142 )"),
143 LifetimesAre({{"S::f", "(a, b): -> a"}, {"target", "(a, b), a -> a"}}));
144}
145
146TEST_F(LifetimeAnalysisTest, StructSimpleInheritanceChained) {
147 EXPECT_THAT(
148 GetLifetimes(R"(
149struct [[clang::annotate("lifetime_params", "a")]] A {
150 [[clang::annotate("member_lifetimes", "a")]]
151 int* a;
152};
153struct B : public A {
154 int* f() { return a; }
155};
156struct S : public B {
157};
158int* target(S* s, int* a) {
159 s->a = a;
160 return s->f();
161}
162 )"),
163 LifetimesAre({{"B::f", "(a, b): -> a"}, {"target", "(a, b), a -> a"}}));
164}
165
166TEST_F(LifetimeAnalysisTest, StructSimpleInheritanceWithSwappedTemplateArgs) {
167 // Base and Derived have template arguments where the order is swapped, so
168 // if the code reuse the same vector representation for the lifetimes
169 // Derived (T, U) for the base class where Base has (U, T) this code fails.
170 EXPECT_THAT(GetLifetimes(R"(
171template <typename U, typename T>
172struct Base {
173 T base_t;
174 U base_u;
175};
176
177template <typename T, typename U>
178struct Derived : public Base<U, T> {
179 T derived_t;
180 U derived_u;
181};
182
183int* target(Derived<int*, float*>* d, int* t1, int* t2) {
184 d->derived_t = t1;
185 d->base_t = t2;
186 return d->derived_t;
187}
188 )"),
189 // The lifetime for Derived::derived_t should also be
190 // Base::base_t. See discussions at cl/411724984.
191 LifetimesAre({{"target", "(<a, b>, c), a, a -> a"}}));
192}
193
194TEST_F(LifetimeAnalysisTest, StructSimpleInheritanceWithDoubledTemplateArgs) {
195 // Base and Derived have different number of template arguments.
196 // Similar test case as StructSimpleInheritanceWithSwappedTemplateArgs.
197 EXPECT_THAT(GetLifetimes(R"(
198template <typename T, typename U>
199struct Base {
200 T base_t;
201 U base_u;
202};
203
204template <typename T>
205struct Derived : public Base<T, T> {
206 T derived_t;
207};
208
209int* target(Derived<int*>* d, int* t1, int* t2, int* t3) {
210 d->derived_t = t1;
211 d->base_t = t2;
212 d->base_u = t3;
213 return d->derived_t;
214}
215 )"),
216 LifetimesAre({{"target", "(a, b), a, a, a -> a"}}));
217}
218
219TEST_F(LifetimeAnalysisTest,
220 StructSimpleInheritanceWithTemplateSubstitutedAndArgs) {
221 // Base is a template type and has different number of template arguments from
222 // Derived. Similar test case as
223 // StructSimpleInheritanceWithSwappedTemplateArgs.
224 EXPECT_THAT(GetLifetimes(R"(
225template <typename T>
226struct Base {
227 T base_t;
228};
229
230template <typename B, typename T>
231struct Derived : public B {
232 T derived_t;
233};
234
235int* target(Derived<Base<int*>, int*>* d, int* t1, int* t2) {
236 d->derived_t = t1;
237 d->base_t = t2;
238 return d->derived_t;
239}
240 )"),
241 LifetimesAre({{"target", "(<a, b>, c), b, a -> b"}}));
242}
243
244TEST_F(LifetimeAnalysisTest, PassDerivedByValue) {
245 EXPECT_THAT(GetLifetimes(R"(
246struct [[clang::annotate("lifetime_params", "a")]] B {
247 [[clang::annotate("member_lifetimes", "a")]]
248 int* a;
249 int* f() { return a; }
250};
251struct S : public B {
252};
253int* target(S s) {
254 return s.f();
255}
256 )"),
257 LifetimesAre({{"B::f", "(a, b): -> a"}, {"target", "a -> a"}}));
258}
259
260TEST_F(LifetimeAnalysisTest, PassDerivedByValue_BaseIsTemplate) {
261 EXPECT_THAT(
262 GetLifetimes(R"(
263template <class T>
264struct B {
265 T a;
266 T f() { return a; }
267};
268template <class T>
269struct S : public B<T> {
270};
271int* target(S<int *> s) {
272 return s.f();
273}
274 )"),
275 LifetimesAre({{"B<int *>::f", "(a, b): -> a"}, {"target", "a -> a"}}));
276}
277
278} // namespace
279} // namespace lifetimes
280} // namespace tidy
281} // namespace clang