xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.cpp (revision cebb7c010854e39a77065cfd681db91a79e7ce15)
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