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