| // 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 |