189a1d03eSRichard // RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \ 2e8a3ddafSNathan James // RUN: -config="{CheckOptions: {modernize-use-nullptr.NullMacros: 'MY_NULL,NULL'}}" 389a1d03eSRichard 489a1d03eSRichard #define NULL 0 589a1d03eSRichard 689a1d03eSRichard namespace std { 789a1d03eSRichard 889a1d03eSRichard typedef decltype(nullptr) nullptr_t; 989a1d03eSRichard 1089a1d03eSRichard } // namespace std 1189a1d03eSRichard 1289a1d03eSRichard // Just to make sure make_null() could have side effects. 1389a1d03eSRichard void external(); 1489a1d03eSRichard 1589a1d03eSRichard std::nullptr_t make_null() { 1689a1d03eSRichard external(); 1789a1d03eSRichard return nullptr; 1889a1d03eSRichard } 1989a1d03eSRichard 2089a1d03eSRichard void func() { 2189a1d03eSRichard void *CallTest = make_null(); 2289a1d03eSRichard 2389a1d03eSRichard int var = 1; 2489a1d03eSRichard void *CommaTest = (var+=2, make_null()); 2589a1d03eSRichard 2689a1d03eSRichard int *CastTest = static_cast<int*>(make_null()); 2789a1d03eSRichard } 2889a1d03eSRichard 2989a1d03eSRichard void dummy(int*) {} 3089a1d03eSRichard void side_effect() {} 3189a1d03eSRichard 3289a1d03eSRichard #define MACRO_EXPANSION_HAS_NULL \ 3389a1d03eSRichard void foo() { \ 3489a1d03eSRichard dummy(0); \ 3589a1d03eSRichard dummy(NULL); \ 3689a1d03eSRichard side_effect(); \ 3789a1d03eSRichard } 3889a1d03eSRichard 3989a1d03eSRichard MACRO_EXPANSION_HAS_NULL; 4089a1d03eSRichard #undef MACRO_EXPANSION_HAS_NULL 4189a1d03eSRichard 4289a1d03eSRichard 4389a1d03eSRichard void test_macro_expansion1() { 4489a1d03eSRichard #define MACRO_EXPANSION_HAS_NULL \ 4589a1d03eSRichard dummy(NULL); \ 4689a1d03eSRichard side_effect(); 4789a1d03eSRichard 4889a1d03eSRichard MACRO_EXPANSION_HAS_NULL; 4989a1d03eSRichard 5089a1d03eSRichard #undef MACRO_EXPANSION_HAS_NULL 5189a1d03eSRichard } 5289a1d03eSRichard 5389a1d03eSRichard // Test macro expansion with cast sequence, PR15572. 5489a1d03eSRichard void test_macro_expansion2() { 5589a1d03eSRichard #define MACRO_EXPANSION_HAS_NULL \ 5689a1d03eSRichard dummy((int*)0); \ 5789a1d03eSRichard side_effect(); 5889a1d03eSRichard 5989a1d03eSRichard MACRO_EXPANSION_HAS_NULL; 6089a1d03eSRichard 6189a1d03eSRichard #undef MACRO_EXPANSION_HAS_NULL 6289a1d03eSRichard } 6389a1d03eSRichard 6489a1d03eSRichard void test_macro_expansion3() { 6589a1d03eSRichard #define MACRO_EXPANSION_HAS_NULL \ 6689a1d03eSRichard dummy(NULL); \ 6789a1d03eSRichard side_effect(); 6889a1d03eSRichard 6989a1d03eSRichard #define OUTER_MACRO \ 7089a1d03eSRichard MACRO_EXPANSION_HAS_NULL; \ 7189a1d03eSRichard side_effect(); 7289a1d03eSRichard 7389a1d03eSRichard OUTER_MACRO; 7489a1d03eSRichard 7589a1d03eSRichard #undef OUTER_MACRO 7689a1d03eSRichard #undef MACRO_EXPANSION_HAS_NULL 7789a1d03eSRichard } 7889a1d03eSRichard 7989a1d03eSRichard void test_macro_expansion4() { 8089a1d03eSRichard #define MY_NULL NULL 8189a1d03eSRichard int *p = MY_NULL; 8289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr] 8389a1d03eSRichard // CHECK-FIXES: int *p = nullptr; 8489a1d03eSRichard #undef MY_NULL 8589a1d03eSRichard } 8689a1d03eSRichard 87*cebb7c01SThomas Köppe template <typename T> struct pear { 88*cebb7c01SThomas Köppe // If you say __null (or NULL), we assume that T will always be a pointer 89*cebb7c01SThomas Köppe // type, so we suggest replacing it with nullptr. (We only check __null here, 90*cebb7c01SThomas Köppe // because in this test NULL is defined as 0, but real library implementations 91*cebb7c01SThomas Köppe // it is often defined as __null and the check will catch it.) 92*cebb7c01SThomas Köppe void f() { x = __null; } 93*cebb7c01SThomas Köppe // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr [modernize-use-nullptr] 94*cebb7c01SThomas Köppe // CHECK-FIXES: x = nullptr; 95*cebb7c01SThomas Köppe 96*cebb7c01SThomas Köppe // But if you say 0, we allow the possibility that T can be used with integral 97*cebb7c01SThomas Köppe // and pointer types, and "0" is an acceptable initializer (even if "{}" might 98*cebb7c01SThomas Köppe // be even better). 99*cebb7c01SThomas Köppe void g() { y = 0; } 100*cebb7c01SThomas Köppe // CHECK-MESSAGES-NOT: :[[@LINE-1]] warning: use nullptr 101*cebb7c01SThomas Köppe 102*cebb7c01SThomas Köppe T x; 103*cebb7c01SThomas Köppe T y; 104*cebb7c01SThomas Köppe }; 105*cebb7c01SThomas Köppe void test_templated() { 106*cebb7c01SThomas Köppe pear<int*> p; 107*cebb7c01SThomas Köppe p.f(); 108*cebb7c01SThomas Köppe p.g(); 109*cebb7c01SThomas Köppe dummy(p.x); 110*cebb7c01SThomas Köppe } 111*cebb7c01SThomas Köppe 11289a1d03eSRichard #define IS_EQ(x, y) if (x != y) return; 11389a1d03eSRichard void test_macro_args() { 11489a1d03eSRichard int i = 0; 11589a1d03eSRichard int *Ptr; 11689a1d03eSRichard 11789a1d03eSRichard IS_EQ(static_cast<int*>(0), Ptr); 11889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr 11989a1d03eSRichard // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr); 12089a1d03eSRichard 12189a1d03eSRichard IS_EQ(0, Ptr); // literal 12289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr 12389a1d03eSRichard // CHECK-FIXES: IS_EQ(nullptr, Ptr); 12489a1d03eSRichard 12589a1d03eSRichard IS_EQ(NULL, Ptr); // macro 12689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr 12789a1d03eSRichard // CHECK-FIXES: IS_EQ(nullptr, Ptr); 12889a1d03eSRichard 12989a1d03eSRichard // These are ok since the null literal is not spelled within a macro. 13089a1d03eSRichard #define myassert(x) if (!(x)) return; 13189a1d03eSRichard myassert(0 == Ptr); 13289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr 13389a1d03eSRichard // CHECK-FIXES: myassert(nullptr == Ptr); 13489a1d03eSRichard 13589a1d03eSRichard myassert(NULL == Ptr); 13689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr 13789a1d03eSRichard // CHECK-FIXES: myassert(nullptr == Ptr); 13889a1d03eSRichard 13989a1d03eSRichard // These are bad as the null literal is buried in a macro. 14089a1d03eSRichard #define BLAH(X) myassert(0 == (X)); 14189a1d03eSRichard #define BLAH2(X) myassert(NULL == (X)); 14289a1d03eSRichard BLAH(Ptr); 14389a1d03eSRichard BLAH2(Ptr); 14489a1d03eSRichard 14589a1d03eSRichard // Same as above but testing extra macro expansion. 14689a1d03eSRichard #define EXPECT_NULL(X) IS_EQ(0, X); 14789a1d03eSRichard #define EXPECT_NULL2(X) IS_EQ(NULL, X); 14889a1d03eSRichard EXPECT_NULL(Ptr); 14989a1d03eSRichard EXPECT_NULL2(Ptr); 15089a1d03eSRichard 15189a1d03eSRichard // Almost the same as above but now null literal is not in a macro so ok 15289a1d03eSRichard // to transform. 15389a1d03eSRichard #define EQUALS_PTR(X) IS_EQ(X, Ptr); 15489a1d03eSRichard EQUALS_PTR(0); 15589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr 15689a1d03eSRichard // CHECK-FIXES: EQUALS_PTR(nullptr); 15789a1d03eSRichard EQUALS_PTR(NULL); 15889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr 15989a1d03eSRichard // CHECK-FIXES: EQUALS_PTR(nullptr); 16089a1d03eSRichard 16189a1d03eSRichard // Same as above but testing extra macro expansion. 16289a1d03eSRichard #define EQUALS_PTR_I(X) EQUALS_PTR(X) 16389a1d03eSRichard EQUALS_PTR_I(0); 16489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 16589a1d03eSRichard // CHECK-FIXES: EQUALS_PTR_I(nullptr); 16689a1d03eSRichard EQUALS_PTR_I(NULL); 16789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 16889a1d03eSRichard // CHECK-FIXES: EQUALS_PTR_I(nullptr); 16989a1d03eSRichard 17089a1d03eSRichard // Ok since null literal not within macro. However, now testing macro 17189a1d03eSRichard // used as arg to another macro. 17289a1d03eSRichard #define decorate(EXPR) side_effect(); EXPR; 17389a1d03eSRichard decorate(IS_EQ(NULL, Ptr)); 17489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr 17589a1d03eSRichard // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr)); 17689a1d03eSRichard decorate(IS_EQ(0, Ptr)); 17789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr 17889a1d03eSRichard // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr)); 17989a1d03eSRichard 18089a1d03eSRichard // This macro causes a NullToPointer cast to happen where 0 is assigned to z 18189a1d03eSRichard // but the 0 literal cannot be replaced because it is also used as an 18289a1d03eSRichard // integer in the comparison. 18389a1d03eSRichard #define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false) 18489a1d03eSRichard INT_AND_PTR_USE(0); 18589a1d03eSRichard 18689a1d03eSRichard // Both uses of X in this case result in NullToPointer casts so replacement 18789a1d03eSRichard // is possible. 18889a1d03eSRichard #define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false) 18989a1d03eSRichard PTR_AND_PTR_USE(0); 19089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr 19189a1d03eSRichard // CHECK-FIXES: PTR_AND_PTR_USE(nullptr); 19289a1d03eSRichard PTR_AND_PTR_USE(NULL); 19389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr 19489a1d03eSRichard // CHECK-FIXES: PTR_AND_PTR_USE(nullptr); 19589a1d03eSRichard 19689a1d03eSRichard #define OPTIONAL_CODE(...) __VA_ARGS__ 19789a1d03eSRichard #define NOT_NULL dummy(0) 19889a1d03eSRichard #define CALL(X) X 19989a1d03eSRichard OPTIONAL_CODE(NOT_NULL); 20089a1d03eSRichard CALL(NOT_NULL); 20189a1d03eSRichard 20289a1d03eSRichard #define ENTRY(X) {X} 20389a1d03eSRichard struct A { 20489a1d03eSRichard int *Ptr; 20589a1d03eSRichard } a[2] = {ENTRY(0), {0}}; 20689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr 20789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr 20889a1d03eSRichard // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}}; 20989a1d03eSRichard #undef ENTRY 21089a1d03eSRichard 21189a1d03eSRichard #define assert1(expr) (expr) ? 0 : 1 21289a1d03eSRichard #define assert2 assert1 21389a1d03eSRichard int *p; 21489a1d03eSRichard assert2(p == 0); 21589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 21689a1d03eSRichard // CHECK-FIXES: assert2(p == nullptr); 21789a1d03eSRichard assert2(p == NULL); 21889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 21989a1d03eSRichard // CHECK-FIXES: assert2(p == nullptr); 22089a1d03eSRichard #undef assert2 22189a1d03eSRichard #undef assert1 22289a1d03eSRichard 22389a1d03eSRichard #define ASSERT_EQ(a, b) a == b 22489a1d03eSRichard #define ASSERT_NULL(x) ASSERT_EQ(static_cast<void *>(NULL), x) 22589a1d03eSRichard int *pp; 22689a1d03eSRichard ASSERT_NULL(pp); 22789a1d03eSRichard ASSERT_NULL(NULL); 22889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use nullptr 22989a1d03eSRichard // CHECK-FIXES: ASSERT_NULL(nullptr); 23089a1d03eSRichard #undef ASSERT_NULL 23189a1d03eSRichard #undef ASSERT_EQ 23289a1d03eSRichard } 23389a1d03eSRichard 23489a1d03eSRichard // One of the ancestor of the cast is a NestedNameSpecifierLoc. 23589a1d03eSRichard class NoDef; 23689a1d03eSRichard char function(NoDef *p); 23789a1d03eSRichard #define F(x) (sizeof(function(x)) == 1) 23889a1d03eSRichard template<class T, T t> 23989a1d03eSRichard class C {}; 24089a1d03eSRichard C<bool, F(0)> c; 24189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr 24289a1d03eSRichard // CHECK-FIXES: C<bool, F(nullptr)> c; 24389a1d03eSRichard #undef F 24489a1d03eSRichard 24589a1d03eSRichard // Test default argument expression. 24689a1d03eSRichard struct D { 24789a1d03eSRichard explicit D(void *t, int *c = NULL) {} 24889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use nullptr 24989a1d03eSRichard // CHECK-FIXES: explicit D(void *t, int *c = nullptr) {} 25089a1d03eSRichard }; 25189a1d03eSRichard 25289a1d03eSRichard void test_default_argument() { 25389a1d03eSRichard D(nullptr); 25489a1d03eSRichard } 25589a1d03eSRichard 25689a1d03eSRichard // Test on two neighbour CXXDefaultArgExprs nodes. 25789a1d03eSRichard typedef unsigned long long uint64; 25889a1d03eSRichard struct ZZ { 25989a1d03eSRichard explicit ZZ(uint64, const uint64* = NULL) {} 26089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: use nullptr 26189a1d03eSRichard // CHECK-FIXES: explicit ZZ(uint64, const uint64* = nullptr) {} 26289a1d03eSRichard operator bool() { return true; } 26389a1d03eSRichard }; 26489a1d03eSRichard 26589a1d03eSRichard uint64 Hash(uint64 seed = 0) { return 0; } 26689a1d03eSRichard 26789a1d03eSRichard void f() { 26889a1d03eSRichard bool a; 26989a1d03eSRichard a = ZZ(Hash()); 27089a1d03eSRichard } 27189a1d03eSRichard 27289a1d03eSRichard // Test on ignoring substituted template types. 27389a1d03eSRichard template<typename T> 27489a1d03eSRichard class TemplateClass { 27589a1d03eSRichard public: 27689a1d03eSRichard explicit TemplateClass(int a, T default_value = 0) {} 27789a1d03eSRichard 27889a1d03eSRichard void h(T *default_value = 0) {} 27989a1d03eSRichard 28089a1d03eSRichard void f(int* p = 0) {} 28189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr 28289a1d03eSRichard // CHECK-FIXES: void f(int* p = nullptr) {} 28389a1d03eSRichard }; 28489a1d03eSRichard 28589a1d03eSRichard void IgnoreSubstTemplateType() { 28689a1d03eSRichard TemplateClass<int*> a(1); 28789a1d03eSRichard } 28889a1d03eSRichard 28989a1d03eSRichard // Test on casting nullptr. 29089a1d03eSRichard struct G { 29189a1d03eSRichard explicit G(bool, const char * = NULL) {} 29289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use nullptr 29389a1d03eSRichard // CHECK-FIXES: explicit G(bool, const char * = nullptr) {} 29489a1d03eSRichard }; 29589a1d03eSRichard bool g(const char*); 29689a1d03eSRichard void test_cast_nullptr() { 29789a1d03eSRichard G(g(nullptr)); 29889a1d03eSRichard G(g((nullptr))); 29989a1d03eSRichard G(g(static_cast<char*>(nullptr))); 30089a1d03eSRichard G(g(static_cast<const char*>(nullptr))); 30189a1d03eSRichard } 30289a1d03eSRichard 30389a1d03eSRichard // Test on recognizing multiple NULLs. 30489a1d03eSRichard class H { 30589a1d03eSRichard public: 30689a1d03eSRichard H(bool); 30789a1d03eSRichard }; 30889a1d03eSRichard 30989a1d03eSRichard #define T(expression) H(expression); 31089a1d03eSRichard bool h(int *, int *, int * = nullptr); 31189a1d03eSRichard void test_multiple_nulls() { 31289a1d03eSRichard T(h(NULL, NULL)); 31389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr 31489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr 31589a1d03eSRichard // CHECK-FIXES: T(h(nullptr, nullptr)); 31689a1d03eSRichard T(h(NULL, nullptr)); 31789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr 31889a1d03eSRichard // CHECK-FIXES: T(h(nullptr, nullptr)); 31989a1d03eSRichard T(h(nullptr, NULL)); 32089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr 32189a1d03eSRichard // CHECK-FIXES: T(h(nullptr, nullptr)); 32289a1d03eSRichard T(h(nullptr, nullptr)); 32389a1d03eSRichard T(h(NULL, NULL, NULL)); 32489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr 32589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: use nullptr 32689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:19: warning: use nullptr 32789a1d03eSRichard // CHECK-FIXES: T(h(nullptr, nullptr, nullptr)); 32889a1d03eSRichard } 32989a1d03eSRichard #undef T 330