1 // RUN: %check_clang_tidy -std=c++98 %s modernize-use-nullptr %t -- -- -Wno-non-literal-null-conversion 2 // 3 // Some parts of the test (e.g. assignment of `const int` to `int *`) fail in 4 // C++11, so we need to run the test in C++98 mode. 5 // 6 // FIXME: Make the test work in all language modes. 7 8 const unsigned int g_null = 0; 9 #define NULL 0 10 11 void test_assignment() { 12 int *p1 = 0; 13 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr] 14 // CHECK-FIXES: int *p1 = nullptr; 15 p1 = 0; 16 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr 17 // CHECK-FIXES: p1 = nullptr; 18 19 int *p2 = NULL; 20 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr 21 // CHECK-FIXES: int *p2 = nullptr; 22 23 p2 = p1; 24 // CHECK-FIXES: p2 = p1; 25 26 const int null = 0; 27 int *p3 = null; 28 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr 29 // CHECK-FIXES: int *p3 = nullptr; 30 31 p3 = NULL; 32 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr 33 // CHECK-FIXES: p3 = nullptr; 34 35 int *p4 = p3; 36 // CHECK-FIXES: int *p4 = p3; 37 38 p4 = null; 39 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr 40 // CHECK-FIXES: p4 = nullptr; 41 42 int i1 = 0; 43 44 int i2 = NULL; 45 46 int i3 = null; 47 48 int *p5, *p6, *p7; 49 p5 = p6 = p7 = NULL; 50 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr 51 // CHECK-FIXES: p5 = p6 = p7 = nullptr; 52 } 53 54 struct Foo { 55 Foo(int *p = NULL) : m_p1(p) {} 56 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 57 // CHECK-FIXES: Foo(int *p = nullptr) : m_p1(p) {} 58 59 void bar(int *p = 0) {} 60 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use nullptr 61 // CHECK-FIXES: void bar(int *p = nullptr) {} 62 63 void baz(int i = 0) {} 64 65 int *m_p1; 66 static int *m_p2; 67 }; 68 69 int *Foo::m_p2 = NULL; 70 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr 71 // CHECK-FIXES: int *Foo::m_p2 = nullptr; 72 73 template <typename T> 74 struct Bar { 75 Bar(T *p) : m_p(p) { 76 m_p = static_cast<T*>(NULL); 77 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr 78 // CHECK-FIXES: m_p = static_cast<T*>(nullptr); 79 80 m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); 81 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr 82 // CHECK-FIXES: m_p = static_cast<T*>(nullptr); 83 84 m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null)); 85 // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr 86 // CHECK-FIXES: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr)); 87 88 T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); 89 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr 90 // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr); 91 92 m_p = NULL; 93 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr 94 // CHECK-FIXES: m_p = nullptr; 95 96 int i = static_cast<int>(0.f); 97 T *i2 = static_cast<int>(0.f); 98 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr 99 // CHECK-FIXES: T *i2 = nullptr; 100 } 101 102 T *m_p; 103 }; 104 105 struct Baz { 106 Baz() : i(0) {} 107 int i; 108 }; 109 110 void test_cxx_cases() { 111 Foo f(g_null); 112 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr 113 // CHECK-FIXES: Foo f(nullptr); 114 115 f.bar(NULL); 116 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr 117 // CHECK-FIXES: f.bar(nullptr); 118 119 f.baz(g_null); 120 121 f.m_p1 = 0; 122 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr 123 // CHECK-FIXES: f.m_p1 = nullptr; 124 125 Bar<int> b(g_null); 126 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr 127 // CHECK-FIXES: Bar<int> b(nullptr); 128 129 Baz b2; 130 int Baz::*memptr(0); 131 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr 132 // CHECK-FIXES: int Baz::*memptr(nullptr); 133 134 memptr = 0; 135 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr 136 // CHECK-FIXES: memptr = nullptr; 137 } 138 139 void test_function_default_param1(void *p = 0); 140 // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr 141 // CHECK-FIXES: void test_function_default_param1(void *p = nullptr); 142 143 void test_function_default_param2(void *p = NULL); 144 // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr 145 // CHECK-FIXES: void test_function_default_param2(void *p = nullptr); 146 147 void test_function_default_param3(void *p = g_null); 148 // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr 149 // CHECK-FIXES: void test_function_default_param3(void *p = nullptr); 150 151 void test_function(int *p) {} 152 153 void test_function_no_ptr_param(int i) {} 154 155 void test_function_call() { 156 test_function(0); 157 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr 158 // CHECK-FIXES: test_function(nullptr); 159 160 test_function(NULL); 161 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr 162 // CHECK-FIXES: test_function(nullptr); 163 164 test_function(g_null); 165 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr 166 // CHECK-FIXES: test_function(nullptr); 167 168 test_function_no_ptr_param(0); 169 } 170 171 char *test_function_return1() { 172 return 0; 173 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr 174 // CHECK-FIXES: return nullptr; 175 } 176 177 void *test_function_return2() { 178 return NULL; 179 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr 180 // CHECK-FIXES: return nullptr; 181 } 182 183 long *test_function_return3() { 184 return g_null; 185 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr 186 // CHECK-FIXES: return nullptr; 187 } 188 189 int test_function_return4() { 190 return 0; 191 } 192 193 int test_function_return5() { 194 return NULL; 195 } 196 197 int test_function_return6() { 198 return g_null; 199 } 200 201 int *test_function_return_cast1() { 202 return(int)0; 203 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr 204 // CHECK-FIXES: return nullptr; 205 } 206 207 int *test_function_return_cast2() { 208 #define RET return 209 RET(int)0; 210 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr 211 // CHECK-FIXES: RET nullptr; 212 #undef RET 213 } 214 215 // Test parentheses expressions resulting in a nullptr. 216 int *test_parentheses_expression1() { 217 return(0); 218 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr 219 // CHECK-FIXES: return(nullptr); 220 } 221 222 int *test_parentheses_expression2() { 223 return(int(0.f)); 224 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr 225 // CHECK-FIXES: return(nullptr); 226 } 227 228 int *test_nested_parentheses_expression() { 229 return((((0)))); 230 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr 231 // CHECK-FIXES: return((((nullptr)))); 232 } 233 234 void *test_parentheses_explicit_cast() { 235 return(static_cast<void*>(0)); 236 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr 237 // CHECK-FIXES: return(static_cast<void*>(nullptr)); 238 } 239 240 void *test_parentheses_explicit_cast_sequence1() { 241 return(static_cast<void*>(static_cast<int*>((void*)NULL))); 242 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr 243 // CHECK-FIXES: return(static_cast<void*>(nullptr)); 244 } 245 246 void *test_parentheses_explicit_cast_sequence2() { 247 return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f)))); 248 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr 249 // CHECK-FIXES: return(static_cast<void*>(nullptr)); 250 } 251 252 // Test explicit cast expressions resulting in nullptr. 253 struct Bam { 254 Bam(int *a) {} 255 Bam(float *a) {} 256 Bam operator=(int *a) { return Bam(a); } 257 Bam operator=(float *a) { return Bam(a); } 258 }; 259 260 void ambiguous_function(int *a) {} 261 void ambiguous_function(float *a) {} 262 void const_ambiguous_function(const int *p) {} 263 void const_ambiguous_function(const float *p) {} 264 265 void test_explicit_cast_ambiguous1() { 266 ambiguous_function((int*)0); 267 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr 268 // CHECK-FIXES: ambiguous_function((int*)nullptr); 269 } 270 271 void test_explicit_cast_ambiguous2() { 272 ambiguous_function((int*)(0)); 273 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr 274 // CHECK-FIXES: ambiguous_function((int*)nullptr); 275 } 276 277 void test_explicit_cast_ambiguous3() { 278 ambiguous_function(static_cast<int*>(reinterpret_cast<int*>((float*)0))); 279 // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use nullptr 280 // CHECK-FIXES: ambiguous_function(static_cast<int*>(nullptr)); 281 } 282 283 Bam test_explicit_cast_ambiguous4() { 284 return(((int*)(0))); 285 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr 286 // CHECK-FIXES: return(((int*)nullptr)); 287 } 288 289 void test_explicit_cast_ambiguous5() { 290 // Test for ambiguous overloaded constructors. 291 Bam k((int*)(0)); 292 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr 293 // CHECK-FIXES: Bam k((int*)nullptr); 294 295 // Test for ambiguous overloaded operators. 296 k = (int*)0; 297 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr 298 // CHECK-FIXES: k = (int*)nullptr; 299 } 300 301 void test_const_pointers_abiguous() { 302 const_ambiguous_function((int*)0); 303 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use nullptr 304 // CHECK-FIXES: const_ambiguous_function((int*)nullptr); 305 } 306 307 // Test where the implicit cast to null is surrounded by another implicit cast 308 // with possible explicit casts in-between. 309 void test_const_pointers() { 310 const int *const_p1 = 0; 311 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr 312 // CHECK-FIXES: const int *const_p1 = nullptr; 313 const int *const_p2 = NULL; 314 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr 315 // CHECK-FIXES: const int *const_p2 = nullptr; 316 const int *const_p3 = (int)0; 317 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr 318 // CHECK-FIXES: const int *const_p3 = nullptr; 319 const int *const_p4 = (int)0.0f; 320 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr 321 // CHECK-FIXES: const int *const_p4 = nullptr; 322 const int *const_p5 = (int*)0; 323 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr 324 // CHECK-FIXES: const int *const_p5 = (int*)nullptr; 325 int *t; 326 const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0)); 327 // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr 328 // CHECK-FIXES: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr)); 329 } 330 331 void test_nested_implicit_cast_expr() { 332 int func0(void*, void*); 333 int func1(int, void*, void*); 334 335 (double)func1(0, 0, 0); 336 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr 337 // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr 338 // CHECK-FIXES: (double)func1(0, nullptr, nullptr); 339 (double)func1(func0(0, 0), 0, 0); 340 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr 341 // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr 342 // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr 343 // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr 344 // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr); 345 } 346 347 // FIXME: currently, the check doesn't work as it should with templates. 348 template<typename T> 349 class A { 350 public: 351 A(T *p = NULL) {} 352 353 void f() { 354 Ptr = NULL; 355 } 356 T *Ptr; 357 }; 358 359 template<typename T> 360 T *f2(T *a = NULL) { 361 return a ? a : NULL; 362 } 363