198 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %check_clang_tidy %s modernize-use-nullptr %t -- \
 | |
| // RUN:   -config="{CheckOptions: [{key: modernize-use-nullptr.NullMacros, value: 'MY_NULL,NULL'}]}" \
 | |
| // RUN:   -- -std=c++11
 | |
| 
 | |
| #define NULL 0
 | |
| 
 | |
| namespace std {
 | |
| 
 | |
| typedef decltype(nullptr) nullptr_t;
 | |
| 
 | |
| } // namespace std
 | |
| 
 | |
| // Just to make sure make_null() could have side effects.
 | |
| void external();
 | |
| 
 | |
| std::nullptr_t make_null() {
 | |
|   external();
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| void func() {
 | |
|   void *CallTest = make_null();
 | |
| 
 | |
|   int var = 1;
 | |
|   void *CommaTest = (var+=2, make_null());
 | |
| 
 | |
|   int *CastTest = static_cast<int*>(make_null());
 | |
| }
 | |
| 
 | |
| void dummy(int*) {}
 | |
| void side_effect() {}
 | |
| 
 | |
| #define MACRO_EXPANSION_HAS_NULL \
 | |
|   void foo() { \
 | |
|     dummy(0); \
 | |
|     dummy(NULL); \
 | |
|     side_effect(); \
 | |
|   }
 | |
| 
 | |
| MACRO_EXPANSION_HAS_NULL;
 | |
| #undef MACRO_EXPANSION_HAS_NULL
 | |
| 
 | |
| 
 | |
| void test_macro_expansion1() {
 | |
| #define MACRO_EXPANSION_HAS_NULL \
 | |
|   dummy(NULL); \
 | |
|   side_effect();
 | |
| 
 | |
|   MACRO_EXPANSION_HAS_NULL;
 | |
| 
 | |
| #undef MACRO_EXPANSION_HAS_NULL
 | |
| }
 | |
| 
 | |
| // Test macro expansion with cast sequence, PR15572.
 | |
| void test_macro_expansion2() {
 | |
| #define MACRO_EXPANSION_HAS_NULL \
 | |
|   dummy((int*)0); \
 | |
|   side_effect();
 | |
| 
 | |
|   MACRO_EXPANSION_HAS_NULL;
 | |
| 
 | |
| #undef MACRO_EXPANSION_HAS_NULL
 | |
| }
 | |
| 
 | |
| void test_macro_expansion3() {
 | |
| #define MACRO_EXPANSION_HAS_NULL \
 | |
|   dummy(NULL); \
 | |
|   side_effect();
 | |
| 
 | |
| #define OUTER_MACRO \
 | |
|   MACRO_EXPANSION_HAS_NULL; \
 | |
|   side_effect();
 | |
| 
 | |
|   OUTER_MACRO;
 | |
| 
 | |
| #undef OUTER_MACRO
 | |
| #undef MACRO_EXPANSION_HAS_NULL
 | |
| }
 | |
| 
 | |
| void test_macro_expansion4() {
 | |
| #define MY_NULL NULL
 | |
|   int *p = MY_NULL;
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr [modernize-use-nullptr]
 | |
|   // CHECK-FIXES: int *p = nullptr;
 | |
| #undef MY_NULL
 | |
| }
 | |
| 
 | |
| #define IS_EQ(x, y) if (x != y) return;
 | |
| void test_macro_args() {
 | |
|   int i = 0;
 | |
|   int *Ptr;
 | |
| 
 | |
|   IS_EQ(static_cast<int*>(0), Ptr);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr
 | |
|   // CHECK-FIXES: IS_EQ(static_cast<int*>(nullptr), Ptr);
 | |
| 
 | |
|   IS_EQ(0, Ptr);    // literal
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
 | |
|   // CHECK-FIXES: IS_EQ(nullptr, Ptr);
 | |
| 
 | |
|   IS_EQ(NULL, Ptr); // macro
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
 | |
|   // CHECK-FIXES: IS_EQ(nullptr, Ptr);
 | |
| 
 | |
|   // These are ok since the null literal is not spelled within a macro.
 | |
| #define myassert(x) if (!(x)) return;
 | |
|   myassert(0 == Ptr);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
 | |
|   // CHECK-FIXES: myassert(nullptr == Ptr);
 | |
| 
 | |
|   myassert(NULL == Ptr);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr
 | |
|   // CHECK-FIXES: myassert(nullptr == Ptr);
 | |
| 
 | |
|   // These are bad as the null literal is buried in a macro.
 | |
| #define BLAH(X) myassert(0 == (X));
 | |
| #define BLAH2(X) myassert(NULL == (X));
 | |
|   BLAH(Ptr);
 | |
|   BLAH2(Ptr);
 | |
| 
 | |
|   // Same as above but testing extra macro expansion.
 | |
| #define EXPECT_NULL(X) IS_EQ(0, X);
 | |
| #define EXPECT_NULL2(X) IS_EQ(NULL, X);
 | |
|   EXPECT_NULL(Ptr);
 | |
|   EXPECT_NULL2(Ptr);
 | |
| 
 | |
|   // Almost the same as above but now null literal is not in a macro so ok
 | |
|   // to transform.
 | |
| #define EQUALS_PTR(X) IS_EQ(X, Ptr);
 | |
|   EQUALS_PTR(0);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
 | |
|   // CHECK-FIXES: EQUALS_PTR(nullptr);
 | |
|   EQUALS_PTR(NULL);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr
 | |
|   // CHECK-FIXES: EQUALS_PTR(nullptr);
 | |
| 
 | |
|   // Same as above but testing extra macro expansion.
 | |
| #define EQUALS_PTR_I(X) EQUALS_PTR(X)
 | |
|   EQUALS_PTR_I(0);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
 | |
|   // CHECK-FIXES: EQUALS_PTR_I(nullptr);
 | |
|   EQUALS_PTR_I(NULL);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use nullptr
 | |
|   // CHECK-FIXES: EQUALS_PTR_I(nullptr);
 | |
| 
 | |
|   // Ok since null literal not within macro. However, now testing macro
 | |
|   // used as arg to another macro.
 | |
| #define decorate(EXPR) side_effect(); EXPR;
 | |
|   decorate(IS_EQ(NULL, Ptr));
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
 | |
|   // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
 | |
|   decorate(IS_EQ(0, Ptr));
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
 | |
|   // CHECK-FIXES: decorate(IS_EQ(nullptr, Ptr));
 | |
| 
 | |
|   // This macro causes a NullToPointer cast to happen where 0 is assigned to z
 | |
|   // but the 0 literal cannot be replaced because it is also used as an
 | |
|   // integer in the comparison.
 | |
| #define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
 | |
|   INT_AND_PTR_USE(0);
 | |
| 
 | |
|   // Both uses of X in this case result in NullToPointer casts so replacement
 | |
|   // is possible.
 | |
| #define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
 | |
|   PTR_AND_PTR_USE(0);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
 | |
|   // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
 | |
|   PTR_AND_PTR_USE(NULL);
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
 | |
|   // CHECK-FIXES: PTR_AND_PTR_USE(nullptr);
 | |
| 
 | |
| #define OPTIONAL_CODE(...) __VA_ARGS__
 | |
| #define NOT_NULL dummy(0)
 | |
| #define CALL(X) X
 | |
|   OPTIONAL_CODE(NOT_NULL);
 | |
|   CALL(NOT_NULL);
 | |
| 
 | |
| #define ENTRY(X) {X}
 | |
|   struct A {
 | |
|     int *Ptr;
 | |
|   } a[2] = {ENTRY(0), {0}};
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use nullptr
 | |
|   // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use nullptr
 | |
|   // CHECK-FIXES: a[2] = {ENTRY(nullptr), {nullptr}};
 | |
| #undef ENTRY
 | |
| }
 | |
| 
 | |
| // One of the ancestor of the cast is a NestedNameSpecifierLoc.
 | |
| class NoDef;
 | |
| char function(NoDef *p);
 | |
| #define F(x) (sizeof(function(x)) == 1)
 | |
| template<class T, T t>
 | |
| class C {};
 | |
| C<bool, F(0)> c;
 | |
| // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr
 | |
| // CHECK-FIXES: C<bool, F(nullptr)> c;
 | |
| #undef F
 |