xref: /llvm-project/libcxx/test/libcxx/utilities/utility/pairs/pairs.pair/abi.trivial_copy_move.pass.cpp (revision 02af67c88f393cd6998949cc1bf8075553579a42)
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 // <utility>
10 
11 // template <class T1, class T2> struct pair
12 
13 // Test that we properly provide the trivial copy operations by default.
14 
15 // FreeBSD still provides the old ABI for std::pair.
16 // XFAIL: freebsd
17 // ADDITIONAL_COMPILE_FLAGS: -Wno-invalid-offsetof
18 
19 #include <utility>
20 #include <type_traits>
21 #include <cstdlib>
22 #include <cstddef>
23 #include <cassert>
24 
25 #include "test_macros.h"
26 
27 template <class T>
28 struct HasTrivialABI : std::integral_constant<bool,
29     std::is_trivially_destructible<T>::value
30     && (!std::is_copy_constructible<T>::value || std::is_trivially_copy_constructible<T>::value)
31 #if TEST_STD_VER >= 11
32    && (!std::is_move_constructible<T>::value || std::is_trivially_move_constructible<T>::value)
33 #endif
34 > {};
35 
36 #if TEST_STD_VER >= 11
37 struct NonTrivialDtor {
38     NonTrivialDtor(NonTrivialDtor const&) = default;
39     ~NonTrivialDtor();
40 };
~NonTrivialDtor()41 NonTrivialDtor::~NonTrivialDtor() {}
42 static_assert(!HasTrivialABI<NonTrivialDtor>::value, "");
43 
44 struct NonTrivialCopy {
45     NonTrivialCopy(NonTrivialCopy const&);
46 };
NonTrivialCopy(NonTrivialCopy const &)47 NonTrivialCopy::NonTrivialCopy(NonTrivialCopy const&) {}
48 static_assert(!HasTrivialABI<NonTrivialCopy>::value, "");
49 
50 struct NonTrivialMove {
51     NonTrivialMove(NonTrivialMove const&) = default;
52     NonTrivialMove(NonTrivialMove&&);
53 };
NonTrivialMove(NonTrivialMove &&)54 NonTrivialMove::NonTrivialMove(NonTrivialMove&&) {}
55 static_assert(!HasTrivialABI<NonTrivialMove>::value, "");
56 
57 struct DeletedCopy {
58     DeletedCopy(DeletedCopy const&) = delete;
59     DeletedCopy(DeletedCopy&&) = default;
60 };
61 static_assert(HasTrivialABI<DeletedCopy>::value, "");
62 
63 struct TrivialMove {
64   TrivialMove(TrivialMove &&) = default;
65 };
66 static_assert(HasTrivialABI<TrivialMove>::value, "");
67 
68 struct Trivial {
69     Trivial(Trivial const&) = default;
70 };
71 static_assert(HasTrivialABI<Trivial>::value, "");
72 #endif
73 
74 struct TrivialNoAssignment {
75   int arr[4];
76   TrivialNoAssignment& operator=(const TrivialNoAssignment&) = delete;
77 };
78 
79 struct TrivialNoConstruction {
80   int arr[4];
81   TrivialNoConstruction()                                        = default;
82   TrivialNoConstruction(const TrivialNoConstruction&)            = delete;
83   TrivialNoConstruction& operator=(const TrivialNoConstruction&) = default;
84 };
85 
test_trivial()86 void test_trivial()
87 {
88     {
89         typedef std::pair<int, short> P;
90         static_assert(std::is_copy_constructible<P>::value, "");
91         static_assert(HasTrivialABI<P>::value, "");
92     }
93 #if TEST_STD_VER >= 11
94     {
95         typedef std::pair<int, short> P;
96         static_assert(std::is_move_constructible<P>::value, "");
97         static_assert(HasTrivialABI<P>::value, "");
98     }
99     {
100         using P = std::pair<NonTrivialDtor, int>;
101         static_assert(!std::is_trivially_destructible<P>::value, "");
102         static_assert(std::is_copy_constructible<P>::value, "");
103         static_assert(!std::is_trivially_copy_constructible<P>::value, "");
104         static_assert(std::is_move_constructible<P>::value, "");
105         static_assert(!std::is_trivially_move_constructible<P>::value, "");
106         static_assert(!HasTrivialABI<P>::value, "");
107     }
108     {
109         using P = std::pair<NonTrivialCopy, int>;
110         static_assert(std::is_copy_constructible<P>::value, "");
111         static_assert(!std::is_trivially_copy_constructible<P>::value, "");
112         static_assert(std::is_move_constructible<P>::value, "");
113         static_assert(!std::is_trivially_move_constructible<P>::value, "");
114         static_assert(!HasTrivialABI<P>::value, "");
115     }
116     {
117         using P = std::pair<NonTrivialMove, int>;
118         static_assert(std::is_copy_constructible<P>::value, "");
119         static_assert(std::is_trivially_copy_constructible<P>::value, "");
120         static_assert(std::is_move_constructible<P>::value, "");
121         static_assert(!std::is_trivially_move_constructible<P>::value, "");
122         static_assert(!HasTrivialABI<P>::value, "");
123     }
124     {
125         using P = std::pair<DeletedCopy, int>;
126         static_assert(!std::is_copy_constructible<P>::value, "");
127         static_assert(!std::is_trivially_copy_constructible<P>::value, "");
128         static_assert(std::is_move_constructible<P>::value, "");
129         static_assert(std::is_trivially_move_constructible<P>::value, "");
130         static_assert(HasTrivialABI<P>::value, "");
131     }
132     {
133         using P = std::pair<Trivial, int>;
134         static_assert(std::is_copy_constructible<P>::value, "");
135         static_assert(std::is_trivially_copy_constructible<P>::value, "");
136         static_assert(std::is_move_constructible<P>::value, "");
137         static_assert(std::is_trivially_move_constructible<P>::value, "");
138         static_assert(HasTrivialABI<P>::value, "");
139     }
140     {
141         using P = std::pair<TrivialMove, int>;
142         static_assert(!std::is_copy_constructible<P>::value, "");
143         static_assert(!std::is_trivially_copy_constructible<P>::value, "");
144         static_assert(std::is_move_constructible<P>::value, "");
145         static_assert(std::is_trivially_move_constructible<P>::value, "");
146         static_assert(HasTrivialABI<P>::value, "");
147     }
148 #endif
149     {
150         using P = std::pair<TrivialNoAssignment, int>;
151         static_assert(std::is_trivially_copy_constructible<P>::value, "");
152         static_assert(std::is_trivially_move_constructible<P>::value, "");
153 #if TEST_STD_VER >= 11 // This is https://llvm.org/PR90605
154         static_assert(!std::is_trivially_copy_assignable<P>::value, "");
155         static_assert(!std::is_trivially_move_assignable<P>::value, "");
156 #endif // TEST_STD_VER >= 11
157         static_assert(std::is_trivially_destructible<P>::value, "");
158     }
159     {
160         using P = std::pair<TrivialNoConstruction, int>;
161 #if TEST_STD_VER >= 11
162         static_assert(!std::is_trivially_copy_constructible<P>::value, "");
163         static_assert(!std::is_trivially_move_constructible<P>::value, "");
164 #endif // TEST_STD_VER >= 11
165         static_assert(!std::is_trivially_copy_assignable<P>::value, "");
166         static_assert(!std::is_trivially_move_assignable<P>::value, "");
167         static_assert(std::is_trivially_destructible<P>::value, "");
168     }
169 }
170 
test_layout()171 void test_layout() {
172     typedef std::pair<std::pair<char, char>, char> PairT;
173     static_assert(sizeof(PairT) == 3, "");
174     static_assert(TEST_ALIGNOF(PairT) == TEST_ALIGNOF(char), "");
175     static_assert(offsetof(PairT, first) == 0, "");
176 }
177 
main(int,char **)178 int main(int, char**) {
179     test_trivial();
180     test_layout();
181     return 0;
182 }
183