brintos

brintos / llvm-project-archived public Read only

0
0
Text · 46.4 KiB · a8c7626 Raw
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