// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- -- \ // RUN: -std=c++98 -Wno-non-literal-null-conversion // // Some parts of the test (e.g. assignment of `const int` to `int *`) fail in // C++11, so we need to run the test in C++98 mode. const unsigned int g_null = 0; #define NULL 0 void test_assignment() { int *p1 = 0; // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr] // CHECK-FIXES: int *p1 = nullptr; p1 = 0; // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr // CHECK-FIXES: p1 = nullptr; int *p2 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr // CHECK-FIXES: int *p2 = nullptr; p2 = p1; // CHECK-FIXES: p2 = p1; const int null = 0; int *p3 = null; // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr // CHECK-FIXES: int *p3 = nullptr; p3 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr // CHECK-FIXES: p3 = nullptr; int *p4 = p3; // CHECK-FIXES: int *p4 = p3; p4 = null; // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr // CHECK-FIXES: p4 = nullptr; int i1 = 0; int i2 = NULL; int i3 = null; int *p5, *p6, *p7; p5 = p6 = p7 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr // CHECK-FIXES: p5 = p6 = p7 = nullptr; } struct Foo { Foo(int *p = NULL) : m_p1(p) {} // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr // CHECK-FIXES: Foo(int *p = nullptr) : m_p1(p) {} void bar(int *p = 0) {} // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use nullptr // CHECK-FIXES: void bar(int *p = nullptr) {} void baz(int i = 0) {} int *m_p1; static int *m_p2; }; int *Foo::m_p2 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr // CHECK-FIXES: int *Foo::m_p2 = nullptr; template struct Bar { Bar(T *p) : m_p(p) { m_p = static_cast(NULL); // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr // CHECK-FIXES: m_p = static_cast(nullptr); m_p = static_cast(reinterpret_cast((void*)NULL)); // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr // CHECK-FIXES: m_p = static_cast(nullptr); m_p = static_cast(p ? p : static_cast(g_null)); // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr // CHECK-FIXES: m_p = static_cast(p ? p : static_cast(nullptr)); T *p2 = static_cast(reinterpret_cast((void*)NULL)); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr // CHECK-FIXES: T *p2 = static_cast(nullptr); m_p = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr // CHECK-FIXES: m_p = nullptr; int i = static_cast(0.f); T *i2 = static_cast(0.f); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr // CHECK-FIXES: T *i2 = nullptr; } T *m_p; }; struct Baz { Baz() : i(0) {} int i; }; void test_cxx_cases() { Foo f(g_null); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr // CHECK-FIXES: Foo f(nullptr); f.bar(NULL); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr // CHECK-FIXES: f.bar(nullptr); f.baz(g_null); f.m_p1 = 0; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr // CHECK-FIXES: f.m_p1 = nullptr; Bar b(g_null); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr // CHECK-FIXES: Bar b(nullptr); Baz b2; int Baz::*memptr(0); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr // CHECK-FIXES: int Baz::*memptr(nullptr); memptr = 0; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr // CHECK-FIXES: memptr = nullptr; } void test_function_default_param1(void *p = 0); // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr // CHECK-FIXES: void test_function_default_param1(void *p = nullptr); void test_function_default_param2(void *p = NULL); // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr // CHECK-FIXES: void test_function_default_param2(void *p = nullptr); void test_function_default_param3(void *p = g_null); // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr // CHECK-FIXES: void test_function_default_param3(void *p = nullptr); void test_function(int *p) {} void test_function_no_ptr_param(int i) {} void test_function_call() { test_function(0); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr // CHECK-FIXES: test_function(nullptr); test_function(NULL); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr // CHECK-FIXES: test_function(nullptr); test_function(g_null); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr // CHECK-FIXES: test_function(nullptr); test_function_no_ptr_param(0); } char *test_function_return1() { return 0; // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return nullptr; } void *test_function_return2() { return NULL; // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return nullptr; } long *test_function_return3() { return g_null; // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return nullptr; } int test_function_return4() { return 0; } int test_function_return5() { return NULL; } int test_function_return6() { return g_null; } int *test_function_return_cast1() { return(int)0; // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr // CHECK-FIXES: return nullptr; } int *test_function_return_cast2() { #define RET return RET(int)0; // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr // CHECK-FIXES: RET nullptr; #undef RET } // Test parentheses expressions resulting in a nullptr. int *test_parentheses_expression1() { return(0); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return(nullptr); } int *test_parentheses_expression2() { return(int(0.f)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return(nullptr); } int *test_nested_parentheses_expression() { return((((0)))); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr // CHECK-FIXES: return((((nullptr)))); } void *test_parentheses_explicit_cast() { return(static_cast(0)); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr // CHECK-FIXES: return(static_cast(nullptr)); } void *test_parentheses_explicit_cast_sequence1() { return(static_cast(static_cast((void*)NULL))); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr // CHECK-FIXES: return(static_cast(nullptr)); } void *test_parentheses_explicit_cast_sequence2() { return(static_cast(reinterpret_cast((float*)int(0.f)))); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr // CHECK-FIXES: return(static_cast(nullptr)); } // Test explicit cast expressions resulting in nullptr. struct Bam { Bam(int *a) {} Bam(float *a) {} Bam operator=(int *a) { return Bam(a); } Bam operator=(float *a) { return Bam(a); } }; void ambiguous_function(int *a) {} void ambiguous_function(float *a) {} void const_ambiguous_function(const int *p) {} void const_ambiguous_function(const float *p) {} void test_explicit_cast_ambiguous1() { ambiguous_function((int*)0); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr // CHECK-FIXES: ambiguous_function((int*)nullptr); } void test_explicit_cast_ambiguous2() { ambiguous_function((int*)(0)); // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use nullptr // CHECK-FIXES: ambiguous_function((int*)nullptr); } void test_explicit_cast_ambiguous3() { ambiguous_function(static_cast(reinterpret_cast((float*)0))); // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use nullptr // CHECK-FIXES: ambiguous_function(static_cast(nullptr)); } Bam test_explicit_cast_ambiguous4() { return(((int*)(0))); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr // CHECK-FIXES: return(((int*)nullptr)); } void test_explicit_cast_ambiguous5() { // Test for ambiguous overloaded constructors. Bam k((int*)(0)); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr // CHECK-FIXES: Bam k((int*)nullptr); // Test for ambiguous overloaded operators. k = (int*)0; // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr // CHECK-FIXES: k = (int*)nullptr; } void test_const_pointers_abiguous() { const_ambiguous_function((int*)0); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use nullptr // CHECK-FIXES: const_ambiguous_function((int*)nullptr); } // Test where the implicit cast to null is surrounded by another implict cast // with possible explict casts in-between. void test_const_pointers() { const int *const_p1 = 0; // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr // CHECK-FIXES: const int *const_p1 = nullptr; const int *const_p2 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr // CHECK-FIXES: const int *const_p2 = nullptr; const int *const_p3 = (int)0; // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr // CHECK-FIXES: const int *const_p3 = nullptr; const int *const_p4 = (int)0.0f; // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr // CHECK-FIXES: const int *const_p4 = nullptr; const int *const_p5 = (int*)0; // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr // CHECK-FIXES: const int *const_p5 = (int*)nullptr; int *t; const int *const_p6 = static_cast(t ? t : static_cast(0)); // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr // CHECK-FIXES: const int *const_p6 = static_cast(t ? t : static_cast(nullptr)); } void test_nested_implicit_cast_expr() { int func0(void*, void*); int func1(int, void*, void*); (double)func1(0, 0, 0); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr // CHECK-FIXES: (double)func1(0, nullptr, nullptr); (double)func1(func0(0, 0), 0, 0); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr); } // FIXME: currently, the check doesn't work as it should with templates. template class A { public: A(T *p = NULL) {} void f() { Ptr = NULL; } T *Ptr; }; template T *f2(T *a = NULL) { return a ? a : NULL; }