1 // RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \
2 // RUN: -config="{CheckOptions: [{key: modernize-use-nullptr.NullMacros, value: '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
make_null()15 std::nullptr_t make_null() {
16 external();
17 return nullptr;
18 }
19
func()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
dummy(int *)29 void dummy(int*) {}
side_effect()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
test_macro_expansion1()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.
test_macro_expansion2()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
test_macro_expansion3()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
test_macro_expansion4()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 #define IS_EQ(x, y) if (x != y) return;
test_macro_args()88 void 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), {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.
210 class NoDef;
211 char function(NoDef *p);
212 #define F(x) (sizeof(function(x)) == 1)
213 template<class T, T t>
214 class C {};
215 C<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.
221 struct D {
DD222 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
test_default_argument()227 void test_default_argument() {
228 D(nullptr);
229 }
230
231 // Test on two neighbour CXXDefaultArgExprs nodes.
232 typedef unsigned long long uint64;
233 struct ZZ {
ZZZZ234 explicit ZZ(uint64, const uint64* = NULL) {}
235 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr
236 // CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {}
operator boolZZ237 operator bool() { return true; }
238 };
239
Hash(uint64 seed=0)240 uint64 Hash(uint64 seed = 0) { return 0; }
241
f()242 void f() {
243 bool a;
244 a = ZZ(Hash());
245 }
246
247 // Test on ignoring substituted template types.
248 template<typename T>
249 class TemplateClass {
250 public:
TemplateClass(int a,T default_value=0)251 explicit TemplateClass(int a, T default_value = 0) {}
252
h(T * default_value=0)253 void h(T *default_value = 0) {}
254
f(int * p=0)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
IgnoreSubstTemplateType()260 void IgnoreSubstTemplateType() {
261 TemplateClass<int*> a(1);
262 }
263
264 // Test on casting nullptr.
265 struct G {
GG266 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 };
270 bool g(const char*);
test_cast_nullptr()271 void 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.
279 class H {
280 public:
281 H(bool);
282 };
283
284 #define T(expression) H(expression);
285 bool h(int *, int *, int * = nullptr);
test_multiple_nulls()286 void 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