diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h index 5bdbb302a6d75..53ebec1eb3a54 100644 --- a/llvm/include/llvm/ADT/StringSwitch.h +++ b/llvm/include/llvm/ADT/StringSwitch.h @@ -41,6 +41,8 @@ namespace llvm { /// .Cases({"violet", "purple"}, Violet) /// .Default(UnknownColor); /// \endcode +/// +/// When multiple matches are found, the value of the first match is returned. template class StringSwitch { /// The string we are matching. @@ -213,23 +215,30 @@ class StringSwitch { [[nodiscard]] operator R() { return DefaultUnreachable(); } private: - // Returns true when `Str` matches the `S` argument, and stores the result. + // Returns true when a match is found. If `Str` matches the `S` argument, + // stores the result. bool CaseImpl(StringLiteral S, T &Value) { - if (!Result && Str == S) { - Result = std::move(Value); + if (Result) return true; - } - return false; + + if (Str != S) + return false; + + Result = std::move(Value); + return true; } - // Returns true when `Str` matches the `S` argument (case-insensitive), and - // stores the result. + // Returns true when a match is found. If `Str` matches the `S` argument + // (case-insensitive), stores the result. bool CaseLowerImpl(StringLiteral S, T &Value) { - if (!Result && Str.equals_insensitive(S)) { - Result = std::move(Value); + if (Result) return true; - } - return false; + + if (!Str.equals_insensitive(S)) + return false; + + Result = std::move(Value); + return true; } StringSwitch &CasesImpl(std::initializer_list Cases, diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp index c94feb54d0b7d..75d50f4dd1b5b 100644 --- a/llvm/unittests/ADT/StringSwitchTest.cpp +++ b/llvm/unittests/ADT/StringSwitchTest.cpp @@ -240,6 +240,23 @@ TEST(StringSwitchTest, CasesCopies) { EXPECT_EQ(NumCopies, 1u); } +TEST(StringSwitchTest, StringSwitchMultipleMatches) { + auto Translate = [](StringRef S) { + return llvm::StringSwitch(S) + .CaseLower("A", 0) + .Case("b", 1) + .Case("a", 2) + .CasesLower({"a", "b"}, 3) + .DefaultUnreachable(); + }; + + // Check that the value of the first match is returned. + EXPECT_EQ(0, Translate("A")); + EXPECT_EQ(0, Translate("a")); + EXPECT_EQ(3, Translate("B")); + EXPECT_EQ(1, Translate("b")); +} + TEST(StringSwitchTest, DefaultUnreachable) { auto Translate = [](StringRef S) { return llvm::StringSwitch(S)