xref: /llvm-project/clang/test/SemaCXX/builtin-operator-new-delete.cpp (revision fa752f23cc20d38259a84a1c44e508df4503f284)
1 // RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s
3 // RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify %s
4 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
5 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fsized-deallocation %s
6 
7 #if !__has_builtin(__builtin_operator_new) || !__has_builtin(__builtin_operator_delete)
8 #error builtins should always be available
9 #endif
10 
11 #if __has_builtin(__builtin_operator_new) != 201802L || \
12     __has_builtin(__builtin_operator_delete) != 201802L
13 #error builtin should report updated value
14 #endif
15 
16 typedef __SIZE_TYPE__ size_t;
17 namespace std {
18   struct nothrow_t {};
19 #if __cplusplus >= 201103L
20 enum class align_val_t : size_t {};
21 #else
22   enum align_val_t { __zero = 0,
23                      __max = (size_t)-1 };
24 #endif
25 }
26 std::nothrow_t nothrow;
27 
28 void *operator new(size_t); // expected-note 1+ {{candidate function}}
29 void operator delete(void *); // expected-note 1+ {{candidate function}}
30 
31 // Declare the reserved placement operators.
32 void *operator new(size_t, void*) throw(); // expected-note 1+ {{candidate function}}
33 void operator delete(void *, void *)throw(); // expected-note 1+ {{candidate function}}
34 void *operator new[](size_t, void*) throw();
35 void operator delete[](void*, void*) throw();
36 
37 // Declare the replaceable global allocation operators.
38 void *operator new(size_t, const std::nothrow_t &) throw(); // expected-note 1+ {{candidate function}}
39 void *operator new[](size_t, const std::nothrow_t &) throw();
40 void operator delete(void *, const std::nothrow_t &)throw(); // expected-note 1+ {{candidate function}}
41 void operator delete[](void *, const std::nothrow_t &) throw();
42 
43 // aligned allocation and deallocation functions.
44 void* operator new  ( size_t count, std::align_val_t al); // expected-note 1+ {{candidate function}}
45 void operator delete(void *, std::align_val_t); // expected-note 1+ {{candidate}}
46 #ifndef __cpp_aligned_new
47 // expected-note@-3 1+ {{non-usual 'operator new' declared here}}
48 // expected-note@-3 1+ {{non-usual 'operator delete' declared here}}
49 #endif
50 void *operator new[](size_t count, std::align_val_t al);
51 void operator delete[](void*, std::align_val_t);
52 
53 void operator delete(void *, size_t); // expected-note 1+ {{candidate}}
54 #ifndef __cpp_sized_deallocation
55 // expected-note@-2 1+ {{non-usual 'operator delete' declared here}}
56 #endif
57 void operator delete[](void*, size_t);
58 
59 // Declare some other placemenet operators.
60 void *operator new(size_t, void*, bool) throw(); // expected-note 1+ {{candidate function}}
61 void *operator new[](size_t, void*, bool) throw();
62 
63 void *NP = 0;
64 
65 void test_typo_in_args() {
66   __builtin_operator_new(DNE);          // expected-error {{undeclared identifier 'DNE'}}
67   __builtin_operator_new(DNE, DNE2);    // expected-error {{undeclared identifier 'DNE'}} expected-error {{'DNE2'}}
68   __builtin_operator_delete(DNE);       // expected-error {{'DNE'}}
69   __builtin_operator_delete(DNE, DNE2); // expected-error {{'DNE'}} expected-error {{'DNE2'}}
70 }
71 
72 void test_arg_types() {
73   __builtin_operator_new(NP);                      // expected-error {{no matching function for call to 'operator new'}}
74   __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}}
75 }
76 void test_return_type() {
77   int w = __builtin_operator_new(42);        // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
78   int y = __builtin_operator_delete(NP);     // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void'}}
79 }
80 
81 void test_aligned_new() {
82 #ifdef __cpp_aligned_new
83   void *p = __builtin_operator_new(42, std::align_val_t(2));
84   __builtin_operator_delete(p, std::align_val_t(2));
85 #else
86   // FIXME: We've manually declared the aligned new/delete overloads,
87   // but LangOpts::AlignedAllocation is false. Should our overloads be considered
88   // usual allocation/deallocation functions?
89   void *p = __builtin_operator_new(42, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
90   __builtin_operator_delete(p, std::align_val_t(2));         // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
91 #endif
92 }
93 
94 void test_sized_delete() {
95 #ifdef __cpp_sized_deallocation
96   __builtin_operator_delete(NP, 4);
97 #else
98   __builtin_operator_delete(NP, 4); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
99 #endif
100 }
101 
102 void *operator new(size_t, bool);   // expected-note 1+ {{candidate}}
103 // expected-note@-1 {{non-usual 'operator new' declared here}}
104 void operator delete(void *, bool); // expected-note 1+ {{candidate}}
105 // expected-note@-1 {{non-usual 'operator delete' declared here}}
106 
107 void test_non_usual() {
108   __builtin_operator_new(42, true);     // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
109   __builtin_operator_delete(NP, false); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
110 }
111 
112 template <int ID>
113 struct Tag {};
114 struct ConvertsToTypes {
115   operator std::align_val_t() const;
116   operator Tag<0>() const;
117 };
118 
119 void *operator new(size_t, Tag<0>);   // expected-note 0+ {{candidate}}
120 void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}}
121 
122 void test_ambiguous() {
123 #ifdef __cpp_aligned_new
124   ConvertsToTypes cvt;
125   __builtin_operator_new(42, cvt);    // expected-error {{call to 'operator new' is ambiguous}}
126   __builtin_operator_delete(NP, cvt); // expected-error {{call to 'operator delete' is ambiguous}}
127 #endif
128 }
129 
130 void test_no_args() {
131   __builtin_operator_new();    // expected-error {{no matching function for call to 'operator new'}}
132   __builtin_operator_delete(); // expected-error {{no matching function for call to 'operator delete'}}
133 }
134 
135 void test_no_matching_fn() {
136   Tag<1> tag;
137   __builtin_operator_new(42, tag);    // expected-error {{no matching function for call to 'operator new'}}
138   __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}}
139 }
140 
141 template <class Tp, class Up, class RetT>
142 void test_dependent_call(Tp new_arg, Up delete_arg, RetT) {
143   RetT ret = __builtin_operator_new(new_arg);
144   __builtin_operator_delete(delete_arg);
145 }
146 template void test_dependent_call(int, int*, void*);
147 
148 void test_const_attribute() {
149   __builtin_operator_new(42); // expected-warning {{ignoring return value of function declared with const attribute}}
150 #ifdef __cpp_aligned_new
151   __builtin_operator_new(42, std::align_val_t(8)); // expected-warning {{ignoring return value of function declared with const attribute}}
152 #endif
153 }
154