[clang] [lld] [llvm] [ADT] Prepare for deprecation of StringSwitch cases with 4+ args. NFC. (PR #164173)
Jakub Kuderski via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 19 11:38:50 PDT 2025
https://github.com/kuhar updated https://github.com/llvm/llvm-project/pull/164173
>From b06d53db357a5620abed42dcb79e1d2ada19178c Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Sun, 19 Oct 2025 14:30:03 -0400
Subject: [PATCH 1/2] [ADT] Prepare for deprecation of StringSwitch cases with
4+ args. NFC.
Update `.Cases` and `.CasesLower` with 4+ args to use the
`initializer_list` overload. The deprecation of these functions will
come in a separate PR.
For more context, see: https://github.com/llvm/llvm-project/pull/163405.
---
clang/lib/Basic/Targets/Mips.cpp | 10 ++++----
clang/lib/Driver/ToolChains/Arch/Mips.cpp | 6 ++---
clang/lib/Driver/ToolChains/Darwin.cpp | 14 +++++------
clang/lib/Frontend/FrontendAction.cpp | 2 +-
clang/lib/Lex/PPLexerChange.cpp | 2 +-
clang/lib/Sema/SemaChecking.cpp | 12 +++++-----
clang/lib/Sema/SemaExpr.cpp | 2 +-
clang/lib/Sema/SemaInit.cpp | 11 +++++----
clang/lib/Sema/SemaStmtAttr.cpp | 2 +-
.../utils/TableGen/ClangOptionDocEmitter.cpp | 23 ++++++++++---------
lld/ELF/ScriptParser.cpp | 10 ++++----
llvm/include/llvm/ADT/StringSwitch.h | 2 ++
llvm/lib/MC/MCParser/MasmParser.cpp | 2 +-
.../Target/RISCV/MCA/RISCVCustomBehaviour.cpp | 2 +-
llvm/lib/TargetParser/ARMTargetParser.cpp | 8 +++----
llvm/unittests/ADT/StringSwitchTest.cpp | 8 +++----
16 files changed, 60 insertions(+), 56 deletions(-)
diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp
index de6ccff64f4eb..a999d1410d254 100644
--- a/clang/lib/Basic/Targets/Mips.cpp
+++ b/clang/lib/Basic/Targets/Mips.cpp
@@ -68,11 +68,11 @@ void MipsTargetInfo::fillValidCPUList(
unsigned MipsTargetInfo::getISARev() const {
return llvm::StringSwitch<unsigned>(getCPU())
- .Cases("mips32", "mips64", 1)
- .Cases("mips32r2", "mips64r2", "octeon", "octeon+", 2)
- .Cases("mips32r3", "mips64r3", 3)
- .Cases("mips32r5", "mips64r5", "p5600", 5)
- .Cases("mips32r6", "mips64r6", "i6400", "i6500", 6)
+ .Cases({"mips32", "mips64"}, 1)
+ .Cases({"mips32r2", "mips64r2", "octeon", "octeon+"}, 2)
+ .Cases({"mips32r3", "mips64r3"}, 3)
+ .Cases({"mips32r5", "mips64r5", "p5600"}, 5)
+ .Cases({"mips32r6", "mips64r6", "i6400", "i6500"}, 6)
.Default(0);
}
diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp
index bac8681921877..227c6a0d3d202 100644
--- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -482,9 +482,9 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
return false;
return llvm::StringSwitch<bool>(CPUName)
- .Cases("mips2", "mips3", "mips4", "mips5", true)
- .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
- .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
+ .Cases({"mips2", "mips3", "mips4", "mips5"}, true)
+ .Cases({"mips32", "mips32r2", "mips32r3", "mips32r5"}, true)
+ .Cases({"mips64", "mips64r2", "mips64r3", "mips64r5"}, true)
.Default(false);
}
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index d2356ebdfa86c..cc5bcd1816c52 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -51,15 +51,15 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// translation.
return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
- .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
- .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
+ .Cases({"i386", "i486", "i486SX", "i586", "i686"}, llvm::Triple::x86)
+ .Cases({"pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4"},
llvm::Triple::x86)
- .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
+ .Cases({"x86_64", "x86_64h"}, llvm::Triple::x86_64)
// This is derived from the driver.
- .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
- .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
- .Cases("armv7s", "xscale", llvm::Triple::arm)
- .Cases("arm64", "arm64e", llvm::Triple::aarch64)
+ .Cases({"arm", "armv4t", "armv5", "armv6", "armv6m"}, llvm::Triple::arm)
+ .Cases({"armv7", "armv7em", "armv7k", "armv7m"}, llvm::Triple::arm)
+ .Cases({"armv7s", "xscale"}, llvm::Triple::arm)
+ .Cases({"arm64", "arm64e"}, llvm::Triple::aarch64)
.Case("arm64_32", llvm::Triple::aarch64_32)
.Case("r600", llvm::Triple::r600)
.Case("amdgcn", llvm::Triple::amdgcn)
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 1b63c40a6efd7..0daa20a87dd7d 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -629,7 +629,7 @@ static std::error_code collectModuleHeaderIncludes(
// Check whether this entry has an extension typically associated with
// headers.
if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
- .Cases(".h", ".H", ".hh", ".hpp", true)
+ .Cases({".h", ".H", ".hh", ".hpp"}, true)
.Default(false))
continue;
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index d8f61c02a9837..b014124153c83 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -302,7 +302,7 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
// Check whether this entry has an extension typically associated with
// headers.
if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
- .Cases(".h", ".H", ".hh", ".hpp", true)
+ .Cases({".h", ".H", ".hh", ".hpp"}, true)
.Default(false))
continue;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ef1be23dcf277..2990fd67cc53d 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -6926,13 +6926,13 @@ StringRef Sema::GetFormatStringTypeName(FormatStringType FST) {
FormatStringType Sema::GetFormatStringType(StringRef Flavor) {
return llvm::StringSwitch<FormatStringType>(Flavor)
- .Cases("gnu_scanf", "scanf", FormatStringType::Scanf)
- .Cases("gnu_printf", "printf", "printf0", "syslog",
+ .Cases({"gnu_scanf", "scanf"}, FormatStringType::Scanf)
+ .Cases({"gnu_printf", "printf", "printf0", "syslog"},
FormatStringType::Printf)
- .Cases("NSString", "CFString", FormatStringType::NSString)
- .Cases("gnu_strftime", "strftime", FormatStringType::Strftime)
- .Cases("gnu_strfmon", "strfmon", FormatStringType::Strfmon)
- .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err",
+ .Cases({"NSString", "CFString"}, FormatStringType::NSString)
+ .Cases({"gnu_strftime", "strftime"}, FormatStringType::Strftime)
+ .Cases({"gnu_strfmon", "strfmon"}, FormatStringType::Strfmon)
+ .Cases({"kprintf", "cmn_err", "vcmn_err", "zcmn_err"},
FormatStringType::Kprintf)
.Case("freebsd_kprintf", FormatStringType::FreeBSDKPrintf)
.Case("os_trace", FormatStringType::OSLog)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index dca9d6e7ea358..a50c27610dc96 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12811,7 +12811,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
if (CTSD->isInStdNamespace() &&
llvm::StringSwitch<bool>(CTSD->getName())
- .Cases("less", "less_equal", "greater", "greater_equal", true)
+ .Cases({"less", "less_equal", "greater", "greater_equal"}, true)
.Default(false)) {
if (RHSType->isNullPtrType())
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index f7974eb0a91c7..7debe332cab3e 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -672,11 +672,12 @@ ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc,
IsInStd = true;
}
- if (IsInStd && llvm::StringSwitch<bool>(R->getName())
- .Cases("basic_string", "deque", "forward_list", true)
- .Cases("list", "map", "multimap", "multiset", true)
- .Cases("priority_queue", "queue", "set", "stack", true)
- .Cases("unordered_map", "unordered_set", "vector", true)
+ if (IsInStd &&
+ llvm::StringSwitch<bool>(R->getName())
+ .Cases({"basic_string", "deque", "forward_list"}, true)
+ .Cases({"list", "map", "multimap", "multiset"}, true)
+ .Cases({"priority_queue", "queue", "set", "stack"}, true)
+ .Cases({"unordered_map", "unordered_set", "vector"}, true)
.Default(false)) {
InitSeq.InitializeFrom(
SemaRef, Entity,
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 50acc83f1841c..27fd5563cc40e 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -81,7 +81,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
StringRef PragmaName =
llvm::StringSwitch<StringRef>(
PragmaNameLoc->getIdentifierInfo()->getName())
- .Cases("unroll", "nounroll", "unroll_and_jam", "nounroll_and_jam",
+ .Cases({"unroll", "nounroll", "unroll_and_jam", "nounroll_and_jam"},
PragmaNameLoc->getIdentifierInfo()->getName())
.Default("clang loop");
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 8a31686bc7727..d779c8418e57e 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -173,11 +173,11 @@ Documentation extractDocumentation(const RecordKeeper &Records,
// Get the first and successive separators to use for an OptionKind.
std::pair<StringRef,StringRef> getSeparatorsForKind(const Record *OptionKind) {
return StringSwitch<std::pair<StringRef, StringRef>>(OptionKind->getName())
- .Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE",
- "KIND_JOINED_AND_SEPARATE",
- "KIND_REMAINING_ARGS_JOINED", {"", " "})
- .Case("KIND_COMMAJOINED", {"", ","})
- .Default({" ", " "});
+ .Cases({"KIND_JOINED", "KIND_JOINED_OR_SEPARATE",
+ "KIND_JOINED_AND_SEPARATE", "KIND_REMAINING_ARGS_JOINED"},
+ {"", " "})
+ .Case("KIND_COMMAJOINED", {"", ","})
+ .Default({" ", " "});
}
const unsigned UnlimitedArgs = unsigned(-1);
@@ -186,12 +186,13 @@ const unsigned UnlimitedArgs = unsigned(-1);
// arguments are accepted.
unsigned getNumArgsForKind(const Record *OptionKind, const Record *Option) {
return StringSwitch<unsigned>(OptionKind->getName())
- .Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE", "KIND_SEPARATE", 1)
- .Cases("KIND_REMAINING_ARGS", "KIND_REMAINING_ARGS_JOINED",
- "KIND_COMMAJOINED", UnlimitedArgs)
- .Case("KIND_JOINED_AND_SEPARATE", 2)
- .Case("KIND_MULTIARG", Option->getValueAsInt("NumArgs"))
- .Default(0);
+ .Cases({"KIND_JOINED", "KIND_JOINED_OR_SEPARATE", "KIND_SEPARATE"}, 1)
+ .Cases({"KIND_REMAINING_ARGS", "KIND_REMAINING_ARGS_JOINED",
+ "KIND_COMMAJOINED"},
+ UnlimitedArgs)
+ .Case("KIND_JOINED_AND_SEPARATE", 2)
+ .Case("KIND_MULTIARG", Option->getValueAsInt("NumArgs"))
+ .Default(0);
}
std::string escapeRST(StringRef Str) {
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index ddfa24d9cacf5..22fe0bf3f920a 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -721,11 +721,11 @@ void ScriptParser::readTarget() {
static int precedence(StringRef op) {
return StringSwitch<int>(op)
- .Cases("*", "/", "%", 11)
- .Cases("+", "-", 10)
- .Cases("<<", ">>", 9)
- .Cases("<", "<=", ">", ">=", 8)
- .Cases("==", "!=", 7)
+ .Cases({"/", "*", "%"}, 11)
+ .Cases({"+", "-"}, 10)
+ .Cases({">>", "<<"}, 9)
+ .Cases({"<", "<=", ">", ">="}, 8)
+ .Cases({"!=", "=="}, 7)
.Case("&", 6)
.Case("^", 5)
.Case("|", 4)
diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h
index 26d568298207e..8be22117e1590 100644
--- a/llvm/include/llvm/ADT/StringSwitch.h
+++ b/llvm/include/llvm/ADT/StringSwitch.h
@@ -103,6 +103,7 @@ class StringSwitch {
return CasesImpl({S0, S1, S2, S3}, Value);
}
+ [[deprecated("Pass cases in std::initializer_list instead")]]
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
StringLiteral S3, StringLiteral S4, T Value) {
return CasesImpl({S0, S1, S2, S3, S4}, Value);
@@ -184,6 +185,7 @@ class StringSwitch {
return CasesLowerImpl({S0, S1, S2, S3}, Value);
}
+ [[deprecated("Pass cases in std::initializer_list instead")]]
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
StringLiteral S3, StringLiteral S4, T Value) {
return CasesLowerImpl({S0, S1, S2, S3, S4}, Value);
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index 7f0ea7830b495..d4901d95e565a 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -2903,7 +2903,7 @@ bool MasmParser::parseIdentifier(StringRef &Res,
if (Position == StartOfStatement &&
StringSwitch<bool>(Res)
.CaseLower("echo", true)
- .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true)
+ .CasesLower({"ifdef", "ifndef", "elseifdef", "elseifndef"}, true)
.Default(false)) {
ExpandNextToken = DoNotExpandMacros;
}
diff --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
index ab93bbaef7e8a..b00589a2d75be 100644
--- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
+++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
@@ -68,7 +68,7 @@ const llvm::StringRef RISCVSEWInstrument::DESC_NAME = "RISCV-SEW";
bool RISCVSEWInstrument::isDataValid(llvm::StringRef Data) {
// Return true if not one of the valid SEW strings
return StringSwitch<bool>(Data)
- .Cases("E8", "E16", "E32", "E64", true)
+ .Cases({"E8", "E16", "E32", "E64"}, true)
.Default(false);
}
diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp b/llvm/lib/TargetParser/ARMTargetParser.cpp
index 08944e6148a00..788204574c1b7 100644
--- a/llvm/lib/TargetParser/ARMTargetParser.cpp
+++ b/llvm/lib/TargetParser/ARMTargetParser.cpp
@@ -235,16 +235,16 @@ ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) {
StringRef ARM::getFPUSynonym(StringRef FPU) {
return StringSwitch<StringRef>(FPU)
- .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
+ .Cases({"fpa", "fpe2", "fpe3", "maverick"}, "invalid") // Unsupported
.Case("vfp2", "vfpv2")
.Case("vfp3", "vfpv3")
.Case("vfp4", "vfpv4")
.Case("vfp3-d16", "vfpv3-d16")
.Case("vfp4-d16", "vfpv4-d16")
- .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
- .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
+ .Cases({"fp4-sp-d16", "vfpv4-sp-d16"}, "fpv4-sp-d16")
+ .Cases({"fp4-dp-d16", "fpv4-dp-d16"}, "vfpv4-d16")
.Case("fp5-sp-d16", "fpv5-sp-d16")
- .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
+ .Cases({"fp5-dp-d16", "fpv5-dp-d16"}, "fpv5-d16")
// FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
.Case("neon-vfpv3", "neon")
.Default(FPU);
diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp
index 0fbf37153593e..d88a0ff034d61 100644
--- a/llvm/unittests/ADT/StringSwitchTest.cpp
+++ b/llvm/unittests/ADT/StringSwitchTest.cpp
@@ -159,7 +159,7 @@ TEST(StringSwitchTest, Cases) {
return llvm::StringSwitch<OSType>(S)
.Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
OSType::Windows)
- .Cases("linux", "unix", "*nix", "posix", OSType::Linux)
+ .Cases({"linux", "unix", "*nix", "posix"}, OSType::Linux)
.Cases({"macos", "osx"}, OSType::MacOS)
.Default(OSType::Unknown);
};
@@ -191,7 +191,7 @@ TEST(StringSwitchTest, CasesLower) {
return llvm::StringSwitch<OSType>(S)
.CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
OSType::Windows)
- .CasesLower("linux", "unix", "*nix", "posix", OSType::Linux)
+ .CasesLower({"linux", "unix", "*nix", "posix"}, OSType::Linux)
.CasesLower({"macos", "osx"}, OSType::MacOS)
.Default(OSType::Unknown);
};
@@ -230,13 +230,13 @@ TEST(StringSwitchTest, CasesCopies) {
// Check that evaluating multiple cases does not cause unnecessary copies.
unsigned NumCopies = 0;
- llvm::StringSwitch<Copyable, void>("baz").Cases("foo", "bar", "baz", "qux",
+ llvm::StringSwitch<Copyable, void>("baz").Cases({"foo", "bar", "baz", "qux"},
Copyable{NumCopies});
EXPECT_EQ(NumCopies, 1u);
NumCopies = 0;
llvm::StringSwitch<Copyable, void>("baz").CasesLower(
- "Foo", "Bar", "Baz", "Qux", Copyable{NumCopies});
+ {"Foo", "Bar", "Baz", "Qux"}, Copyable{NumCopies});
EXPECT_EQ(NumCopies, 1u);
}
>From 793b762fcbedd4e1bf8b55457de98adea7d5c6de Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Sun, 19 Oct 2025 14:38:41 -0400
Subject: [PATCH 2/2] Tighten deprecations
---
llvm/include/llvm/ADT/StringSwitch.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h
index 8be22117e1590..2262b1162e330 100644
--- a/llvm/include/llvm/ADT/StringSwitch.h
+++ b/llvm/include/llvm/ADT/StringSwitch.h
@@ -98,6 +98,7 @@ class StringSwitch {
return CasesImpl({S0, S1, S2}, Value);
}
+ [[deprecated("Pass cases in std::initializer_list instead")]]
StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
StringLiteral S3, T Value) {
return CasesImpl({S0, S1, S2, S3}, Value);
@@ -180,6 +181,7 @@ class StringSwitch {
return CasesLowerImpl({S0, S1, S2}, Value);
}
+ [[deprecated("Pass cases in std::initializer_list instead")]]
StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
StringLiteral S3, T Value) {
return CasesLowerImpl({S0, S1, S2, S3}, Value);
More information about the cfe-commits
mailing list