1 | // RUN: %check_clang_tidy %s misc-new-delete-overloads %t |
2 | |
3 | typedef decltype(sizeof(int)) size_t; |
4 | |
5 | struct S { |
6 | // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope [misc-new-delete-overloads] |
7 | void *operator new(size_t size) noexcept; |
8 | // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new[]' has no matching declaration of 'operator delete[]' at the same scope |
9 | void *operator new[](size_t size) noexcept; |
10 | }; |
11 | |
12 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope |
13 | void *operator new(size_t size) noexcept(false); |
14 | |
15 | struct T { |
16 | // Sized deallocations are not enabled by default, and so this new/delete pair |
17 | // does not match. However, we expect only one warning, for the new, because |
18 | // the operator delete is a placement delete and we do not warn on mismatching |
19 | // placement operations. |
20 | // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope |
21 | void *operator new(size_t size) noexcept; |
22 | void operator delete(void *ptr, size_t) noexcept; // ok only if sized deallocation is enabled |
23 | }; |
24 | |
25 | struct U { |
26 | void *operator new(size_t size) noexcept; |
27 | void operator delete(void *ptr) noexcept; |
28 | |
29 | void *operator new[](size_t) noexcept; |
30 | void operator delete[](void *) noexcept; |
31 | }; |
32 | |
33 | struct Z { |
34 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete' has no matching declaration of 'operator new' at the same scope |
35 | void operator delete(void *ptr) noexcept; |
36 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: declaration of 'operator delete[]' has no matching declaration of 'operator new[]' at the same scope |
37 | void operator delete[](void *ptr) noexcept; |
38 | }; |
39 | |
40 | struct A { |
41 | void *operator new(size_t size, Z) noexcept; // ok, placement new |
42 | }; |
43 | |
44 | struct B { |
45 | void operator delete(void *ptr, A) noexcept; // ok, placement delete |
46 | }; |
47 | |
48 | // It is okay to have a class with an inaccessible free store operator. |
49 | struct C { |
50 | void *operator new(size_t, A) noexcept; // ok, placement new |
51 | private: |
52 | void operator delete(void *) noexcept; |
53 | }; |
54 | |
55 | // It is also okay to have a class with a delete free store operator. |
56 | struct D { |
57 | void *operator new(size_t, A) noexcept; // ok, placement new |
58 | void operator delete(void *) noexcept = delete; |
59 | }; |
60 | |
61 | struct E : U { |
62 | void *operator new(size_t) noexcept; // okay, we inherit operator delete from U |
63 | }; |
64 | |
65 | struct F : S { |
66 | // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope |
67 | void *operator new(size_t) noexcept; |
68 | }; |
69 | |
70 | class G { |
71 | void operator delete(void *) noexcept; |
72 | }; |
73 | |
74 | struct H : G { |
75 | // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope |
76 | void *operator new(size_t) noexcept; // base class operator is inaccessible |
77 | }; |
78 | |
79 | template <typename Base> struct Derived : Base { |
80 | void operator delete(void *); |
81 | }; |
82 | |