247 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// Test libc++'s implementation of align_val_t, and the relevant new/delete10// overloads in all dialects when -faligned-allocation is present.11 12// Libc++ when built for z/OS doesn't contain the aligned allocation functions,13// nor does the dynamic library shipped with z/OS.14// XFAIL: target={{.+}}-zos{{.*}}15 16// XFAIL: sanitizer-new-delete && !hwasan17 18// TODO: Investigate this failure19// UNSUPPORTED: ubsan20 21// GCC doesn't support the aligned-allocation flags.22// XFAIL: gcc23 24// RUN: %{build} -faligned-allocation -fsized-deallocation25// RUN: %{run}26// RUN: %{build} -faligned-allocation -fno-sized-deallocation -DNO_SIZE27// RUN: %{run}28// RUN: %{build} -fno-aligned-allocation -fsized-deallocation -DNO_ALIGN29// RUN: %{run}30// RUN: %{build} -fno-aligned-allocation -fno-sized-deallocation -DNO_ALIGN -DNO_SIZE31// RUN: %{run}32 33#include <cassert>34#include <cstdlib>35#include <new>36 37#include "test_macros.h"38 39TEST_DIAGNOSTIC_PUSH40TEST_CLANG_DIAGNOSTIC_IGNORED("-Wprivate-header")41#include <__cxx03/__memory/aligned_alloc.h>42TEST_DIAGNOSTIC_POP43 44struct alloc_stats {45 alloc_stats() { reset(); }46 47 int aligned_sized_called;48 int aligned_called;49 int sized_called;50 int plain_called;51 int last_size;52 int last_align;53 54 void reset() {55 aligned_sized_called = aligned_called = sized_called = plain_called = 0;56 last_align = last_size = -1;57 }58 59 bool expect_plain() const {60 assert(aligned_sized_called == 0);61 assert(aligned_called == 0);62 assert(sized_called == 0);63 assert(last_size == -1);64 assert(last_align == -1);65 return plain_called == 1;66 }67 68 bool expect_size(int n) const {69 assert(plain_called == 0);70 assert(aligned_sized_called == 0);71 assert(aligned_called == 0);72 assert(last_size == n);73 assert(last_align == -1);74 return sized_called == 1;75 }76 77 bool expect_align(int a) const {78 assert(plain_called == 0);79 assert(aligned_sized_called == 0);80 assert(sized_called == 0);81 assert(last_size == -1);82 assert(last_align == a);83 return aligned_called == 1;84 }85 86 bool expect_size_align(int n, int a) const {87 assert(plain_called == 0);88 assert(sized_called == 0);89 assert(aligned_called == 0);90 assert(last_size == n);91 assert(last_align == a);92 return aligned_sized_called == 1;93 }94};95alloc_stats stats;96 97void operator delete(void* p) TEST_NOEXCEPT {98 ::free(p);99 stats.plain_called++;100 stats.last_size = stats.last_align = -1;101}102 103#ifndef NO_SIZE104void operator delete(void* p, std::size_t n) TEST_NOEXCEPT {105 ::free(p);106 stats.sized_called++;107 stats.last_size = n;108 stats.last_align = -1;109}110#endif111 112#ifndef NO_ALIGN113void operator delete(void* p, std::align_val_t a) TEST_NOEXCEPT {114 std::__libcpp_aligned_free(p);115 stats.aligned_called++;116 stats.last_align = static_cast<int>(a);117 stats.last_size = -1;118}119 120void operator delete(void* p, std::size_t n, std::align_val_t a) TEST_NOEXCEPT {121 std::__libcpp_aligned_free(p);122 stats.aligned_sized_called++;123 stats.last_align = static_cast<int>(a);124 stats.last_size = n;125}126#endif127 128void test_libcpp_dealloc() {129 void* p = nullptr;130#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__131 std::size_t over_align_val = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2;132#else133 std::size_t over_align_val = TEST_ALIGNOF(std::max_align_t) * 2;134#endif135 std::size_t under_align_val = TEST_ALIGNOF(int);136 std::size_t with_size_val = 2;137 138 {139 std::__libcpp_deallocate_unsized(p, under_align_val);140 assert(stats.expect_plain());141 }142 stats.reset();143 144#if defined(NO_SIZE) && defined(NO_ALIGN)145 {146 std::__libcpp_deallocate(p, with_size_val, over_align_val);147 assert(stats.expect_plain());148 }149 stats.reset();150#elif defined(NO_SIZE)151 {152 std::__libcpp_deallocate(p, with_size_val, over_align_val);153 assert(stats.expect_align(over_align_val));154 }155 stats.reset();156#elif defined(NO_ALIGN)157 {158 std::__libcpp_deallocate(p, with_size_val, over_align_val);159 assert(stats.expect_size(with_size_val));160 }161 stats.reset();162#else163 {164 std::__libcpp_deallocate(p, with_size_val, over_align_val);165 assert(stats.expect_size_align(with_size_val, over_align_val));166 }167 stats.reset();168 {169 std::__libcpp_deallocate_unsized(p, over_align_val);170 assert(stats.expect_align(over_align_val));171 }172 stats.reset();173 {174 std::__libcpp_deallocate(p, with_size_val, under_align_val);175 assert(stats.expect_size(with_size_val));176 }177 stats.reset();178#endif179}180 181struct TEST_ALIGNAS(128) AlignedType {182 AlignedType() : elem(0) {}183 TEST_ALIGNAS(128) char elem;184};185 186void test_allocator_and_new_match() {187 stats.reset();188#if defined(NO_SIZE) && defined(NO_ALIGN)189 {190 int* x = DoNotOptimize(new int(42));191 delete x;192 assert(stats.expect_plain());193 }194 stats.reset();195 {196 AlignedType* a = DoNotOptimize(new AlignedType());197 delete a;198 assert(stats.expect_plain());199 }200 stats.reset();201#elif defined(NO_SIZE)202 stats.reset();203 stats.reset();204 {205 AlignedType* a = DoNotOptimize(new AlignedType());206 delete a;207 assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));208 }209 stats.reset();210#elif defined(NO_ALIGN)211 stats.reset();212 {213 int* x = DoNotOptimize(new int(42));214 delete x;215 assert(stats.expect_size(sizeof(int)));216 }217 stats.reset();218 {219 AlignedType* a = DoNotOptimize(new AlignedType());220 delete a;221 assert(stats.expect_size(sizeof(AlignedType)));222 }223 stats.reset();224#else225 stats.reset();226 {227 int* x = DoNotOptimize(new int(42));228 delete x;229 assert(stats.expect_size(sizeof(int)));230 }231 stats.reset();232 {233 AlignedType* a = DoNotOptimize(new AlignedType());234 delete a;235 assert(stats.expect_size_align(sizeof(AlignedType), TEST_ALIGNOF(AlignedType)));236 }237 stats.reset();238#endif239}240 241int main(int, char**) {242 test_libcpp_dealloc();243 test_allocator_and_new_match();244 245 return 0;246}247