aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/new-delete.cpp
blob: 7facd10ca5fc8d93de9deca0338f79ee6a084265 (plain) (blame)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu

#include <stddef.h>

struct S // expected-note {{candidate}}
{
  S(int, int, double); // expected-note {{candidate}}
  S(double, int); // expected-note 2 {{candidate}}
  S(float, int); // expected-note 2 {{candidate}}
};
struct T; // expected-note{{forward declaration of 'T'}}
struct U
{
  // A special new, to verify that the global version isn't used.
  void* operator new(size_t, S*); // expected-note {{candidate}}
};
struct V : U
{
};

inline void operator delete(void *); // expected-warning {{replacement function 'operator delete' cannot be declared 'inline'}}

__attribute__((used))
inline void *operator new(size_t) { // no warning, due to __attribute__((used))
  return 0;
}

// PR5823
void* operator new(const size_t); // expected-note 2 {{candidate}}
void* operator new(size_t, int*); // expected-note 3 {{candidate}}
void* operator new(size_t, float*); // expected-note 3 {{candidate}}
void* operator new(size_t, S); // expected-note 2 {{candidate}}

struct foo { };

void good_news()
{
  int *pi = new int;
  float *pf = new (pi) float();
  pi = new int(1);
  pi = new int('c');
  const int *pci = new const int();
  S *ps = new S(1, 2, 3.4);
  ps = new (pf) (S)(1, 2, 3.4);
  S *(*paps)[2] = new S*[*pi][2];
  typedef int ia4[4];
  ia4 *pai = new (int[3][4]);
  pi = ::new int;
  U *pu = new (ps) U;
  V *pv = new (ps) V;
  
  pi = new (S(1.0f, 2)) int;
  
  (void)new int[true];

  // PR7147
  typedef int a[2];
  foo* f1 = new foo;
  foo* f2 = new foo[2];
  typedef foo x[2];
  typedef foo y[2][2];
  x* f3 = new y;
}

struct abstract {
  virtual ~abstract() = 0;
};

void bad_news(int *ip)
{
  int i = 1; // expected-note 2{{here}}
  (void)new; // expected-error {{expected a type}}
  (void)new 4; // expected-error {{expected a type}}
  (void)new () int; // expected-error {{expected expression}}
  (void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}}
  (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
  (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
  (void)new (int[i]); // expected-warning {{when type is in parentheses}}
  (void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}}
  (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}}
  (void)new S(1); // expected-error {{no matching constructor}}
  (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}}
  (void)new const int; // expected-error {{default initialization of an object of const type 'const int'}}
  (void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}}
  // Undefined, but clang should reject it directly.
  (void)new int[-1]; // expected-error {{array size is negative}}
  (void)new int[2000000000]; // expected-error {{array is too large}}
  (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumeration type, not 'S'}}
  (void)::S::new int; // expected-error {{expected unqualified-id}}
  (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}
  // This must fail, because the member version shouldn't be found.
  (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
  // This must fail, because any member version hides all global versions.
  (void)new U; // expected-error {{no matching function for call to 'operator new'}}
  (void)new (int[]); // expected-error {{array size must be specified in new expressions}}
  (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}}
  // Some lacking cases due to lack of sema support.
}

void good_deletes()
{
  delete (int*)0;
  delete [](int*)0;
  delete (S*)0;
  ::delete (int*)0;
}

void bad_deletes()
{
  delete 0; // expected-error {{cannot delete expression of type 'int'}}
  delete [0] (int*)0; // expected-error {{expected expression}}
  delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}}
  delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
  ::S::delete (int*)0; // expected-error {{expected unqualified-id}}
}

struct X0 { };

struct X1 {
  operator int*();
  operator float();
};

struct X2 {
  operator int*(); // expected-note {{conversion}}
  operator float*(); // expected-note {{conversion}}
};

void test_delete_conv(X0 x0, X1 x1, X2 x2) {
  delete x0; // expected-error{{cannot delete}}
  delete x1;
  delete x2; // expected-error{{ambiguous conversion of delete expression of type 'X2' to a pointer}}
}

// PR4782
class X3 {
public:
  static void operator delete(void * mem, size_t size);
};

class X4 {
public:
  static void release(X3 *x);
  static void operator delete(void * mem, size_t size);
};


void X4::release(X3 *x) {
  delete x;
}

class X5 {
public:
  void Destroy() const { delete this; }
};

class Base {
public:
  static void *operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}}
  static int operator new[] (size_t) throw(); // expected-error {{operator new[]' must return type 'void *'}}
};

class Tier {};
class Comp : public Tier {};

class Thai : public Base {
public:
  Thai(const Tier *adoptDictionary);
};

void loadEngineFor() {
  const Comp *dict;
  new Thai(dict);
}

template <class T> struct TBase {
  void* operator new(T size, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}}
};

TBase<int> t1;

class X6 {
public:
  static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}}
};

class X7 {
public:
  static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}}
};

class X8 : public X6, public X7 {
};

void f(X8 *x8) {
  delete x8; // expected-error {{member 'operator delete' found in multiple base classes of different types}}
}

class X9 {
public:
  static void operator delete(void*, int); // expected-note {{'operator delete' declared here}}
  static void operator delete(void*, float); // expected-note {{'operator delete' declared here}}
};

void f(X9 *x9) {
  delete x9; // expected-error {{no suitable member 'operator delete' in 'X9'}}
}

struct X10 {
  virtual ~X10();
};

struct X11 : X10 { // expected-error {{no suitable member 'operator delete' in 'X11'}}
  void operator delete(void*, int); // expected-note {{'operator delete' declared here}}
};

void f() {
  X11 x11; // expected-note {{implicit destructor for 'X11' first required here}}
}

struct X12 {
  void* operator new(size_t, void*);
};

struct X13 : X12 {
  using X12::operator new;
};

static void* f(void* g)
{
    return new (g) X13();
}

class X14 {
public:
  static void operator delete(void*, const size_t);
};

void f(X14 *x14a, X14 *x14b) {
  delete x14a;
}

class X15 {
private:
  X15(); // expected-note {{declared private here}}
  ~X15(); // expected-note {{declared private here}}
};

void f(X15* x) {
  new X15(); // expected-error {{calling a private constructor}}
  delete x; // expected-error {{calling a private destructor}}
}

namespace PR5918 { // Look for template operator new overloads.
  struct S { template<typename T> static void* operator new(size_t, T); };
  void test() {
    (void)new(0) S;
  }
}

namespace Test1 {

void f() {
  (void)new int[10](1, 2); // expected-error {{array 'new' cannot have initialization arguments}}
  
  typedef int T[10];
  (void)new T(1, 2); // expected-error {{array 'new' cannot have initialization arguments}}
}

template<typename T>
void g(unsigned i) {
  (void)new T[1](i); // expected-error {{array 'new' cannot have initialization arguments}}
}

template<typename T>
void h(unsigned i) {
  (void)new T(i); // expected-error {{array 'new' cannot have initialization arguments}}
}
template void h<unsigned>(unsigned);
template void h<unsigned[10]>(unsigned); // expected-note {{in instantiation of function template specialization 'Test1::h<unsigned int [10]>' requested here}}

}

// Don't diagnose access for overload candidates that aren't selected.
namespace PR7436 {
struct S1 {
  void* operator new(size_t);
  void operator delete(void* p);

private:
  void* operator new(size_t, void*); // expected-note {{declared private here}}
  void operator delete(void*, void*);
};
class S2 {
  void* operator new(size_t); // expected-note {{declared private here}}
  void operator delete(void* p); // expected-note {{declared private here}}
};

void test(S1* s1, S2* s2) { 
  delete s1;
  delete s2; // expected-error {{is a private member}}
  (void)new S1();
  (void)new (0L) S1(); // expected-error {{is a private member}}
  (void)new S2(); // expected-error {{is a private member}}
}
}

namespace rdar8018245 {
  struct X0 {
    static const int value = 17;
  };

  const int X0::value;

  struct X1 {
    static int value;
  };

  int X1::value;

  template<typename T>
  int *f() {
    return new (int[T::value]); // expected-warning{{when type is in parentheses, array cannot have dynamic size}}
  }

  template int *f<X0>();
  template int *f<X1>(); // expected-note{{in instantiation of}}

}

// <rdar://problem/8248780>
namespace Instantiate {
  template<typename T> struct X { 
    operator T*();
  };

  void f(X<int> &xi) {
    delete xi;
  }
}

namespace PR7810 {
  struct X {
    // cv is ignored in arguments
    static void operator delete(void *const);
  };
  struct Y {
    // cv is ignored in arguments
    static void operator delete(void *volatile);
  };
}

// Don't crash on template delete operators
namespace TemplateDestructors {
  struct S {
    virtual ~S() {}

    void* operator new(const size_t size);
    template<class T> void* operator new(const size_t, const int, T*);
    void operator delete(void*, const size_t);
    template<class T> void operator delete(void*, const size_t, const int, T*);
  };
}

namespace DeleteParam {
  struct X {
    void operator delete(X*); // expected-error{{first parameter of 'operator delete' must have type 'void *'}}
  };

  struct Y {
    void operator delete(void* const);
  };
}

// <rdar://problem/8427878>
// Test that the correct 'operator delete' is selected to pair with
// the unexpected placement 'operator new'.
namespace PairedDelete {
  template <class T> struct A {
    A();
    void *operator new(size_t s, double d = 0);
    void operator delete(void *p, double d);
    void operator delete(void *p) {
      T::dealloc(p);
    }
  };

  A<int> *test() {
    return new A<int>();
  }
}

namespace PR7702 {
  void test1() {
    new DoesNotExist; // expected-error {{unknown type name 'DoesNotExist'}}
  }
}

namespace ArrayNewNeedsDtor {
  struct A { A(); private: ~A(); }; // expected-note {{declared private here}}
  struct B { B(); A a; }; // expected-error {{field of type 'ArrayNewNeedsDtor::A' has private destructor}}
  B *test9() {
    return new B[5]; // expected-note {{implicit destructor for 'ArrayNewNeedsDtor::B' first required here}}
  }
}

namespace DeleteIncompleteClass {
  struct A; // expected-note {{forward declaration}}
  extern A x;
  void f() { delete x; } // expected-error {{deleting incomplete class type}}
}

namespace DeleteIncompleteClassPointerError {
  struct A; // expected-note {{forward declaration}}
  void f(A *x) { 1+delete x; } // expected-warning {{deleting pointer to incomplete type}} \
                               // expected-error {{invalid operands to binary expression}}
}

namespace PR10504 {
  struct A {
    virtual void foo() = 0;
  };
  void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}}
}

struct PlacementArg {};
inline void *operator new[](size_t, const PlacementArg &) throw () {
  return 0;
}
inline void operator delete[](void *, const PlacementArg &) throw () {
}

namespace r150682 {

  template <typename X>
  struct S {
    struct Inner {};
    S() { new Inner[1]; }
  };

  struct T {
  };

  template<typename X>
  void tfn() {
    new (*(PlacementArg*)0) T[1];
  }

  void fn() {
    tfn<int>();
  }

}

namespace P12023 {
  struct CopyCounter
  {
      CopyCounter();
      CopyCounter(const CopyCounter&);
  };

  int main()
  {
    CopyCounter* f = new CopyCounter[10](CopyCounter()); // expected-error {{cannot have initialization arguments}}
      return 0;
  }
}

namespace PR12061 {
  template <class C> struct scoped_array {
    scoped_array(C* p = __null);
  };
  template <class Payload> struct Foo {
    Foo() : a_(new scoped_array<int>[5]) { }
    scoped_array< scoped_array<int> > a_;
  };
  class Bar {};
  Foo<Bar> x;

  template <class C> struct scoped_array2 {
    scoped_array2(C* p = __null, C* q = __null);
  };
  template <class Payload> struct Foo2 {
    Foo2() : a_(new scoped_array2<int>[5]) { }
    scoped_array2< scoped_array2<int> > a_;
  };
  class Bar2 {};
  Foo2<Bar2> x2;

  class MessageLoop {
  public:
    explicit MessageLoop(int type = 0);
  };
  template <class CookieStoreTestTraits>
  class CookieStoreTest {
  protected:
    CookieStoreTest() {
      new MessageLoop;
    }
  };
  struct CookieMonsterTestTraits {
  };
  class DeferredCookieTaskTest : public CookieStoreTest<CookieMonsterTestTraits>
  {
    DeferredCookieTaskTest() {}
  };
}

class DeletingPlaceholder {
  int* f() {
    delete f; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
    return 0;
  }
  int* g(int, int) {
    delete g; // expected-error {{reference to non-static member function must be called}}
    return 0;
  }
};