Skip to content

Commit 25ed923

Browse files
authored
[ADT] Handle and document multiple matches in StringSwitch (llvm#166177)
Specify that the first match is returned and bail out early when processing multiple case values.
1 parent af68efc commit 25ed923

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

llvm/include/llvm/ADT/StringSwitch.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace llvm {
4141
/// .Cases({"violet", "purple"}, Violet)
4242
/// .Default(UnknownColor);
4343
/// \endcode
44+
///
45+
/// When multiple matches are found, the value of the first match is returned.
4446
template<typename T, typename R = T>
4547
class StringSwitch {
4648
/// The string we are matching.
@@ -213,23 +215,30 @@ class StringSwitch {
213215
[[nodiscard]] operator R() { return DefaultUnreachable(); }
214216

215217
private:
216-
// Returns true when `Str` matches the `S` argument, and stores the result.
218+
// Returns true when a match is found. If `Str` matches the `S` argument,
219+
// stores the result.
217220
bool CaseImpl(StringLiteral S, T &Value) {
218-
if (!Result && Str == S) {
219-
Result = std::move(Value);
221+
if (Result)
220222
return true;
221-
}
222-
return false;
223+
224+
if (Str != S)
225+
return false;
226+
227+
Result = std::move(Value);
228+
return true;
223229
}
224230

225-
// Returns true when `Str` matches the `S` argument (case-insensitive), and
226-
// stores the result.
231+
// Returns true when a match is found. If `Str` matches the `S` argument
232+
// (case-insensitive), stores the result.
227233
bool CaseLowerImpl(StringLiteral S, T &Value) {
228-
if (!Result && Str.equals_insensitive(S)) {
229-
Result = std::move(Value);
234+
if (Result)
230235
return true;
231-
}
232-
return false;
236+
237+
if (!Str.equals_insensitive(S))
238+
return false;
239+
240+
Result = std::move(Value);
241+
return true;
233242
}
234243

235244
StringSwitch &CasesImpl(std::initializer_list<StringLiteral> Cases,

llvm/unittests/ADT/StringSwitchTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,23 @@ TEST(StringSwitchTest, CasesCopies) {
240240
EXPECT_EQ(NumCopies, 1u);
241241
}
242242

243+
TEST(StringSwitchTest, StringSwitchMultipleMatches) {
244+
auto Translate = [](StringRef S) {
245+
return llvm::StringSwitch<int>(S)
246+
.CaseLower("A", 0)
247+
.Case("b", 1)
248+
.Case("a", 2)
249+
.CasesLower({"a", "b"}, 3)
250+
.DefaultUnreachable();
251+
};
252+
253+
// Check that the value of the first match is returned.
254+
EXPECT_EQ(0, Translate("A"));
255+
EXPECT_EQ(0, Translate("a"));
256+
EXPECT_EQ(3, Translate("B"));
257+
EXPECT_EQ(1, Translate("b"));
258+
}
259+
243260
TEST(StringSwitchTest, DefaultUnreachable) {
244261
auto Translate = [](StringRef S) {
245262
return llvm::StringSwitch<int>(S)

0 commit comments

Comments
 (0)