1 | // RUN: %check_clang_tidy -std=c++98 %s modernize-use-nullptr %t -- -- -Wno-non-literal-null-conversion |
2 | // |
3 | // Some parts of the test (e.g. assignment of `const int` to `int *`) fail in |
4 | // C++11, so we need to run the test in C++98 mode. |
5 | // |
6 | // FIXME: Make the test work in all language modes. |
7 | |
8 | const unsigned int g_null = 0; |
9 | #define NULL 0 |
10 | |
11 | void test_assignment() { |
12 | int *p1 = 0; |
13 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr] |
14 | // CHECK-FIXES: int *p1 = nullptr; |
15 | p1 = 0; |
16 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr |
17 | // CHECK-FIXES: p1 = nullptr; |
18 | |
19 | int *p2 = NULL; |
20 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr |
21 | // CHECK-FIXES: int *p2 = nullptr; |
22 | |
23 | p2 = p1; |
24 | // CHECK-FIXES: p2 = p1; |
25 | |
26 | const int null = 0; |
27 | int *p3 = null; |
28 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr |
29 | // CHECK-FIXES: int *p3 = nullptr; |
30 | |
31 | p3 = NULL; |
32 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr |
33 | // CHECK-FIXES: p3 = nullptr; |
34 | |
35 | int *p4 = p3; |
36 | // CHECK-FIXES: int *p4 = p3; |
37 | |
38 | p4 = null; |
39 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr |
40 | // CHECK-FIXES: p4 = nullptr; |
41 | |
42 | int i1 = 0; |
43 | |
44 | int i2 = NULL; |
45 | |
46 | int i3 = null; |
47 | |
48 | int *p5, *p6, *p7; |
49 | p5 = p6 = p7 = NULL; |
50 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr |
51 | // CHECK-FIXES: p5 = p6 = p7 = nullptr; |
52 | } |
53 | |
54 | struct Foo { |
55 | Foo(int *p = NULL) : m_p1(p) {} |
56 | // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr |
57 | // CHECK-FIXES: Foo(int *p = nullptr) : m_p1(p) {} |
58 | |
59 | void bar(int *p = 0) {} |
60 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use nullptr |
61 | // CHECK-FIXES: void bar(int *p = nullptr) {} |
62 | |
63 | void baz(int i = 0) {} |
64 | |
65 | int *m_p1; |
66 | static int *m_p2; |
67 | }; |
68 | |
69 | int *Foo::m_p2 = NULL; |
70 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr |
71 | // CHECK-FIXES: int *Foo::m_p2 = nullptr; |
72 | |
73 | template <typename T> |
74 | struct Bar { |
75 | Bar(T *p) : m_p(p) { |
76 | m_p = static_cast<T*>(NULL); |
77 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr |
78 | // CHECK-FIXES: m_p = static_cast<T*>(nullptr); |
79 | |
80 | m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); |
81 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr |
82 | // CHECK-FIXES: m_p = static_cast<T*>(nullptr); |
83 | |
84 | m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null)); |
85 | // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr |
86 | // CHECK-FIXES: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr)); |
87 | |
88 | T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); |
89 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr |
90 | // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr); |
91 | |
92 | m_p = NULL; |
93 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr |
94 | // CHECK-FIXES: m_p = nullptr; |
95 | |
96 | int i = static_cast<int>(0.f); |
97 | T *i2 = static_cast<int>(0.f); |
98 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr |
99 | // CHECK-FIXES: T *i2 = nullptr; |
100 | } |
101 | |
102 | T *m_p; |
103 | }; |
104 | |
105 | struct Baz { |
106 | Baz() : i(0) {} |
107 | int i; |
108 | }; |
109 | |
110 | void test_cxx_cases() { |
111 | Foo f(g_null); |
112 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr |
113 | // CHECK-FIXES: Foo f(nullptr); |
114 | |
115 | f.bar(NULL); |
116 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr |
117 | // CHECK-FIXES: f.bar(nullptr); |
118 | |
119 | f.baz(i: g_null); |
120 | |
121 | f.m_p1 = 0; |
122 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr |
123 | // CHECK-FIXES: f.m_p1 = nullptr; |
124 | |
125 | Bar<int> b(g_null); |
126 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr |
127 | // CHECK-FIXES: Bar<int> b(nullptr); |
128 | |
129 | Baz b2; |
130 | int Baz::*memptr(0); |
131 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr |
132 | // CHECK-FIXES: int Baz::*memptr(nullptr); |
133 | |
134 | memptr = 0; |
135 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr |
136 | // CHECK-FIXES: memptr = nullptr; |
137 | } |
138 | |
139 | void test_function_default_param1(void *p = 0); |
140 | // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr |
141 | // CHECK-FIXES: void test_function_default_param1(void *p = nullptr); |
142 | |
143 | void test_function_default_param2(void *p = NULL); |
144 | // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr |
145 | // CHECK-FIXES: void test_function_default_param2(void *p = nullptr); |
146 | |
147 | void test_function_default_param3(void *p = g_null); |
148 | // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr |
149 | // CHECK-FIXES: void test_function_default_param3(void *p = nullptr); |
150 | |
151 | void test_function(int *p) {} |
152 | |
153 | void test_function_no_ptr_param(int i) {} |
154 | |
155 | void test_function_call() { |
156 | test_function(p: 0); |
157 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr |
158 | // CHECK-FIXES: test_function(nullptr); |
159 | |
160 | test_function(NULL); |
161 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr |
162 | // CHECK-FIXES: test_function(nullptr); |
163 | |
164 | test_function(g_null); |
165 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr |
166 | // CHECK-FIXES: test_function(nullptr); |
167 | |
168 | test_function_no_ptr_param(i: 0); |
169 | } |
170 | |
171 | char *test_function_return1() { |
172 | return 0; |
173 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr |
174 | // CHECK-FIXES: return nullptr; |
175 | } |
176 | |
177 | void *test_function_return2() { |
178 | return NULL; |
179 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr |
180 | // CHECK-FIXES: return nullptr; |
181 | } |
182 | |
183 | long *test_function_return3() { |
184 | return g_null; |
185 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr |
186 | // CHECK-FIXES: return nullptr; |
187 | } |
188 | |
189 | int test_function_return4() { |
190 | return 0; |
191 | } |
192 | |
193 | int test_function_return5() { |
194 | return NULL; |
195 | } |
196 | |
197 | int test_function_return6() { |
198 | return g_null; |
199 | } |
200 | |
201 | int *test_function_return_cast1() { |
202 | return(int)0; |
203 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr |
204 | // CHECK-FIXES: return nullptr; |
205 | } |
206 | |
207 | int *test_function_return_cast2() { |
208 | #define RET return |
209 | RET(int)0; |
210 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr |
211 | // CHECK-FIXES: RET nullptr; |
212 | #undef RET |
213 | } |
214 | |
215 | // Test parentheses expressions resulting in a nullptr. |
216 | int *test_parentheses_expression1() { |
217 | return(0); |
218 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr |
219 | // CHECK-FIXES: return(nullptr); |
220 | } |
221 | |
222 | int *test_parentheses_expression2() { |
223 | return(int(0.f)); |
224 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr |
225 | // CHECK-FIXES: return(nullptr); |
226 | } |
227 | |
228 | int *test_nested_parentheses_expression() { |
229 | return((((0)))); |
230 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr |
231 | // CHECK-FIXES: return((((nullptr)))); |
232 | } |
233 | |
234 | void *test_parentheses_explicit_cast() { |
235 | return(static_cast<void*>(0)); |
236 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr |
237 | // CHECK-FIXES: return(static_cast<void*>(nullptr)); |
238 | } |
239 | |
240 | void *test_parentheses_explicit_cast_sequence1() { |
241 | return(static_cast<void*>(static_cast<int*>((void*)NULL))); |
242 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr |
243 | // CHECK-FIXES: return(static_cast<void*>(nullptr)); |
244 | } |
245 | |
246 | void *test_parentheses_explicit_cast_sequence2() { |
247 | return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f)))); |
248 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr |
249 | // CHECK-FIXES: return(static_cast<void*>(nullptr)); |
250 | } |
251 | |
252 | // Test explicit cast expressions resulting in nullptr. |
253 | struct Bam { |
254 | Bam(int *a) {} |
255 | Bam(float *a) {} |
256 | Bam operator=(int *a) { return Bam(a); } |
257 | Bam operator=(float *a) { return Bam(a); } |
258 | }; |
259 | |
260 | void ambiguous_function(int *a) {} |
261 | void ambiguous_function(float *a) {} |
262 | void const_ambiguous_function(const int *p) {} |
263 | void const_ambiguous_function(const float *p) {} |
264 | |
265 | void test_explicit_cast_ambiguous1() { |
266 | ambiguous_function(a: (int*)0); |
267 | // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr |
268 | // CHECK-FIXES: ambiguous_function((int*)nullptr); |
269 | } |
270 | |
271 | void test_explicit_cast_ambiguous2() { |
272 | ambiguous_function(a: (int*)(0)); |
273 | // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr |
274 | // CHECK-FIXES: ambiguous_function((int*)nullptr); |
275 | } |
276 | |
277 | void test_explicit_cast_ambiguous3() { |
278 | ambiguous_function(a: static_cast<int*>(reinterpret_cast<int*>((float*)0))); |
279 | // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use nullptr |
280 | // CHECK-FIXES: ambiguous_function(static_cast<int*>(nullptr)); |
281 | } |
282 | |
283 | Bam test_explicit_cast_ambiguous4() { |
284 | return(((int*)(0))); |
285 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr |
286 | // CHECK-FIXES: return(((int*)nullptr)); |
287 | } |
288 | |
289 | void test_explicit_cast_ambiguous5() { |
290 | // Test for ambiguous overloaded constructors. |
291 | Bam k((int*)(0)); |
292 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr |
293 | // CHECK-FIXES: Bam k((int*)nullptr); |
294 | |
295 | // Test for ambiguous overloaded operators. |
296 | k = (int*)0; |
297 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr |
298 | // CHECK-FIXES: k = (int*)nullptr; |
299 | } |
300 | |
301 | void test_const_pointers_abiguous() { |
302 | const_ambiguous_function(p: (int*)0); |
303 | // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use nullptr |
304 | // CHECK-FIXES: const_ambiguous_function((int*)nullptr); |
305 | } |
306 | |
307 | // Test where the implicit cast to null is surrounded by another implicit cast |
308 | // with possible explicit casts in-between. |
309 | void test_const_pointers() { |
310 | const int *const_p1 = 0; |
311 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr |
312 | // CHECK-FIXES: const int *const_p1 = nullptr; |
313 | const int *const_p2 = NULL; |
314 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr |
315 | // CHECK-FIXES: const int *const_p2 = nullptr; |
316 | const int *const_p3 = (int)0; |
317 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr |
318 | // CHECK-FIXES: const int *const_p3 = nullptr; |
319 | const int *const_p4 = (int)0.0f; |
320 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr |
321 | // CHECK-FIXES: const int *const_p4 = nullptr; |
322 | const int *const_p5 = (int*)0; |
323 | // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr |
324 | // CHECK-FIXES: const int *const_p5 = (int*)nullptr; |
325 | int *t; |
326 | const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0)); |
327 | // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr |
328 | // CHECK-FIXES: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr)); |
329 | } |
330 | |
331 | void test_nested_implicit_cast_expr() { |
332 | int func0(void*, void*); |
333 | int func1(int, void*, void*); |
334 | |
335 | (double)func1(0, 0, 0); |
336 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr |
337 | // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr |
338 | // CHECK-FIXES: (double)func1(0, nullptr, nullptr); |
339 | (double)func1(func0(0, 0), 0, 0); |
340 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr |
341 | // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr |
342 | // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr |
343 | // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr |
344 | // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr); |
345 | } |
346 | |
347 | // FIXME: currently, the check doesn't work as it should with templates. |
348 | template<typename T> |
349 | class A { |
350 | public: |
351 | A(T *p = NULL) {} |
352 | |
353 | void f() { |
354 | Ptr = NULL; |
355 | } |
356 | T *Ptr; |
357 | }; |
358 | |
359 | template<typename T> |
360 | T *f2(T *a = NULL) { |
361 | return a ? a : NULL; |
362 | } |
363 | |