1 | // RUN: %check_clang_tidy %s readability-redundant-smartptr-get %t |
2 | |
3 | #define NULL __null |
4 | |
5 | namespace std { |
6 | |
7 | template <typename T> |
8 | struct unique_ptr { |
9 | T& operator*() const; |
10 | T* operator->() const; |
11 | T* get() const; |
12 | explicit operator bool() const noexcept; |
13 | }; |
14 | |
15 | template <typename T> |
16 | struct unique_ptr<T[]> { |
17 | T& operator[](unsigned) const; |
18 | T* get() const; |
19 | explicit operator bool() const noexcept; |
20 | }; |
21 | |
22 | template <typename T> |
23 | struct shared_ptr { |
24 | T& operator*() const; |
25 | T* operator->() const; |
26 | T* get() const; |
27 | explicit operator bool() const noexcept; |
28 | }; |
29 | |
30 | template <typename T> |
31 | struct shared_ptr<T[]> { |
32 | T& operator[](unsigned) const; |
33 | T* get() const; |
34 | explicit operator bool() const noexcept; |
35 | }; |
36 | |
37 | template <typename T> |
38 | struct vector { |
39 | vector(); |
40 | bool operator==(const vector<T>& other) const; |
41 | bool operator!=(const vector<T>& other) const; |
42 | unsigned long size() const; |
43 | bool empty() const; |
44 | |
45 | using iterator = T*; |
46 | |
47 | iterator begin(); |
48 | iterator end(); |
49 | |
50 | T* data; |
51 | unsigned long sz; |
52 | }; |
53 | |
54 | } // namespace std |
55 | |
56 | struct Bar { |
57 | void Do(); |
58 | void ConstDo() const; |
59 | }; |
60 | struct BarPtr { |
61 | Bar* operator->(); |
62 | Bar& operator*(); |
63 | Bar* get(); |
64 | explicit operator bool() const; |
65 | }; |
66 | struct int_ptr { |
67 | int* get(); |
68 | int* operator->(); |
69 | int& operator*(); |
70 | }; |
71 | |
72 | struct Fail1 { |
73 | Bar* get(); |
74 | }; |
75 | struct Fail2 { |
76 | Bar* get(); |
77 | int* operator->(); |
78 | int& operator*(); |
79 | }; |
80 | |
81 | struct PointerWithOverloadedGet { |
82 | int* get(); |
83 | template <typename T> |
84 | T* get(); |
85 | int* operator->(); |
86 | int& operator*(); |
87 | }; |
88 | |
89 | void Positive() { |
90 | BarPtr u; |
91 | // CHECK-FIXES: BarPtr u; |
92 | BarPtr().get()->Do(); |
93 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call on smart pointer [readability-redundant-smartptr-get] |
94 | // CHECK-MESSAGES: BarPtr().get()->Do(); |
95 | // CHECK-FIXES: BarPtr()->Do(); |
96 | |
97 | u.get()->ConstDo(); |
98 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call |
99 | // CHECK-MESSAGES: u.get()->ConstDo(); |
100 | // CHECK-FIXES: u->ConstDo(); |
101 | |
102 | Bar& b = *BarPtr().get(); |
103 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call |
104 | // CHECK-MESSAGES: Bar& b = *BarPtr().get(); |
105 | // CHECK-FIXES: Bar& b = *BarPtr(); |
106 | |
107 | Bar& b2 = *std::unique_ptr<Bar>().get(); |
108 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call |
109 | // CHECK-MESSAGES: Bar& b2 = *std::unique_ptr<Bar>().get(); |
110 | // CHECK-FIXES: Bar& b2 = *std::unique_ptr<Bar>(); |
111 | |
112 | (*BarPtr().get()).ConstDo(); |
113 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call |
114 | // CHECK-MESSAGES: (*BarPtr().get()).ConstDo(); |
115 | // CHECK-FIXES: (*BarPtr()).ConstDo(); |
116 | |
117 | (*std::unique_ptr<Bar>().get()).ConstDo(); |
118 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call |
119 | // CHECK-MESSAGES: (*std::unique_ptr<Bar>().get()).ConstDo(); |
120 | // CHECK-FIXES: (*std::unique_ptr<Bar>()).ConstDo(); |
121 | |
122 | std::unique_ptr<Bar>* up; |
123 | (*up->get()).Do(); |
124 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call |
125 | // CHECK-MESSAGES: (*up->get()).Do(); |
126 | // CHECK-FIXES: (**up).Do(); |
127 | |
128 | int_ptr ip; |
129 | int i = *ip.get(); |
130 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: redundant get() call |
131 | // CHECK-MESSAGES: int i = *ip.get(); |
132 | // CHECK-FIXES: int i = *ip; |
133 | |
134 | auto ip2 = ip; |
135 | i = *ip2.get(); |
136 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
137 | // CHECK-MESSAGES: i = *ip2.get(); |
138 | // CHECK-FIXES: i = *ip2; |
139 | |
140 | std::unique_ptr<int> uu; |
141 | std::shared_ptr<double> *ss; |
142 | bool bb = uu.get() == nullptr; |
143 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call |
144 | // CHECK-MESSAGES: uu.get() == nullptr; |
145 | // CHECK-FIXES: bool bb = uu == nullptr; |
146 | |
147 | if (up->get()); |
148 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call |
149 | // CHECK-MESSAGES: if (up->get()); |
150 | // CHECK-FIXES: if (*up); |
151 | if ((uu.get())); |
152 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
153 | // CHECK-MESSAGES: if ((uu.get())); |
154 | // CHECK-FIXES: if ((uu)); |
155 | bb = !ss->get(); |
156 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant get() call |
157 | // CHECK-MESSAGES: bb = !ss->get(); |
158 | // CHECK-FIXES: bb = !*ss; |
159 | bb = u.get() ? true : false; |
160 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
161 | // CHECK-MESSAGES: bb = u.get() ? true : false; |
162 | // CHECK-FIXES: bb = u ? true : false; |
163 | |
164 | bb = nullptr != ss->get(); |
165 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: redundant get() call |
166 | // CHECK-MESSAGES: nullptr != ss->get(); |
167 | // CHECK-FIXES: bb = nullptr != *ss; |
168 | |
169 | i = *PointerWithOverloadedGet().get(); |
170 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
171 | // CHECK-MESSAGES: i = *PointerWithOverloadedGet().get(); |
172 | // CHECK-FIXES: i = *PointerWithOverloadedGet(); |
173 | |
174 | bb = std::unique_ptr<int>().get() == NULL; |
175 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
176 | // CHECK-MESSAGES: bb = std::unique_ptr<int>().get() == NULL; |
177 | // CHECK-FIXES: bb = std::unique_ptr<int>() == NULL; |
178 | bb = ss->get() == NULL; |
179 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
180 | // CHECK-MESSAGES: bb = ss->get() == NULL; |
181 | // CHECK-FIXES: bb = *ss == NULL; |
182 | |
183 | std::unique_ptr<int> x, y; |
184 | if (x.get() == nullptr); |
185 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call |
186 | // CHECK-MESSAGES: if (x.get() == nullptr); |
187 | // CHECK-FIXES: if (x == nullptr); |
188 | if (nullptr == y.get()); |
189 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant get() call |
190 | // CHECK-MESSAGES: if (nullptr == y.get()); |
191 | // CHECK-FIXES: if (nullptr == y); |
192 | if (x.get() == NULL); |
193 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call |
194 | // CHECK-MESSAGES: if (x.get() == NULL); |
195 | // CHECK-FIXES: if (x == NULL); |
196 | if (NULL == x.get()); |
197 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant get() call |
198 | // CHECK-MESSAGES: if (NULL == x.get()); |
199 | // CHECK-FIXES: if (NULL == x); |
200 | } |
201 | |
202 | template <typename T> |
203 | void testTemplate() { |
204 | T().get()->Do(); |
205 | } |
206 | |
207 | template <typename T> |
208 | void testTemplate2() { |
209 | std::unique_ptr<T> up; |
210 | up.get()->Do(); |
211 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant get() call |
212 | // CHECK-FIXES: up->Do(); |
213 | } |
214 | |
215 | void instantiate() { |
216 | testTemplate<BarPtr>(); |
217 | testTemplate<std::unique_ptr<Bar>>(); |
218 | testTemplate<Fail2>(); |
219 | |
220 | testTemplate2<Bar>(); |
221 | } |
222 | |
223 | struct S { |
224 | |
225 | void foo() { |
226 | m_up.get()->Do(); |
227 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call |
228 | // CHECK-FIXES: m_up->Do(); |
229 | m_bp.get()->Do(); |
230 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant get() call |
231 | // CHECK-FIXES: m_bp->Do(); |
232 | } |
233 | |
234 | std::unique_ptr<Bar> m_up; |
235 | BarPtr m_bp; |
236 | }; |
237 | |
238 | #define MACRO(p) p.get() |
239 | |
240 | void Negative() { |
241 | struct NegPtr { |
242 | int* get(); |
243 | int* operator->() { |
244 | return &*this->get(); |
245 | } |
246 | int& operator*() { |
247 | return *get(); |
248 | } |
249 | }; |
250 | |
251 | long l = *PointerWithOverloadedGet().get<long>(); |
252 | |
253 | std::unique_ptr<Bar>* u; |
254 | u->get()->Do(); |
255 | |
256 | Fail1().get()->Do(); |
257 | Fail2().get()->Do(); |
258 | const Bar& b = *Fail1().get(); |
259 | (*Fail2().get()).Do(); |
260 | |
261 | int_ptr ip; |
262 | bool bb = ip.get() == nullptr; |
263 | bb = !ip.get(); |
264 | bb = ip.get() ? true : false; |
265 | std::unique_ptr<int> x; |
266 | if (MACRO(x) == nullptr) |
267 | ; |
268 | } |
269 | |
270 | void test_redundant_get() { |
271 | std::vector<std::shared_ptr<int>> v; |
272 | auto f = [](int) {}; |
273 | for (auto i = v.begin(); i != v.end(); ++i) { |
274 | f(*i->get()); |
275 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
276 | // CHECK-FIXES: f(**i); |
277 | } |
278 | } |
279 | |
280 | struct Inner { |
281 | int a; |
282 | int *getValue() { return &a; } |
283 | }; |
284 | |
285 | struct Example { |
286 | Inner inner; |
287 | Inner* get() { return &inner; } |
288 | int *getValue() { return inner.getValue(); } |
289 | }; |
290 | |
291 | void test_redundant_get_with_member() { |
292 | std::vector<std::shared_ptr<Example>> v; |
293 | auto f = [](int) {}; |
294 | for (auto i = v.begin(); i != v.end(); ++i) { |
295 | f(*(*i).get()->get()->getValue()); |
296 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: redundant get() call |
297 | // CHECK-FIXES: f(**i->get()->getValue()); |
298 | } |
299 | } |
300 | |
301 | void test_smart_ptr_to_array() { |
302 | std::unique_ptr<int[]> i; |
303 | // The array specialization does not have operator*(), so make sure |
304 | // we do not incorrectly suggest sizeof(*i) here. |
305 | // FIXME: alternatively, we could suggest sizeof(i[0]) |
306 | auto sz = sizeof(*i.get()); |
307 | |
308 | std::shared_ptr<Inner[]> s; |
309 | // The array specialization does not have operator->() either |
310 | s.get()->getValue(); |
311 | |
312 | bool b1 = !s.get(); |
313 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant get() call |
314 | // CHECK-FIXES: bool b1 = !s; |
315 | |
316 | if (s.get()) {} |
317 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant get() call |
318 | // CHECK-FIXES: if (s) {} |
319 | |
320 | int x = s.get() ? 1 : 2; |
321 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant get() call |
322 | // CHECK-FIXES: int x = s ? 1 : 2; |
323 | |
324 | bool b2 = s.get() == nullptr; |
325 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant get() call |
326 | // CHECK-FIXES: bool b2 = s == nullptr; |
327 | } |
328 | |