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
6namespace std {
7
8typedef decltype(nullptr) nullptr_t;
9
10} // namespace std
11
12// Just to make sure make_null() could have side effects.
13void external();
14
15std::nullptr_t make_null() {
16 external();
17 return nullptr;
18}
19
20void 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
29void dummy(int*) {}
30void side_effect() {}
31
32#define MACRO_EXPANSION_HAS_NULL \
33 void foo() { \
34 dummy(0); \
35 dummy(NULL); \
36 side_effect(); \
37 }
38
39MACRO_EXPANSION_HAS_NULL;
40#undef MACRO_EXPANSION_HAS_NULL
41
42
43void 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.
54void 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
64void 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
79void 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#define IS_EQ(x, y) if (x != y) return;
88void test_macro_args() {
89 int i = 0;
90 int *Ptr;
91
92 IS_EQ(static_cast<int*>(0), Ptr);
93 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
94 // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr);
95
96 IS_EQ(0, Ptr); // literal
97 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
98 // CHECK-FIXES: IS_EQ(nullptr, Ptr);
99
100 IS_EQ(NULL, Ptr); // macro
101 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
102 // CHECK-FIXES: IS_EQ(nullptr, Ptr);
103
104 // These are ok since the null literal is not spelled within a macro.
105#define myassert(x) if (!(x)) return;
106 myassert(0 == Ptr);
107 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
108 // CHECK-FIXES: myassert(nullptr == Ptr);
109
110 myassert(NULL == Ptr);
111 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
112 // CHECK-FIXES: myassert(nullptr == Ptr);
113
114 // These are bad as the null literal is buried in a macro.
115#define BLAH(X) myassert(0 == (X));
116#define BLAH2(X) myassert(NULL == (X));
117 BLAH(Ptr);
118 BLAH2(Ptr);
119
120 // Same as above but testing extra macro expansion.
121#define EXPECT_NULL(X) IS_EQ(0, X);
122#define EXPECT_NULL2(X) IS_EQ(NULL, X);
123 EXPECT_NULL(Ptr);
124 EXPECT_NULL2(Ptr);
125
126 // Almost the same as above but now null literal is not in a macro so ok
127 // to transform.
128#define EQUALS_PTR(X) IS_EQ(X, Ptr);
129 EQUALS_PTR(0);
130 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
131 // CHECK-FIXES: EQUALS_PTR(nullptr);
132 EQUALS_PTR(NULL);
133 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
134 // CHECK-FIXES: EQUALS_PTR(nullptr);
135
136 // Same as above but testing extra macro expansion.
137#define EQUALS_PTR_I(X) EQUALS_PTR(X)
138 EQUALS_PTR_I(0);
139 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
140 // CHECK-FIXES: EQUALS_PTR_I(nullptr);
141 EQUALS_PTR_I(NULL);
142 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
143 // CHECK-FIXES: EQUALS_PTR_I(nullptr);
144
145 // Ok since null literal not within macro. However, now testing macro
146 // used as arg to another macro.
147#define decorate(EXPR) side_effect(); EXPR;
148 decorate(IS_EQ(NULL, Ptr));
149 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
150 // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
151 decorate(IS_EQ(0, Ptr));
152 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
153 // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
154
155 // This macro causes a NullToPointer cast to happen where 0 is assigned to z
156 // but the 0 literal cannot be replaced because it is also used as an
157 // integer in the comparison.
158#define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
159 INT_AND_PTR_USE(0);
160
161 // Both uses of X in this case result in NullToPointer casts so replacement
162 // is possible.
163#define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
164 PTR_AND_PTR_USE(0);
165 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
166 // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
167 PTR_AND_PTR_USE(NULL);
168 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
169 // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
170
171#define OPTIONAL_CODE(...) __VA_ARGS__
172#define NOT_NULL dummy(0)
173#define CALL(X) X
174 OPTIONAL_CODE(NOT_NULL);
175 CALL(NOT_NULL);
176
177#define ENTRY(X) {X}
178 struct A {
179 int *Ptr;
180 } a[2] = {ENTRY(0), {.Ptr: 0}};
181 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
182 // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
183 // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
184#undef ENTRY
185
186#define assert1(expr) (expr) ? 0 : 1
187#define assert2 assert1
188 int *p;
189 assert2(p == 0);
190 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
191 // CHECK-FIXES: assert2(p == nullptr);
192 assert2(p == NULL);
193 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
194 // CHECK-FIXES: assert2(p == nullptr);
195#undef assert2
196#undef assert1
197
198#define ASSERT_EQ(a, b) a == b
199#define ASSERT_NULL(x) ASSERT_EQ(static_cast<void *>(NULL), x)
200 int *pp;
201 ASSERT_NULL(pp);
202 ASSERT_NULL(NULL);
203 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr
204 // CHECK-FIXES: ASSERT_NULL(nullptr);
205#undef ASSERT_NULL
206#undef ASSERT_EQ
207}
208
209// One of the ancestor of the cast is a NestedNameSpecifierLoc.
210class NoDef;
211char function(NoDef *p);
212#define F(x) (sizeof(function(x)) == 1)
213template<class T, T t>
214class C {};
215C<bool, F(0)> c;
216// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
217// CHECK-FIXES: C<bool, F(nullptr)> c;
218#undef F
219
220// Test default argument expression.
221struct D {
222 explicit D(void *t, int *c = NULL) {}
223 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use nullptr
224 // CHECK-FIXES: explicit D(void *t, int *c = nullptr) {}
225};
226
227void test_default_argument() {
228 D(nullptr);
229}
230
231// Test on two neighbour CXXDefaultArgExprs nodes.
232typedef unsigned long long uint64;
233struct ZZ {
234 explicit ZZ(uint64, const uint64* = NULL) {}
235// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
236// CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
237 operator bool() { return true; }
238};
239
240uint64 Hash(uint64 seed = 0) { return 0; }
241
242void f() {
243 bool a;
244 a = ZZ(Hash());
245}
246
247// Test on ignoring substituted template types.
248template<typename T>
249class TemplateClass {
250 public:
251 explicit TemplateClass(int a, T default_value = 0) {}
252
253 void h(T *default_value = 0) {}
254
255 void f(int* p = 0) {}
256// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
257// CHECK-FIXES: void f(int* p = nullptr) {}
258};
259
260void IgnoreSubstTemplateType() {
261 TemplateClass<int*> a(1);
262}
263
264// Test on casting nullptr.
265struct G {
266 explicit G(bool, const char * = NULL) {}
267 // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr
268 // CHECK-FIXES: explicit G(bool, const char * = nullptr) {}
269};
270bool g(const char*);
271void test_cast_nullptr() {
272 G(g(nullptr));
273 G(g((nullptr)));
274 G(g(static_cast<char*>(nullptr)));
275 G(g(static_cast<const char*>(nullptr)));
276}
277
278// Test on recognizing multiple NULLs.
279class H {
280public:
281 H(bool);
282};
283
284#define T(expression) H(expression);
285bool h(int *, int *, int * = nullptr);
286void test_multiple_nulls() {
287 T(h(NULL, NULL));
288// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
289// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
290// CHECK-FIXES: T(h(nullptr, nullptr));
291 T(h(NULL, nullptr));
292// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
293// CHECK-FIXES: T(h(nullptr, nullptr));
294 T(h(nullptr, NULL));
295// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
296// CHECK-FIXES: T(h(nullptr, nullptr));
297 T(h(nullptr, nullptr));
298 T(h(NULL, NULL, NULL));
299// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr
300// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr
301// CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr
302// CHECK-FIXES: T(h(nullptr, nullptr, nullptr));
303}
304#undef T
305

source code of clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp