1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/container/internal/layout.h"
16
17 // We need ::max_align_t because some libstdc++ versions don't provide
18 // std::max_align_t
19 #include <stddef.h>
20
21 #include <cstdint>
22 #include <cstring>
23 #include <initializer_list>
24 #include <memory>
25 #include <ostream>
26 #include <string>
27 #include <tuple>
28 #include <type_traits>
29
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/config.h"
33 #include "absl/log/check.h"
34 #include "absl/types/span.h"
35 #include "absl/utility/utility.h"
36
37 namespace absl {
38 ABSL_NAMESPACE_BEGIN
39 namespace container_internal {
40 namespace {
41
42 using ::absl::Span;
43 using ::testing::ElementsAre;
44
Distance(const void * from,const void * to)45 size_t Distance(const void* from, const void* to) {
46 CHECK_LE(from, to) << "Distance must be non-negative";
47 return static_cast<const char*>(to) - static_cast<const char*>(from);
48 }
49
50 template <class Expected, class Actual>
Type(Actual val)51 Expected Type(Actual val) {
52 static_assert(std::is_same<Expected, Actual>(), "");
53 return val;
54 }
55
56 // Helper classes to test different size and alignments.
57 struct alignas(8) Int128 {
58 uint64_t a, b;
operator ==(Int128 lhs,Int128 rhs)59 friend bool operator==(Int128 lhs, Int128 rhs) {
60 return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
61 }
62
Nameabsl::container_internal::__anonbf23a5d60111::Int12863 static std::string Name() {
64 return internal_layout::adl_barrier::TypeName<Int128>();
65 }
66 };
67
68 // int64_t is *not* 8-byte aligned on all platforms!
69 struct alignas(8) Int64 {
70 int64_t a;
operator ==(Int64 lhs,Int64 rhs)71 friend bool operator==(Int64 lhs, Int64 rhs) { return lhs.a == rhs.a; }
72 };
73
74 // Properties of types that this test relies on.
75 static_assert(sizeof(int8_t) == 1, "");
76 static_assert(alignof(int8_t) == 1, "");
77 static_assert(sizeof(int16_t) == 2, "");
78 static_assert(alignof(int16_t) == 2, "");
79 static_assert(sizeof(int32_t) == 4, "");
80 static_assert(alignof(int32_t) == 4, "");
81 static_assert(sizeof(Int64) == 8, "");
82 static_assert(alignof(Int64) == 8, "");
83 static_assert(sizeof(Int128) == 16, "");
84 static_assert(alignof(Int128) == 8, "");
85
86 template <class Expected, class Actual>
SameType()87 void SameType() {
88 static_assert(std::is_same<Expected, Actual>(), "");
89 }
90
TEST(Layout,ElementType)91 TEST(Layout, ElementType) {
92 {
93 using L = Layout<int32_t>;
94 SameType<int32_t, L::ElementType<0>>();
95 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
96 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
97 }
98 {
99 using L = Layout<int32_t, int32_t>;
100 SameType<int32_t, L::ElementType<0>>();
101 SameType<int32_t, L::ElementType<1>>();
102 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
103 SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
104 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
105 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
106 }
107 {
108 using L = Layout<int8_t, int32_t, Int128>;
109 SameType<int8_t, L::ElementType<0>>();
110 SameType<int32_t, L::ElementType<1>>();
111 SameType<Int128, L::ElementType<2>>();
112 SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
113 SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
114 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
115 SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
116 SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
117 SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
118 SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
119 SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
120 SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
121 }
122 }
123
TEST(Layout,ElementTypes)124 TEST(Layout, ElementTypes) {
125 {
126 using L = Layout<int32_t>;
127 SameType<std::tuple<int32_t>, L::ElementTypes>();
128 SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
129 SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
130 }
131 {
132 using L = Layout<int32_t, int32_t>;
133 SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
134 SameType<std::tuple<int32_t, int32_t>,
135 decltype(L::Partial())::ElementTypes>();
136 SameType<std::tuple<int32_t, int32_t>,
137 decltype(L::Partial(0))::ElementTypes>();
138 }
139 {
140 using L = Layout<int8_t, int32_t, Int128>;
141 SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
142 SameType<std::tuple<int8_t, int32_t, Int128>,
143 decltype(L::Partial())::ElementTypes>();
144 SameType<std::tuple<int8_t, int32_t, Int128>,
145 decltype(L::Partial(0))::ElementTypes>();
146 SameType<std::tuple<int8_t, int32_t, Int128>,
147 decltype(L::Partial(0, 0))::ElementTypes>();
148 SameType<std::tuple<int8_t, int32_t, Int128>,
149 decltype(L::Partial(0, 0, 0))::ElementTypes>();
150 }
151 }
152
TEST(Layout,OffsetByIndex)153 TEST(Layout, OffsetByIndex) {
154 {
155 using L = Layout<int32_t>;
156 EXPECT_EQ(0, L::Partial().Offset<0>());
157 EXPECT_EQ(0, L::Partial(3).Offset<0>());
158 EXPECT_EQ(0, L(3).Offset<0>());
159 }
160 {
161 using L = Layout<int32_t, int32_t>;
162 EXPECT_EQ(0, L::Partial().Offset<0>());
163 EXPECT_EQ(0, L::Partial(3).Offset<0>());
164 EXPECT_EQ(12, L::Partial(3).Offset<1>());
165 EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
166 EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
167 EXPECT_EQ(0, L(3, 5).Offset<0>());
168 EXPECT_EQ(12, L(3, 5).Offset<1>());
169 }
170 {
171 using L = Layout<int8_t, int32_t, Int128>;
172 EXPECT_EQ(0, L::Partial().Offset<0>());
173 EXPECT_EQ(0, L::Partial(0).Offset<0>());
174 EXPECT_EQ(0, L::Partial(0).Offset<1>());
175 EXPECT_EQ(0, L::Partial(1).Offset<0>());
176 EXPECT_EQ(4, L::Partial(1).Offset<1>());
177 EXPECT_EQ(0, L::Partial(5).Offset<0>());
178 EXPECT_EQ(8, L::Partial(5).Offset<1>());
179 EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
180 EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
181 EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
182 EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
183 EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
184 EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
185 EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
186 EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
187 EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
188 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
189 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
190 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
191 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
192 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
193 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
194 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
195 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
196 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
197 EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
198 EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
199 EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
200 }
201 }
202
TEST(Layout,OffsetByType)203 TEST(Layout, OffsetByType) {
204 {
205 using L = Layout<int32_t>;
206 EXPECT_EQ(0, L::Partial().Offset<int32_t>());
207 EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
208 EXPECT_EQ(0, L(3).Offset<int32_t>());
209 }
210 {
211 using L = Layout<int8_t, int32_t, Int128>;
212 EXPECT_EQ(0, L::Partial().Offset<int8_t>());
213 EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
214 EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
215 EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
216 EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
217 EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
218 EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
219 EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
220 EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
221 EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
222 EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
223 EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
224 EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
225 EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
226 EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
227 EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
228 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
229 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
230 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
231 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
232 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
233 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
234 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
235 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
236 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
237 EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
238 EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
239 EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
240 }
241 }
242
TEST(Layout,Offsets)243 TEST(Layout, Offsets) {
244 {
245 using L = Layout<int32_t>;
246 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
247 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
248 EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
249 }
250 {
251 using L = Layout<int32_t, int32_t>;
252 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
253 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
254 EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
255 EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
256 }
257 {
258 using L = Layout<int8_t, int32_t, Int128>;
259 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
260 EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
261 EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
262 EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
263 EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
264 EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
265 EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
266 EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
267 EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
268 EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
269 }
270 }
271
TEST(Layout,StaticOffsets)272 TEST(Layout, StaticOffsets) {
273 using L = Layout<int8_t, int32_t, Int128>;
274 {
275 using SL = L::WithStaticSizes<>;
276 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0));
277 EXPECT_THAT(SL::Partial(5).Offsets(), ElementsAre(0, 8));
278 EXPECT_THAT(SL::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
279 EXPECT_THAT(SL(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
280 }
281 {
282 using SL = L::WithStaticSizes<5>;
283 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8));
284 EXPECT_THAT(SL::Partial(3).Offsets(), ElementsAre(0, 8, 24));
285 EXPECT_THAT(SL::Partial(3, 1).Offsets(), ElementsAre(0, 8, 24));
286 EXPECT_THAT(SL(3, 1).Offsets(), ElementsAre(0, 8, 24));
287 }
288 {
289 using SL = L::WithStaticSizes<5, 3>;
290 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));
291 EXPECT_THAT(SL::Partial(1).Offsets(), ElementsAre(0, 8, 24));
292 EXPECT_THAT(SL(1).Offsets(), ElementsAre(0, 8, 24));
293 }
294 {
295 using SL = L::WithStaticSizes<5, 3, 1>;
296 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24));
297 EXPECT_THAT(SL().Offsets(), ElementsAre(0, 8, 24));
298 }
299 }
300
TEST(Layout,AllocSize)301 TEST(Layout, AllocSize) {
302 {
303 using L = Layout<int32_t>;
304 EXPECT_EQ(0, L::Partial(0).AllocSize());
305 EXPECT_EQ(12, L::Partial(3).AllocSize());
306 EXPECT_EQ(12, L(3).AllocSize());
307 }
308 {
309 using L = Layout<int32_t, int32_t>;
310 EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
311 EXPECT_EQ(32, L(3, 5).AllocSize());
312 }
313 {
314 using L = Layout<int8_t, int32_t, Int128>;
315 EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
316 EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
317 EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
318 EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
319 EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
320 EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
321 EXPECT_EQ(136, L(3, 5, 7).AllocSize());
322 }
323 }
324
TEST(Layout,StaticAllocSize)325 TEST(Layout, StaticAllocSize) {
326 using L = Layout<int8_t, int32_t, Int128>;
327 {
328 using SL = L::WithStaticSizes<>;
329 EXPECT_EQ(136, SL::Partial(3, 5, 7).AllocSize());
330 EXPECT_EQ(136, SL(3, 5, 7).AllocSize());
331 }
332 {
333 using SL = L::WithStaticSizes<3>;
334 EXPECT_EQ(136, SL::Partial(5, 7).AllocSize());
335 EXPECT_EQ(136, SL(5, 7).AllocSize());
336 }
337 {
338 using SL = L::WithStaticSizes<3, 5>;
339 EXPECT_EQ(136, SL::Partial(7).AllocSize());
340 EXPECT_EQ(136, SL(7).AllocSize());
341 }
342 {
343 using SL = L::WithStaticSizes<3, 5, 7>;
344 EXPECT_EQ(136, SL::Partial().AllocSize());
345 EXPECT_EQ(136, SL().AllocSize());
346 }
347 }
348
TEST(Layout,SizeByIndex)349 TEST(Layout, SizeByIndex) {
350 {
351 using L = Layout<int32_t>;
352 EXPECT_EQ(0, L::Partial(0).Size<0>());
353 EXPECT_EQ(3, L::Partial(3).Size<0>());
354 EXPECT_EQ(3, L(3).Size<0>());
355 }
356 {
357 using L = Layout<int32_t, int32_t>;
358 EXPECT_EQ(0, L::Partial(0).Size<0>());
359 EXPECT_EQ(3, L::Partial(3).Size<0>());
360 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
361 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
362 EXPECT_EQ(3, L(3, 5).Size<0>());
363 EXPECT_EQ(5, L(3, 5).Size<1>());
364 }
365 {
366 using L = Layout<int8_t, int32_t, Int128>;
367 EXPECT_EQ(3, L::Partial(3).Size<0>());
368 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
369 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
370 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
371 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
372 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
373 EXPECT_EQ(3, L(3, 5, 7).Size<0>());
374 EXPECT_EQ(5, L(3, 5, 7).Size<1>());
375 EXPECT_EQ(7, L(3, 5, 7).Size<2>());
376 }
377 }
378
TEST(Layout,SizeByType)379 TEST(Layout, SizeByType) {
380 {
381 using L = Layout<int32_t>;
382 EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
383 EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
384 EXPECT_EQ(3, L(3).Size<int32_t>());
385 }
386 {
387 using L = Layout<int8_t, int32_t, Int128>;
388 EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
389 EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
390 EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
391 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
392 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
393 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
394 EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
395 EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
396 EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
397 }
398 }
399
TEST(Layout,Sizes)400 TEST(Layout, Sizes) {
401 {
402 using L = Layout<int32_t>;
403 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
404 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
405 EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
406 }
407 {
408 using L = Layout<int32_t, int32_t>;
409 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
410 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
411 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
412 EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
413 }
414 {
415 using L = Layout<int8_t, int32_t, Int128>;
416 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
417 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
418 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
419 EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
420 EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
421 }
422 }
423
TEST(Layout,StaticSize)424 TEST(Layout, StaticSize) {
425 using L = Layout<int8_t, int32_t, Int128>;
426 {
427 using SL = L::WithStaticSizes<>;
428 EXPECT_THAT(SL::Partial().Sizes(), ElementsAre());
429 EXPECT_THAT(SL::Partial(3).Size<0>(), 3);
430 EXPECT_THAT(SL::Partial(3).Size<int8_t>(), 3);
431 EXPECT_THAT(SL::Partial(3).Sizes(), ElementsAre(3));
432 EXPECT_THAT(SL::Partial(3, 5, 7).Size<0>(), 3);
433 EXPECT_THAT(SL::Partial(3, 5, 7).Size<int8_t>(), 3);
434 EXPECT_THAT(SL::Partial(3, 5, 7).Size<2>(), 7);
435 EXPECT_THAT(SL::Partial(3, 5, 7).Size<Int128>(), 7);
436 EXPECT_THAT(SL::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
437 EXPECT_THAT(SL(3, 5, 7).Size<0>(), 3);
438 EXPECT_THAT(SL(3, 5, 7).Size<int8_t>(), 3);
439 EXPECT_THAT(SL(3, 5, 7).Size<2>(), 7);
440 EXPECT_THAT(SL(3, 5, 7).Size<Int128>(), 7);
441 EXPECT_THAT(SL(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
442 }
443 }
444
TEST(Layout,PointerByIndex)445 TEST(Layout, PointerByIndex) {
446 alignas(max_align_t) const unsigned char p[100] = {0};
447 {
448 using L = Layout<int32_t>;
449 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
450 EXPECT_EQ(0,
451 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
452 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
453 }
454 {
455 using L = Layout<int32_t, int32_t>;
456 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
457 EXPECT_EQ(0,
458 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
459 EXPECT_EQ(12,
460 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
461 EXPECT_EQ(
462 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
463 EXPECT_EQ(
464 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
465 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
466 EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
467 }
468 {
469 using L = Layout<int8_t, int32_t, Int128>;
470 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
471 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
472 EXPECT_EQ(0,
473 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
474 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
475 EXPECT_EQ(4,
476 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
477 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
478 EXPECT_EQ(8,
479 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
480 EXPECT_EQ(0,
481 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
482 EXPECT_EQ(
483 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
484 EXPECT_EQ(0,
485 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
486 EXPECT_EQ(0,
487 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
488 EXPECT_EQ(
489 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
490 EXPECT_EQ(8,
491 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
492 EXPECT_EQ(0,
493 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
494 EXPECT_EQ(
495 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
496 EXPECT_EQ(24,
497 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
498 EXPECT_EQ(
499 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
500 EXPECT_EQ(
501 0,
502 Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
503 EXPECT_EQ(
504 0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
505 EXPECT_EQ(
506 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
507 EXPECT_EQ(
508 4,
509 Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
510 EXPECT_EQ(
511 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
512 EXPECT_EQ(
513 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
514 EXPECT_EQ(
515 24,
516 Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
517 EXPECT_EQ(
518 8,
519 Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
520 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
521 EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
522 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
523 }
524 }
525
TEST(Layout,PointerByType)526 TEST(Layout, PointerByType) {
527 alignas(max_align_t) const unsigned char p[100] = {0};
528 {
529 using L = Layout<int32_t>;
530 EXPECT_EQ(
531 0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
532 EXPECT_EQ(
533 0,
534 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
535 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
536 }
537 {
538 using L = Layout<int8_t, int32_t, Int128>;
539 EXPECT_EQ(
540 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
541 EXPECT_EQ(
542 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
543 EXPECT_EQ(
544 0,
545 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
546 EXPECT_EQ(
547 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
548 EXPECT_EQ(
549 4,
550 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
551 EXPECT_EQ(
552 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
553 EXPECT_EQ(
554 8,
555 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
556 EXPECT_EQ(
557 0,
558 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
559 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
560 L::Partial(0, 0).Pointer<int32_t>(p))));
561 EXPECT_EQ(
562 0,
563 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
564 EXPECT_EQ(
565 0,
566 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
567 EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
568 L::Partial(1, 0).Pointer<int32_t>(p))));
569 EXPECT_EQ(
570 8,
571 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
572 EXPECT_EQ(
573 0,
574 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
575 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
576 L::Partial(5, 3).Pointer<int32_t>(p))));
577 EXPECT_EQ(
578 24,
579 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
580 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
581 L::Partial(0, 0, 0).Pointer<int8_t>(p))));
582 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
583 L::Partial(0, 0, 0).Pointer<int32_t>(p))));
584 EXPECT_EQ(0, Distance(p, Type<const Int128*>(
585 L::Partial(0, 0, 0).Pointer<Int128>(p))));
586 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
587 L::Partial(1, 0, 0).Pointer<int8_t>(p))));
588 EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
589 L::Partial(1, 0, 0).Pointer<int32_t>(p))));
590 EXPECT_EQ(8, Distance(p, Type<const Int128*>(
591 L::Partial(1, 0, 0).Pointer<Int128>(p))));
592 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
593 L::Partial(5, 3, 1).Pointer<int8_t>(p))));
594 EXPECT_EQ(24, Distance(p, Type<const Int128*>(
595 L::Partial(5, 3, 1).Pointer<Int128>(p))));
596 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
597 L::Partial(5, 3, 1).Pointer<int32_t>(p))));
598 EXPECT_EQ(24,
599 Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
600 EXPECT_EQ(
601 8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
602 }
603 }
604
TEST(Layout,MutablePointerByIndex)605 TEST(Layout, MutablePointerByIndex) {
606 alignas(max_align_t) unsigned char p[100] = {0};
607 {
608 using L = Layout<int32_t>;
609 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
610 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
611 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
612 }
613 {
614 using L = Layout<int32_t, int32_t>;
615 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
616 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
617 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
618 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
619 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
620 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
621 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
622 }
623 {
624 using L = Layout<int8_t, int32_t, Int128>;
625 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
626 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
627 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
628 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
629 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
630 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
631 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
632 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
633 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
634 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
635 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
636 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
637 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
638 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
639 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
640 EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
641 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
642 EXPECT_EQ(0,
643 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
644 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
645 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
646 EXPECT_EQ(4,
647 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
648 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
649 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
650 EXPECT_EQ(24,
651 Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
652 EXPECT_EQ(8,
653 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
654 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
655 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
656 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
657 }
658 }
659
TEST(Layout,MutablePointerByType)660 TEST(Layout, MutablePointerByType) {
661 alignas(max_align_t) unsigned char p[100] = {0};
662 {
663 using L = Layout<int32_t>;
664 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
665 EXPECT_EQ(0,
666 Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
667 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
668 }
669 {
670 using L = Layout<int8_t, int32_t, Int128>;
671 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
672 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
673 EXPECT_EQ(0,
674 Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
675 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
676 EXPECT_EQ(4,
677 Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
678 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
679 EXPECT_EQ(8,
680 Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
681 EXPECT_EQ(0,
682 Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
683 EXPECT_EQ(
684 0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
685 EXPECT_EQ(0,
686 Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
687 EXPECT_EQ(0,
688 Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
689 EXPECT_EQ(
690 4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
691 EXPECT_EQ(8,
692 Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
693 EXPECT_EQ(0,
694 Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
695 EXPECT_EQ(
696 8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
697 EXPECT_EQ(24,
698 Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
699 EXPECT_EQ(
700 0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
701 EXPECT_EQ(
702 0,
703 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
704 EXPECT_EQ(
705 0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
706 EXPECT_EQ(
707 0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
708 EXPECT_EQ(
709 4,
710 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
711 EXPECT_EQ(
712 8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
713 EXPECT_EQ(
714 0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
715 EXPECT_EQ(
716 24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
717 EXPECT_EQ(
718 8,
719 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
720 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
721 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
722 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
723 }
724 }
725
TEST(Layout,Pointers)726 TEST(Layout, Pointers) {
727 alignas(max_align_t) const unsigned char p[100] = {0};
728 using L = Layout<int8_t, int8_t, Int128>;
729 {
730 const auto x = L::Partial();
731 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
732 Type<std::tuple<const int8_t*>>(x.Pointers(p)));
733 }
734 {
735 const auto x = L::Partial(1);
736 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
737 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
738 }
739 {
740 const auto x = L::Partial(1, 2);
741 EXPECT_EQ(
742 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
743 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
744 x.Pointers(p))));
745 }
746 {
747 const auto x = L::Partial(1, 2, 3);
748 EXPECT_EQ(
749 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
750 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
751 x.Pointers(p))));
752 }
753 {
754 const L x(1, 2, 3);
755 EXPECT_EQ(
756 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
757 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
758 x.Pointers(p))));
759 }
760 }
761
TEST(Layout,MutablePointers)762 TEST(Layout, MutablePointers) {
763 alignas(max_align_t) unsigned char p[100] = {0};
764 using L = Layout<int8_t, int8_t, Int128>;
765 {
766 const auto x = L::Partial();
767 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
768 Type<std::tuple<int8_t*>>(x.Pointers(p)));
769 }
770 {
771 const auto x = L::Partial(1);
772 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
773 (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
774 }
775 {
776 const auto x = L::Partial(1, 2);
777 EXPECT_EQ(
778 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
779 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
780 }
781 {
782 const auto x = L::Partial(1, 2, 3);
783 EXPECT_EQ(
784 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
785 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
786 }
787 {
788 const L x(1, 2, 3);
789 EXPECT_EQ(
790 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
791 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
792 }
793 }
794
TEST(Layout,StaticPointers)795 TEST(Layout, StaticPointers) {
796 alignas(max_align_t) const unsigned char p[100] = {0};
797 using L = Layout<int8_t, int8_t, Int128>;
798 {
799 const auto x = L::WithStaticSizes<>::Partial();
800 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
801 Type<std::tuple<const int8_t*>>(x.Pointers(p)));
802 }
803 {
804 const auto x = L::WithStaticSizes<>::Partial(1);
805 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
806 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
807 }
808 {
809 const auto x = L::WithStaticSizes<1>::Partial();
810 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
811 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
812 }
813 {
814 const auto x = L::WithStaticSizes<>::Partial(1, 2, 3);
815 EXPECT_EQ(
816 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
817 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
818 x.Pointers(p))));
819 }
820 {
821 const auto x = L::WithStaticSizes<1>::Partial(2, 3);
822 EXPECT_EQ(
823 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
824 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
825 x.Pointers(p))));
826 }
827 {
828 const auto x = L::WithStaticSizes<1, 2>::Partial(3);
829 EXPECT_EQ(
830 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
831 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
832 x.Pointers(p))));
833 }
834 {
835 const auto x = L::WithStaticSizes<1, 2, 3>::Partial();
836 EXPECT_EQ(
837 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
838 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
839 x.Pointers(p))));
840 }
841 {
842 const L::WithStaticSizes<1, 2, 3> x;
843 EXPECT_EQ(
844 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
845 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
846 x.Pointers(p))));
847 }
848 }
849
TEST(Layout,SliceByIndexSize)850 TEST(Layout, SliceByIndexSize) {
851 alignas(max_align_t) const unsigned char p[100] = {0};
852 {
853 using L = Layout<int32_t>;
854 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
855 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
856 EXPECT_EQ(3, L(3).Slice<0>(p).size());
857 }
858 {
859 using L = Layout<int32_t, int32_t>;
860 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
861 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
862 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
863 }
864 {
865 using L = Layout<int8_t, int32_t, Int128>;
866 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
867 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
868 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
869 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
870 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
871 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
872 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
873 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
874 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
875 }
876 }
877
TEST(Layout,SliceByTypeSize)878 TEST(Layout, SliceByTypeSize) {
879 alignas(max_align_t) const unsigned char p[100] = {0};
880 {
881 using L = Layout<int32_t>;
882 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
883 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
884 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
885 }
886 {
887 using L = Layout<int8_t, int32_t, Int128>;
888 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
889 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
890 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
891 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
892 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
893 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
894 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
895 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
896 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
897 }
898 }
TEST(Layout,MutableSliceByIndexSize)899 TEST(Layout, MutableSliceByIndexSize) {
900 alignas(max_align_t) unsigned char p[100] = {0};
901 {
902 using L = Layout<int32_t>;
903 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
904 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
905 EXPECT_EQ(3, L(3).Slice<0>(p).size());
906 }
907 {
908 using L = Layout<int32_t, int32_t>;
909 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
910 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
911 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
912 }
913 {
914 using L = Layout<int8_t, int32_t, Int128>;
915 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
916 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
917 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
918 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
919 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
920 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
921 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
922 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
923 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
924 }
925 }
926
TEST(Layout,MutableSliceByTypeSize)927 TEST(Layout, MutableSliceByTypeSize) {
928 alignas(max_align_t) unsigned char p[100] = {0};
929 {
930 using L = Layout<int32_t>;
931 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
932 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
933 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
934 }
935 {
936 using L = Layout<int8_t, int32_t, Int128>;
937 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
938 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
939 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
940 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
941 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
942 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
943 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
944 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
945 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
946 }
947 }
948
TEST(Layout,StaticSliceSize)949 TEST(Layout, StaticSliceSize) {
950 alignas(max_align_t) const unsigned char cp[100] = {0};
951 alignas(max_align_t) unsigned char p[100] = {0};
952 using L = Layout<int8_t, int32_t, Int128>;
953 using SL = L::WithStaticSizes<3, 5>;
954
955 EXPECT_EQ(3, SL::Partial().Slice<0>(cp).size());
956 EXPECT_EQ(3, SL::Partial().Slice<int8_t>(cp).size());
957 EXPECT_EQ(3, SL::Partial(7).Slice<0>(cp).size());
958 EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(cp).size());
959
960 EXPECT_EQ(5, SL::Partial().Slice<1>(cp).size());
961 EXPECT_EQ(5, SL::Partial().Slice<int32_t>(cp).size());
962 EXPECT_EQ(5, SL::Partial(7).Slice<1>(cp).size());
963 EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(cp).size());
964
965 EXPECT_EQ(7, SL::Partial(7).Slice<2>(cp).size());
966 EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(cp).size());
967
968 EXPECT_EQ(3, SL::Partial().Slice<0>(p).size());
969 EXPECT_EQ(3, SL::Partial().Slice<int8_t>(p).size());
970 EXPECT_EQ(3, SL::Partial(7).Slice<0>(p).size());
971 EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(p).size());
972
973 EXPECT_EQ(5, SL::Partial().Slice<1>(p).size());
974 EXPECT_EQ(5, SL::Partial().Slice<int32_t>(p).size());
975 EXPECT_EQ(5, SL::Partial(7).Slice<1>(p).size());
976 EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(p).size());
977
978 EXPECT_EQ(7, SL::Partial(7).Slice<2>(p).size());
979 EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(p).size());
980 }
981
TEST(Layout,SliceByIndexData)982 TEST(Layout, SliceByIndexData) {
983 alignas(max_align_t) const unsigned char p[100] = {0};
984 {
985 using L = Layout<int32_t>;
986 EXPECT_EQ(
987 0, Distance(
988 p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
989 EXPECT_EQ(
990 0, Distance(
991 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
992 EXPECT_EQ(0,
993 Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
994 }
995 {
996 using L = Layout<int32_t, int32_t>;
997 EXPECT_EQ(
998 0, Distance(
999 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1000 EXPECT_EQ(
1001 0,
1002 Distance(
1003 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1004 EXPECT_EQ(
1005 12,
1006 Distance(
1007 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1008 EXPECT_EQ(
1009 0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
1010 EXPECT_EQ(
1011 12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
1012 }
1013 {
1014 using L = Layout<int8_t, int32_t, Int128>;
1015 EXPECT_EQ(
1016 0, Distance(
1017 p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1018 EXPECT_EQ(
1019 0, Distance(
1020 p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1021 EXPECT_EQ(
1022 0, Distance(
1023 p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1024 EXPECT_EQ(
1025 0,
1026 Distance(
1027 p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1028 EXPECT_EQ(
1029 0,
1030 Distance(
1031 p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1032 EXPECT_EQ(
1033 0,
1034 Distance(
1035 p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1036 EXPECT_EQ(
1037 4,
1038 Distance(
1039 p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1040 EXPECT_EQ(
1041 0,
1042 Distance(
1043 p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1044 EXPECT_EQ(
1045 8,
1046 Distance(
1047 p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1048 EXPECT_EQ(
1049 0,
1050 Distance(
1051 p,
1052 Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1053 EXPECT_EQ(
1054 0,
1055 Distance(
1056 p,
1057 Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1058 EXPECT_EQ(
1059 0,
1060 Distance(
1061 p,
1062 Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1063 EXPECT_EQ(
1064 0,
1065 Distance(
1066 p,
1067 Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1068 EXPECT_EQ(
1069 4,
1070 Distance(
1071 p,
1072 Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1073 EXPECT_EQ(
1074 8,
1075 Distance(
1076 p,
1077 Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1078 EXPECT_EQ(
1079 0,
1080 Distance(
1081 p,
1082 Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1083 EXPECT_EQ(
1084 24,
1085 Distance(
1086 p,
1087 Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1088 EXPECT_EQ(
1089 8,
1090 Distance(
1091 p,
1092 Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1093 EXPECT_EQ(
1094 0,
1095 Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1096 EXPECT_EQ(
1097 24,
1098 Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1099 EXPECT_EQ(
1100 8,
1101 Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1102 }
1103 }
1104
TEST(Layout,SliceByTypeData)1105 TEST(Layout, SliceByTypeData) {
1106 alignas(max_align_t) const unsigned char p[100] = {0};
1107 {
1108 using L = Layout<int32_t>;
1109 EXPECT_EQ(
1110 0,
1111 Distance(
1112 p,
1113 Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1114 EXPECT_EQ(
1115 0,
1116 Distance(
1117 p,
1118 Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1119 EXPECT_EQ(
1120 0,
1121 Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
1122 }
1123 {
1124 using L = Layout<int8_t, int32_t, Int128>;
1125 EXPECT_EQ(
1126 0,
1127 Distance(
1128 p,
1129 Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1130 EXPECT_EQ(
1131 0,
1132 Distance(
1133 p,
1134 Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1135 EXPECT_EQ(
1136 0,
1137 Distance(
1138 p,
1139 Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1140 EXPECT_EQ(
1141 0,
1142 Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
1143 .data()));
1144 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
1145 L::Partial(0, 0).Slice<int32_t>(p))
1146 .data()));
1147 EXPECT_EQ(
1148 0,
1149 Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
1150 .data()));
1151 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
1152 L::Partial(1, 0).Slice<int32_t>(p))
1153 .data()));
1154 EXPECT_EQ(
1155 0,
1156 Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
1157 .data()));
1158 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1159 L::Partial(5, 3).Slice<int32_t>(p))
1160 .data()));
1161 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1162 L::Partial(0, 0, 0).Slice<int8_t>(p))
1163 .data()));
1164 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
1165 L::Partial(0, 0, 0).Slice<int32_t>(p))
1166 .data()));
1167 EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
1168 L::Partial(0, 0, 0).Slice<Int128>(p))
1169 .data()));
1170 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1171 L::Partial(1, 0, 0).Slice<int8_t>(p))
1172 .data()));
1173 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
1174 L::Partial(1, 0, 0).Slice<int32_t>(p))
1175 .data()));
1176 EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
1177 L::Partial(1, 0, 0).Slice<Int128>(p))
1178 .data()));
1179 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1180 L::Partial(5, 3, 1).Slice<int8_t>(p))
1181 .data()));
1182 EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
1183 L::Partial(5, 3, 1).Slice<Int128>(p))
1184 .data()));
1185 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1186 L::Partial(5, 3, 1).Slice<int32_t>(p))
1187 .data()));
1188 EXPECT_EQ(
1189 0,
1190 Distance(p,
1191 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1192 EXPECT_EQ(
1193 24,
1194 Distance(p,
1195 Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1196 EXPECT_EQ(
1197 8,
1198 Distance(
1199 p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1200 }
1201 }
1202
TEST(Layout,MutableSliceByIndexData)1203 TEST(Layout, MutableSliceByIndexData) {
1204 alignas(max_align_t) unsigned char p[100] = {0};
1205 {
1206 using L = Layout<int32_t>;
1207 EXPECT_EQ(
1208 0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
1209 EXPECT_EQ(
1210 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1211 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
1212 }
1213 {
1214 using L = Layout<int32_t, int32_t>;
1215 EXPECT_EQ(
1216 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1217 EXPECT_EQ(
1218 0,
1219 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1220 EXPECT_EQ(
1221 12,
1222 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1223 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
1224 EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
1225 }
1226 {
1227 using L = Layout<int8_t, int32_t, Int128>;
1228 EXPECT_EQ(
1229 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1230 EXPECT_EQ(
1231 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1232 EXPECT_EQ(
1233 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1234 EXPECT_EQ(
1235 0,
1236 Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1237 EXPECT_EQ(
1238 0,
1239 Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1240 EXPECT_EQ(
1241 0,
1242 Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1243 EXPECT_EQ(
1244 4,
1245 Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1246 EXPECT_EQ(
1247 0,
1248 Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1249 EXPECT_EQ(
1250 8,
1251 Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1252 EXPECT_EQ(
1253 0, Distance(
1254 p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1255 EXPECT_EQ(
1256 0, Distance(
1257 p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1258 EXPECT_EQ(
1259 0, Distance(
1260 p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1261 EXPECT_EQ(
1262 0, Distance(
1263 p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1264 EXPECT_EQ(
1265 4, Distance(
1266 p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1267 EXPECT_EQ(
1268 8, Distance(
1269 p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1270 EXPECT_EQ(
1271 0, Distance(
1272 p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1273 EXPECT_EQ(
1274 24, Distance(
1275 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1276 EXPECT_EQ(
1277 8, Distance(
1278 p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1279 EXPECT_EQ(0,
1280 Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1281 EXPECT_EQ(24,
1282 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1283 EXPECT_EQ(8,
1284 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1285 }
1286 }
1287
TEST(Layout,MutableSliceByTypeData)1288 TEST(Layout, MutableSliceByTypeData) {
1289 alignas(max_align_t) unsigned char p[100] = {0};
1290 {
1291 using L = Layout<int32_t>;
1292 EXPECT_EQ(
1293 0, Distance(
1294 p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1295 EXPECT_EQ(
1296 0, Distance(
1297 p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1298 EXPECT_EQ(0,
1299 Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
1300 }
1301 {
1302 using L = Layout<int8_t, int32_t, Int128>;
1303 EXPECT_EQ(
1304 0,
1305 Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1306 EXPECT_EQ(
1307 0,
1308 Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1309 EXPECT_EQ(
1310 0,
1311 Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1312 EXPECT_EQ(
1313 0,
1314 Distance(p,
1315 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
1316 EXPECT_EQ(
1317 0,
1318 Distance(
1319 p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
1320 EXPECT_EQ(
1321 0,
1322 Distance(p,
1323 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
1324 EXPECT_EQ(
1325 4,
1326 Distance(
1327 p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
1328 EXPECT_EQ(
1329 0,
1330 Distance(p,
1331 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
1332 EXPECT_EQ(
1333 8,
1334 Distance(
1335 p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
1336 EXPECT_EQ(
1337 0,
1338 Distance(
1339 p,
1340 Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
1341 EXPECT_EQ(
1342 0,
1343 Distance(
1344 p,
1345 Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
1346 EXPECT_EQ(
1347 0,
1348 Distance(
1349 p,
1350 Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
1351 EXPECT_EQ(
1352 0,
1353 Distance(
1354 p,
1355 Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
1356 EXPECT_EQ(
1357 4,
1358 Distance(
1359 p,
1360 Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
1361 EXPECT_EQ(
1362 8,
1363 Distance(
1364 p,
1365 Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
1366 EXPECT_EQ(
1367 0,
1368 Distance(
1369 p,
1370 Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
1371 EXPECT_EQ(
1372 24,
1373 Distance(
1374 p,
1375 Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
1376 EXPECT_EQ(
1377 8,
1378 Distance(
1379 p,
1380 Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
1381 EXPECT_EQ(
1382 0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1383 EXPECT_EQ(
1384 24,
1385 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1386 EXPECT_EQ(
1387 8,
1388 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1389 }
1390 }
1391
TEST(Layout,StaticSliceData)1392 TEST(Layout, StaticSliceData) {
1393 alignas(max_align_t) const unsigned char cp[100] = {0};
1394 alignas(max_align_t) unsigned char p[100] = {0};
1395 using L = Layout<int8_t, int32_t, Int128>;
1396 using SL = L::WithStaticSizes<3, 5>;
1397
1398 EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<0>(cp).data()));
1399 EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<int8_t>(cp).data()));
1400 EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<0>(cp).data()));
1401 EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<int8_t>(cp).data()));
1402
1403 EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<1>(cp).data()));
1404 EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<int32_t>(cp).data()));
1405 EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<1>(cp).data()));
1406 EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<int32_t>(cp).data()));
1407
1408 EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<2>(cp).data()));
1409 EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<Int128>(cp).data()));
1410
1411 EXPECT_EQ(0, Distance(p, SL::Partial().Slice<0>(p).data()));
1412 EXPECT_EQ(0, Distance(p, SL::Partial().Slice<int8_t>(p).data()));
1413 EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<0>(p).data()));
1414 EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<int8_t>(p).data()));
1415
1416 EXPECT_EQ(4, Distance(p, SL::Partial().Slice<1>(p).data()));
1417 EXPECT_EQ(4, Distance(p, SL::Partial().Slice<int32_t>(p).data()));
1418 EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<1>(p).data()));
1419 EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<int32_t>(p).data()));
1420
1421 EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<2>(p).data()));
1422 EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<Int128>(p).data()));
1423 }
1424
1425 MATCHER_P(IsSameSlice, slice, "") {
1426 return arg.size() == slice.size() && arg.data() == slice.data();
1427 }
1428
1429 template <typename... M>
1430 class TupleMatcher {
1431 public:
TupleMatcher(M...matchers)1432 explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
1433
1434 template <typename Tuple>
MatchAndExplain(const Tuple & p,testing::MatchResultListener *) const1435 bool MatchAndExplain(const Tuple& p,
1436 testing::MatchResultListener* /* listener */) const {
1437 static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
1438 return MatchAndExplainImpl(
1439 p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
1440 }
1441
1442 // For the matcher concept. Left empty as we don't really need the diagnostics
1443 // right now.
DescribeTo(::std::ostream * os) const1444 void DescribeTo(::std::ostream* os) const {}
DescribeNegationTo(::std::ostream * os) const1445 void DescribeNegationTo(::std::ostream* os) const {}
1446
1447 private:
1448 template <typename Tuple, size_t... Is>
MatchAndExplainImpl(const Tuple & p,absl::index_sequence<Is...>) const1449 bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
1450 // Using std::min as a simple variadic "and".
1451 return std::min(
1452 {true, testing::SafeMatcherCast<
1453 const typename std::tuple_element<Is, Tuple>::type&>(
1454 std::get<Is>(matchers_))
1455 .Matches(std::get<Is>(p))...});
1456 }
1457
1458 std::tuple<M...> matchers_;
1459 };
1460
1461 template <typename... M>
Tuple(M...matchers)1462 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
1463 return testing::MakePolymorphicMatcher(
1464 TupleMatcher<M...>(std::move(matchers)...));
1465 }
1466
TEST(Layout,Slices)1467 TEST(Layout, Slices) {
1468 alignas(max_align_t) const unsigned char p[100] = {0};
1469 using L = Layout<int8_t, int8_t, Int128>;
1470 {
1471 const auto x = L::Partial();
1472 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1473 }
1474 {
1475 const auto x = L::Partial(1);
1476 EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
1477 Tuple(IsSameSlice(x.Slice<0>(p))));
1478 }
1479 {
1480 const auto x = L::Partial(1, 2);
1481 EXPECT_THAT(
1482 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
1483 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1484 }
1485 {
1486 const auto x = L::Partial(1, 2, 3);
1487 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1488 Span<const Int128>>>(x.Slices(p))),
1489 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1490 IsSameSlice(x.Slice<2>(p))));
1491 }
1492 {
1493 const L x(1, 2, 3);
1494 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1495 Span<const Int128>>>(x.Slices(p))),
1496 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1497 IsSameSlice(x.Slice<2>(p))));
1498 }
1499 }
1500
TEST(Layout,MutableSlices)1501 TEST(Layout, MutableSlices) {
1502 alignas(max_align_t) unsigned char p[100] = {0};
1503 using L = Layout<int8_t, int8_t, Int128>;
1504 {
1505 const auto x = L::Partial();
1506 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1507 }
1508 {
1509 const auto x = L::Partial(1);
1510 EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
1511 Tuple(IsSameSlice(x.Slice<0>(p))));
1512 }
1513 {
1514 const auto x = L::Partial(1, 2);
1515 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1516 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1517 }
1518 {
1519 const auto x = L::Partial(1, 2, 3);
1520 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1521 x.Slices(p))),
1522 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1523 IsSameSlice(x.Slice<2>(p))));
1524 }
1525 {
1526 const L x(1, 2, 3);
1527 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1528 x.Slices(p))),
1529 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1530 IsSameSlice(x.Slice<2>(p))));
1531 }
1532 }
1533
TEST(Layout,StaticSlices)1534 TEST(Layout, StaticSlices) {
1535 alignas(max_align_t) const unsigned char cp[100] = {0};
1536 alignas(max_align_t) unsigned char p[100] = {0};
1537 using SL = Layout<int8_t, int8_t, Int128>::WithStaticSizes<1, 2>;
1538 {
1539 const auto x = SL::Partial();
1540 EXPECT_THAT(
1541 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(
1542 x.Slices(cp))),
1543 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp))));
1544 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1545 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1546 }
1547 {
1548 const auto x = SL::Partial(3);
1549 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1550 Span<const Int128>>>(x.Slices(cp))),
1551 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),
1552 IsSameSlice(x.Slice<2>(cp))));
1553 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1554 x.Slices(p))),
1555 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1556 IsSameSlice(x.Slice<2>(p))));
1557 }
1558 {
1559 const SL x(3);
1560 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1561 Span<const Int128>>>(x.Slices(cp))),
1562 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)),
1563 IsSameSlice(x.Slice<2>(cp))));
1564 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1565 x.Slices(p))),
1566 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1567 IsSameSlice(x.Slice<2>(p))));
1568 }
1569 }
1570
TEST(Layout,UnalignedTypes)1571 TEST(Layout, UnalignedTypes) {
1572 constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
1573 alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
1574 EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
1575 }
1576
TEST(Layout,CustomAlignment)1577 TEST(Layout, CustomAlignment) {
1578 constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
1579 alignas(max_align_t) unsigned char p[x.AllocSize()];
1580 EXPECT_EQ(10, x.AllocSize());
1581 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
1582 }
1583
TEST(Layout,OverAligned)1584 TEST(Layout, OverAligned) {
1585 constexpr size_t M = alignof(max_align_t);
1586 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1587 #ifdef __GNUC__
1588 // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:
1589 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
1590 __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];
1591 #else
1592 alignas(2 * M) unsigned char p[x.AllocSize()];
1593 #endif
1594 EXPECT_EQ(2 * M + 3, x.AllocSize());
1595 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
1596 }
1597
TEST(Layout,Alignment)1598 TEST(Layout, Alignment) {
1599 static_assert(Layout<int8_t>::Alignment() == 1, "");
1600 static_assert(Layout<int32_t>::Alignment() == 4, "");
1601 static_assert(Layout<Int64>::Alignment() == 8, "");
1602 static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
1603 static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
1604 static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
1605 static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
1606 static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
1607 static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
1608 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1609 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1610 static_assert(
1611 Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, "");
1612 static_assert(
1613 Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, "");
1614 }
1615
TEST(Layout,StaticAlignment)1616 TEST(Layout, StaticAlignment) {
1617 static_assert(Layout<int8_t>::WithStaticSizes<>::Alignment() == 1, "");
1618 static_assert(Layout<int8_t>::WithStaticSizes<0>::Alignment() == 1, "");
1619 static_assert(Layout<int8_t>::WithStaticSizes<7>::Alignment() == 1, "");
1620 static_assert(Layout<int32_t>::WithStaticSizes<>::Alignment() == 4, "");
1621 static_assert(Layout<int32_t>::WithStaticSizes<0>::Alignment() == 4, "");
1622 static_assert(Layout<int32_t>::WithStaticSizes<3>::Alignment() == 4, "");
1623 static_assert(
1624 Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, "");
1625 static_assert(
1626 Layout<Aligned<int8_t, 64>>::WithStaticSizes<0>::Alignment() == 64, "");
1627 static_assert(
1628 Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, "");
1629 static_assert(
1630 Layout<int32_t, Int64, int8_t>::WithStaticSizes<>::Alignment() == 8, "");
1631 static_assert(
1632 Layout<int32_t, Int64, int8_t>::WithStaticSizes<0, 0, 0>::Alignment() ==
1633 8,
1634 "");
1635 static_assert(
1636 Layout<int32_t, Int64, int8_t>::WithStaticSizes<1, 1, 1>::Alignment() ==
1637 8,
1638 "");
1639 }
1640
TEST(Layout,ConstexprPartial)1641 TEST(Layout, ConstexprPartial) {
1642 constexpr size_t M = alignof(max_align_t);
1643 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1644 static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
1645 }
1646
TEST(Layout,StaticConstexpr)1647 TEST(Layout, StaticConstexpr) {
1648 constexpr size_t M = alignof(max_align_t);
1649 using L = Layout<unsigned char, Aligned<unsigned char, 2 * M>>;
1650 using SL = L::WithStaticSizes<1, 3>;
1651 constexpr SL x;
1652 static_assert(x.Offset<1>() == 2 * M, "");
1653 }
1654
1655 // [from, to)
1656 struct Region {
1657 size_t from;
1658 size_t to;
1659 };
1660
ExpectRegionPoisoned(const unsigned char * p,size_t n,bool poisoned)1661 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
1662 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
1663 for (size_t i = 0; i != n; ++i) {
1664 EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
1665 }
1666 #endif
1667 }
1668
1669 template <size_t N>
ExpectPoisoned(const unsigned char (& buf)[N],std::initializer_list<Region> reg)1670 void ExpectPoisoned(const unsigned char (&buf)[N],
1671 std::initializer_list<Region> reg) {
1672 size_t prev = 0;
1673 for (const Region& r : reg) {
1674 ExpectRegionPoisoned(buf + prev, r.from - prev, false);
1675 ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
1676 prev = r.to;
1677 }
1678 ExpectRegionPoisoned(buf + prev, N - prev, false);
1679 }
1680
TEST(Layout,PoisonPadding)1681 TEST(Layout, PoisonPadding) {
1682 using L = Layout<int8_t, Int64, int32_t, Int128>;
1683
1684 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1685 {
1686 constexpr auto x = L::Partial();
1687 alignas(max_align_t) const unsigned char c[n] = {};
1688 x.PoisonPadding(c);
1689 EXPECT_EQ(x.Slices(c), x.Slices(c));
1690 ExpectPoisoned(c, {});
1691 }
1692 {
1693 constexpr auto x = L::Partial(1);
1694 alignas(max_align_t) const unsigned char c[n] = {};
1695 x.PoisonPadding(c);
1696 EXPECT_EQ(x.Slices(c), x.Slices(c));
1697 ExpectPoisoned(c, {{1, 8}});
1698 }
1699 {
1700 constexpr auto x = L::Partial(1, 2);
1701 alignas(max_align_t) const unsigned char c[n] = {};
1702 x.PoisonPadding(c);
1703 EXPECT_EQ(x.Slices(c), x.Slices(c));
1704 ExpectPoisoned(c, {{1, 8}});
1705 }
1706 {
1707 constexpr auto x = L::Partial(1, 2, 3);
1708 alignas(max_align_t) const unsigned char c[n] = {};
1709 x.PoisonPadding(c);
1710 EXPECT_EQ(x.Slices(c), x.Slices(c));
1711 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1712 }
1713 {
1714 constexpr auto x = L::Partial(1, 2, 3, 4);
1715 alignas(max_align_t) const unsigned char c[n] = {};
1716 x.PoisonPadding(c);
1717 EXPECT_EQ(x.Slices(c), x.Slices(c));
1718 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1719 }
1720 {
1721 constexpr L x(1, 2, 3, 4);
1722 alignas(max_align_t) const unsigned char c[n] = {};
1723 x.PoisonPadding(c);
1724 EXPECT_EQ(x.Slices(c), x.Slices(c));
1725 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1726 }
1727 }
1728
TEST(Layout,StaticPoisonPadding)1729 TEST(Layout, StaticPoisonPadding) {
1730 using L = Layout<int8_t, Int64, int32_t, Int128>;
1731 using SL = L::WithStaticSizes<1, 2>;
1732
1733 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1734 {
1735 constexpr auto x = SL::Partial();
1736 alignas(max_align_t) const unsigned char c[n] = {};
1737 x.PoisonPadding(c);
1738 EXPECT_EQ(x.Slices(c), x.Slices(c));
1739 ExpectPoisoned(c, {{1, 8}});
1740 }
1741 {
1742 constexpr auto x = SL::Partial(3);
1743 alignas(max_align_t) const unsigned char c[n] = {};
1744 x.PoisonPadding(c);
1745 EXPECT_EQ(x.Slices(c), x.Slices(c));
1746 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1747 }
1748 {
1749 constexpr auto x = SL::Partial(3, 4);
1750 alignas(max_align_t) const unsigned char c[n] = {};
1751 x.PoisonPadding(c);
1752 EXPECT_EQ(x.Slices(c), x.Slices(c));
1753 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1754 }
1755 {
1756 constexpr SL x(3, 4);
1757 alignas(max_align_t) const unsigned char c[n] = {};
1758 x.PoisonPadding(c);
1759 EXPECT_EQ(x.Slices(c), x.Slices(c));
1760 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1761 }
1762 }
1763
TEST(Layout,DebugString)1764 TEST(Layout, DebugString) {
1765 {
1766 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
1767 EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1768 }
1769 {
1770 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
1771 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1772 }
1773 {
1774 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
1775 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1776 x.DebugString());
1777 }
1778 {
1779 constexpr auto x =
1780 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
1781 EXPECT_EQ(
1782 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1783 "@16" +
1784 Int128::Name() + "(16)",
1785 x.DebugString());
1786 }
1787 {
1788 constexpr auto x =
1789 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
1790 EXPECT_EQ(
1791 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1792 "@16" +
1793 Int128::Name() + "(16)[4]",
1794 x.DebugString());
1795 }
1796 {
1797 constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
1798 EXPECT_EQ(
1799 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1800 "@16" +
1801 Int128::Name() + "(16)[4]",
1802 x.DebugString());
1803 }
1804 }
1805
TEST(Layout,StaticDebugString)1806 TEST(Layout, StaticDebugString) {
1807 {
1808 constexpr auto x =
1809 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial();
1810 EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1811 }
1812 {
1813 constexpr auto x =
1814 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1);
1815 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1816 }
1817 {
1818 constexpr auto x =
1819 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial();
1820 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1821 }
1822 {
1823 constexpr auto x =
1824 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1,
1825 2);
1826 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1827 x.DebugString());
1828 }
1829 {
1830 constexpr auto x =
1831 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial(2);
1832 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1833 x.DebugString());
1834 }
1835 {
1836 constexpr auto x = Layout<int8_t, int32_t, int8_t,
1837 Int128>::WithStaticSizes<1, 2>::Partial();
1838 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1839 x.DebugString());
1840 }
1841 {
1842 constexpr auto x = Layout<int8_t, int32_t, int8_t,
1843 Int128>::WithStaticSizes<1, 2, 3, 4>::Partial();
1844 EXPECT_EQ(
1845 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1846 "@16" +
1847 Int128::Name() + "(16)[4]",
1848 x.DebugString());
1849 }
1850 {
1851 constexpr Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1, 2, 3,
1852 4>
1853 x;
1854 EXPECT_EQ(
1855 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1856 "@16" +
1857 Int128::Name() + "(16)[4]",
1858 x.DebugString());
1859 }
1860 }
1861
TEST(Layout,CharTypes)1862 TEST(Layout, CharTypes) {
1863 constexpr Layout<int32_t> x(1);
1864 alignas(max_align_t) char c[x.AllocSize()] = {};
1865 alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
1866 alignas(max_align_t) signed char sc[x.AllocSize()] = {};
1867 alignas(max_align_t) const char cc[x.AllocSize()] = {};
1868 alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
1869 alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
1870
1871 Type<int32_t*>(x.Pointer<0>(c));
1872 Type<int32_t*>(x.Pointer<0>(uc));
1873 Type<int32_t*>(x.Pointer<0>(sc));
1874 Type<const int32_t*>(x.Pointer<0>(cc));
1875 Type<const int32_t*>(x.Pointer<0>(cuc));
1876 Type<const int32_t*>(x.Pointer<0>(csc));
1877
1878 Type<int32_t*>(x.Pointer<int32_t>(c));
1879 Type<int32_t*>(x.Pointer<int32_t>(uc));
1880 Type<int32_t*>(x.Pointer<int32_t>(sc));
1881 Type<const int32_t*>(x.Pointer<int32_t>(cc));
1882 Type<const int32_t*>(x.Pointer<int32_t>(cuc));
1883 Type<const int32_t*>(x.Pointer<int32_t>(csc));
1884
1885 Type<std::tuple<int32_t*>>(x.Pointers(c));
1886 Type<std::tuple<int32_t*>>(x.Pointers(uc));
1887 Type<std::tuple<int32_t*>>(x.Pointers(sc));
1888 Type<std::tuple<const int32_t*>>(x.Pointers(cc));
1889 Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
1890 Type<std::tuple<const int32_t*>>(x.Pointers(csc));
1891
1892 Type<Span<int32_t>>(x.Slice<0>(c));
1893 Type<Span<int32_t>>(x.Slice<0>(uc));
1894 Type<Span<int32_t>>(x.Slice<0>(sc));
1895 Type<Span<const int32_t>>(x.Slice<0>(cc));
1896 Type<Span<const int32_t>>(x.Slice<0>(cuc));
1897 Type<Span<const int32_t>>(x.Slice<0>(csc));
1898
1899 Type<std::tuple<Span<int32_t>>>(x.Slices(c));
1900 Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
1901 Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
1902 Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
1903 Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
1904 Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
1905 }
1906
TEST(Layout,ConstElementType)1907 TEST(Layout, ConstElementType) {
1908 constexpr Layout<const int32_t> x(1);
1909 alignas(int32_t) char c[x.AllocSize()] = {};
1910 const char* cc = c;
1911 const int32_t* p = reinterpret_cast<const int32_t*>(cc);
1912
1913 EXPECT_EQ(alignof(int32_t), x.Alignment());
1914
1915 EXPECT_EQ(0, x.Offset<0>());
1916 EXPECT_EQ(0, x.Offset<const int32_t>());
1917
1918 EXPECT_THAT(x.Offsets(), ElementsAre(0));
1919
1920 EXPECT_EQ(1, x.Size<0>());
1921 EXPECT_EQ(1, x.Size<const int32_t>());
1922
1923 EXPECT_THAT(x.Sizes(), ElementsAre(1));
1924
1925 EXPECT_EQ(sizeof(int32_t), x.AllocSize());
1926
1927 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
1928 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
1929
1930 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
1931 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
1932
1933 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
1934 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
1935
1936 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
1937 IsSameSlice(Span<const int32_t>(p, 1)));
1938 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
1939 IsSameSlice(Span<const int32_t>(p, 1)));
1940
1941 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
1942 IsSameSlice(Span<const int32_t>(p, 1)));
1943 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
1944 IsSameSlice(Span<const int32_t>(p, 1)));
1945
1946 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
1947 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1948 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
1949 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1950 }
1951
1952 namespace example {
1953
1954 // Immutable move-only string with sizeof equal to sizeof(void*). The string
1955 // size and the characters are kept in the same heap allocation.
1956 class CompactString {
1957 public:
CompactString(const char * s="")1958 CompactString(const char* s = "") { // NOLINT
1959 const size_t size = strlen(s);
1960 // size_t[1], followed by char[size + 1].
1961 // This statement doesn't allocate memory.
1962 const L layout(1, size + 1);
1963 // AllocSize() tells us how much memory we need to allocate for all our
1964 // data.
1965 p_.reset(new unsigned char[layout.AllocSize()]);
1966 // If running under ASAN, mark the padding bytes, if any, to catch memory
1967 // errors.
1968 layout.PoisonPadding(p_.get());
1969 // Store the size in the allocation.
1970 // Pointer<size_t>() is a synonym for Pointer<0>().
1971 *layout.Pointer<size_t>(p_.get()) = size;
1972 // Store the characters in the allocation.
1973 memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
1974 }
1975
size() const1976 size_t size() const {
1977 // Equivalent to reinterpret_cast<size_t&>(*p).
1978 return *L::Partial().Pointer<size_t>(p_.get());
1979 }
1980
c_str() const1981 const char* c_str() const {
1982 // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
1983 // The argument in Partial(1) specifies that we have size_t[1] in front of
1984 // the characters.
1985 return L::Partial(1).Pointer<char>(p_.get());
1986 }
1987
1988 private:
1989 // Our heap allocation contains a size_t followed by an array of chars.
1990 using L = Layout<size_t, char>;
1991 std::unique_ptr<unsigned char[]> p_;
1992 };
1993
TEST(CompactString,Works)1994 TEST(CompactString, Works) {
1995 CompactString s = "hello";
1996 EXPECT_EQ(5, s.size());
1997 EXPECT_STREQ("hello", s.c_str());
1998 }
1999
2000 // Same as the previous CompactString example, except we set the first array
2001 // size to 1 statically, since we know it is always 1. This allows us to compute
2002 // the offset of the character array at compile time.
2003 class StaticCompactString {
2004 public:
StaticCompactString(const char * s="")2005 StaticCompactString(const char* s = "") { // NOLINT
2006 const size_t size = strlen(s);
2007 const SL layout(size + 1);
2008 p_.reset(new unsigned char[layout.AllocSize()]);
2009 layout.PoisonPadding(p_.get());
2010 *layout.Pointer<size_t>(p_.get()) = size;
2011 memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
2012 }
2013
size() const2014 size_t size() const { return *SL::Partial().Pointer<size_t>(p_.get()); }
2015
c_str() const2016 const char* c_str() const { return SL::Partial().Pointer<char>(p_.get()); }
2017
2018 private:
2019 using SL = Layout<size_t, char>::WithStaticSizes<1>;
2020 std::unique_ptr<unsigned char[]> p_;
2021 };
2022
TEST(StaticCompactString,Works)2023 TEST(StaticCompactString, Works) {
2024 StaticCompactString s = "hello";
2025 EXPECT_EQ(5, s.size());
2026 EXPECT_STREQ("hello", s.c_str());
2027 }
2028
2029 } // namespace example
2030
2031 } // namespace
2032 } // namespace container_internal
2033 ABSL_NAMESPACE_END
2034 } // namespace absl
2035