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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14 10 11 // <any> 12 13 // Check that we're consistently using std::allocator_traits to 14 // allocate/deallocate/construct/destroy objects in std::any. 15 // See https://llvm.org/PR45099 for details. 16 17 #include <any> 18 #include <cassert> 19 #include <cstddef> 20 #include <memory> 21 #include <type_traits> 22 #include <utility> 23 24 #include "test_macros.h" 25 26 27 // Make sure we don't fit in std::any's SBO 28 struct Large { char big[sizeof(std::any) + 1]; }; 29 30 // Make sure we fit in std::any's SBO 31 struct Small { }; 32 33 bool Large_was_allocated = false; 34 bool Large_was_constructed = false; 35 bool Large_was_destroyed = false; 36 bool Large_was_deallocated = false; 37 38 bool Small_was_constructed = false; 39 bool Small_was_destroyed = false; 40 41 namespace std { 42 template <> 43 struct allocator<Large> { 44 using value_type = Large; 45 using size_type = std::size_t; 46 using difference_type = std::ptrdiff_t; 47 using propagate_on_container_move_assignment = std::true_type; 48 using is_always_equal = std::true_type; 49 allocatestd::allocator50 Large* allocate(std::size_t n) { 51 Large_was_allocated = true; 52 return static_cast<Large*>(::operator new(n * sizeof(Large))); 53 } 54 55 template <typename ...Args> constructstd::allocator56 void construct(Large* p, Args&& ...args) { 57 new (p) Large(std::forward<Args>(args)...); 58 Large_was_constructed = true; 59 } 60 destroystd::allocator61 void destroy(Large* p) { 62 p->~Large(); 63 Large_was_destroyed = true; 64 } 65 deallocatestd::allocator66 void deallocate(Large* p, std::size_t) { 67 Large_was_deallocated = true; 68 return ::operator delete(p); 69 } 70 }; 71 72 template <> 73 struct allocator<Small> { 74 using value_type = Small; 75 using size_type = std::size_t; 76 using difference_type = std::ptrdiff_t; 77 using propagate_on_container_move_assignment = std::true_type; 78 using is_always_equal = std::true_type; 79 allocatestd::allocator80 Small* allocate(std::size_t) { assert(false); return nullptr; } 81 82 template <typename ...Args> constructstd::allocator83 void construct(Small* p, Args&& ...args) { 84 new (p) Small(std::forward<Args>(args)...); 85 Small_was_constructed = true; 86 } 87 destroystd::allocator88 void destroy(Small* p) { 89 p->~Small(); 90 Small_was_destroyed = true; 91 } 92 deallocatestd::allocator93 void deallocate(Small*, std::size_t) { assert(false); } 94 }; 95 } // end namespace std 96 97 main(int,char **)98int main(int, char**) { 99 // Test large types 100 { 101 { 102 std::any a = Large(); 103 (void)a; 104 105 assert(Large_was_allocated); 106 assert(Large_was_constructed); 107 } 108 109 assert(Large_was_destroyed); 110 assert(Large_was_deallocated); 111 } 112 113 // Test small types 114 { 115 { 116 std::any a = Small(); 117 (void)a; 118 119 assert(Small_was_constructed); 120 } 121 122 assert(Small_was_destroyed); 123 } 124 125 return 0; 126 } 127