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 #ifndef _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H
10 #define _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H
11 
12 #include <__config>
13 #include <__type_traits/conditional.h>
14 #include <__type_traits/integral_constant.h>
15 #include <__type_traits/nat.h>
16 #include <__type_traits/type_list.h>
17 #include <cstddef>
18 
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #  pragma GCC system_header
21 #endif
22 
23 _LIBCPP_BEGIN_NAMESPACE_STD
24 
25 template <class _Tp>
26 struct __align_type {
27   static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp);
28   typedef _Tp type;
29 };
30 
31 struct __struct_double {
32   long double __lx;
33 };
34 struct __struct_double4 {
35   double __lx[4];
36 };
37 
38 // clang-format off
39 typedef __type_list<__align_type<unsigned char>,
40         __type_list<__align_type<unsigned short>,
41         __type_list<__align_type<unsigned int>,
42         __type_list<__align_type<unsigned long>,
43         __type_list<__align_type<unsigned long long>,
44         __type_list<__align_type<double>,
45         __type_list<__align_type<long double>,
46         __type_list<__align_type<__struct_double>,
47         __type_list<__align_type<__struct_double4>,
48         __type_list<__align_type<int*>,
49         __nat
50         > > > > > > > > > > __all_types;
51 // clang-format on
52 
53 template <size_t _Align>
54 struct _ALIGNAS(_Align) __fallback_overaligned {};
55 
56 template <class _TL, size_t _Align>
57 struct __find_pod;
58 
59 template <class _Hp, size_t _Align>
60 struct __find_pod<__type_list<_Hp, __nat>, _Align> {
61   typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type;
62 };
63 
64 template <class _Hp, class _Tp, size_t _Align>
65 struct __find_pod<__type_list<_Hp, _Tp>, _Align> {
66   typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type;
67 };
68 
69 template <class _TL, size_t _Len>
70 struct __find_max_align;
71 
72 template <class _Hp, size_t _Len>
73 struct __find_max_align<__type_list<_Hp, __nat>, _Len> : public integral_constant<size_t, _Hp::value> {};
74 
75 template <size_t _Len, size_t _A1, size_t _A2>
76 struct __select_align {
77 private:
78   static const size_t __min = _A2 < _A1 ? _A2 : _A1;
79   static const size_t __max = _A1 < _A2 ? _A2 : _A1;
80 
81 public:
82   static const size_t value = _Len < __max ? __min : __max;
83 };
84 
85 template <class _Hp, class _Tp, size_t _Len>
86 struct __find_max_align<__type_list<_Hp, _Tp>, _Len>
87     : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {};
88 
89 template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
90 struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage {
91   typedef typename __find_pod<__all_types, _Align>::type _Aligner;
92   union type {
93     _Aligner __align;
94     unsigned char __data[(_Len + _Align - 1) / _Align * _Align];
95   };
96 };
97 
98 #if _LIBCPP_STD_VER >= 14
99 
100 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
101 template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
102 using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type;
103 _LIBCPP_SUPPRESS_DEPRECATED_POP
104 
105 #endif
106 
107 #define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n)                                                                      \
108   template <size_t _Len>                                                                                               \
109   struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n> {                                   \
110     struct _ALIGNAS(n) type {                                                                                          \
111       unsigned char __lx[(_Len + n - 1) / n * n];                                                                      \
112     };                                                                                                                 \
113   }
114 
115 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1);
116 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2);
117 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4);
118 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x8);
119 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x10);
120 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x20);
121 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x40);
122 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x80);
123 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x100);
124 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x200);
125 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x400);
126 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x800);
127 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1000);
128 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2000);
129 // PE/COFF does not support alignment beyond 8192 (=0x2000)
130 #if !defined(_LIBCPP_OBJECT_FORMAT_COFF)
131 _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4000);
132 #endif // !defined(_LIBCPP_OBJECT_FORMAT_COFF)
133 
134 #undef _CREATE_ALIGNED_STORAGE_SPECIALIZATION
135 
136 _LIBCPP_END_NAMESPACE_STD
137 
138 #endif // _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H
139