summaryrefslogtreecommitdiff
path: root/test/SemaCXX/delete.cpp
blob: 0c853f68c061095d2c4eab532d78314f97a9df2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 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