xref: /llvm-project/compiler-rt/test/scudo/aligned-new.cpp (revision c27415ff86a617bdaaf310f6888f084bdf0705ea)
1*c27415ffSFangrui Song // RUN: %clangxx_scudo %s -o %t
2f7c5c0d8SMitch Phillips // RUN:                                                 %run %t valid   2>&1
3f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=allocator_may_return_null=1     %run %t invalid 2>&1
4f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s
5f7c5c0d8SMitch Phillips 
6f7c5c0d8SMitch Phillips // Tests that the C++17 aligned new/delete operators are working as expected.
7f7c5c0d8SMitch Phillips // Currently we do not check the consistency of the alignment on deallocation,
8f7c5c0d8SMitch Phillips // so this just tests that the APIs work.
9f7c5c0d8SMitch Phillips 
10f7c5c0d8SMitch Phillips #include <assert.h>
11f7c5c0d8SMitch Phillips #include <stdint.h>
12f7c5c0d8SMitch Phillips #include <stdio.h>
13f7c5c0d8SMitch Phillips #include <string.h>
14f7c5c0d8SMitch Phillips 
15f7c5c0d8SMitch Phillips // Define all new/delete to not depend on the version provided by the platform.
16f7c5c0d8SMitch Phillips 
17f7c5c0d8SMitch Phillips namespace std {
18f7c5c0d8SMitch Phillips struct nothrow_t {};
19f7c5c0d8SMitch Phillips static const nothrow_t nothrow;
20f7c5c0d8SMitch Phillips enum class align_val_t : size_t {};
21f7c5c0d8SMitch Phillips } // namespace std
22f7c5c0d8SMitch Phillips 
23f7c5c0d8SMitch Phillips void *operator new(size_t);
24f7c5c0d8SMitch Phillips void *operator new[](size_t);
25f7c5c0d8SMitch Phillips void *operator new(size_t, std::nothrow_t const &);
26f7c5c0d8SMitch Phillips void *operator new[](size_t, std::nothrow_t const &);
27f7c5c0d8SMitch Phillips void *operator new(size_t, std::align_val_t);
28f7c5c0d8SMitch Phillips void *operator new[](size_t, std::align_val_t);
29f7c5c0d8SMitch Phillips void *operator new(size_t, std::align_val_t, std::nothrow_t const &);
30f7c5c0d8SMitch Phillips void *operator new[](size_t, std::align_val_t, std::nothrow_t const &);
31f7c5c0d8SMitch Phillips 
32f7c5c0d8SMitch Phillips void operator delete(void *) throw();
33f7c5c0d8SMitch Phillips void operator delete[](void *) throw();
34f7c5c0d8SMitch Phillips void operator delete(void *, std::nothrow_t const &);
35f7c5c0d8SMitch Phillips void operator delete[](void *, std::nothrow_t const &);
36f7c5c0d8SMitch Phillips void operator delete(void *, size_t) throw();
37f7c5c0d8SMitch Phillips void operator delete[](void *, size_t) throw();
38f7c5c0d8SMitch Phillips void operator delete(void *, std::align_val_t) throw();
39f7c5c0d8SMitch Phillips void operator delete[](void *, std::align_val_t) throw();
40f7c5c0d8SMitch Phillips void operator delete(void *, std::align_val_t, std::nothrow_t const &);
41f7c5c0d8SMitch Phillips void operator delete[](void *, std::align_val_t, std::nothrow_t const &);
42f7c5c0d8SMitch Phillips void operator delete(void *, size_t, std::align_val_t) throw();
43f7c5c0d8SMitch Phillips void operator delete[](void *, size_t, std::align_val_t) throw();
44f7c5c0d8SMitch Phillips 
45f7c5c0d8SMitch Phillips template <typename T>
46f7c5c0d8SMitch Phillips inline T *break_optimization(T *arg) {
47f7c5c0d8SMitch Phillips   __asm__ __volatile__(""
48f7c5c0d8SMitch Phillips                        :
49f7c5c0d8SMitch Phillips                        : "r"(arg)
50f7c5c0d8SMitch Phillips                        : "memory");
51f7c5c0d8SMitch Phillips   return arg;
52f7c5c0d8SMitch Phillips }
53f7c5c0d8SMitch Phillips 
54f7c5c0d8SMitch Phillips struct S12 {
55f7c5c0d8SMitch Phillips   int a, b, c;
56f7c5c0d8SMitch Phillips };
57f7c5c0d8SMitch Phillips struct alignas(128) S12_128 {
58f7c5c0d8SMitch Phillips   int a, b, c;
59f7c5c0d8SMitch Phillips };
60f7c5c0d8SMitch Phillips struct alignas(256) S12_256 {
61f7c5c0d8SMitch Phillips   int a, b, c;
62f7c5c0d8SMitch Phillips };
63f7c5c0d8SMitch Phillips struct alignas(512) S1024_512 {
64f7c5c0d8SMitch Phillips   char a[1024];
65f7c5c0d8SMitch Phillips };
66f7c5c0d8SMitch Phillips struct alignas(1024) S1024_1024 {
67f7c5c0d8SMitch Phillips   char a[1024];
68f7c5c0d8SMitch Phillips };
69f7c5c0d8SMitch Phillips 
70f7c5c0d8SMitch Phillips int main(int argc, char **argv) {
71f7c5c0d8SMitch Phillips   assert(argc == 2);
72f7c5c0d8SMitch Phillips 
73f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "valid")) {
74f7c5c0d8SMitch Phillips     // Standard use case.
75f7c5c0d8SMitch Phillips     delete break_optimization(new S12);
76f7c5c0d8SMitch Phillips     delete break_optimization(new S12_128);
77f7c5c0d8SMitch Phillips     delete[] break_optimization(new S12_128[4]);
78f7c5c0d8SMitch Phillips     delete break_optimization(new S12_256);
79f7c5c0d8SMitch Phillips     delete break_optimization(new S1024_512);
80f7c5c0d8SMitch Phillips     delete[] break_optimization(new S1024_512[4]);
81f7c5c0d8SMitch Phillips     delete break_optimization(new S1024_1024);
82f7c5c0d8SMitch Phillips 
83f7c5c0d8SMitch Phillips     // Call directly the aligned versions of the operators.
84f7c5c0d8SMitch Phillips     const size_t alignment = 1U << 8;
85f7c5c0d8SMitch Phillips     void *p = operator new(1, static_cast<std::align_val_t>(alignment));
86f7c5c0d8SMitch Phillips     assert((reinterpret_cast<uintptr_t>(p) & (alignment - 1)) == 0);
87f7c5c0d8SMitch Phillips     operator delete(p, static_cast<std::align_val_t>(alignment));
88f7c5c0d8SMitch Phillips   }
89f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "invalid")) {
90f7c5c0d8SMitch Phillips     // Alignment must be a power of 2.
91f7c5c0d8SMitch Phillips     const size_t alignment = (1U << 8) - 1;
92f7c5c0d8SMitch Phillips     void *p = operator new(1, static_cast<std::align_val_t>(alignment),
93f7c5c0d8SMitch Phillips                            std::nothrow);
94f7c5c0d8SMitch Phillips     // CHECK: Scudo ERROR: invalid allocation alignment
95f7c5c0d8SMitch Phillips     assert(!p);
96f7c5c0d8SMitch Phillips   }
97f7c5c0d8SMitch Phillips 
98f7c5c0d8SMitch Phillips   return 0;
99f7c5c0d8SMitch Phillips }
100