brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 0a92717 Raw
186 lines · cpp
1//===- TypeSwitchTest.cpp - TypeSwitch unit tests -------------------------===//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 "llvm/ADT/TypeSwitch.h"10#include "gtest/gtest.h"11 12using namespace llvm;13 14namespace {15/// Utility classes to setup casting functionality.16struct Base {17  enum Kind { DerivedA, DerivedB, DerivedC, DerivedD, DerivedE };18  Kind kind;19};20template <Base::Kind DerivedKind> struct DerivedImpl : Base {21  DerivedImpl() : Base{DerivedKind} {}22  static bool classof(const Base *base) { return base->kind == DerivedKind; }23};24struct DerivedA : public DerivedImpl<Base::DerivedA> {};25struct DerivedB : public DerivedImpl<Base::DerivedB> {};26struct DerivedC : public DerivedImpl<Base::DerivedC> {};27struct DerivedD : public DerivedImpl<Base::DerivedD> {};28struct DerivedE : public DerivedImpl<Base::DerivedE> {};29} // end anonymous namespace30 31TEST(TypeSwitchTest, CaseResult) {32  auto translate = [](auto value) {33    return TypeSwitch<Base *, int>(&value)34        .Case<DerivedA>([](DerivedA *) { return 0; })35        .Case([](DerivedB *) { return 1; })36        .Case([](DerivedC *) { return 2; })37        .Default([](Base *) { return -1; });38  };39  EXPECT_EQ(0, translate(DerivedA()));40  EXPECT_EQ(1, translate(DerivedB()));41  EXPECT_EQ(2, translate(DerivedC()));42  EXPECT_EQ(-1, translate(DerivedD()));43}44 45TEST(TypeSwitchTest, CasesResult) {46  auto translate = [](auto value) {47    return TypeSwitch<Base *, int>(&value)48        .Case<DerivedA, DerivedB, DerivedD>([](auto *) { return 0; })49        .Case([](DerivedC *) { return 1; })50        .Default(-1);51  };52  EXPECT_EQ(0, translate(DerivedA()));53  EXPECT_EQ(0, translate(DerivedB()));54  EXPECT_EQ(1, translate(DerivedC()));55  EXPECT_EQ(0, translate(DerivedD()));56  EXPECT_EQ(-1, translate(DerivedE()));57}58 59TEST(TypeSwitchTest, CaseVoid) {60  auto translate = [](auto value) {61    int result = -2;62    TypeSwitch<Base *>(&value)63        .Case([&](DerivedA *) { result = 0; })64        .Case([&](DerivedB *) { result = 1; })65        .Case([&](DerivedC *) { result = 2; })66        .Default([&](Base *) { result = -1; });67    return result;68  };69  EXPECT_EQ(0, translate(DerivedA()));70  EXPECT_EQ(1, translate(DerivedB()));71  EXPECT_EQ(2, translate(DerivedC()));72  EXPECT_EQ(-1, translate(DerivedD()));73}74 75TEST(TypeSwitchTest, CasesVoid) {76  auto translate = [](auto value) {77    int result = -1;78    TypeSwitch<Base *>(&value)79        .Case<DerivedA, DerivedB, DerivedD>([&](auto *) { result = 0; })80        .Case([&](DerivedC *) { result = 1; });81    return result;82  };83  EXPECT_EQ(0, translate(DerivedA()));84  EXPECT_EQ(0, translate(DerivedB()));85  EXPECT_EQ(1, translate(DerivedC()));86  EXPECT_EQ(0, translate(DerivedD()));87  EXPECT_EQ(-1, translate(DerivedE()));88}89 90TEST(TypeSwitchTest, CaseOptional) {91  auto translate = [](auto value) {92    return TypeSwitch<Base *, std::optional<int>>(&value)93        .Case([](DerivedA *) { return 0; })94        .Case([](DerivedC *) { return std::nullopt; })95        .Default([](Base *) { return -1; });96  };97  EXPECT_EQ(0, translate(DerivedA()));98  EXPECT_EQ(std::nullopt, translate(DerivedC()));99  EXPECT_EQ(-1, translate(DerivedD()));100  EXPECT_EQ(std::nullopt,101            (TypeSwitch<Base *, std::optional<int>>(nullptr).Default(102                [](Base *) { return std::nullopt; })));103}104 105TEST(TypeSwitchTest, CasesOptional) {106  auto translate = [](auto value) {107    return TypeSwitch<Base *, std::optional<int>>(&value)108        .Case<DerivedB, DerivedC>([](auto *) { return std::nullopt; })109        .Case([](DerivedA *) { return 0; })110        .Default([](Base *) { return -1; });111  };112  EXPECT_EQ(0, translate(DerivedA()));113  EXPECT_EQ(std::nullopt, translate(DerivedB()));114  EXPECT_EQ(std::nullopt, translate(DerivedC()));115  EXPECT_EQ(-1, translate(DerivedD()));116}117 118TEST(TypeSwitchTest, DefaultUnreachableWithValue) {119  auto translate = [](auto value) {120    return TypeSwitch<Base *, int>(&value)121        .Case([](DerivedA *) { return 0; })122        .DefaultUnreachable("Unhandled type");123  };124  EXPECT_EQ(0, translate(DerivedA()));125 126#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)127  EXPECT_DEATH((void)translate(DerivedD()), "Unhandled type");128#endif129}130 131TEST(TypeSwitchTest, DefaultUnreachableWithVoid) {132  auto translate = [](auto value) {133    int result = -1;134    TypeSwitch<Base *>(&value)135        .Case([&result](DerivedA *) { result = 0; })136        .DefaultUnreachable("Unhandled type");137    return result;138  };139  EXPECT_EQ(0, translate(DerivedA()));140 141#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)142  EXPECT_DEATH((void)translate(DerivedD()), "Unhandled type");143#endif144}145 146TEST(TypeSwitchTest, DefaultNullopt) {147  auto translate = [](auto value) {148    return TypeSwitch<Base *, std::optional<int>>(&value)149        .Case([](DerivedA *) { return 0; })150        .Default(std::nullopt);151  };152  EXPECT_EQ(0, translate(DerivedA()));153  EXPECT_EQ(std::nullopt, translate(DerivedD()));154}155 156TEST(TypeSwitchTest, DefaultNullptr) {157  float foo = 0.0f;158  auto translate = [&](auto value) {159    return TypeSwitch<Base *, float *>(&value)160        .Case([&](DerivedA *) { return &foo; })161        .Default(nullptr);162  };163  EXPECT_EQ(&foo, translate(DerivedA()));164  EXPECT_EQ(nullptr, translate(DerivedD()));165}166 167TEST(TypeSwitchTest, DefaultNullptrForPointerLike) {168  struct Value {169    void *ptr;170    Value(const Value &other) = default;171    Value(std::nullptr_t) : ptr(nullptr) {}172    Value() : Value(nullptr) {}173  };174 175  float foo = 0.0f;176  Value fooVal;177  fooVal.ptr = &foo;178  auto translate = [&](auto value) {179    return TypeSwitch<Base *, Value>(&value)180        .Case([&](DerivedA *) { return fooVal; })181        .Default(nullptr);182  };183  EXPECT_EQ(&foo, translate(DerivedA()).ptr);184  EXPECT_EQ(nullptr, translate(DerivedD()).ptr);185}186