Clang Project

clang_source_code/test/SemaCXX/builtin-operator-new-delete.cpp
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
16typedef __SIZE_TYPE__ size_t;
17namespace std {
18  struct nothrow_t {};
19#if __cplusplus >= 201103L
20enum 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}
30std::nothrow_t nothrow;
31
32void *operator new(size_t); // expected-note 1+ {{candidate function}}
33void operator delete(void *); // expected-note 1+ {{candidate function}}
34
35// Declare the reserved placement operators.
36void *operator new(size_t, void*) throw(); // expected-note 1+ {{candidate function}}
37void operator delete(void *, void *)throw(); // expected-note 1+ {{candidate function}}
38void *operator new[](size_t, void*) throw();
39void operator delete[](void*, void*) throw();
40
41// Declare the replaceable global allocation operators.
42void *operator new(size_t, const std::nothrow_t &) throw(); // expected-note 1+ {{candidate function}}
43void *operator new[](size_t, const std::nothrow_t &) throw();
44void operator delete(void *, const std::nothrow_t &)throw(); // expected-note 1+ {{candidate function}}
45void operator delete[](void *, const std::nothrow_t &) throw();
46
47// aligned allocation and deallocation functions.
48void* operator new  ( size_t count, std::align_val_t al); // expected-note 1+ {{candidate function}}
49void 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
54void *operator new[](size_t count, std::align_val_t al);
55void operator delete[](void*, std::align_val_t);
56
57void 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
61void operator delete[](void*, size_t);
62
63// Declare some other placemenet operators.
64void *operator new(size_t, void*, bool) throw(); // expected-note 1+ {{candidate function}}
65void *operator new[](size_t, void*, bool) throw();
66
67void *NP = 0;
68
69void 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
76void 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}
80void 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
85void 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
98void 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
106void *operator new(size_t, bool);   // expected-note 1+ {{candidate}}
107// expected-note@-1 {{non-usual 'operator new' declared here}}
108void operator delete(void *, bool); // expected-note 1+ {{candidate}}
109// expected-note@-1 {{non-usual 'operator delete' declared here}}
110
111void 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
116template <int ID>
117struct Tag {};
118struct ConvertsToTypes {
119  operator std::align_val_t() const;
120  operator Tag<0>() const;
121};
122
123void *operator new(size_t, Tag<0>);   // expected-note 0+ {{candidate}}
124void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}}
125
126void 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
134void 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
139void 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
145template <class Tp, class Up, class RetT>
146void 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}
150template void test_dependent_call(int, int*, void*);
151
152void 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