1 //===- unittests/StaticAnalyzer/RangeSetTest.cpp ----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Basic/Builtins.h"
10 #include "clang/Basic/FileManager.h"
11 #include "clang/Basic/SourceManager.h"
12 #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
13 #include "clang/Tooling/Tooling.h"
14 #include "llvm/ADT/APSInt.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include "gtest/gtest.h"
18 using namespace clang
;
24 template <class RangeOrSet
> static std::string
toString(const RangeOrSet
&Obj
) {
25 std::string ObjRepresentation
;
26 llvm::raw_string_ostream
SS(ObjRepresentation
);
30 LLVM_ATTRIBUTE_UNUSED
static std::string
toString(const llvm::APSInt
&Point
) {
31 return toString(Point
, 10);
33 // We need it here for better fail diagnostics from gtest.
34 LLVM_ATTRIBUTE_UNUSED
static std::ostream
&operator<<(std::ostream
&OS
,
35 const RangeSet
&Set
) {
36 return OS
<< toString(Set
);
38 // We need it here for better fail diagnostics from gtest.
39 LLVM_ATTRIBUTE_UNUSED
static std::ostream
&operator<<(std::ostream
&OS
,
41 return OS
<< toString(R
);
43 LLVM_ATTRIBUTE_UNUSED
static std::ostream
&operator<<(std::ostream
&OS
,
45 return OS
<< (Ty
.isUnsigned() ? "u" : "s") << Ty
.getBitWidth();
53 template <class T
> constexpr bool is_signed_v
= std::is_signed
<T
>::value
;
55 template <typename T
> struct TestValues
{
56 static constexpr T MIN
= std::numeric_limits
<T
>::min();
57 static constexpr T MAX
= std::numeric_limits
<T
>::max();
58 // MID is a value in the middle of the range
59 // which unary minus does not affect on,
60 // e.g. int8/int32(0), uint8(128), uint32(2147483648).
61 static constexpr T MID
=
62 is_signed_v
<T
> ? 0 : ~(static_cast<T
>(-1) / static_cast<T
>(2));
63 static constexpr T A
= MID
- (MAX
- MID
) / 3 * 2;
64 static constexpr T B
= MID
- (MAX
- MID
) / 3;
65 static constexpr T C
= -B
;
66 static constexpr T D
= -A
;
68 static_assert(MIN
< A
&& A
< B
&& B
< MID
&& MID
< C
&& C
< D
&& D
< MAX
,
69 "Values shall be in an ascending order");
70 // Clear bits in low bytes by the given amount.
71 template <T Value
, size_t Bytes
>
72 static constexpr T ClearLowBytes
=
73 static_cast<T
>(static_cast<uint64_t>(Value
)
74 << ((Bytes
>= CHAR_BIT
) ? 0 : Bytes
) * CHAR_BIT
);
76 template <T Value
, typename Base
>
77 static constexpr T TruncZeroOf
= ClearLowBytes
<Value
+ 1, sizeof(Base
)>;
79 // Random number with active bits in every byte. 0xAAAA'AAAA
80 static constexpr T XAAA
= static_cast<T
>(
81 0b10101010'10101010'10101010'10101010'10101010'10101010'10101010'10101010);
82 template <typename Base
>
83 static constexpr T XAAATruncZeroOf
= TruncZeroOf
<XAAA
, Base
>; // 0xAAAA'AB00
85 // Random number with active bits in every byte. 0x5555'5555
86 static constexpr T X555
= static_cast<T
>(
87 0b01010101'01010101'01010101'01010101'01010101'01010101'01010101'01010101);
88 template <typename Base
>
89 static constexpr T X555TruncZeroOf
= TruncZeroOf
<X555
, Base
>; // 0x5555'5600
91 // Silence 'warning C4309: 'initializing': truncation of constant value'
92 // in RangeSetCastToPromotionConversionTest.
93 #if defined(_MSC_VER) && !defined(__clang__)
95 #pragma warning(disable : 4309)
97 // Numbers for ranges with the same bits in the lowest byte.
99 static constexpr T FromA
= ClearLowBytes
<XAAA
, sizeof(T
) - 1> + 42;
100 static constexpr T ToA
= FromA
+ 2; // 0xAAAA'AA2C
102 static constexpr T FromB
= ClearLowBytes
<X555
, sizeof(T
) - 1> + 42;
103 static constexpr T ToB
= FromB
+ 2; // 0x5555'552C
105 #if defined(_MSC_VER) && !defined(__clang__)
110 template <typename T
>
111 static constexpr APSIntType APSIntTy
=
112 APSIntType(sizeof(T
) * CHAR_BIT
, !is_signed_v
<T
>);
114 template <typename BaseType
> class RangeSetTest
: public testing::Test
{
117 std::unique_ptr
<ASTUnit
> AST
= tooling::buildASTFromCode("struct foo;");
118 ASTContext
&Context
= AST
->getASTContext();
119 llvm::BumpPtrAllocator Arena
;
120 BasicValueFactory BVF
{Context
, Arena
};
121 RangeSet::Factory F
{BVF
};
124 using Self
= RangeSetTest
<BaseType
>;
125 template <typename T
> using RawRangeT
= std::pair
<T
, T
>;
126 template <typename T
>
127 using RawRangeSetT
= std::initializer_list
<RawRangeT
<T
>>;
128 using RawRange
= RawRangeT
<BaseType
>;
129 using RawRangeSet
= RawRangeSetT
<BaseType
>;
131 template <typename T
> const llvm::APSInt
&from(T X
) {
132 static llvm::APSInt Int
= APSIntTy
<T
>.getZeroValue();
134 return BVF
.getValue(Int
);
137 template <typename T
> Range
from(const RawRangeT
<T
> &Init
) {
138 return Range(from(Init
.first
), from(Init
.second
));
141 template <typename T
>
142 RangeSet
from(RawRangeSetT
<T
> Init
, APSIntType Ty
= APSIntTy
<BaseType
>) {
143 RangeSet RangeSet
= F
.getEmptySet();
144 for (const auto &Raw
: Init
) {
145 RangeSet
= F
.add(RangeSet
, from(Raw
));
150 template <class F
, class... RawArgTypes
>
151 void wrap(F ActualFunction
, RawArgTypes
&&... Args
) {
152 (this->*ActualFunction
)(from(std::forward
<RawArgTypes
>(Args
))...);
155 void checkNegateImpl(RangeSet Original
, RangeSet Expected
) {
156 RangeSet NegatedFromOriginal
= F
.negate(Original
);
157 EXPECT_EQ(NegatedFromOriginal
, Expected
);
158 // Negate negated back and check with original.
159 RangeSet NegatedBackward
= F
.negate(NegatedFromOriginal
);
160 EXPECT_EQ(NegatedBackward
, Original
);
163 void checkNegate(RawRangeSet RawOriginal
, RawRangeSet RawExpected
) {
164 wrap(&Self::checkNegateImpl
, RawOriginal
, RawExpected
);
167 template <class PointOrSet
>
168 void checkIntersectImpl(RangeSet LHS
, PointOrSet RHS
, RangeSet Expected
) {
169 RangeSet Result
= F
.intersect(LHS
, RHS
);
170 EXPECT_EQ(Result
, Expected
)
171 << "while intersecting " << toString(LHS
) << " and " << toString(RHS
);
174 void checkIntersectRangeImpl(RangeSet LHS
, const llvm::APSInt
&Lower
,
175 const llvm::APSInt
&Upper
, RangeSet Expected
) {
176 RangeSet Result
= F
.intersect(LHS
, Lower
, Upper
);
177 EXPECT_EQ(Result
, Expected
)
178 << "while intersecting " << toString(LHS
) << " and [" << toString(Lower
)
179 << ", " << toString(Upper
) << "]";
182 void checkIntersect(RawRangeSet RawLHS
, RawRangeSet RawRHS
,
183 RawRangeSet RawExpected
) {
184 wrap(&Self::checkIntersectImpl
<RangeSet
>, RawLHS
, RawRHS
, RawExpected
);
187 void checkIntersect(RawRangeSet RawLHS
, BaseType RawRHS
,
188 RawRangeSet RawExpected
) {
189 wrap(&Self::checkIntersectImpl
<const llvm::APSInt
&>, RawLHS
, RawRHS
,
193 void checkIntersect(RawRangeSet RawLHS
, BaseType RawLower
, BaseType RawUpper
,
194 RawRangeSet RawExpected
) {
195 wrap(&Self::checkIntersectRangeImpl
, RawLHS
, RawLower
, RawUpper
,
199 void checkContainsImpl(RangeSet LHS
, const llvm::APSInt
&RHS
, bool Expected
) {
200 bool Result
= LHS
.contains(RHS
);
201 EXPECT_EQ(Result
, Expected
)
202 << toString(LHS
) << (Result
? " contains " : " doesn't contain ")
206 void checkContains(RawRangeSet RawLHS
, BaseType RawRHS
, bool Expected
) {
207 checkContainsImpl(from(RawLHS
), from(RawRHS
), Expected
);
210 template <class RHSType
>
211 void checkAddImpl(RangeSet LHS
, RHSType RHS
, RangeSet Expected
) {
212 RangeSet Result
= F
.add(LHS
, RHS
);
213 EXPECT_EQ(Result
, Expected
)
214 << "while adding " << toString(LHS
) << " and " << toString(RHS
);
217 void checkAdd(RawRangeSet RawLHS
, RawRange RawRHS
, RawRangeSet RawExpected
) {
218 wrap(&Self::checkAddImpl
<Range
>, RawLHS
, RawRHS
, RawExpected
);
221 void checkAdd(RawRangeSet RawLHS
, RawRangeSet RawRHS
,
222 RawRangeSet RawExpected
) {
223 wrap(&Self::checkAddImpl
<RangeSet
>, RawLHS
, RawRHS
, RawExpected
);
226 void checkAdd(RawRangeSet RawLHS
, BaseType RawRHS
, RawRangeSet RawExpected
) {
227 wrap(&Self::checkAddImpl
<const llvm::APSInt
&>, RawLHS
, RawRHS
,
231 template <class RHSType
>
232 void checkUniteImpl(RangeSet LHS
, RHSType RHS
, RangeSet Expected
) {
233 RangeSet Result
= F
.unite(LHS
, RHS
);
234 EXPECT_EQ(Result
, Expected
)
235 << "while uniting " << toString(LHS
) << " and " << toString(RHS
);
238 void checkUnite(RawRangeSet RawLHS
, RawRange RawRHS
,
239 RawRangeSet RawExpected
) {
240 wrap(&Self::checkUniteImpl
<Range
>, RawLHS
, RawRHS
, RawExpected
);
243 void checkUnite(RawRangeSet RawLHS
, RawRangeSet RawRHS
,
244 RawRangeSet RawExpected
) {
245 wrap(&Self::checkUniteImpl
<RangeSet
>, RawLHS
, RawRHS
, RawExpected
);
248 void checkUnite(RawRangeSet RawLHS
, BaseType RawRHS
,
249 RawRangeSet RawExpected
) {
250 wrap(&Self::checkUniteImpl
<const llvm::APSInt
&>, RawLHS
, RawRHS
,
254 void checkDeleteImpl(const llvm::APSInt
&Point
, RangeSet From
,
256 RangeSet Result
= F
.deletePoint(From
, Point
);
257 EXPECT_EQ(Result
, Expected
)
258 << "while deleting " << toString(Point
) << " from " << toString(From
);
261 void checkDelete(BaseType Point
, RawRangeSet RawFrom
,
262 RawRangeSet RawExpected
) {
263 wrap(&Self::checkDeleteImpl
, Point
, RawFrom
, RawExpected
);
266 void checkCastToImpl(RangeSet What
, APSIntType Ty
, RangeSet Expected
) {
267 RangeSet Result
= F
.castTo(What
, Ty
);
268 EXPECT_EQ(Result
, Expected
)
269 << "while casting " << toString(What
) << " to " << Ty
;
272 template <typename From
, typename To
>
273 void checkCastTo(RawRangeSetT
<From
> What
, RawRangeSetT
<To
> Expected
) {
274 static constexpr APSIntType FromTy
= APSIntTy
<From
>;
275 static constexpr APSIntType ToTy
= APSIntTy
<To
>;
276 this->checkCastToImpl(from(What
, FromTy
), ToTy
, from(Expected
, ToTy
));
280 using IntTypes
= ::testing::Types
<int8_t, uint8_t, int16_t, uint16_t, int32_t,
281 uint32_t, int64_t, uint64_t>;
282 TYPED_TEST_SUITE(RangeSetTest
, IntTypes
, );
284 TYPED_TEST(RangeSetTest
, RangeSetNegateTest
) {
285 using TV
= TestValues
<TypeParam
>;
286 constexpr auto MIN
= TV::MIN
;
287 constexpr auto MAX
= TV::MAX
;
288 constexpr auto MID
= TV::MID
;
289 constexpr auto A
= TV::A
;
290 constexpr auto B
= TV::B
;
291 constexpr auto C
= TV::C
;
292 constexpr auto D
= TV::D
;
294 this->checkNegate({{MIN
, A
}}, {{MIN
, MIN
}, {D
, MAX
}});
295 this->checkNegate({{MIN
, C
}}, {{MIN
, MIN
}, {B
, MAX
}});
296 this->checkNegate({{MIN
, MID
}}, {{MIN
, MIN
}, {MID
, MAX
}});
297 this->checkNegate({{MIN
, MAX
}}, {{MIN
, MAX
}});
298 this->checkNegate({{A
, D
}}, {{A
, D
}});
299 this->checkNegate({{A
, B
}}, {{C
, D
}});
300 this->checkNegate({{MIN
, A
}, {D
, MAX
}}, {{MIN
, A
}, {D
, MAX
}});
301 this->checkNegate({{MIN
, B
}, {MID
, D
}}, {{MIN
, MIN
}, {A
, MID
}, {C
, MAX
}});
302 this->checkNegate({{MIN
, MID
}, {C
, D
}}, {{MIN
, MIN
}, {A
, B
}, {MID
, MAX
}});
303 this->checkNegate({{MIN
, MID
}, {C
, MAX
}}, {{MIN
, B
}, {MID
, MAX
}});
304 this->checkNegate({{A
, MID
}, {D
, MAX
}}, {{MIN
+ 1, A
}, {MID
, D
}});
305 this->checkNegate({{A
, A
}}, {{D
, D
}});
306 this->checkNegate({{MID
, MID
}}, {{MID
, MID
}});
307 this->checkNegate({{MAX
, MAX
}}, {{MIN
+ 1, MIN
+ 1}});
310 TYPED_TEST(RangeSetTest
, RangeSetPointIntersectTest
) {
311 // Check that we can correctly intersect empty sets.
312 this->checkIntersect({}, 42, {});
313 // Check that intersection with itself produces the same set.
314 this->checkIntersect({{42, 42}}, 42, {{42, 42}});
315 // Check more general cases.
316 this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 42, {});
317 this->checkIntersect({{0, 10}, {20, 30}, {30, 60}}, 42, {{42, 42}});
320 TYPED_TEST(RangeSetTest
, RangeSetRangeIntersectTest
) {
321 using TV
= TestValues
<TypeParam
>;
322 constexpr auto MIN
= TV::MIN
;
323 constexpr auto MAX
= TV::MAX
;
325 // Check that we can correctly intersect empty sets.
326 this->checkIntersect({}, 10, 20, {});
327 this->checkIntersect({}, 20, 10, {});
328 // Check that intersection with itself produces the same set.
329 this->checkIntersect({{10, 20}}, 10, 20, {{10, 20}});
330 this->checkIntersect({{MIN
, 10}, {20, MAX
}}, 20, 10, {{MIN
, 10}, {20, MAX
}});
331 // Check non-overlapping range intersections.
332 this->checkIntersect({{10, 20}}, 21, 9, {});
333 this->checkIntersect({{MIN
, 9}, {21, MAX
}}, 10, 20, {});
334 // Check more general cases.
335 this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 10, 35,
336 {{10, 10}, {20, 30}, {30, 35}});
337 this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 35, 10,
338 {{0, 10}, {35, 40}, {50, 60}});
341 TYPED_TEST(RangeSetTest
, RangeSetGenericIntersectTest
) {
342 // Check that we can correctly intersect empty sets.
343 this->checkIntersect({}, {}, {});
344 this->checkIntersect({}, {{0, 10}}, {});
345 this->checkIntersect({{0, 10}}, {}, {});
347 this->checkIntersect({{0, 10}}, {{4, 6}}, {{4, 6}});
348 this->checkIntersect({{0, 10}}, {{4, 20}}, {{4, 10}});
349 // Check that intersection with points works as expected.
350 this->checkIntersect({{0, 10}}, {{4, 4}}, {{4, 4}});
351 // All ranges are closed, check that intersection with edge points works as
353 this->checkIntersect({{0, 10}}, {{10, 10}}, {{10, 10}});
355 // Let's check that we can skip some intervals and partially intersect
357 this->checkIntersect({{0, 2}, {4, 5}, {6, 9}, {10, 11}, {12, 12}, {13, 15}},
359 {{8, 9}, {10, 11}, {12, 12}, {13, 14}});
360 // Check more generic case.
361 this->checkIntersect(
362 {{0, 1}, {2, 3}, {5, 6}, {7, 15}, {25, 30}},
363 {{4, 10}, {11, 11}, {12, 16}, {17, 17}, {19, 20}, {21, 23}, {24, 27}},
364 {{5, 6}, {7, 10}, {11, 11}, {12, 15}, {25, 27}});
367 TYPED_TEST(RangeSetTest
, RangeSetContainsTest
) {
368 // Check with an empty set.
369 this->checkContains({}, 10, false);
370 // Check contains with sets of size one:
371 // * when the whole range is less
372 this->checkContains({{0, 5}}, 10, false);
373 // * when the whole range is greater
374 this->checkContains({{20, 25}}, 10, false);
375 // * when the range is just the point we are looking for
376 this->checkContains({{10, 10}}, 10, true);
377 // * when the range starts with the point
378 this->checkContains({{10, 15}}, 10, true);
379 // * when the range ends with the point
380 this->checkContains({{5, 10}}, 10, true);
381 // * when the range has the point somewhere in the middle
382 this->checkContains({{0, 25}}, 10, true);
383 // Check similar cases, but with larger sets.
384 this->checkContains({{0, 5}, {10, 10}, {15, 20}}, 10, true);
385 this->checkContains({{0, 5}, {10, 12}, {15, 20}}, 10, true);
386 this->checkContains({{0, 5}, {5, 7}, {8, 10}, {12, 41}}, 10, true);
388 using TV
= TestValues
<TypeParam
>;
389 constexpr auto MIN
= TV::MIN
;
390 constexpr auto MAX
= TV::MAX
;
391 constexpr auto MID
= TV::MID
;
393 this->checkContains({{MIN
, MAX
}}, 0, true);
394 this->checkContains({{MIN
, MAX
}}, MID
, true);
395 this->checkContains({{MIN
, MAX
}}, -10, true);
396 this->checkContains({{MIN
, MAX
}}, 10, true);
399 TYPED_TEST(RangeSetTest
, RangeSetAddTest
) {
400 // Check adding single points
401 this->checkAdd({}, 10, {{10, 10}});
402 this->checkAdd({{0, 5}}, 10, {{0, 5}, {10, 10}});
403 this->checkAdd({{0, 5}, {30, 40}}, 10, {{0, 5}, {10, 10}, {30, 40}});
405 // Check adding single ranges.
406 this->checkAdd({}, {10, 20}, {{10, 20}});
407 this->checkAdd({{0, 5}}, {10, 20}, {{0, 5}, {10, 20}});
408 this->checkAdd({{0, 5}, {30, 40}}, {10, 20}, {{0, 5}, {10, 20}, {30, 40}});
410 // Check adding whole sets of ranges.
411 this->checkAdd({{0, 5}}, {{10, 20}}, {{0, 5}, {10, 20}});
412 // Check that ordering of ranges is as expected.
413 this->checkAdd({{0, 5}, {30, 40}}, {{10, 20}}, {{0, 5}, {10, 20}, {30, 40}});
414 this->checkAdd({{0, 5}, {30, 40}}, {{10, 20}, {50, 60}},
415 {{0, 5}, {10, 20}, {30, 40}, {50, 60}});
416 this->checkAdd({{10, 20}, {50, 60}}, {{0, 5}, {30, 40}, {70, 80}},
417 {{0, 5}, {10, 20}, {30, 40}, {50, 60}, {70, 80}});
420 TYPED_TEST(RangeSetTest
, RangeSetDeletePointTest
) {
421 using TV
= TestValues
<TypeParam
>;
422 constexpr auto MIN
= TV::MIN
;
423 constexpr auto MAX
= TV::MAX
;
424 constexpr auto MID
= TV::MID
;
426 this->checkDelete(MID
, {{MIN
, MAX
}}, {{MIN
, MID
- 1}, {MID
+ 1, MAX
}});
427 // Check that delete works with an empty set.
428 this->checkDelete(10, {}, {});
429 // Check that delete can remove entire ranges.
430 this->checkDelete(10, {{10, 10}}, {});
431 this->checkDelete(10, {{0, 5}, {10, 10}, {20, 30}}, {{0, 5}, {20, 30}});
432 // Check that delete can split existing ranges into two.
433 this->checkDelete(10, {{0, 5}, {7, 15}, {20, 30}},
434 {{0, 5}, {7, 9}, {11, 15}, {20, 30}});
435 // Check that delete of the point not from the range set works as expected.
436 this->checkDelete(10, {{0, 5}, {20, 30}}, {{0, 5}, {20, 30}});
439 TYPED_TEST(RangeSetTest
, RangeSetUniteTest
) {
440 using TV
= TestValues
<TypeParam
>;
441 constexpr auto MIN
= TV::MIN
;
442 constexpr auto MAX
= TV::MAX
;
443 constexpr auto MID
= TV::MID
;
444 constexpr auto A
= TV::A
;
445 constexpr auto B
= TV::B
;
446 constexpr auto C
= TV::C
;
447 constexpr auto D
= TV::D
;
449 // LHS and RHS is empty.
452 // ___________________ ___________________
453 this->checkUnite({}, {}, {});
457 // LHS => _____ = _____
458 // ______/_____\______ ______/_____\______
459 this->checkUnite({{A
, B
}}, {}, {{A
, B
}});
460 this->checkUnite({{A
, B
}, {C
, D
}}, {}, {{A
, B
}, {C
, D
}});
461 this->checkUnite({{MIN
, MIN
}}, {}, {{MIN
, MIN
}});
462 this->checkUnite({{MAX
, MAX
}}, {}, {{MAX
, MAX
}});
463 this->checkUnite({{MIN
, MIN
}, {MAX
, MAX
}}, {}, {{MIN
, MIN
}, {MAX
, MAX
}});
467 // LHS => / \ = _____
468 // ______/_____\______ ______/_____\______
469 this->checkUnite({}, B
, {{B
, B
}});
470 this->checkUnite({}, {B
, C
}, {{B
, C
}});
471 this->checkUnite({}, {{MIN
, B
}, {C
, MAX
}}, {{MIN
, B
}, {C
, MAX
}});
472 this->checkUnite({}, {{MIN
, MIN
}}, {{MIN
, MIN
}});
473 this->checkUnite({}, {{MAX
, MAX
}}, {{MAX
, MAX
}});
474 this->checkUnite({}, {{MIN
, MIN
}, {MAX
, MAX
}}, {{MIN
, MIN
}, {MAX
, MAX
}});
476 // RHS is detached from LHS.
478 // LHS => ___ / \ = ___ _____
479 // __/___\___/_____\__ __/___\___/_____\__
480 this->checkUnite({{A
, C
}}, D
, {{A
, C
}, {D
, D
}});
481 this->checkUnite({{MID
, C
}, {D
, MAX
}}, A
, {{A
, A
}, {MID
, C
}, {D
, MAX
}});
482 this->checkUnite({{A
, B
}}, {MID
, D
}, {{A
, B
}, {MID
, D
}});
483 this->checkUnite({{MIN
, A
}, {D
, MAX
}}, {B
, C
}, {{MIN
, A
}, {B
, C
}, {D
, MAX
}});
484 this->checkUnite({{B
, MID
}, {D
, MAX
}}, {{MIN
, A
}, {C
, C
}},
485 {{MIN
, A
}, {B
, MID
}, {C
, C
}, {D
, MAX
}});
486 this->checkUnite({{MIN
, A
}, {C
, C
}}, {{B
, MID
}, {D
, MAX
}},
487 {{MIN
, A
}, {B
, MID
}, {C
, C
}, {D
, MAX
}});
488 this->checkUnite({{A
, B
}}, {{MAX
, MAX
}}, {{A
, B
}, {MAX
, MAX
}});
489 this->checkUnite({{MIN
, MIN
}}, {A
, B
}, {{MIN
, MIN
}, {A
, B
}});
490 this->checkUnite({{MIN
, MIN
}}, {MAX
, MAX
}, {{MIN
, MIN
}, {MAX
, MAX
}});
492 // RHS is inside LHS.
494 // LHS => ___/___\___ = ___________
495 // ___/__/_____\__\___ ___/___________\___
496 this->checkUnite({{A
, C
}}, MID
, {{A
, C
}});
497 this->checkUnite({{A
, D
}}, {B
, C
}, {{A
, D
}});
498 this->checkUnite({{MIN
, MAX
}}, {B
, C
}, {{MIN
, MAX
}});
502 // LHS => / _____ \ = ___________
503 // ___/__/_____\__\___ ___/___________\___
504 this->checkUnite({{MID
, MID
}}, {A
, D
}, {{A
, D
}});
505 this->checkUnite({{B
, C
}}, {A
, D
}, {{A
, D
}});
506 this->checkUnite({{A
, B
}}, {MIN
, MAX
}, {{MIN
, MAX
}});
508 // RHS equals to LHS.
510 // LHS => /_________\ = ___________
511 // ___/___________\___ ___/___________\___
512 this->checkUnite({{MIN
, MIN
}}, MIN
, {{MIN
, MIN
}});
513 this->checkUnite({{A
, B
}}, {A
, B
}, {{A
, B
}});
514 this->checkUnite({{MAX
, MAX
}}, {{MAX
, MAX
}}, {{MAX
, MAX
}});
515 this->checkUnite({{MIN
, MIN
}}, {{MIN
, MIN
}}, {{MIN
, MIN
}});
516 this->checkUnite({{MIN
, MIN
}, {MAX
, MAX
}}, {{MIN
, MIN
}, {MAX
, MAX
}},
517 {{MIN
, MIN
}, {MAX
, MAX
}});
519 // RHS edge is MIN and attached and inside LHS.
521 // LHS => /_____\_____ = ___________
522 // /_______\____\___ /___________\___
523 this->checkUnite({{MIN
, A
}}, {MIN
, B
}, {{MIN
, B
}});
525 // RHS edge is MIN and attached and outsude LHS.
527 // LHS => /______ \ = ___________
528 // /_______\____\___ /___________\___
529 this->checkUnite({{MIN
, B
}}, {MIN
, A
}, {{MIN
, B
}});
531 // RHS intersects right of LHS.
533 // LHS => ___/____ \ = ___________
534 // ___/__/_____\__\___ ___/___________\___
535 this->checkUnite({{A
, C
}}, C
, {{A
, C
}});
536 this->checkUnite({{A
, C
}}, {B
, D
}, {{A
, D
}});
538 // RHS intersects left of LHS.
540 // LHS => / ____\___ = ___________
541 // ___/__/_____\__\___ ___/___________\___
542 this->checkUnite({{B
, D
}}, B
, {{B
, D
}});
543 this->checkUnite({{B
, D
}}, {A
, C
}, {{A
, D
}});
544 this->checkUnite({{MID
, MAX
}}, {MIN
, MID
}, {{MIN
, MAX
}});
546 // RHS adjacent to LHS on right.
548 // LHS => ______ / \ = _______________
549 // _/______\/_______\_ _/_______________\_
550 this->checkUnite({{A
, B
- 1}}, B
, {{A
, B
}});
551 this->checkUnite({{A
, C
}}, {C
+ 1, D
}, {{A
, D
}});
552 this->checkUnite({{MIN
, MID
}}, {MID
+ 1, MAX
}, {{MIN
, MAX
}});
554 // RHS adjacent to LHS on left.
556 // LHS => / \ ______ = _______________
557 // _/_______\/______\_ _/_______________\_
558 this->checkUnite({{B
+ 1, C
}}, B
, {{B
, C
}});
559 this->checkUnite({{B
, D
}}, {A
, B
- 1}, {{A
, D
}});
561 // RHS adjacent to LHS in between.
563 // LHS => ___ / \ ___ = _______________
564 // _/___\/_____\/___\_ _/_______________\_
565 this->checkUnite({{A
, MID
- 1}, {MID
+ 1, D
}}, MID
, {{A
, D
}});
566 this->checkUnite({{MIN
, A
}, {D
, MAX
}}, {A
+ 1, D
- 1}, {{MIN
, MAX
}});
568 // RHS adjacent to LHS on the outside.
570 // LHS => / \ ___ / \ = _______________
571 // _/____\/___\/____\_ _/_______________\_
572 this->checkUnite({{C
, C
}}, {{A
, C
- 1}, {C
+ 1, D
}}, {{A
, D
}});
573 this->checkUnite({{B
, MID
}}, {{A
, B
- 1}, {MID
+ 1, D
}}, {{A
, D
}});
575 // RHS wraps two subranges of LHS.
576 // RHS => ___________
577 // LHS => / ___ ___ \ = _____________
578 // __/_/___\_/___\_\__ __/_____________\__
579 this->checkUnite({{B
, B
}, {MID
, MID
}, {C
, C
}}, {{A
, D
}}, {{A
, D
}});
580 this->checkUnite({{A
, B
}, {MID
, C
}}, {{MIN
, D
}}, {{MIN
, D
}});
582 // RHS intersects two subranges of LHS.
584 // LHS => __/__ _\__ = _______________
585 // _/_/___\____/__\_\_ _/_______________\_
586 this->checkUnite({{MIN
, B
}, {C
, MAX
}}, {{A
, D
}}, {{MIN
, MAX
}});
587 this->checkUnite({{A
, MID
}, {C
, MAX
}}, {{B
, D
}}, {{A
, MAX
}});
589 // Multiple intersections.
593 // LHS => /\ /\ = __ __
594 // _/__\_/__\_/\_/\_/\_ _/__\_/__\_/\_/\_/\_
595 this->checkUnite({{MID
, C
}, {C
+ 2, D
- 2}, {D
, MAX
}},
596 {{MIN
, A
}, {A
+ 2, B
}},
597 {{MIN
, A
}, {A
+ 2, B
}, {MID
, C
}, {C
+ 2, D
- 2}, {D
, MAX
}});
598 this->checkUnite({{B
, B
}, {C
, C
}, {MAX
, MAX
}},
599 {{MIN
, MIN
}, {A
, A
}},
600 {{MIN
, MIN
}, {A
, A
}, {B
, B
}, {C
, C
}, {MAX
, MAX
}});
603 // LHS => /\ /\ = __ __
604 // _/\_/\_/\__/__\_/__\_ _/\_/\_/\_/__\_/__\_
605 this->checkUnite({{MIN
, A
}, {A
+ 2, B
}, {MID
, C
}},
606 {{C
+ 2, D
- 2}, {D
, MAX
}},
607 {{MIN
, A
}, {A
+ 2, B
}, {MID
, C
}, {C
+ 2, D
- 2}, {D
, MAX
}});
608 this->checkUnite({{MIN
, MIN
}, {A
, A
}, {B
, B
}},
609 {{C
, C
}, {MAX
, MAX
}},
610 {{MIN
, MIN
}, {A
, A
}, {B
, B
}, {C
, C
}, {MAX
, MAX
}});
613 // LHS => _ /\ _ /\ _ /\ =
614 // _/_\_/__\_/_\_/__\_/_\_/__\_
616 // RSLT => _ __ _ __ _ __
617 // _/_\_/__\_/_\_/__\_/_\_/__\_
618 this->checkUnite({{MIN
, A
}, {B
+ 2, MID
}, {C
+ 2, D
}},
619 {{A
+ 2, B
}, {MID
+ 2, C
}, {D
+ 2, MAX
}},
620 {{MIN
, A
}, {A
+ 2, B
}, {B
+ 2, MID
}, {MID
+ 2, C
}, {C
+ 2, D
}, {D
+ 2, MAX
}});
621 this->checkUnite({{MIN
, MIN
}, {B
, B
}, {D
, D
}},
622 {{A
, A
}, {C
, C
}, {MAX
, MAX
}},
623 {{MIN
, MIN
}, {A
, A
}, {B
, B
}, {C
, C
}, {D
, D
}, {MAX
, MAX
}});
626 // LHS => /\ _ /\ _ /\ _ =
627 // _/__\_/_\_/__\_/_\_/__\_/_\_
629 // RSLT => __ _ __ _ __ _
630 // _/__\_/_\_/__\_/_\_/__\_/_\_
631 this->checkUnite({{A
+ 2, B
}, {MID
+ 2, C
}, {D
+ 2, MAX
}},
632 {{MIN
, A
}, {B
+ 2, MID
}, {C
+ 2, D
}},
633 {{MIN
, A
}, {A
+ 2, B
}, {B
+ 2, MID
}, {MID
+ 2, C
}, {C
+ 2, D
}, {D
+ 2, MAX
}});
634 this->checkUnite({{A
, A
}, {C
, C
}, {MAX
, MAX
}},
635 {{MIN
, MIN
}, {B
, B
}, {D
, D
}},
636 {{MIN
, MIN
}, {A
, A
}, {B
, B
}, {C
, C
}, {D
, D
}, {MAX
, MAX
}});
639 // LHS => /_\ /_ \ _ / \ = ___ ____________
640 // _/___\_/__\_\/_\/___\_ _/___\_/____________\_
641 this->checkUnite({{MIN
, A
}, {B
, C
}, {D
, MAX
}},
642 {{MIN
, A
}, {B
, C
- 2}, {C
+ 1, D
- 1}},
643 {{MIN
, A
}, {B
, MAX
}});
644 this->checkUnite({{A
, A
}, {B
, MID
}, {D
, D
}},
645 {{A
, A
}, {B
, B
}, {MID
+ 1, D
- 1}},
649 // LHS => /\ _/_ \_ / _ \ /\ =
650 // _/\_/__\//__\ /\\_/_/_\_\_/__\_
652 // RSLT => ___________ _____ __
653 // _/\_/___________\_/_____\_/__\_
654 this->checkUnite({{MIN
, MIN
}, {B
, MID
}, {MID
+ 1, C
}, {C
+ 4, D
- 1}},
655 {{A
, B
- 1}, {B
+ 1, C
- 1}, {C
+ 2, D
}, {MAX
- 1, MAX
}},
656 {{MIN
, MIN
}, {A
, C
}, {C
+ 2, D
}, {MAX
- 1, MAX
}});
660 template <typename From
, typename To
> struct CastType
{
661 using FromType
= From
;
665 template <typename Type
>
666 class RangeSetCastToNoopTest
: public RangeSetTest
<typename
Type::FromType
> {};
667 template <typename Type
>
668 class RangeSetCastToPromotionTest
669 : public RangeSetTest
<typename
Type::FromType
> {};
670 template <typename Type
>
671 class RangeSetCastToTruncationTest
672 : public RangeSetTest
<typename
Type::FromType
> {};
673 template <typename Type
>
674 class RangeSetCastToConversionTest
675 : public RangeSetTest
<typename
Type::FromType
> {};
676 template <typename Type
>
677 class RangeSetCastToPromotionConversionTest
678 : public RangeSetTest
<typename
Type::FromType
> {};
679 template <typename Type
>
680 class RangeSetCastToTruncationConversionTest
681 : public RangeSetTest
<typename
Type::FromType
> {};
683 using NoopCastTypes
=
684 ::testing::Types
<CastType
<int8_t, int8_t>, CastType
<uint8_t, uint8_t>,
685 CastType
<int16_t, int16_t>, CastType
<uint16_t, uint16_t>,
686 CastType
<int32_t, int32_t>, CastType
<uint32_t, uint32_t>,
687 CastType
<int64_t, int64_t>, CastType
<uint64_t, uint64_t>>;
689 using PromotionCastTypes
=
690 ::testing::Types
<CastType
<int8_t, int16_t>, CastType
<int8_t, int32_t>,
691 CastType
<int8_t, int64_t>, CastType
<uint8_t, uint16_t>,
692 CastType
<uint8_t, uint32_t>, CastType
<uint8_t, uint64_t>,
693 CastType
<int16_t, int32_t>, CastType
<int16_t, int64_t>,
694 CastType
<uint16_t, uint32_t>, CastType
<uint16_t, uint64_t>,
695 CastType
<int32_t, int64_t>, CastType
<uint32_t, uint64_t>>;
697 using TruncationCastTypes
=
698 ::testing::Types
<CastType
<int16_t, int8_t>, CastType
<uint16_t, uint8_t>,
699 CastType
<int32_t, int16_t>, CastType
<int32_t, int8_t>,
700 CastType
<uint32_t, uint16_t>, CastType
<uint32_t, uint8_t>,
701 CastType
<int64_t, int32_t>, CastType
<int64_t, int16_t>,
702 CastType
<int64_t, int8_t>, CastType
<uint64_t, uint32_t>,
703 CastType
<uint64_t, uint16_t>, CastType
<uint64_t, uint8_t>>;
705 using ConversionCastTypes
=
706 ::testing::Types
<CastType
<int8_t, uint8_t>, CastType
<uint8_t, int8_t>,
707 CastType
<int16_t, uint16_t>, CastType
<uint16_t, int16_t>,
708 CastType
<int32_t, uint32_t>, CastType
<uint32_t, int32_t>,
709 CastType
<int64_t, uint64_t>, CastType
<uint64_t, int64_t>>;
711 using PromotionConversionCastTypes
=
712 ::testing::Types
<CastType
<int8_t, uint16_t>, CastType
<int8_t, uint32_t>,
713 CastType
<int8_t, uint64_t>, CastType
<uint8_t, int16_t>,
714 CastType
<uint8_t, int32_t>, CastType
<uint8_t, int64_t>,
715 CastType
<int16_t, uint32_t>, CastType
<int16_t, uint64_t>,
716 CastType
<uint16_t, int32_t>, CastType
<uint16_t, int64_t>,
717 CastType
<int32_t, uint64_t>, CastType
<uint32_t, int64_t>>;
719 using TruncationConversionCastTypes
=
720 ::testing::Types
<CastType
<int16_t, uint8_t>, CastType
<uint16_t, int8_t>,
721 CastType
<int32_t, uint16_t>, CastType
<int32_t, uint8_t>,
722 CastType
<uint32_t, int16_t>, CastType
<uint32_t, int8_t>,
723 CastType
<int64_t, uint32_t>, CastType
<int64_t, uint16_t>,
724 CastType
<int64_t, uint8_t>, CastType
<uint64_t, int32_t>,
725 CastType
<uint64_t, int16_t>, CastType
<uint64_t, int8_t>>;
727 TYPED_TEST_SUITE(RangeSetCastToNoopTest
, NoopCastTypes
, );
728 TYPED_TEST_SUITE(RangeSetCastToPromotionTest
, PromotionCastTypes
, );
729 TYPED_TEST_SUITE(RangeSetCastToTruncationTest
, TruncationCastTypes
, );
730 TYPED_TEST_SUITE(RangeSetCastToConversionTest
, ConversionCastTypes
, );
731 TYPED_TEST_SUITE(RangeSetCastToPromotionConversionTest
,
732 PromotionConversionCastTypes
, );
733 TYPED_TEST_SUITE(RangeSetCastToTruncationConversionTest
,
734 TruncationConversionCastTypes
, );
736 TYPED_TEST(RangeSetCastToNoopTest
, RangeSetCastToNoopTest
) {
737 // Just to reduce the verbosity.
738 using F
= typename
TypeParam::FromType
; // From
739 using T
= typename
TypeParam::ToType
; // To
741 using TV
= TestValues
<F
>;
742 constexpr auto MIN
= TV::MIN
;
743 constexpr auto MAX
= TV::MAX
;
744 constexpr auto MID
= TV::MID
;
745 constexpr auto B
= TV::B
;
746 constexpr auto C
= TV::C
;
748 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
749 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
750 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
751 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
752 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
754 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}},
755 {{MIN
, MIN
}, {MAX
, MAX
}});
756 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
757 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
758 {{MID
, MID
}, {MAX
, MAX
}});
759 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
760 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
761 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
762 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
764 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{MIN
, MAX
}});
765 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{MIN
, MID
}});
766 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{MID
, MAX
}});
767 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{B
, MAX
}});
768 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{C
, MAX
}});
769 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{MIN
, C
}});
770 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{MIN
, B
}});
771 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{B
, C
}});
773 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}}, {{MIN
, B
}, {C
, MAX
}});
774 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}}, {{B
, MID
}, {C
, MAX
}});
775 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{MIN
, B
}, {MID
, C
}});
778 TYPED_TEST(RangeSetCastToPromotionTest
, Test
) {
779 // Just to reduce the verbosity.
780 using F
= typename
TypeParam::FromType
; // From
781 using T
= typename
TypeParam::ToType
; // To
783 using TV
= TestValues
<F
>;
784 constexpr auto MIN
= TV::MIN
;
785 constexpr auto MAX
= TV::MAX
;
786 constexpr auto MID
= TV::MID
;
787 constexpr auto B
= TV::B
;
788 constexpr auto C
= TV::C
;
790 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
791 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
792 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
793 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
794 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
796 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}},
797 {{MIN
, MIN
}, {MAX
, MAX
}});
798 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
799 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
800 {{MID
, MID
}, {MAX
, MAX
}});
801 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
802 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
803 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
804 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
806 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{MIN
, MAX
}});
807 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{MIN
, MID
}});
808 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{MID
, MAX
}});
809 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{B
, MAX
}});
810 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{C
, MAX
}});
811 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{MIN
, C
}});
812 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{MIN
, B
}});
813 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{B
, C
}});
815 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}}, {{MIN
, B
}, {C
, MAX
}});
816 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}}, {{B
, MID
}, {C
, MAX
}});
817 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{MIN
, B
}, {MID
, C
}});
820 TYPED_TEST(RangeSetCastToTruncationTest
, Test
) {
821 // Just to reduce the verbosity.
822 using F
= typename
TypeParam::FromType
; // From
823 using T
= typename
TypeParam::ToType
; // To
825 using TV
= TestValues
<F
>;
826 constexpr auto MIN
= TV::MIN
;
827 constexpr auto MAX
= TV::MAX
;
828 constexpr auto MID
= TV::MID
;
829 constexpr auto B
= TV::B
;
830 constexpr auto C
= TV::C
;
833 // NOTE: We can't use ToMIN, ToMAX, ... everywhere. That would be incorrect:
834 // int16(-32768, 32767) -> int8(-128, 127),
835 // aka (MIN, MAX) -> (ToMIN, ToMAX) // OK.
836 // int16(-32768, -32768) -> int8(-128, -128),
837 // aka (MIN, MIN) -> (ToMIN, ToMIN) // NOK.
838 // int16(-32768,-32768) -> int8(0, 0),
839 // aka (MIN, MIN) -> ((int8)MIN, (int8)MIN) // OK.
840 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
841 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
842 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
843 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
844 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
846 // Use `if constexpr` here.
847 if (is_signed_v
<F
>) {
848 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}}, {{MAX
, MIN
}});
849 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}}, {{MAX
, MID
}});
851 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}},
852 {{MIN
, MIN
}, {MAX
, MAX
}});
853 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
854 {{MID
, MID
}, {MAX
, MAX
}});
856 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
857 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
858 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
859 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
860 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
862 constexpr auto ToMIN
= TestValues
<T
>::MIN
;
863 constexpr auto ToMAX
= TestValues
<T
>::MAX
;
864 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{ToMIN
, ToMAX
}});
865 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{ToMIN
, ToMAX
}});
866 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{ToMIN
, ToMAX
}});
867 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{ToMIN
, ToMAX
}});
868 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{ToMIN
, ToMAX
}});
869 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{ToMIN
, ToMAX
}});
870 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{ToMIN
, ToMAX
}});
871 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{ToMIN
, ToMAX
}});
873 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}}, {{ToMIN
, ToMAX
}});
874 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}}, {{ToMIN
, ToMAX
}});
875 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{ToMIN
, ToMAX
}});
876 constexpr auto XAAA
= TV::XAAA
;
877 constexpr auto X555
= TV::X555
;
878 constexpr auto ZA
= TV::template XAAATruncZeroOf
<T
>;
879 constexpr auto Z5
= TV::template X555TruncZeroOf
<T
>;
880 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}, {X555
, Z5
}},
881 {{ToMIN
, 0}, {X555
, ToMAX
}});
882 // Use `if constexpr` here.
883 if (is_signed_v
<F
>) {
885 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}}, {{XAAA
, 0}});
887 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}, {1, 42}}, {{XAAA
, 42}});
890 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}}, {{0, 0}, {XAAA
, ToMAX
}});
892 this->template checkCastTo
<F
, T
>({{1, 42}, {XAAA
, ZA
}},
893 {{0, 42}, {XAAA
, ToMAX
}});
895 constexpr auto FromA
= TV::FromA
;
896 constexpr auto ToA
= TV::ToA
;
897 constexpr auto FromB
= TV::FromB
;
898 constexpr auto ToB
= TV::ToB
;
900 // (0x00'01, 0x00'05)U(0xFF'01, 0xFF'05) casts to
901 // (0x01, 0x05)U(0x01, 0x05) unites to
903 this->template checkCastTo
<F
, T
>({{FromA
, ToA
}, {FromB
, ToB
}},
907 TYPED_TEST(RangeSetCastToConversionTest
, Test
) {
908 // Just to reduce the verbosity.
909 using F
= typename
TypeParam::FromType
; // From
910 using T
= typename
TypeParam::ToType
; // To
912 using TV
= TestValues
<F
>;
913 constexpr auto MIN
= TV::MIN
;
914 constexpr auto MAX
= TV::MAX
;
915 constexpr auto MID
= TV::MID
;
916 constexpr auto B
= TV::B
;
917 constexpr auto C
= TV::C
;
919 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
920 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
921 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
922 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
923 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
925 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}}, {{MAX
, MIN
}});
926 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
927 {{MID
, MID
}, {MAX
, MAX
}});
928 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
929 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
930 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
931 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
932 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
934 constexpr auto ToMIN
= TestValues
<T
>::MIN
;
935 constexpr auto ToMAX
= TestValues
<T
>::MAX
;
936 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{ToMIN
, ToMAX
}});
937 this->template checkCastTo
<F
, T
>({{MIN
, MID
}},
938 {{ToMIN
, ToMIN
}, {MIN
, ToMAX
}});
939 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{MID
, MAX
}});
940 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{ToMIN
, MAX
}, {B
, ToMAX
}});
941 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{C
, MAX
}});
942 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{ToMIN
, C
}, {MIN
, ToMAX
}});
943 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{MIN
, B
}});
944 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{ToMIN
, C
}, {B
, ToMAX
}});
946 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}}, {{C
, B
}});
947 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}},
948 {{MID
, MID
}, {C
, MAX
}, {B
, ToMAX
}});
949 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{MID
, C
}, {MIN
, B
}});
952 TYPED_TEST(RangeSetCastToPromotionConversionTest
, Test
) {
953 // Just to reduce the verbosity.
954 using F
= typename
TypeParam::FromType
; // From
955 using T
= typename
TypeParam::ToType
; // To
957 using TV
= TestValues
<F
>;
958 constexpr auto MIN
= TV::MIN
;
959 constexpr auto MAX
= TV::MAX
;
960 constexpr auto MID
= TV::MID
;
961 constexpr auto B
= TV::B
;
962 constexpr auto C
= TV::C
;
964 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
965 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
966 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
967 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
968 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
970 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}},
971 {{MAX
, MAX
}, {MIN
, MIN
}});
972 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
973 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
974 {{MID
, MID
}, {MAX
, MAX
}});
975 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
976 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
977 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
978 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
980 // Use `if constexpr` here.
981 if (is_signed_v
<F
>) {
983 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{0, MAX
}, {MIN
, -1}});
984 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{0, 0}, {MIN
, -1}});
985 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{0, MAX
}});
986 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{0, MAX
}, {B
, -1}});
987 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{C
, MAX
}});
988 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{0, C
}, {MIN
, -1}});
989 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{MIN
, B
}});
990 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{0, C
}, {B
, -1}});
992 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}},
993 {{C
, MAX
}, {MIN
, B
}});
994 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}},
995 {{0, 0}, {C
, MAX
}, {B
, -1}});
996 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{0, C
}, {MIN
, B
}});
999 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{MIN
, MAX
}});
1000 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{MIN
, MID
}});
1001 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{MID
, MAX
}});
1002 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{B
, MAX
}});
1003 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{C
, MAX
}});
1004 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{MIN
, C
}});
1005 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{MIN
, B
}});
1006 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{B
, C
}});
1008 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}},
1009 {{MIN
, B
}, {C
, MAX
}});
1010 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}},
1011 {{B
, MID
}, {C
, MAX
}});
1012 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}},
1013 {{MIN
, B
}, {MID
, C
}});
1017 TYPED_TEST(RangeSetCastToTruncationConversionTest
, Test
) {
1018 // Just to reduce the verbosity.
1019 using F
= typename
TypeParam::FromType
; // From
1020 using T
= typename
TypeParam::ToType
; // To
1022 using TV
= TestValues
<F
>;
1023 constexpr auto MIN
= TV::MIN
;
1024 constexpr auto MAX
= TV::MAX
;
1025 constexpr auto MID
= TV::MID
;
1026 constexpr auto B
= TV::B
;
1027 constexpr auto C
= TV::C
;
1029 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}}, {{MIN
, MIN
}});
1030 this->template checkCastTo
<F
, T
>({{MAX
, MAX
}}, {{MAX
, MAX
}});
1031 this->template checkCastTo
<F
, T
>({{MID
, MID
}}, {{MID
, MID
}});
1032 this->template checkCastTo
<F
, T
>({{B
, B
}}, {{B
, B
}});
1033 this->template checkCastTo
<F
, T
>({{C
, C
}}, {{C
, C
}});
1035 // Use `if constexpr` here.
1036 if (is_signed_v
<F
>) {
1037 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}},
1038 {{MIN
, MIN
}, {MAX
, MAX
}});
1039 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}},
1040 {{MID
, MID
}, {MAX
, MAX
}});
1042 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {MAX
, MAX
}}, {{MAX
, MIN
}});
1043 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {MAX
, MAX
}}, {{MAX
, MIN
}});
1045 this->template checkCastTo
<F
, T
>({{MIN
, MIN
}, {B
, B
}}, {{MIN
, MIN
}, {B
, B
}});
1046 this->template checkCastTo
<F
, T
>({{C
, C
}, {MAX
, MAX
}}, {{C
, C
}, {MAX
, MAX
}});
1047 this->template checkCastTo
<F
, T
>({{MID
, MID
}, {C
, C
}}, {{MID
, MID
}, {C
, C
}});
1048 this->template checkCastTo
<F
, T
>({{B
, B
}, {MID
, MID
}}, {{B
, B
}, {MID
, MID
}});
1049 this->template checkCastTo
<F
, T
>({{B
, B
}, {C
, C
}}, {{B
, B
}, {C
, C
}});
1051 constexpr auto ToMIN
= TestValues
<T
>::MIN
;
1052 constexpr auto ToMAX
= TestValues
<T
>::MAX
;
1053 this->template checkCastTo
<F
, T
>({{MIN
, MAX
}}, {{ToMIN
, ToMAX
}});
1054 this->template checkCastTo
<F
, T
>({{MIN
, MID
}}, {{ToMIN
, ToMAX
}});
1055 this->template checkCastTo
<F
, T
>({{MID
, MAX
}}, {{ToMIN
, ToMAX
}});
1056 this->template checkCastTo
<F
, T
>({{B
, MAX
}}, {{ToMIN
, ToMAX
}});
1057 this->template checkCastTo
<F
, T
>({{C
, MAX
}}, {{ToMIN
, ToMAX
}});
1058 this->template checkCastTo
<F
, T
>({{MIN
, C
}}, {{ToMIN
, ToMAX
}});
1059 this->template checkCastTo
<F
, T
>({{MIN
, B
}}, {{ToMIN
, ToMAX
}});
1060 this->template checkCastTo
<F
, T
>({{B
, C
}}, {{ToMIN
, ToMAX
}});
1062 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {C
, MAX
}}, {{ToMIN
, ToMAX
}});
1063 this->template checkCastTo
<F
, T
>({{B
, MID
}, {C
, MAX
}}, {{ToMIN
, ToMAX
}});
1064 this->template checkCastTo
<F
, T
>({{MIN
, B
}, {MID
, C
}}, {{ToMIN
, ToMAX
}});
1065 constexpr auto XAAA
= TV::XAAA
;
1066 constexpr auto X555
= TV::X555
;
1067 constexpr auto ZA
= TV::template XAAATruncZeroOf
<T
>;
1068 constexpr auto Z5
= TV::template X555TruncZeroOf
<T
>;
1069 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}, {X555
, Z5
}},
1070 {{ToMIN
, 0}, {X555
, ToMAX
}});
1071 // Use `if constexpr` here.
1072 if (is_signed_v
<F
>) {
1074 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}}, {{0, 0}, {XAAA
, ToMAX
}});
1076 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}, {1, 42}},
1077 {{0, 42}, {XAAA
, ToMAX
}});
1080 this->template checkCastTo
<F
, T
>({{XAAA
, ZA
}}, {{XAAA
, 0}});
1082 this->template checkCastTo
<F
, T
>({{1, 42}, {XAAA
, ZA
}}, {{XAAA
, 42}});
1084 constexpr auto FromA
= TV::FromA
;
1085 constexpr auto ToA
= TV::ToA
;
1086 constexpr auto FromB
= TV::FromB
;
1087 constexpr auto ToB
= TV::ToB
;
1088 this->template checkCastTo
<F
, T
>({{FromA
, ToA
}, {FromB
, ToB
}},