diff --git a/llvm/include/llvm/ADT/TypeSwitch.h b/llvm/include/llvm/ADT/TypeSwitch.h index f9323a50891c7a..10a2d48e918db9 100644 --- a/llvm/include/llvm/ADT/TypeSwitch.h +++ b/llvm/include/llvm/ADT/TypeSwitch.h @@ -119,7 +119,7 @@ class TypeSwitch : public detail::TypeSwitchBase, T> { // Check to see if CaseT applies to 'value'. if (auto caseValue = BaseT::template castValue(this->value)) - result = caseFn(caseValue); + result.emplace(caseFn(caseValue)); return *this; } diff --git a/llvm/unittests/ADT/TypeSwitchTest.cpp b/llvm/unittests/ADT/TypeSwitchTest.cpp index 442ac1910a054b..c54b7987edf7ea 100644 --- a/llvm/unittests/ADT/TypeSwitchTest.cpp +++ b/llvm/unittests/ADT/TypeSwitchTest.cpp @@ -86,3 +86,31 @@ TEST(TypeSwitchTest, CasesVoid) { EXPECT_EQ(0, translate(DerivedD())); EXPECT_EQ(-1, translate(DerivedE())); } + +TEST(TypeSwitchTest, CaseOptional) { + auto translate = [](auto value) { + return TypeSwitch>(&value) + .Case([](DerivedA *) { return 0; }) + .Case([](DerivedC *) { return std::nullopt; }) + .Default([](Base *) { return -1; }); + }; + EXPECT_EQ(0, translate(DerivedA())); + EXPECT_EQ(std::nullopt, translate(DerivedC())); + EXPECT_EQ(-1, translate(DerivedD())); + EXPECT_EQ(std::nullopt, + (TypeSwitch>(nullptr).Default( + [](Base *) { return std::nullopt; }))); +} + +TEST(TypeSwitchTest, CasesOptional) { + auto translate = [](auto value) { + return TypeSwitch>(&value) + .Case([](auto *) { return std::nullopt; }) + .Case([](DerivedA *) { return 0; }) + .Default([](Base *) { return -1; }); + }; + EXPECT_EQ(0, translate(DerivedA())); + EXPECT_EQ(std::nullopt, translate(DerivedB())); + EXPECT_EQ(std::nullopt, translate(DerivedC())); + EXPECT_EQ(-1, translate(DerivedD())); +}