xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp (revision cebb7c010854e39a77065cfd681db91a79e7ce15)
1 // RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \
2 // RUN:   -config="{CheckOptions: {modernize-use-nullptr.NullMacros: 'MY_NULL,NULL'}}"
3 
4 #define NULL 0
5 
6 namespace std {
7 
8 typedef decltype(nullptr) nullptr_t;
9 
10 } // namespace std
11 
12 // Just to make sure make_null() could have side effects.
13 void external();
14 
15 std::nullptr_t make_null() {
16   external();
17   return nullptr;
18 }
19 
20 void func() {
21   void *CallTest = make_null();
22 
23   int var = 1;
24   void *CommaTest = (var+=2, make_null());
25 
26   int *CastTest = static_cast<int*>(make_null());
27 }
28 
29 void dummy(int*) {}
30 void side_effect() {}
31 
32 #define MACRO_EXPANSION_HAS_NULL \
33   void foo() { \
34     dummy(0); \
35     dummy(NULL); \
36     side_effect(); \
37   }
38 
39 MACRO_EXPANSION_HAS_NULL;
40 #undef MACRO_EXPANSION_HAS_NULL
41 
42 
43 void test_macro_expansion1() {
44 #define MACRO_EXPANSION_HAS_NULL \
45   dummy(NULL); \
46   side_effect();
47 
48   MACRO_EXPANSION_HAS_NULL;
49 
50 #undef MACRO_EXPANSION_HAS_NULL
51 }
52 
53 // Test macro expansion with cast sequence, PR15572.
54 void test_macro_expansion2() {
55 #define MACRO_EXPANSION_HAS_NULL \
56   dummy((int*)0); \
57   side_effect();
58 
59   MACRO_EXPANSION_HAS_NULL;
60 
61 #undef MACRO_EXPANSION_HAS_NULL
62 }
63 
64 void test_macro_expansion3() {
65 #define MACRO_EXPANSION_HAS_NULL \
66   dummy(NULL); \
67   side_effect();
68 
69 #define OUTER_MACRO \
70   MACRO_EXPANSION_HAS_NULL; \
71   side_effect();
72 
73   OUTER_MACRO;
74 
75 #undef OUTER_MACRO
76 #undef MACRO_EXPANSION_HAS_NULL
77 }
78 
79 void test_macro_expansion4() {
80 #define MY_NULL NULL
81   int *p = MY_NULL;
82   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
83   // CHECK-FIXES: int *p = nullptr;
84 #undef MY_NULL
85 }
86 
87 template <typename T> struct pear {
88   // If you say __null (or NULL), we assume that T will always be a pointer
89   // type, so we suggest replacing it with nullptr. (We only check __null here,
90   // because in this test NULL is defined as 0, but real library implementations
91   // it is often defined as __null and the check will catch it.)
92   void f() { x = __null; }
93   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr [modernize-use-nullptr]
94   // CHECK-FIXES: x = nullptr;
95 
96   // But if you say 0, we allow the possibility that T can be used with integral
97   // and pointer types, and "0" is an acceptable initializer (even if "{}" might
98   // be even better).
99   void g() { y = 0; }
100   // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use nullptr
101 
102   T x;
103   T y;
104 };
105 void test_templated() {
106   pear<int*> p;
107   p.f();
108   p.g();
109   dummy(p.x);
110 }
111 
112 #define IS_EQ(x, y) if (x != y) return;
113 void test_macro_args() {
114   int i = 0;
115   int *Ptr;
116 
117   IS_EQ(static_cast<int*>(0), Ptr);
118   // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
119   // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr);
120 
121   IS_EQ(0, Ptr);    // literal
122   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
123   // CHECK-FIXES: IS_EQ(nullptr, Ptr);
124 
125   IS_EQ(NULL, Ptr); // macro
126   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
127   // CHECK-FIXES: IS_EQ(nullptr, Ptr);
128 
129   // These are ok since the null literal is not spelled within a macro.
130 #define myassert(x) if (!(x)) return;
131   myassert(0 == Ptr);
132   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
133   // CHECK-FIXES: myassert(nullptr == Ptr);
134 
135   myassert(NULL == Ptr);
136   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
137   // CHECK-FIXES: myassert(nullptr == Ptr);
138 
139   // These are bad as the null literal is buried in a macro.
140 #define BLAH(X) myassert(0 == (X));
141 #define BLAH2(X) myassert(NULL == (X));
142   BLAH(Ptr);
143   BLAH2(Ptr);
144 
145   // Same as above but testing extra macro expansion.
146 #define EXPECT_NULL(X) IS_EQ(0, X);
147 #define EXPECT_NULL2(X) IS_EQ(NULL, X);
148   EXPECT_NULL(Ptr);
149   EXPECT_NULL2(Ptr);
150 
151   // Almost the same as above but now null literal is not in a macro so ok
152   // to transform.
153 #define EQUALS_PTR(X) IS_EQ(X, Ptr);
154   EQUALS_PTR(0);
155   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
156   // CHECK-FIXES: EQUALS_PTR(nullptr);
157   EQUALS_PTR(NULL);
158   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
159   // CHECK-FIXES: EQUALS_PTR(nullptr);
160 
161   // Same as above but testing extra macro expansion.
162 #define EQUALS_PTR_I(X) EQUALS_PTR(X)
163   EQUALS_PTR_I(0);
164   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
165   // CHECK-FIXES: EQUALS_PTR_I(nullptr);
166   EQUALS_PTR_I(NULL);
167   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
168   // CHECK-FIXES: EQUALS_PTR_I(nullptr);
169 
170   // Ok since null literal not within macro. However, now testing macro
171   // used as arg to another macro.
172 #define decorate(EXPR) side_effect(); EXPR;
173   decorate(IS_EQ(NULL, Ptr));
174   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
175   // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
176   decorate(IS_EQ(0, Ptr));
177   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
178   // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
179 
180   // This macro causes a NullToPointer cast to happen where 0 is assigned to z
181   // but the 0 literal cannot be replaced because it is also used as an
182   // integer in the comparison.
183 #define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
184   INT_AND_PTR_USE(0);
185 
186   // Both uses of X in this case result in NullToPointer casts so replacement
187   // is possible.
188 #define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
189   PTR_AND_PTR_USE(0);
190   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
191   // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
192   PTR_AND_PTR_USE(NULL);
193   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
194   // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
195 
196 #define OPTIONAL_CODE(...) __VA_ARGS__
197 #define NOT_NULL dummy(0)
198 #define CALL(X) X
199   OPTIONAL_CODE(NOT_NULL);
200   CALL(NOT_NULL);
201 
202 #define ENTRY(X) {X}
203   struct A {
204     int *Ptr;
205   } a[2] = {ENTRY(0), {0}};
206   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
207   // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
208   // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
209 #undef ENTRY
210 
211 #define assert1(expr) (expr) ? 0 : 1
212 #define assert2 assert1
213   int *p;
214   assert2(p == 0);
215   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
216   // CHECK-FIXES: assert2(p == nullptr);
217   assert2(p == NULL);
218   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
219   // CHECK-FIXES: assert2(p == nullptr);
220 #undef assert2
221 #undef assert1
222 
223 #define ASSERT_EQ(a, b) a == b
224 #define ASSERT_NULL(x) ASSERT_EQ(static_cast<void *>(NULL), x)
225   int *pp;
226   ASSERT_NULL(pp);
227   ASSERT_NULL(NULL);
228   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
229   // CHECK-FIXES: ASSERT_NULL(nullptr);
230 #undef ASSERT_NULL
231 #undef ASSERT_EQ
232 }
233 
234 // One of the ancestor of the cast is a NestedNameSpecifierLoc.
235 class NoDef;
236 char function(NoDef *p);
237 #define F(x) (sizeof(function(x)) == 1)
238 template<class T, T t>
239 class C {};
240 C<bool, F(0)> c;
241 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
242 // CHECK-FIXES: C<bool, F(nullptr)> c;
243 #undef F
244 
245 // Test default argument expression.
246 struct D {
247   explicit D(void *t, int *c = NULL) {}
248   // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use nullptr
249   // CHECK-FIXES: explicit D(void *t, int *c = nullptr) {}
250 };
251 
252 void test_default_argument() {
253   D(nullptr);
254 }
255 
256 // Test on two neighbour CXXDefaultArgExprs nodes.
257 typedef unsigned long long uint64;
258 struct ZZ {
259   explicit ZZ(uint64, const uint64* = NULL) {}
260 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
261 // CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
262   operator bool()  { return true; }
263 };
264 
265 uint64 Hash(uint64 seed = 0) { return 0; }
266 
267 void f() {
268   bool a;
269   a = ZZ(Hash());
270 }
271 
272 // Test on ignoring substituted template types.
273 template<typename T>
274 class TemplateClass {
275  public:
276   explicit TemplateClass(int a, T default_value = 0) {}
277 
278   void h(T *default_value = 0) {}
279 
280   void f(int* p = 0) {}
281 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
282 // CHECK-FIXES: void f(int* p = nullptr) {}
283 };
284 
285 void IgnoreSubstTemplateType() {
286   TemplateClass<int*> a(1);
287 }
288 
289 // Test on casting nullptr.
290 struct G {
291   explicit G(bool, const char * = NULL) {}
292   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr
293   // CHECK-FIXES: explicit G(bool, const char * = nullptr) {}
294 };
295 bool g(const char*);
296 void test_cast_nullptr() {
297   G(g(nullptr));
298   G(g((nullptr)));
299   G(g(static_cast<char*>(nullptr)));
300   G(g(static_cast<const char*>(nullptr)));
301 }
302 
303 // Test on recognizing multiple NULLs.
304 class H {
305 public:
306   H(bool);
307 };
308 
309 #define T(expression) H(expression);
310 bool h(int *, int *, int * = nullptr);
311 void test_multiple_nulls() {
312   T(h(NULL, NULL));
313 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
314 // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
315 // CHECK-FIXES: T(h(nullptr, nullptr));
316   T(h(NULL, nullptr));
317 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
318 // CHECK-FIXES: T(h(nullptr, nullptr));
319   T(h(nullptr, NULL));
320 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
321 // CHECK-FIXES: T(h(nullptr, nullptr));
322   T(h(nullptr, nullptr));
323   T(h(NULL, NULL, NULL));
324 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
325 // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
326 // CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr
327 // CHECK-FIXES: T(h(nullptr, nullptr, nullptr));
328 }
329 #undef T
330