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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ADT/TypeSwitch.h" |
10 | #include "gtest/gtest.h" |
11 | |
12 | using namespace llvm; |
13 | |
14 | namespace { |
15 | /// Utility classes to setup casting functionality. |
16 | struct Base { |
17 | enum Kind { DerivedA, DerivedB, DerivedC, DerivedD, DerivedE }; |
18 | Kind kind; |
19 | }; |
20 | template <Base::Kind DerivedKind> struct DerivedImpl : Base { |
21 | DerivedImpl() : Base{.kind: DerivedKind} {} |
22 | static bool classof(const Base *base) { return base->kind == DerivedKind; } |
23 | }; |
24 | struct DerivedA : public DerivedImpl<Base::DerivedA> {}; |
25 | struct DerivedB : public DerivedImpl<Base::DerivedB> {}; |
26 | struct DerivedC : public DerivedImpl<Base::DerivedC> {}; |
27 | struct DerivedD : public DerivedImpl<Base::DerivedD> {}; |
28 | struct DerivedE : public DerivedImpl<Base::DerivedE> {}; |
29 | } // end anonymous namespace |
30 | |
31 | TEST(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 | |
45 | TEST(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 | |
59 | TEST(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 | |
75 | TEST(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 | |
90 | TEST(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 | |
105 | TEST(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 | |