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 {
23 // We can't force an underlying type when targeting windows.
24 # ifndef _WIN32
25 __zero = 0, __max = (size_t)-1
26 # endif
27 };
28 #endif
29 }
30 std::nothrow_t nothrow;
31
32 void *operator new(size_t); // expected-note 1+ {{candidate function}}
33 void operator delete(void *); // expected-note 1+ {{candidate function}}
34
35 // Declare the reserved placement operators.
36 void *operator new(size_t, void*) throw(); // expected-note 1+ {{candidate function}}
37 void operator delete(void *, void *)throw(); // expected-note 1+ {{candidate function}}
38 void *operator new[](size_t, void*) throw();
39 void operator delete[](void*, void*) throw();
40
41 // Declare the replaceable global allocation operators.
42 void *operator new(size_t, const std::nothrow_t &) throw(); // expected-note 1+ {{candidate function}}
43 void *operator new[](size_t, const std::nothrow_t &) throw();
44 void operator delete(void *, const std::nothrow_t &)throw(); // expected-note 1+ {{candidate function}}
45 void operator delete[](void *, const std::nothrow_t &) throw();
46
47 // aligned allocation and deallocation functions.
48 void* operator new ( size_t count, std::align_val_t al); // expected-note 1+ {{candidate function}}
49 void operator delete(void *, std::align_val_t); // expected-note 1+ {{candidate}}
50 #ifndef __cpp_aligned_new
51 // expected-note@-3 1+ {{non-usual 'operator new' declared here}}
52 // expected-note@-3 1+ {{non-usual 'operator delete' declared here}}
53 #endif
54 void *operator new[](size_t count, std::align_val_t al);
55 void operator delete[](void*, std::align_val_t);
56
57 void operator delete(void *, size_t); // expected-note 1+ {{candidate}}
58 #ifndef __cpp_sized_deallocation
59 // expected-note@-2 1+ {{non-usual 'operator delete' declared here}}
60 #endif
61 void operator delete[](void*, size_t);
62
63 // Declare some other placemenet operators.
64 void *operator new(size_t, void*, bool) throw(); // expected-note 1+ {{candidate function}}
65 void *operator new[](size_t, void*, bool) throw();
66
67 void *NP = 0;
68
test_typo_in_args()69 void test_typo_in_args() {
70 __builtin_operator_new(DNE); // expected-error {{undeclared identifier 'DNE'}}
71 __builtin_operator_new(DNE, DNE2); // expected-error {{undeclared identifier 'DNE'}} expected-error {{'DNE2'}}
72 __builtin_operator_delete(DNE); // expected-error {{'DNE'}}
73 __builtin_operator_delete(DNE, DNE2); // expected-error {{'DNE'}} expected-error {{'DNE2'}}
74 }
75
test_arg_types()76 void test_arg_types() {
77 __builtin_operator_new(NP); // expected-error {{no matching function for call to 'operator new'}}
78 __builtin_operator_new(NP, std::align_val_t(0)); // expected-error {{no matching function for call to 'operator new'}}}
79 }
test_return_type()80 void test_return_type() {
81 int w = __builtin_operator_new(42); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
82 int y = __builtin_operator_delete(NP); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void'}}
83 }
84
test_aligned_new()85 void test_aligned_new() {
86 #ifdef __cpp_aligned_new
87 void *p = __builtin_operator_new(42, std::align_val_t(2));
88 __builtin_operator_delete(p, std::align_val_t(2));
89 #else
90 // FIXME: We've manually declared the aligned new/delete overloads,
91 // but LangOpts::AlignedAllocation is false. Should our overloads be considered
92 // usual allocation/deallocation functions?
93 void *p = __builtin_operator_new(42, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
94 __builtin_operator_delete(p, std::align_val_t(2)); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
95 #endif
96 }
97
test_sized_delete()98 void test_sized_delete() {
99 #ifdef __cpp_sized_deallocation
100 __builtin_operator_delete(NP, 4);
101 #else
102 __builtin_operator_delete(NP, 4); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
103 #endif
104 }
105
106 void *operator new(size_t, bool); // expected-note 1+ {{candidate}}
107 // expected-note@-1 {{non-usual 'operator new' declared here}}
108 void operator delete(void *, bool); // expected-note 1+ {{candidate}}
109 // expected-note@-1 {{non-usual 'operator delete' declared here}}
110
test_non_usual()111 void test_non_usual() {
112 __builtin_operator_new(42, true); // expected-error {{call to '__builtin_operator_new' selects non-usual allocation function}}
113 __builtin_operator_delete(NP, false); // expected-error {{call to '__builtin_operator_delete' selects non-usual deallocation function}}
114 }
115
116 template <int ID>
117 struct Tag {};
118 struct ConvertsToTypes {
119 operator std::align_val_t() const;
120 operator Tag<0>() const;
121 };
122
123 void *operator new(size_t, Tag<0>); // expected-note 0+ {{candidate}}
124 void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}}
125
test_ambiguous()126 void test_ambiguous() {
127 #ifdef __cpp_aligned_new
128 ConvertsToTypes cvt;
129 __builtin_operator_new(42, cvt); // expected-error {{call to 'operator new' is ambiguous}}
130 __builtin_operator_delete(NP, cvt); // expected-error {{call to 'operator delete' is ambiguous}}
131 #endif
132 }
133
test_no_args()134 void test_no_args() {
135 __builtin_operator_new(); // expected-error {{no matching function for call to 'operator new'}}
136 __builtin_operator_delete(); // expected-error {{no matching function for call to 'operator delete'}}
137 }
138
test_no_matching_fn()139 void test_no_matching_fn() {
140 Tag<1> tag;
141 __builtin_operator_new(42, tag); // expected-error {{no matching function for call to 'operator new'}}
142 __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}}
143 }
144
145 template <class Tp, class Up, class RetT>
test_dependent_call(Tp new_arg,Up delete_arg,RetT)146 void test_dependent_call(Tp new_arg, Up delete_arg, RetT) {
147 RetT ret = __builtin_operator_new(new_arg);
148 __builtin_operator_delete(delete_arg);
149 }
150 template void test_dependent_call(int, int*, void*);
151
test_const_attribute()152 void test_const_attribute() {
153 __builtin_operator_new(42); // expected-warning {{ignoring return value of function declared with const attribute}}
154 #ifdef __cpp_aligned_new
155 __builtin_operator_new(42, std::align_val_t(8)); // expected-warning {{ignoring return value of function declared with const attribute}}
156 #endif
157 }
158