1// RUN: %check_clang_tidy --match-partial-fixes %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
87template <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};
105void 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;
113void 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), {.Ptr: 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.
235class NoDef;
236char function(NoDef *p);
237#define F(x) (sizeof(function(x)) == 1)
238template<class T, T t>
239class C {};
240C<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.
246struct 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
252void test_default_argument() {
253 D(nullptr);
254}
255
256// Test on two neighbour CXXDefaultArgExprs nodes.
257typedef unsigned long long uint64;
258struct 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
265uint64 Hash(uint64 seed = 0) { return 0; }
266
267void f() {
268 bool a;
269 a = ZZ(Hash());
270}
271
272// Test on ignoring substituted template types.
273template<typename T>
274class 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
285void IgnoreSubstTemplateType() {
286 TemplateClass<int*> a(1);
287}
288
289// Test on casting nullptr.
290struct 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};
295bool g(const char*);
296void 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.
304class H {
305public:
306 H(bool);
307};
308
309#define T(expression) H(expression);
310bool h(int *, int *, int * = nullptr);
311void 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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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