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
25template <class _Tp>
26struct __align_type
27{
28    static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp);
29    typedef _Tp type;
30};
31
32struct __struct_double {long double __lx;};
33struct __struct_double4 {double __lx[4];};
34
35typedef
36    __type_list<__align_type<unsigned char>,
37    __type_list<__align_type<unsigned short>,
38    __type_list<__align_type<unsigned int>,
39    __type_list<__align_type<unsigned long>,
40    __type_list<__align_type<unsigned long long>,
41    __type_list<__align_type<double>,
42    __type_list<__align_type<long double>,
43    __type_list<__align_type<__struct_double>,
44    __type_list<__align_type<__struct_double4>,
45    __type_list<__align_type<int*>,
46    __nat
47    > > > > > > > > > > __all_types;
48
49template <size_t _Align>
50struct _ALIGNAS(_Align) __fallback_overaligned {};
51
52template <class _TL, size_t _Align> struct __find_pod;
53
54template <class _Hp, size_t _Align>
55struct __find_pod<__type_list<_Hp, __nat>, _Align>
56{
57    typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type;
58};
59
60template <class _Hp, class _Tp, size_t _Align>
61struct __find_pod<__type_list<_Hp, _Tp>, _Align>
62{
63    typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type;
64};
65
66template <class _TL, size_t _Len> struct __find_max_align;
67
68template <class _Hp, size_t _Len>
69struct __find_max_align<__type_list<_Hp, __nat>, _Len> : public integral_constant<size_t, _Hp::value> {};
70
71template <size_t _Len, size_t _A1, size_t _A2>
72struct __select_align
73{
74private:
75    static const size_t __min = _A2 < _A1 ? _A2 : _A1;
76    static const size_t __max = _A1 < _A2 ? _A2 : _A1;
77public:
78    static const size_t value = _Len < __max ? __min : __max;
79};
80
81template <class _Hp, class _Tp, size_t _Len>
82struct __find_max_align<__type_list<_Hp, _Tp>, _Len>
83    : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {};
84
85template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
86struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage
87{
88    typedef typename __find_pod<__all_types, _Align>::type _Aligner;
89    union type
90    {
91        _Aligner __align;
92        unsigned char __data[(_Len + _Align - 1)/_Align * _Align];
93    };
94};
95
96#if _LIBCPP_STD_VER > 11
97
98  _LIBCPP_SUPPRESS_DEPRECATED_PUSH
99template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value>
100    using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type;
101  _LIBCPP_SUPPRESS_DEPRECATED_POP
102
103#endif
104
105#define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \
106template <size_t _Len>\
107struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n>\
108{\
109    struct _ALIGNAS(n) type\
110    {\
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