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