1093 lines · cpp
1//===- unittests/StaticAnalyzer/RangeSetTest.cpp ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 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"17 18using namespace clang;19using namespace ento;20 21namespace clang {22namespace ento {23 24template <class RangeOrSet> static std::string toString(const RangeOrSet &Obj) {25 std::string ObjRepresentation;26 llvm::raw_string_ostream SS(ObjRepresentation);27 Obj.dump(SS);28 return ObjRepresentation;29}30[[maybe_unused]] static std::string toString(const llvm::APSInt &Point) {31 return toString(Point, 10);32}33// We need it here for better fail diagnostics from gtest.34[[maybe_unused]] static std::ostream &operator<<(std::ostream &OS,35 const RangeSet &Set) {36 return OS << toString(Set);37}38// We need it here for better fail diagnostics from gtest.39[[maybe_unused]] static std::ostream &operator<<(std::ostream &OS,40 const Range &R) {41 return OS << toString(R);42}43[[maybe_unused]] static std::ostream &operator<<(std::ostream &OS,44 APSIntType Ty) {45 return OS << (Ty.isUnsigned() ? "u" : "s") << Ty.getBitWidth();46}47 48} // namespace ento49} // namespace clang50 51namespace {52 53template <class T> constexpr bool is_signed_v = std::is_signed<T>::value;54 55template <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 range59 // 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;67 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);75 76 template <T Value, typename Base>77 static constexpr T TruncZeroOf = ClearLowBytes<Value + 1, sizeof(Base)>;78 79 // Random number with active bits in every byte. 0xAAAA'AAAA80 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'AB0084 85 // Random number with active bits in every byte. 0x5555'555586 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'560090 91// Silence 'warning C4309: 'initializing': truncation of constant value'92// in RangeSetCastToPromotionConversionTest.93#if defined(_MSC_VER) && !defined(__clang__)94#pragma warning(push)95#pragma warning(disable : 4309)96#endif97 // Numbers for ranges with the same bits in the lowest byte.98 // 0xAAAA'AA2A99 static constexpr T FromA = ClearLowBytes<XAAA, sizeof(T) - 1> + 42;100 static constexpr T ToA = FromA + 2; // 0xAAAA'AA2C101 // 0x5555'552A102 static constexpr T FromB = ClearLowBytes<X555, sizeof(T) - 1> + 42;103 static constexpr T ToB = FromB + 2; // 0x5555'552C104 105#if defined(_MSC_VER) && !defined(__clang__)106#pragma warning(pop)107#endif108};109 110template <typename T>111static constexpr APSIntType APSIntTy =112 APSIntType(sizeof(T) * CHAR_BIT, !is_signed_v<T>);113 114template <typename BaseType> class RangeSetTest : public testing::Test {115public:116 // Init block117 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};122 // End init block123 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>;130 131 template <typename T> const llvm::APSInt &from(T X) {132 static llvm::APSInt Int = APSIntTy<T>.getZeroValue();133 Int = X;134 return BVF.getValue(Int);135 }136 137 template <typename T> Range from(const RawRangeT<T> &Init) {138 return Range(from(Init.first), from(Init.second));139 }140 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));146 }147 return RangeSet;148 }149 150 template <class F, class... RawArgTypes>151 void wrap(F ActualFunction, RawArgTypes &&... Args) {152 (this->*ActualFunction)(from(std::forward<RawArgTypes>(Args))...);153 }154 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);161 }162 163 void checkNegate(RawRangeSet RawOriginal, RawRangeSet RawExpected) {164 wrap(&Self::checkNegateImpl, RawOriginal, RawExpected);165 }166 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);172 }173 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) << "]";180 }181 182 void checkIntersect(RawRangeSet RawLHS, RawRangeSet RawRHS,183 RawRangeSet RawExpected) {184 wrap(&Self::checkIntersectImpl<RangeSet>, RawLHS, RawRHS, RawExpected);185 }186 187 void checkIntersect(RawRangeSet RawLHS, BaseType RawRHS,188 RawRangeSet RawExpected) {189 wrap(&Self::checkIntersectImpl<const llvm::APSInt &>, RawLHS, RawRHS,190 RawExpected);191 }192 193 void checkIntersect(RawRangeSet RawLHS, BaseType RawLower, BaseType RawUpper,194 RawRangeSet RawExpected) {195 wrap(&Self::checkIntersectRangeImpl, RawLHS, RawLower, RawUpper,196 RawExpected);197 }198 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 ")203 << toString(RHS);204 }205 206 void checkContains(RawRangeSet RawLHS, BaseType RawRHS, bool Expected) {207 checkContainsImpl(from(RawLHS), from(RawRHS), Expected);208 }209 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);215 }216 217 void checkAdd(RawRangeSet RawLHS, RawRange RawRHS, RawRangeSet RawExpected) {218 wrap(&Self::checkAddImpl<Range>, RawLHS, RawRHS, RawExpected);219 }220 221 void checkAdd(RawRangeSet RawLHS, RawRangeSet RawRHS,222 RawRangeSet RawExpected) {223 wrap(&Self::checkAddImpl<RangeSet>, RawLHS, RawRHS, RawExpected);224 }225 226 void checkAdd(RawRangeSet RawLHS, BaseType RawRHS, RawRangeSet RawExpected) {227 wrap(&Self::checkAddImpl<const llvm::APSInt &>, RawLHS, RawRHS,228 RawExpected);229 }230 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);236 }237 238 void checkUnite(RawRangeSet RawLHS, RawRange RawRHS,239 RawRangeSet RawExpected) {240 wrap(&Self::checkUniteImpl<Range>, RawLHS, RawRHS, RawExpected);241 }242 243 void checkUnite(RawRangeSet RawLHS, RawRangeSet RawRHS,244 RawRangeSet RawExpected) {245 wrap(&Self::checkUniteImpl<RangeSet>, RawLHS, RawRHS, RawExpected);246 }247 248 void checkUnite(RawRangeSet RawLHS, BaseType RawRHS,249 RawRangeSet RawExpected) {250 wrap(&Self::checkUniteImpl<const llvm::APSInt &>, RawLHS, RawRHS,251 RawExpected);252 }253 254 void checkDeleteImpl(const llvm::APSInt &Point, RangeSet From,255 RangeSet Expected) {256 RangeSet Result = F.deletePoint(From, Point);257 EXPECT_EQ(Result, Expected)258 << "while deleting " << toString(Point) << " from " << toString(From);259 }260 261 void checkDelete(BaseType Point, RawRangeSet RawFrom,262 RawRangeSet RawExpected) {263 wrap(&Self::checkDeleteImpl, Point, RawFrom, RawExpected);264 }265 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;270 }271 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));277 }278};279 280using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t,281 uint32_t, int64_t, uint64_t>;282TYPED_TEST_SUITE(RangeSetTest, IntTypes, );283 284TYPED_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;293 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}});308}309 310TYPED_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}});318}319 320TYPED_TEST(RangeSetTest, RangeSetRangeIntersectTest) {321 using TV = TestValues<TypeParam>;322 constexpr auto MIN = TV::MIN;323 constexpr auto MAX = TV::MAX;324 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}});339}340 341TYPED_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}}, {}, {});346 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 as352 // expected.353 this->checkIntersect({{0, 10}}, {{10, 10}}, {{10, 10}});354 355 // Let's check that we can skip some intervals and partially intersect356 // other intervals.357 this->checkIntersect({{0, 2}, {4, 5}, {6, 9}, {10, 11}, {12, 12}, {13, 15}},358 {{8, 14}, {20, 30}},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}});365}366 367TYPED_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 less372 this->checkContains({{0, 5}}, 10, false);373 // * when the whole range is greater374 this->checkContains({{20, 25}}, 10, false);375 // * when the range is just the point we are looking for376 this->checkContains({{10, 10}}, 10, true);377 // * when the range starts with the point378 this->checkContains({{10, 15}}, 10, true);379 // * when the range ends with the point380 this->checkContains({{5, 10}}, 10, true);381 // * when the range has the point somewhere in the middle382 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);387 388 using TV = TestValues<TypeParam>;389 constexpr auto MIN = TV::MIN;390 constexpr auto MAX = TV::MAX;391 constexpr auto MID = TV::MID;392 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);397}398 399TYPED_TEST(RangeSetTest, RangeSetAddTest) {400 // Check adding single points401 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}});404 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}});409 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}});418}419 420TYPED_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;425 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}});437}438 439TYPED_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;448 449 // LHS and RHS is empty.450 // RHS =>451 // LHS => =452 // ___________________ ___________________453 this->checkUnite({}, {}, {});454 455 // RHS is empty.456 // RHS =>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}});464 465 // LHS is empty.466 // RHS => ___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}});475 476 // RHS is detached from LHS.477 // RHS => ___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}});491 492 // RHS is inside LHS.493 // RHS => ___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}});499 500 // RHS wraps LHS.501 // RHS => _________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}});507 508 // RHS equals to LHS.509 // RHS => _________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}});518 519 // RHS edge is MIN and attached and inside LHS.520 // RHS => _____521 // LHS => /_____\_____ = ___________522 // /_______\____\___ /___________\___523 this->checkUnite({{MIN, A}}, {MIN, B}, {{MIN, B}});524 525 // RHS edge is MIN and attached and outsude LHS.526 // RHS => __________527 // LHS => /______ \ = ___________528 // /_______\____\___ /___________\___529 this->checkUnite({{MIN, B}}, {MIN, A}, {{MIN, B}});530 531 // RHS intersects right of LHS.532 // RHS => ______533 // LHS => ___/____ \ = ___________534 // ___/__/_____\__\___ ___/___________\___535 this->checkUnite({{A, C}}, C, {{A, C}});536 this->checkUnite({{A, C}}, {B, D}, {{A, D}});537 538 // RHS intersects left of LHS.539 // RHS => ______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}});545 546 // RHS adjacent to LHS on right.547 // RHS => _____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}});553 554 // RHS adjacent to LHS on left.555 // RHS => _____556 // LHS => / \ ______ = _______________557 // _/_______\/______\_ _/_______________\_558 this->checkUnite({{B + 1, C}}, B, {{B, C}});559 this->checkUnite({{B, D}}, {A, B - 1}, {{A, D}});560 561 // RHS adjacent to LHS in between.562 // RHS => ___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}});567 568 // RHS adjacent to LHS on the outside.569 // RHS => __ __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}});574 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}});581 582 // RHS intersects two subranges of LHS.583 // RHS => _________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}});588 589 // Multiple intersections.590 591 // clang-format off592 // RHS =>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}});601 602 // RHS =>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}});611 612 // RHS =>613 // LHS => _ /\ _ /\ _ /\ =614 // _/_\_/__\_/_\_/__\_/_\_/__\_615 //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}});624 625 // RHS =>626 // LHS => /\ _ /\ _ /\ _ =627 // _/__\_/_\_/__\_/_\_/__\_/_\_628 //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}});637 638 // RHS => _ __ _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}},646 {{A, A}, {B, D}});647 648 // RHS => ___ ___649 // LHS => /\ _/_ \_ / _ \ /\ =650 // _/\_/__\//__\ /\\_/_/_\_\_/__\_651 //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}});657 // clang-format on658}659 660template <typename From, typename To> struct CastType {661 using FromType = From;662 using ToType = To;663};664 665template <typename Type>666class RangeSetCastToNoopTest : public RangeSetTest<typename Type::FromType> {};667template <typename Type>668class RangeSetCastToPromotionTest669 : public RangeSetTest<typename Type::FromType> {};670template <typename Type>671class RangeSetCastToTruncationTest672 : public RangeSetTest<typename Type::FromType> {};673template <typename Type>674class RangeSetCastToConversionTest675 : public RangeSetTest<typename Type::FromType> {};676template <typename Type>677class RangeSetCastToPromotionConversionTest678 : public RangeSetTest<typename Type::FromType> {};679template <typename Type>680class RangeSetCastToTruncationConversionTest681 : public RangeSetTest<typename Type::FromType> {};682 683using 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>>;688 689using 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>>;696 697using 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>>;704 705using 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>>;710 711using 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>>;718 719using 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>>;726 727TYPED_TEST_SUITE(RangeSetCastToNoopTest, NoopCastTypes, );728TYPED_TEST_SUITE(RangeSetCastToPromotionTest, PromotionCastTypes, );729TYPED_TEST_SUITE(RangeSetCastToTruncationTest, TruncationCastTypes, );730TYPED_TEST_SUITE(RangeSetCastToConversionTest, ConversionCastTypes, );731TYPED_TEST_SUITE(RangeSetCastToPromotionConversionTest,732 PromotionConversionCastTypes, );733TYPED_TEST_SUITE(RangeSetCastToTruncationConversionTest,734 TruncationConversionCastTypes, );735 736TYPED_TEST(RangeSetCastToNoopTest, RangeSetCastToNoopTest) {737 // Just to reduce the verbosity.738 using F = typename TypeParam::FromType; // From739 using T = typename TypeParam::ToType; // To740 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;747 // One point748 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}});753 // Two points754 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}});763 // One range764 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}});772 // Two ranges773 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}});776}777 778TYPED_TEST(RangeSetCastToPromotionTest, Test) {779 // Just to reduce the verbosity.780 using F = typename TypeParam::FromType; // From781 using T = typename TypeParam::ToType; // To782 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;789 // One point790 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}});795 // Two points796 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}});805 // One range806 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}});814 // Two ranges815 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}});818}819 820TYPED_TEST(RangeSetCastToTruncationTest, Test) {821 // Just to reduce the verbosity.822 using F = typename TypeParam::FromType; // From823 using T = typename TypeParam::ToType; // To824 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;831 // One point832 //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}});845 // Two points846 // 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}});850 } else {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}});855 }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}});861 // One range862 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}});872 // Two ranges873 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>) {884 // One range885 this->template checkCastTo<F, T>({{XAAA, ZA}}, {{XAAA, 0}});886 // Two ranges887 this->template checkCastTo<F, T>({{XAAA, ZA}, {1, 42}}, {{XAAA, 42}});888 } else {889 // One range890 this->template checkCastTo<F, T>({{XAAA, ZA}}, {{0, 0}, {XAAA, ToMAX}});891 // Two ranges892 this->template checkCastTo<F, T>({{1, 42}, {XAAA, ZA}},893 {{0, 42}, {XAAA, ToMAX}});894 }895 constexpr auto FromA = TV::FromA;896 constexpr auto ToA = TV::ToA;897 constexpr auto FromB = TV::FromB;898 constexpr auto ToB = TV::ToB;899 // int16 -> int8900 // (0x00'01, 0x00'05)U(0xFF'01, 0xFF'05) casts to901 // (0x01, 0x05)U(0x01, 0x05) unites to902 // (0x01, 0x05)903 this->template checkCastTo<F, T>({{FromA, ToA}, {FromB, ToB}},904 {{FromA, ToA}});905}906 907TYPED_TEST(RangeSetCastToConversionTest, Test) {908 // Just to reduce the verbosity.909 using F = typename TypeParam::FromType; // From910 using T = typename TypeParam::ToType; // To911 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;918 // One point919 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}});924 // Two points925 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}});933 // One range934 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}});945 // Two ranges946 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}});950}951 952TYPED_TEST(RangeSetCastToPromotionConversionTest, Test) {953 // Just to reduce the verbosity.954 using F = typename TypeParam::FromType; // From955 using T = typename TypeParam::ToType; // To956 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;963 // One point964 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}});969 // Two points970 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}});979 980 // Use `if constexpr` here.981 if (is_signed_v<F>) {982 // One range983 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}});991 // Two ranges992 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}});997 } else {998 // One range999 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}});1007 // Two ranges1008 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}});1014 }1015}1016 1017TYPED_TEST(RangeSetCastToTruncationConversionTest, Test) {1018 // Just to reduce the verbosity.1019 using F = typename TypeParam::FromType; // From1020 using T = typename TypeParam::ToType; // To1021 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;1028 // One point1029 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}});1034 // Two points1035 // 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}});1041 } else {1042 this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, {{MAX, MIN}});1043 this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, {{MAX, MIN}});1044 }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}});1050 // One range1051 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}});1061 // Two ranges1062 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>) {1073 // One range1074 this->template checkCastTo<F, T>({{XAAA, ZA}}, {{0, 0}, {XAAA, ToMAX}});1075 // Two ranges1076 this->template checkCastTo<F, T>({{XAAA, ZA}, {1, 42}},1077 {{0, 42}, {XAAA, ToMAX}});1078 } else {1079 // One range1080 this->template checkCastTo<F, T>({{XAAA, ZA}}, {{XAAA, 0}});1081 // Two ranges1082 this->template checkCastTo<F, T>({{1, 42}, {XAAA, ZA}}, {{XAAA, 42}});1083 }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}},1089 {{FromA, ToA}});1090}1091 1092} // namespace1093