[llvm] [ADT] Handle and document multiple matches in StringSwitch (PR #166177)

Jakub Kuderski via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 3 07:20:55 PST 2025


https://github.com/kuhar updated https://github.com/llvm/llvm-project/pull/166177

>From f0958d2d1058d03c4d58584ca25000784301fae7 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Mon, 3 Nov 2025 10:14:53 -0500
Subject: [PATCH 1/2] [ADT] Handle and document multiple matches in
 StringSwitch

Specify that the first match is returned and bail out early when
processing multiple case values.
---
 llvm/include/llvm/ADT/StringSwitch.h    | 31 ++++++++++++++++---------
 llvm/unittests/ADT/StringSwitchTest.cpp | 17 ++++++++++++++
 2 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h
index 5bdbb302a6d75..cbe0f76ef0903 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<typename T, typename R = T>
 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.
+  // Return 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.
+  // Return 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<StringLiteral> 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<int>(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<int>(S)

>From 046e1804af496c36bf9aebedc169ee771237f51f Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Mon, 3 Nov 2025 10:20:46 -0500
Subject: [PATCH 2/2] Typo

---
 llvm/include/llvm/ADT/StringSwitch.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h
index cbe0f76ef0903..53ebec1eb3a54 100644
--- a/llvm/include/llvm/ADT/StringSwitch.h
+++ b/llvm/include/llvm/ADT/StringSwitch.h
@@ -215,7 +215,7 @@ class StringSwitch {
   [[nodiscard]] operator R() { return DefaultUnreachable(); }
 
 private:
-  // Return true when a match is found. If `Str` matches the `S` argument,
+  // Returns true when a match is found. If `Str` matches the `S` argument,
   // stores the result.
   bool CaseImpl(StringLiteral S, T &Value) {
     if (Result)
@@ -228,7 +228,7 @@ class StringSwitch {
     return true;
   }
 
-  // Return true when a match is found. If `Str` matches the `S` argument
+  // 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)



More information about the llvm-commits mailing list