147 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Test without PCH
 | |
| // RUN: %clang_cc1 -fsyntax-only -include %S/delete-mismatch.h -fdiagnostics-parseable-fixits -std=c++11 %s 2>&1 | FileCheck %s
 | |
| 
 | |
| // Test with PCH
 | |
| // RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/delete-mismatch.h
 | |
| // RUN: %clang_cc1 -std=c++11 -include-pch %t -DWITH_PCH -fsyntax-only -verify %s -ast-dump
 | |
| 
 | |
| void f(int a[10][20]) {
 | |
|   delete a; // expected-warning {{'delete' applied to a pointer-to-array type}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
 | |
| }
 | |
| namespace MemberCheck {
 | |
| struct S {
 | |
|   int *a = new int[5]; // expected-note4 {{allocated with 'new[]' here}}
 | |
|   int *b;
 | |
|   int *c;
 | |
|   static int *d;
 | |
|   S();
 | |
|   S(int);
 | |
|   ~S() {
 | |
|     delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|     delete b;   // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|     delete[] c; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
 | |
|   }
 | |
|   void f();
 | |
| };
 | |
| 
 | |
| void S::f()
 | |
| {
 | |
|   delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   delete b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
| }
 | |
| 
 | |
| S::S()
 | |
| : b(new int[1]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
 | |
| // expected-note@-1 {{allocated with 'new' here}}
 | |
| 
 | |
| S::S(int i)
 | |
| : b(new int[i]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
 | |
| // expected-note@-1 {{allocated with 'new' here}}
 | |
| 
 | |
| struct S2 : S {
 | |
|   ~S2() {
 | |
|     delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   }
 | |
| };
 | |
| int *S::d = new int[42]; // expected-note {{allocated with 'new[]' here}}
 | |
| void f(S *s) {
 | |
|   int *a = new int[1]; // expected-note {{allocated with 'new[]' here}}
 | |
|   delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   delete s->a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   delete s->b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   delete s->c;
 | |
|   delete s->d;
 | |
|   delete S::d; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
| }
 | |
| 
 | |
| // At least one constructor initializes field with matching form of 'new'.
 | |
| struct MatchingNewIsOK {
 | |
|   int *p;
 | |
|   bool is_array_;
 | |
|   MatchingNewIsOK() : p{new int}, is_array_(false) {}
 | |
|   explicit MatchingNewIsOK(unsigned c) : p{new int[c]}, is_array_(true) {}
 | |
|   ~MatchingNewIsOK() {
 | |
|     if (is_array_)
 | |
|       delete[] p;
 | |
|     else
 | |
|       delete p;
 | |
|   }
 | |
| };
 | |
| 
 | |
| // At least one constructor's body is missing; no proof of mismatch.
 | |
| struct CantProve_MissingCtorDefinition {
 | |
|   int *p;
 | |
|   CantProve_MissingCtorDefinition();
 | |
|   CantProve_MissingCtorDefinition(int);
 | |
|   ~CantProve_MissingCtorDefinition();
 | |
| };
 | |
| 
 | |
| CantProve_MissingCtorDefinition::CantProve_MissingCtorDefinition()
 | |
|   : p(new int)
 | |
| { }
 | |
| 
 | |
| CantProve_MissingCtorDefinition::~CantProve_MissingCtorDefinition()
 | |
| {
 | |
|   delete[] p;
 | |
| }
 | |
| 
 | |
| struct base {};
 | |
| struct derived : base {};
 | |
| struct InitList {
 | |
|   base *p, *p2 = nullptr, *p3{nullptr}, *p4;
 | |
|   InitList(unsigned c) : p(new derived[c]), p4(nullptr) {}  // expected-note {{allocated with 'new[]' here}}
 | |
|   InitList(unsigned c, unsigned) : p{new derived[c]}, p4{nullptr} {} // expected-note {{allocated with 'new[]' here}}
 | |
|   ~InitList() {
 | |
|     delete p; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|     delete [] p;
 | |
|     delete p2;
 | |
|     delete [] p3;
 | |
|     delete p4;
 | |
|   }
 | |
| };
 | |
| }
 | |
| 
 | |
| namespace NonMemberCheck {
 | |
| #define DELETE_ARRAY(x) delete[] (x)
 | |
| #define DELETE(x) delete (x)
 | |
| void f() {
 | |
|   int *a = new int(5); // expected-note2 {{allocated with 'new' here}}
 | |
|   delete[] a;          // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
 | |
|   int *b = new int;
 | |
|   delete b;
 | |
|   int *c{new int};    // expected-note {{allocated with 'new' here}}
 | |
|   int *d{new int[1]}; // expected-note2 {{allocated with 'new[]' here}}
 | |
|   delete  [    ] c;   // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:17}:""
 | |
|   delete d;           // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
|   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
 | |
|   DELETE_ARRAY(a);    // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
 | |
|   DELETE(d);          // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
 | |
| }
 | |
| }
 | |
| 
 | |
| namespace MissingInitializer {
 | |
| template<typename T>
 | |
| struct Base {
 | |
|   struct S {
 | |
|     const T *p1 = nullptr;
 | |
|     const T *p2 = new T[3];
 | |
|   };
 | |
| };
 | |
| 
 | |
| void null_init(Base<double>::S s) {
 | |
|   delete s.p1;
 | |
|   delete s.p2;
 | |
| }
 | |
| }
 | |
| 
 | |
| #ifndef WITH_PCH
 | |
| pch_test::X::X()
 | |
|   : a(new int[1])  // expected-note{{allocated with 'new[]' here}}
 | |
| { }
 | |
| pch_test::X::X(int i)
 | |
|   : a(new int[i])  // expected-note{{allocated with 'new[]' here}}
 | |
| { }
 | |
| #endif
 |