1*67e74705SXin Li // Test without PCH
2*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -include %S/delete-mismatch.h -fdiagnostics-parseable-fixits -std=c++11 %s 2>&1 | FileCheck %s
3*67e74705SXin Li
4*67e74705SXin Li // Test with PCH
5*67e74705SXin Li // RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/delete-mismatch.h
6*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -include-pch %t -DWITH_PCH -fsyntax-only -verify %s -ast-dump
7*67e74705SXin Li
f(int a[10][20])8*67e74705SXin Li void f(int a[10][20]) {
9*67e74705SXin Li delete a; // expected-warning {{'delete' applied to a pointer-to-array type}}
10*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
11*67e74705SXin Li }
12*67e74705SXin Li namespace MemberCheck {
13*67e74705SXin Li struct S {
14*67e74705SXin Li int *a = new int[5]; // expected-note4 {{allocated with 'new[]' here}}
15*67e74705SXin Li int *b;
16*67e74705SXin Li int *c;
17*67e74705SXin Li static int *d;
18*67e74705SXin Li S();
19*67e74705SXin Li S(int);
~SMemberCheck::S20*67e74705SXin Li ~S() {
21*67e74705SXin Li delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
22*67e74705SXin Li delete b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
23*67e74705SXin Li delete[] c; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
24*67e74705SXin Li }
25*67e74705SXin Li void f();
26*67e74705SXin Li };
27*67e74705SXin Li
f()28*67e74705SXin Li void S::f()
29*67e74705SXin Li {
30*67e74705SXin Li delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
31*67e74705SXin Li delete b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
32*67e74705SXin Li }
33*67e74705SXin Li
S()34*67e74705SXin Li S::S()
35*67e74705SXin Li : b(new int[1]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
36*67e74705SXin Li // expected-note@-1 {{allocated with 'new' here}}
37*67e74705SXin Li
S(int i)38*67e74705SXin Li S::S(int i)
39*67e74705SXin Li : b(new int[i]), c(new int) {} // expected-note3 {{allocated with 'new[]' here}}
40*67e74705SXin Li // expected-note@-1 {{allocated with 'new' here}}
41*67e74705SXin Li
42*67e74705SXin Li struct S2 : S {
~S2MemberCheck::S243*67e74705SXin Li ~S2() {
44*67e74705SXin Li delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
45*67e74705SXin Li }
46*67e74705SXin Li };
47*67e74705SXin Li int *S::d = new int[42]; // expected-note {{allocated with 'new[]' here}}
f(S * s)48*67e74705SXin Li void f(S *s) {
49*67e74705SXin Li int *a = new int[1]; // expected-note {{allocated with 'new[]' here}}
50*67e74705SXin Li delete a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
51*67e74705SXin Li delete s->a; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
52*67e74705SXin Li delete s->b; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
53*67e74705SXin Li delete s->c;
54*67e74705SXin Li delete s->d;
55*67e74705SXin Li delete S::d; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
56*67e74705SXin Li }
57*67e74705SXin Li
58*67e74705SXin Li // At least one constructor initializes field with matching form of 'new'.
59*67e74705SXin Li struct MatchingNewIsOK {
60*67e74705SXin Li int *p;
61*67e74705SXin Li bool is_array_;
MatchingNewIsOKMemberCheck::MatchingNewIsOK62*67e74705SXin Li MatchingNewIsOK() : p{new int}, is_array_(false) {}
MatchingNewIsOKMemberCheck::MatchingNewIsOK63*67e74705SXin Li explicit MatchingNewIsOK(unsigned c) : p{new int[c]}, is_array_(true) {}
~MatchingNewIsOKMemberCheck::MatchingNewIsOK64*67e74705SXin Li ~MatchingNewIsOK() {
65*67e74705SXin Li if (is_array_)
66*67e74705SXin Li delete[] p;
67*67e74705SXin Li else
68*67e74705SXin Li delete p;
69*67e74705SXin Li }
70*67e74705SXin Li };
71*67e74705SXin Li
72*67e74705SXin Li // At least one constructor's body is missing; no proof of mismatch.
73*67e74705SXin Li struct CantProve_MissingCtorDefinition {
74*67e74705SXin Li int *p;
75*67e74705SXin Li CantProve_MissingCtorDefinition();
76*67e74705SXin Li CantProve_MissingCtorDefinition(int);
77*67e74705SXin Li ~CantProve_MissingCtorDefinition();
78*67e74705SXin Li };
79*67e74705SXin Li
CantProve_MissingCtorDefinition()80*67e74705SXin Li CantProve_MissingCtorDefinition::CantProve_MissingCtorDefinition()
81*67e74705SXin Li : p(new int)
82*67e74705SXin Li { }
83*67e74705SXin Li
~CantProve_MissingCtorDefinition()84*67e74705SXin Li CantProve_MissingCtorDefinition::~CantProve_MissingCtorDefinition()
85*67e74705SXin Li {
86*67e74705SXin Li delete[] p;
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li struct base {};
90*67e74705SXin Li struct derived : base {};
91*67e74705SXin Li struct InitList {
92*67e74705SXin Li base *p, *p2 = nullptr, *p3{nullptr}, *p4;
InitListMemberCheck::InitList93*67e74705SXin Li InitList(unsigned c) : p(new derived[c]), p4(nullptr) {} // expected-note {{allocated with 'new[]' here}}
InitListMemberCheck::InitList94*67e74705SXin Li InitList(unsigned c, unsigned) : p{new derived[c]}, p4{nullptr} {} // expected-note {{allocated with 'new[]' here}}
~InitListMemberCheck::InitList95*67e74705SXin Li ~InitList() {
96*67e74705SXin Li delete p; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
97*67e74705SXin Li delete [] p;
98*67e74705SXin Li delete p2;
99*67e74705SXin Li delete [] p3;
100*67e74705SXin Li delete p4;
101*67e74705SXin Li }
102*67e74705SXin Li };
103*67e74705SXin Li }
104*67e74705SXin Li
105*67e74705SXin Li namespace NonMemberCheck {
106*67e74705SXin Li #define DELETE_ARRAY(x) delete[] (x)
107*67e74705SXin Li #define DELETE(x) delete (x)
f()108*67e74705SXin Li void f() {
109*67e74705SXin Li int *a = new int(5); // expected-note2 {{allocated with 'new' here}}
110*67e74705SXin Li delete[] a; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
111*67e74705SXin Li int *b = new int;
112*67e74705SXin Li delete b;
113*67e74705SXin Li int *c{new int}; // expected-note {{allocated with 'new' here}}
114*67e74705SXin Li int *d{new int[1]}; // expected-note2 {{allocated with 'new[]' here}}
115*67e74705SXin Li delete [ ] c; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
116*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:17}:""
117*67e74705SXin Li delete d; // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
118*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:9}:"[]"
119*67e74705SXin Li DELETE_ARRAY(a); // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}}
120*67e74705SXin Li DELETE(d); // expected-warning {{'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'?}}
121*67e74705SXin Li }
122*67e74705SXin Li }
123*67e74705SXin Li
124*67e74705SXin Li namespace MissingInitializer {
125*67e74705SXin Li template<typename T>
126*67e74705SXin Li struct Base {
127*67e74705SXin Li struct S {
128*67e74705SXin Li const T *p1 = nullptr;
129*67e74705SXin Li const T *p2 = new T[3];
130*67e74705SXin Li };
131*67e74705SXin Li };
132*67e74705SXin Li
null_init(Base<double>::S s)133*67e74705SXin Li void null_init(Base<double>::S s) {
134*67e74705SXin Li delete s.p1;
135*67e74705SXin Li delete s.p2;
136*67e74705SXin Li }
137*67e74705SXin Li }
138*67e74705SXin Li
139*67e74705SXin Li #ifndef WITH_PCH
X()140*67e74705SXin Li pch_test::X::X()
141*67e74705SXin Li : a(new int[1]) // expected-note{{allocated with 'new[]' here}}
142*67e74705SXin Li { }
X(int i)143*67e74705SXin Li pch_test::X::X(int i)
144*67e74705SXin Li : a(new int[i]) // expected-note{{allocated with 'new[]' here}}
145*67e74705SXin Li { }
146*67e74705SXin Li #endif
147