From 6aa443a19746145a409ccac3c7af4b41d5d42186 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Sat, 25 Oct 2025 17:45:04 -0400 Subject: [PATCH 1/3] [ADT] Deprecate StringSwitch Cases with 3+ args. NFC. Suggest the `initializer_list` overload instead. 3+ args is an arbitrary number that allows for incremental depreciation without having to update too many call sites. For more context, see https://github.com/llvm/llvm-project/pull/163117. --- 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 2262b1162e330..98685de8573fa 100644 --- a/llvm/include/llvm/ADT/StringSwitch.h +++ b/llvm/include/llvm/ADT/StringSwitch.h @@ -93,6 +93,7 @@ class StringSwitch { return CasesImpl({S0, S1}, Value); } + [[deprecated("Pass cases in std::initializer_list instead")]] StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return CasesImpl({S0, S1, S2}, Value); @@ -176,6 +177,7 @@ class StringSwitch { return CasesLowerImpl({S0, S1}, Value); } + [[deprecated("Pass cases in std::initializer_list instead")]] StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return CasesLowerImpl({S0, S1, S2}, Value); From f46cff4c86fc6913db9d31eb990809f7924fd312 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Sat, 25 Oct 2025 18:28:08 -0400 Subject: [PATCH 2/3] Update remaining deprecated uses --- .../bugprone/UnsafeFunctionsCheck.cpp | 10 ++++---- clang/lib/AST/CommentSema.cpp | 4 ++-- clang/lib/Driver/ToolChains/Arch/Mips.cpp | 4 ++-- clang/lib/Driver/ToolChains/CommonArgs.cpp | 6 ++--- .../Checkers/MacOSXAPIChecker.cpp | 10 ++++---- .../unittests/Driver/MultilibBuilderTest.cpp | 2 +- clang/unittests/Driver/MultilibTest.cpp | 2 +- lld/Common/DriverDispatcher.cpp | 6 ++--- lldb/source/Host/common/File.cpp | 23 +++++++++---------- lldb/source/Host/common/Socket.cpp | 4 ++-- 10 files changed, 34 insertions(+), 37 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp index 0399af2a673f4..1b643f557382d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp @@ -49,7 +49,7 @@ static StringRef getReplacementFor(StringRef FunctionName, // Try to find a better replacement from Annex K first. StringRef AnnexKReplacementFunction = StringSwitch(FunctionName) - .Cases("asctime", "asctime_r", "asctime_s") + .Cases({"asctime", "asctime_r"}, "asctime_s") .Case("gets", "gets_s") .Default({}); if (!AnnexKReplacementFunction.empty()) @@ -59,7 +59,7 @@ static StringRef getReplacementFor(StringRef FunctionName, // FIXME: Some of these functions are available in C++ under "std::", and // should be matched and suggested. return StringSwitch(FunctionName) - .Cases("asctime", "asctime_r", "strftime") + .Cases({"asctime", "asctime_r"}, "strftime") .Case("gets", "fgets") .Case("rewind", "fseek") .Case("setbuf", "setvbuf"); @@ -90,13 +90,13 @@ static StringRef getReplacementForAdditional(StringRef FunctionName, /// safer alternative. static StringRef getRationaleFor(StringRef FunctionName) { return StringSwitch(FunctionName) - .Cases("asctime", "asctime_r", "ctime", + .Cases({"asctime", "asctime_r"}, "ctime", "is not bounds-checking and non-reentrant") - .Cases("bcmp", "bcopy", "bzero", "is deprecated") + .Cases({"bcmp", "bcopy", "bzero"}, "is deprecated") .Cases("fopen", "freopen", "has no exclusive access to the opened file") .Case("gets", "is insecure, was deprecated and removed in C11 and C++14") .Case("getpw", "is dangerous as it may overflow the provided buffer") - .Cases("rewind", "setbuf", "has no error detection") + .Cases({"rewind", "setbuf"}, "has no error detection") .Case("vfork", "is insecure as it can lead to denial of service " "situations in the parent process") .Default("is not bounds-checking"); diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index 649fba94a2b76..27ff5ab1f0c6b 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -1061,8 +1061,8 @@ InlineCommandRenderKind Sema::getInlineCommandRenderKind(StringRef Name) const { return llvm::StringSwitch(Name) .Case("b", InlineCommandRenderKind::Bold) - .Cases("c", "p", InlineCommandRenderKind::Monospaced) - .Cases("a", "e", "em", InlineCommandRenderKind::Emphasized) + .Cases({"c", "p"}, InlineCommandRenderKind::Monospaced) + .Cases({"a", "e", "em"}, InlineCommandRenderKind::Emphasized) .Case("anchor", InlineCommandRenderKind::Anchor) .Default(InlineCommandRenderKind::Normal); } diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 227c6a0d3d202..6a6a4ee1a647b 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -502,8 +502,8 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, if (Arg *A = Args.getLastArg(options::OPT_mmsa)) if (A->getOption().matches(options::OPT_mmsa)) UseFPXX = llvm::StringSwitch(CPUName) - .Cases("mips32r2", "mips32r3", "mips32r5", false) - .Cases("mips64r2", "mips64r3", "mips64r5", false) + .Cases({"mips32r2", "mips32r3", "mips32r5"}, false) + .Cases({"mips64r2", "mips64r3", "mips64r5"}, false) .Default(UseFPXX); return UseFPXX; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 727af698738d4..ec8dcdc81db56 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -663,11 +663,11 @@ static std::string getAMDGPUTargetGPU(const llvm::Triple &T, if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { auto GPUName = getProcessorFromTargetID(T, A->getValue()); return llvm::StringSwitch(GPUName) - .Cases("rv630", "rv635", "r600") - .Cases("rv610", "rv620", "rs780", "rs880") + .Cases({"rv630", "rv635"}, "r600") + .Cases({"rv610", "rv620", "rs780"}, "rs880") .Case("rv740", "rv770") .Case("palm", "cedar") - .Cases("sumo", "sumo2", "sumo") + .Cases({"sumo", "sumo2"}, "sumo") .Case("hemlock", "cypress") .Case("aruba", "cayman") .Default(GPUName.str()); diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 40985f426bdc2..6439e6cedac08 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -151,12 +151,10 @@ void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE, return; SubChecker SC = - llvm::StringSwitch(Name) - .Cases("dispatch_once", - "_dispatch_once", - "dispatch_once_f", - &MacOSXAPIChecker::CheckDispatchOnce) - .Default(nullptr); + llvm::StringSwitch(Name) + .Cases({"dispatch_once", "_dispatch_once", "dispatch_once_f"}, + &MacOSXAPIChecker::CheckDispatchOnce) + .Default(nullptr); if (SC) (this->*SC)(C, CE, Name); diff --git a/clang/unittests/Driver/MultilibBuilderTest.cpp b/clang/unittests/Driver/MultilibBuilderTest.cpp index 0c1e806d42065..ebcbee7974001 100644 --- a/clang/unittests/Driver/MultilibBuilderTest.cpp +++ b/clang/unittests/Driver/MultilibBuilderTest.cpp @@ -61,7 +61,7 @@ TEST(MultilibBuilderTest, Construction3) { MultilibBuilder().flag("-f1").flag("-f2").flag("-f3", /*Disallow=*/true); for (const std::string &A : M.flags()) { ASSERT_TRUE(llvm::StringSwitch(A) - .Cases("-f1", "-f2", "!f3", true) + .Cases({"-f1", "-f2", "!f3"}, true) .Default(false)); } } diff --git a/clang/unittests/Driver/MultilibTest.cpp b/clang/unittests/Driver/MultilibTest.cpp index 4c11e6a32d7c8..ebb8611d97e1c 100644 --- a/clang/unittests/Driver/MultilibTest.cpp +++ b/clang/unittests/Driver/MultilibTest.cpp @@ -131,7 +131,7 @@ TEST(MultilibTest, Construction3) { E = M.flags().end(); I != E; ++I) { ASSERT_TRUE(llvm::StringSwitch(*I) - .Cases("+f1", "+f2", "-f3", true) + .Cases({"+f1", "+f2", "-f3"}, true) .Default(false)); } } diff --git a/lld/Common/DriverDispatcher.cpp b/lld/Common/DriverDispatcher.cpp index 7c5f1cd3692ef..0b71c08094863 100644 --- a/lld/Common/DriverDispatcher.cpp +++ b/lld/Common/DriverDispatcher.cpp @@ -30,10 +30,10 @@ static void err(const Twine &s) { llvm::errs() << s << "\n"; } static Flavor getFlavor(StringRef s) { return StringSwitch(s) - .CasesLower("ld", "ld.lld", "gnu", Gnu) - .CasesLower("wasm", "ld-wasm", Wasm) + .CasesLower({"ld", "ld.lld", "gnu"}, Gnu) + .CasesLower({"wasm", "ld-wasm"}, Wasm) .CaseLower("link", WinLink) - .CasesLower("ld64", "ld64.lld", "darwin", Darwin) + .CasesLower({"ld64", "ld64.lld", "darwin"}, Darwin) .Default(Invalid); } diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 1272f13c1d82d..65b75bd647c5d 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -81,18 +81,17 @@ File::GetStreamOpenModeFromOptions(File::OpenOptions options) { Expected File::GetOptionsFromMode(llvm::StringRef mode) { OpenOptions opts = llvm::StringSwitch(mode) - .Cases("r", "rb", eOpenOptionReadOnly) - .Cases("w", "wb", eOpenOptionWriteOnly) - .Cases("a", "ab", - eOpenOptionWriteOnly | eOpenOptionAppend | - eOpenOptionCanCreate) - .Cases("r+", "rb+", "r+b", eOpenOptionReadWrite) - .Cases("w+", "wb+", "w+b", - eOpenOptionReadWrite | eOpenOptionCanCreate | - eOpenOptionTruncate) - .Cases("a+", "ab+", "a+b", - eOpenOptionReadWrite | eOpenOptionAppend | - eOpenOptionCanCreate) + .Cases({"r", "rb"}, eOpenOptionReadOnly) + .Cases({"w", "wb"}, eOpenOptionWriteOnly) + .Cases({"a", "ab"}, eOpenOptionWriteOnly | eOpenOptionAppend | + eOpenOptionCanCreate) + .Cases({"r+", "rb+", "r+b"}, eOpenOptionReadWrite) + .Cases({"w+", "wb+", "w+b"}, eOpenOptionReadWrite | + eOpenOptionCanCreate | + eOpenOptionTruncate) + .Cases({"a+", "ab+", "a+b"}, eOpenOptionReadWrite | + eOpenOptionAppend | + eOpenOptionCanCreate) .Default(eOpenOptionInvalid); if (opts != eOpenOptionInvalid) return opts; diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index bc3d849c5c6c6..eb333f7e74396 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -500,13 +500,13 @@ Socket::GetProtocolAndMode(llvm::StringRef scheme) { return llvm::StringSwitch>(scheme) .Case("listen", ProtocolModePair{SocketProtocol::ProtocolTcp, SocketMode::ModeAccept}) - .Cases("accept", "unix-accept", + .Cases({"accept", "unix-accept"}, ProtocolModePair{SocketProtocol::ProtocolUnixDomain, SocketMode::ModeAccept}) .Case("unix-abstract-accept", ProtocolModePair{SocketProtocol::ProtocolUnixAbstract, SocketMode::ModeAccept}) - .Cases("connect", "tcp-connect", "connection", + .Cases({"connect", "tcp-connect", "connection"}, ProtocolModePair{SocketProtocol::ProtocolTcp, SocketMode::ModeConnect}) .Case("udp", ProtocolModePair{SocketProtocol::ProtocolTcp, From 2c3b7170c09acd74e50a54a41fb4e4cf1fc7f3ca Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Sat, 25 Oct 2025 19:03:09 -0400 Subject: [PATCH 3/3] Fixup --- .../clang-tidy/bugprone/UnsafeFunctionsCheck.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp index 1b643f557382d..61ccd26e48c1e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp @@ -90,10 +90,10 @@ static StringRef getReplacementForAdditional(StringRef FunctionName, /// safer alternative. static StringRef getRationaleFor(StringRef FunctionName) { return StringSwitch(FunctionName) - .Cases({"asctime", "asctime_r"}, "ctime", + .Cases({"asctime", "asctime_r", "ctime"}, "is not bounds-checking and non-reentrant") .Cases({"bcmp", "bcopy", "bzero"}, "is deprecated") - .Cases("fopen", "freopen", "has no exclusive access to the opened file") + .Cases({"fopen", "freopen"}, "has no exclusive access to the opened file") .Case("gets", "is insecure, was deprecated and removed in C11 and C++14") .Case("getpw", "is dangerous as it may overflow the provided buffer") .Cases({"rewind", "setbuf"}, "has no error detection")