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