Skip to content

Commit 71055d3

Browse files
committed
Add test cases for RULE-21-6-3
1 parent e33e379 commit 71055d3

File tree

1 file changed

+346
-0
lines changed
  • cpp/misra/test/rules/RULE-21-6-3

1 file changed

+346
-0
lines changed
Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
#include <cstddef>
2+
#include <cstdlib>
3+
#include <memory>
4+
#include <new>
5+
6+
/**
7+
* Fixture class with class-specific operator new/delete declarations and
8+
* definitions.
9+
*/
10+
class C1 {
11+
public:
12+
C1() {}
13+
14+
// Class-specific operator declarations - NON_COMPLIANT (any signature)
15+
void *
16+
operator new(std::size_t size); // NON_COMPLIANT: class-specific declaration
17+
void *
18+
operator new[](std::size_t size); // NON_COMPLIANT: class-specific declaration
19+
void operator delete(
20+
void *ptr) noexcept; // NON_COMPLIANT: class-specific declaration
21+
void operator delete[](
22+
void *ptr) noexcept; // NON_COMPLIANT: class-specific declaration
23+
void *operator new(
24+
std::size_t size,
25+
const std::nothrow_t
26+
&) noexcept; // NON_COMPLIANT: class-specific nothrow declaration
27+
void *operator new(std::size_t size,
28+
void *ptr) noexcept; // NON_COMPLIANT: class-specific
29+
// placement declaration
30+
void *operator new[](std::size_t size,
31+
void *ptr) noexcept; // NON_COMPLIANT: class-specific
32+
// placement declaration
33+
void *
34+
operator new(std::size_t size,
35+
int hint); // NON_COMPLIANT: class-specific custom declaration
36+
void *
37+
operator new(std::size_t size, double alignment,
38+
int pool); // NON_COMPLIANT: class-specific custom declaration
39+
};
40+
41+
/**
42+
* Class-specific operator definitions - NON_COMPLIANT (any signature)
43+
*/
44+
void *C1::operator new(std::size_t size) {
45+
return std::malloc(size);
46+
} // NON_COMPLIANT: class-specific
47+
void *C1::operator new[](std::size_t size) {
48+
return std::malloc(size);
49+
} // NON_COMPLIANT: class-specific
50+
void C1::operator delete(void *ptr) noexcept {
51+
std::free(ptr);
52+
} // NON_COMPLIANT: class-specific
53+
void C1::operator delete[](void *ptr) noexcept {
54+
std::free(ptr);
55+
} // NON_COMPLIANT: class-specific
56+
void *C1::operator new(std::size_t size, const std::nothrow_t &) noexcept {
57+
return std::malloc(size);
58+
} // NON_COMPLIANT: class-specific nothrow
59+
void *C1::operator new(std::size_t size, void *ptr) noexcept {
60+
return ptr;
61+
} // NON_COMPLIANT: class-specific placement
62+
void *C1::operator new[](std::size_t size, void *ptr) noexcept {
63+
return ptr;
64+
} // NON_COMPLIANT: class-specific placement
65+
void *C1::operator new(std::size_t size, int hint) {
66+
return std::malloc(size);
67+
} // NON_COMPLIANT: class-specific custom
68+
void *C1::operator new(std::size_t size, double alignment, int pool) {
69+
return std::malloc(size);
70+
} // NON_COMPLIANT: class-specific custom
71+
72+
/**
73+
* Global replaceable forms - COMPLIANT
74+
* These are the "blessed" signatures that can be replaced globally.
75+
*/
76+
void *
77+
operator new(std::size_t size); // COMPLIANT: re-declaring global replaceable
78+
void *operator new(std::size_t size) {
79+
return std::malloc(size);
80+
} // COMPLIANT: implementing global replaceable
81+
void operator delete(void *ptr) noexcept {
82+
std::free(ptr);
83+
} // COMPLIANT: implementing global replaceable
84+
void *operator new[](std::size_t size) {
85+
return std::malloc(size);
86+
} // COMPLIANT: implementing global replaceable
87+
void operator delete[](void *ptr) noexcept {
88+
std::free(ptr);
89+
} // COMPLIANT: implementing global replaceable
90+
void *operator new(std::size_t size, const std::nothrow_t &) noexcept {
91+
return std::malloc(size);
92+
} // COMPLIANT: implementing global replaceable nothrow
93+
void *operator new[](std::size_t size, const std::nothrow_t &) noexcept {
94+
return std::malloc(size);
95+
} // COMPLIANT: implementing global replaceable nothrow
96+
void operator delete(void *ptr, std::size_t) noexcept {
97+
std::free(ptr);
98+
} // COMPLIANT: implementing global replaceable sized
99+
void operator delete[](void *ptr, std::size_t) noexcept {
100+
std::free(ptr);
101+
} // COMPLIANT: implementing global replaceable sized
102+
void operator delete(void *ptr, const std::nothrow_t &) noexcept {
103+
std::free(ptr);
104+
} // COMPLIANT: implementing global replaceable placement deallocation
105+
void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
106+
std::free(ptr);
107+
} // COMPLIANT: implementing global replaceable placement deallocation
108+
109+
/**
110+
* Global non-standard forms - NON_COMPLIANT
111+
* These are not in the four replaceable categories.
112+
*/
113+
void *
114+
operator new(std::size_t size,
115+
void *ptr) noexcept; // NON_COMPLIANT: user-declared placement new
116+
void *operator new[](
117+
std::size_t size,
118+
void *ptr) noexcept; // NON_COMPLIANT: user-declared placement new[]
119+
void *operator new(std::size_t size, int hint) {
120+
return std::malloc(size);
121+
} // NON_COMPLIANT: custom parameter
122+
void *operator new(std::size_t size, double alignment, int pool) {
123+
return std::malloc(size);
124+
} // NON_COMPLIANT: custom parameters
125+
void operator delete(
126+
void *ptr,
127+
void *) noexcept; // NON_COMPLIANT: user-declared placement delete
128+
void operator delete[](
129+
void *ptr,
130+
void *) noexcept; // NON_COMPLIANT: user-declared placement delete[]
131+
void operator delete(void *ptr, int hint) noexcept {
132+
std::free(ptr);
133+
} // NON_COMPLIANT: custom parameter
134+
135+
/**
136+
* Test placement new expressions.
137+
*/
138+
void use_placement_new() {
139+
std::size_t size = 10;
140+
alignas(C1) std::byte buffer[sizeof(C1)];
141+
C1 *p1 = new (buffer) C1; // NON_COMPLIANT: placement new expression
142+
C1 *p2 = new (buffer)
143+
C1{}; // NON_COMPLIANT: placement new expression with brace init
144+
145+
alignas(C1) std::byte arr_buffer[sizeof(C1) * 10];
146+
C1 *p3 =
147+
new (arr_buffer) C1[size]; // NON_COMPLIANT: placement new[] expression
148+
149+
void *mem = std::malloc(sizeof(C1)); // NON_COMPLIANT (Rule 21.6.2): malloc
150+
C1 *p4 = new (mem) C1; // NON_COMPLIANT: placement new expression
151+
}
152+
153+
/**
154+
* Test custom-parameter new expressions.
155+
*/
156+
void use_custom_new_expressions() {
157+
C1 *p1 = new (42) C1; // NON_COMPLIANT: uses operator new(size_t, int)
158+
C1 *p2 =
159+
new (3.14, 1) C1; // NON_COMPLIANT: uses operator new(size_t, double, int)
160+
}
161+
162+
/**
163+
* Test taking address of global placement new.
164+
*/
165+
void take_address_of_placement_new() {
166+
void *(*p1)(std::size_t, void *) =
167+
&::operator new; // NON_COMPLIANT: address of placement new
168+
void *(*p2)(std::size_t, void *) =
169+
::operator new; // NON_COMPLIANT: implicit address of placement new
170+
void *(*p3)(std::size_t, void *) =
171+
&::operator new[]; // NON_COMPLIANT: address of placement new[]
172+
void *(*p4)(std::size_t, void *) =
173+
::operator new[]; // NON_COMPLIANT: implicit address of placement new[]
174+
}
175+
176+
/**
177+
* Test taking address of global placement delete.
178+
*/
179+
void take_address_of_placement_delete() {
180+
void (*p1)(void *, void *) =
181+
&::operator delete; // NON_COMPLIANT: address of placement delete
182+
void (*p2)(void *, void *) =
183+
::operator delete; // NON_COMPLIANT: implicit address of placement delete
184+
void (*p3)(void *, void *) =
185+
&::operator delete[]; // NON_COMPLIANT: address of placement delete[]
186+
void (*p4)(void *, void *) =
187+
::operator delete[]; // NON_COMPLIANT: implicit address of placement
188+
// delete[]
189+
}
190+
191+
/**
192+
* Test taking address of class-specific operator new.
193+
*/
194+
void take_address_of_class_specific_new() {
195+
void *(*p1)(std::size_t) =
196+
&C1::operator new; // NON_COMPLIANT: address of class-specific new
197+
void *(*p2)(std::size_t) =
198+
&C1::operator new[]; // NON_COMPLIANT: address of class-specific new[]
199+
void *(*p3)(std::size_t, const std::nothrow_t &) =
200+
&C1::operator new; // NON_COMPLIANT: address of class-specific nothrow new
201+
void *(*p4)(std::size_t, void *) =
202+
&C1::operator new; // NON_COMPLIANT: address of class-specific placement
203+
// new
204+
void *(*p5)(std::size_t, int) =
205+
&C1::operator new; // NON_COMPLIANT: address of class-specific custom new
206+
}
207+
208+
/**
209+
* Test taking address of class-specific operator delete.
210+
*/
211+
void take_address_of_class_specific_delete() {
212+
void (*p1)(void *) =
213+
&C1::operator delete; // NON_COMPLIANT: address of class-specific delete
214+
void (*p2)(void *) = &C1::operator delete[]; // NON_COMPLIANT: address of
215+
// class-specific delete[]
216+
}
217+
218+
/**
219+
* Test std::uninitialized_default_construct and
220+
* std::uninitialized_default_construct_n.
221+
*/
222+
void use_uninitialized_default_construct() {
223+
std::size_t size = 10;
224+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
225+
C1 *begin = reinterpret_cast<C1 *>(buffer);
226+
C1 *end = begin + size;
227+
228+
std::uninitialized_default_construct(begin, end); // NON_COMPLIANT
229+
std::uninitialized_default_construct_n(begin, size); // NON_COMPLIANT
230+
}
231+
232+
/**
233+
* Test std::uninitialized_value_construct and
234+
* std::uninitialized_value_construct_n.
235+
*/
236+
void use_uninitialized_value_construct() {
237+
std::size_t size = 10;
238+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
239+
C1 *begin = reinterpret_cast<C1 *>(buffer);
240+
C1 *end = begin + size;
241+
242+
std::uninitialized_value_construct(begin, end); // NON_COMPLIANT
243+
std::uninitialized_value_construct_n(begin, size); // NON_COMPLIANT
244+
}
245+
246+
/**
247+
* Test std::uninitialized_copy and std::uninitialized_copy_n.
248+
*/
249+
void use_uninitialized_copy() {
250+
std::size_t size = 10;
251+
C1 source[10];
252+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
253+
C1 *dest = reinterpret_cast<C1 *>(buffer);
254+
255+
std::uninitialized_copy(source, source + size, dest); // NON_COMPLIANT
256+
std::uninitialized_copy_n(source, size, dest); // NON_COMPLIANT
257+
}
258+
259+
/**
260+
* Test std::uninitialized_move and std::uninitialized_move_n.
261+
*/
262+
void use_uninitialized_move() {
263+
std::size_t size = 10;
264+
C1 source[10];
265+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
266+
C1 *dest = reinterpret_cast<C1 *>(buffer);
267+
268+
std::uninitialized_move(source, source + size, dest); // NON_COMPLIANT
269+
std::uninitialized_move_n(source, size, dest); // NON_COMPLIANT
270+
}
271+
272+
/**
273+
* Test std::uninitialized_fill and std::uninitialized_fill_n.
274+
*/
275+
void use_uninitialized_fill() {
276+
std::size_t size = 10;
277+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
278+
C1 *begin = reinterpret_cast<C1 *>(buffer);
279+
C1 *end = begin + size;
280+
C1 value;
281+
282+
std::uninitialized_fill(begin, end, value); // NON_COMPLIANT
283+
std::uninitialized_fill_n(begin, size, value); // NON_COMPLIANT
284+
}
285+
286+
/**
287+
* Test std::destroy, std::destroy_n, and std::destroy_at.
288+
*/
289+
void use_destroy() {
290+
std::size_t size = 10;
291+
alignas(C1) std::byte buffer[sizeof(C1) * 10];
292+
C1 *begin = reinterpret_cast<C1 *>(buffer);
293+
C1 *end = begin + size;
294+
295+
std::uninitialized_default_construct(begin, end); // NON_COMPLIANT
296+
297+
std::destroy(begin, end); // NON_COMPLIANT
298+
std::destroy_n(begin, size); // NON_COMPLIANT
299+
std::destroy_at(begin); // NON_COMPLIANT
300+
}
301+
302+
/**
303+
* Test std::launder.
304+
*/
305+
void use_launder() {
306+
alignas(C1) std::byte buffer[sizeof(C1)];
307+
C1 *p1 = new (buffer) C1; // NON_COMPLIANT: placement new
308+
p1->~C1(); // NON_COMPLIANT: explicit destructor
309+
C1 *p2 = new (buffer) C1; // NON_COMPLIANT: placement new
310+
311+
C1 *p3 = std::launder(p1); // NON_COMPLIANT: use of std::launder
312+
}
313+
314+
/**
315+
* Test explicit destructor call via pointer.
316+
*/
317+
void use_explicit_destructor() {
318+
C1 obj;
319+
C1 *p = &obj;
320+
321+
p->~C1(); // NON_COMPLIANT: explicit destructor call
322+
}
323+
324+
/**
325+
* Test explicit destructor call via reference.
326+
*/
327+
void use_explicit_destructor_via_reference() {
328+
C1 obj;
329+
C1 &ref = obj;
330+
331+
ref.~C1(); // NON_COMPLIANT: explicit destructor call
332+
}
333+
334+
/**
335+
* Test explicit destructor call in array loop.
336+
*/
337+
void use_explicit_destructor_array() {
338+
std::size_t size = 10;
339+
C1 arr[10];
340+
341+
for (std::size_t i = 0; i < size; ++i) {
342+
arr[i].~C1(); // NON_COMPLIANT: explicit destructor call
343+
}
344+
}
345+
346+
int main() { return 0; }

0 commit comments

Comments
 (0)