https://github.com/steffenlarsen updated 
https://github.com/llvm/llvm-project/pull/183287

>From 92eda02c885aba0804489ac8ada128e6d2ae3b65 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 25 Feb 2026 05:34:50 -0600
Subject: [PATCH 1/4] [Clang][NFCI] Enforce immutability of global strings

This commit intends to clean up the use of global strings in clang by
enforcing immutability. As far as possible, the global and static
variables of either type 'const char *' or 'StringRef' (and arrays
thereof) are either declared 'constexpr' or 'const'. This should help
ensure that these variables are not used as global state at runtime and
reduce the overall global state surface of clang.

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/include/clang/Basic/PlistSupport.h      |  2 +-
 clang/include/clang/Format/Format.h           |  6 +-
 clang/include/clang/Tooling/AllTUsExecution.h |  2 +-
 .../clang/Tooling/StandaloneExecution.h       |  2 +-
 clang/lib/AST/Mangle.cpp                      |  2 +-
 clang/lib/AST/NSAPI.cpp                       | 85 +++++++++----------
 clang/lib/Analysis/IssueHash.cpp              |  4 +-
 clang/lib/CodeGen/CGNonTrivialStruct.cpp      |  2 +-
 clang/lib/Driver/Driver.cpp                   |  4 +-
 clang/lib/Driver/ToolChains/Clang.cpp         |  4 +-
 clang/lib/Format/Format.cpp                   |  6 +-
 clang/lib/InstallAPI/DirectoryScanner.cpp     |  8 +-
 clang/lib/Sema/SemaCodeComplete.cpp           |  4 +-
 .../ObjectFilePCHContainerReader.cpp          |  2 +-
 .../Serialization/PCHContainerOperations.cpp  |  2 +-
 .../Checkers/DereferenceChecker.cpp           |  2 +-
 .../StaticAnalyzer/Checkers/ErrnoModeling.cpp |  2 +-
 .../Checkers/GCDAntipatternChecker.cpp        |  2 +-
 .../Checkers/OSObjectCStyleCast.cpp           |  4 +-
 .../Checkers/ObjCAutoreleaseWriteChecker.cpp  | 10 +--
 .../RunLoopAutoreleaseLeakChecker.cpp         | 10 +--
 .../StaticAnalyzer/Checkers/StreamChecker.cpp |  6 +-
 clang/lib/Tooling/AllTUsExecution.cpp         |  2 -
 clang/lib/Tooling/StandaloneExecution.cpp     |  2 -
 clang/unittests/Tooling/ExecutionTest.cpp     |  4 +-
 25 files changed, 82 insertions(+), 97 deletions(-)

diff --git a/clang/include/clang/Basic/PlistSupport.h 
b/clang/include/clang/Basic/PlistSupport.h
index 1814130f1d2cb..2e248c5066e17 100644
--- a/clang/include/clang/Basic/PlistSupport.h
+++ b/clang/include/clang/Basic/PlistSupport.h
@@ -57,7 +57,7 @@ inline raw_ostream &Indent(raw_ostream &o, const unsigned 
indent) {
 }
 
 inline raw_ostream &EmitPlistHeader(raw_ostream &o) {
-  static const char *PlistHeader =
+  constexpr char PlistHeader[] =
       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
       "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
       "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\";>\n"
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 2028c963ac306..8dba796126f18 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -6174,16 +6174,16 @@ LangOptions getFormattingLangOpts(const FormatStyle 
&Style = getLLVMStyle());
 /// Description to be used for help text for a ``llvm::cl`` option for
 /// specifying format style. The description is closely related to the 
operation
 /// of ``getStyle()``.
-extern const char *StyleOptionHelpDescription;
+extern const char *const StyleOptionHelpDescription;
 
 /// The suggested format style to use by default. This allows tools using
 /// ``getStyle`` to have a consistent default style.
 /// Different builds can modify the value to the preferred styles.
-extern const char *DefaultFormatStyle;
+extern const char *const DefaultFormatStyle;
 
 /// The suggested predefined style to use as the fallback style in 
``getStyle``.
 /// Different builds can modify the value to the preferred styles.
-extern const char *DefaultFallbackStyle;
+extern const char *const DefaultFallbackStyle;
 
 /// Construct a FormatStyle based on ``StyleName``.
 ///
diff --git a/clang/include/clang/Tooling/AllTUsExecution.h 
b/clang/include/clang/Tooling/AllTUsExecution.h
index 03cfc9c67f5c5..d1faeca54ed1f 100644
--- a/clang/include/clang/Tooling/AllTUsExecution.h
+++ b/clang/include/clang/Tooling/AllTUsExecution.h
@@ -25,7 +25,7 @@ namespace tooling {
 /// database.
 class AllTUsToolExecutor : public ToolExecutor {
 public:
-  static const char *ExecutorName;
+  static constexpr char ExecutorName[] = "AllTUsToolExecutor";
 
   /// Init with \p CompilationDatabase.
   /// This uses \p ThreadCount threads to exececute the actions on all files in
diff --git a/clang/include/clang/Tooling/StandaloneExecution.h 
b/clang/include/clang/Tooling/StandaloneExecution.h
index cdbe65a95b9d2..eb669bb063c38 100644
--- a/clang/include/clang/Tooling/StandaloneExecution.h
+++ b/clang/include/clang/Tooling/StandaloneExecution.h
@@ -30,7 +30,7 @@ namespace tooling {
 ///   - `getClangStripDependencyFileAdjuster()`
 class StandaloneToolExecutor : public ToolExecutor {
 public:
-  static const char *ExecutorName;
+  static constexpr char ExecutorName[] = "StandaloneToolExecutor";
 
   /// Init with \p CompilationDatabase and the paths of all files to be
   /// proccessed.
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 780b2c585c810..8291624b76822 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -152,7 +152,7 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl 
*D) {
   return shouldMangleCXXName(D);
 }
 
-static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
+constexpr llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";
 
 /// Given an LLDB function call label, this function prints the label
 /// into \c Out, together with the structor type of \c GD (if the
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 17f5ee5dee3d1..f0973a716e19b 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -21,18 +21,11 @@ NSAPI::NSAPI(ASTContext &ctx)
     NSUTF8StringEncodingId(nullptr) {}
 
 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
-  static const char *ClassName[NumClassIds] = {
-    "NSObject",
-    "NSString",
-    "NSArray",
-    "NSMutableArray",
-    "NSDictionary",
-    "NSMutableDictionary",
-    "NSNumber",
-    "NSMutableSet",
-    "NSMutableOrderedSet",
-    "NSValue"
-  };
+  constexpr const char *const ClassName[NumClassIds] = {
+      "NSObject",       "NSString",     "NSArray",
+      "NSMutableArray", "NSDictionary", "NSMutableDictionary",
+      "NSNumber",       "NSMutableSet", "NSMutableOrderedSet",
+      "NSValue"};
 
   if (!ClassIds[K])
     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
@@ -284,43 +277,41 @@ std::optional<NSAPI::NSSetMethodKind> 
NSAPI::getNSSetMethodKind(Selector Sel) {
 
 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
                                            bool Instance) const {
-  static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
-    "numberWithChar",
-    "numberWithUnsignedChar",
-    "numberWithShort",
-    "numberWithUnsignedShort",
-    "numberWithInt",
-    "numberWithUnsignedInt",
-    "numberWithLong",
-    "numberWithUnsignedLong",
-    "numberWithLongLong",
-    "numberWithUnsignedLongLong",
-    "numberWithFloat",
-    "numberWithDouble",
-    "numberWithBool",
-    "numberWithInteger",
-    "numberWithUnsignedInteger"
-  };
-  static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
-    "initWithChar",
-    "initWithUnsignedChar",
-    "initWithShort",
-    "initWithUnsignedShort",
-    "initWithInt",
-    "initWithUnsignedInt",
-    "initWithLong",
-    "initWithUnsignedLong",
-    "initWithLongLong",
-    "initWithUnsignedLongLong",
-    "initWithFloat",
-    "initWithDouble",
-    "initWithBool",
-    "initWithInteger",
-    "initWithUnsignedInteger"
-  };
+  constexpr const char *const ClassSelectorName[NumNSNumberLiteralMethods] = {
+      "numberWithChar",
+      "numberWithUnsignedChar",
+      "numberWithShort",
+      "numberWithUnsignedShort",
+      "numberWithInt",
+      "numberWithUnsignedInt",
+      "numberWithLong",
+      "numberWithUnsignedLong",
+      "numberWithLongLong",
+      "numberWithUnsignedLongLong",
+      "numberWithFloat",
+      "numberWithDouble",
+      "numberWithBool",
+      "numberWithInteger",
+      "numberWithUnsignedInteger"};
+  constexpr const char *const InstanceSelectorName[NumNSNumberLiteralMethods] =
+      {"initWithChar",
+       "initWithUnsignedChar",
+       "initWithShort",
+       "initWithUnsignedShort",
+       "initWithInt",
+       "initWithUnsignedInt",
+       "initWithLong",
+       "initWithUnsignedLong",
+       "initWithLongLong",
+       "initWithUnsignedLongLong",
+       "initWithFloat",
+       "initWithDouble",
+       "initWithBool",
+       "initWithInteger",
+       "initWithUnsignedInteger"};
 
   Selector *Sels;
-  const char **Names;
+  const char *const *Names;
   if (Instance) {
     Sels = NSNumberInstanceSelectors;
     Names = InstanceSelectorName;
diff --git a/clang/lib/Analysis/IssueHash.cpp b/clang/lib/Analysis/IssueHash.cpp
index e4b73d37a63f3..47fe930cd1de4 100644
--- a/clang/lib/Analysis/IssueHash.cpp
+++ b/clang/lib/Analysis/IssueHash.cpp
@@ -132,7 +132,7 @@ static StringRef 
GetNthLineOfFile(std::optional<llvm::MemoryBufferRef> Buffer,
 
 static std::string NormalizeLine(const SourceManager &SM, const FullSourceLoc 
&L,
                                  const LangOptions &LangOpts) {
-  static StringRef Whitespaces = " \t\n";
+  constexpr StringRef Whitespaces = " \t\n";
 
   StringRef Str = GetNthLineOfFile(SM.getBufferOrNone(L.getFileID(), L),
                                    L.getExpansionLineNumber());
@@ -183,7 +183,7 @@ std::string clang::getIssueString(const FullSourceLoc 
&IssueLoc,
                                   StringRef WarningMessage,
                                   const Decl *IssueDecl,
                                   const LangOptions &LangOpts) {
-  static StringRef Delimiter = "$";
+  constexpr StringRef Delimiter = "$";
 
   return (llvm::Twine(CheckerName) + Delimiter +
           GetEnclosingDeclContextSignature(IssueDecl) + Delimiter +
diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp 
b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index 0a383c8f919d9..4e171691029eb 100644
--- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -32,7 +32,7 @@ static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
 
 namespace {
 enum { DstIdx = 0, SrcIdx = 1 };
-const char *ValNameStr[2] = {"dst", "src"};
+constexpr char *const ValNameStr[2] = {"dst", "src"};
 
 template <class Derived> struct StructVisitor {
   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index c52610f1cae7b..fcf6b05a4411b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -219,7 +219,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef 
TargetTriple,
 }
 
 void Driver::setDriverMode(StringRef Value) {
-  static StringRef OptName =
+  static const StringRef OptName =
       getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
   if (auto M = llvm::StringSwitch<std::optional<DriverMode>>(Value)
                    .Case("gcc", GCCMode)
@@ -7220,7 +7220,7 @@ bool clang::driver::willEmitRemarks(const ArgList &Args) {
 
 llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,
                                              ArrayRef<const char *> Args) {
-  static StringRef OptName =
+  static const StringRef OptName =
       
getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName();
   llvm::StringRef Opt;
   for (StringRef Arg : Args) {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 6dbb51a26868d..be9cb19149da7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6518,8 +6518,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     CmdArgs.push_back("-relocatable-pch");
 
   if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
-    static const char *kCFABIs[] = {
-      "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
+    constexpr char *const kCFABIs[] = {
+        "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
     };
 
     if (!llvm::is_contained(kCFABIs, StringRef(A->getValue())))
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 2f67ec86b101a..6a069778fa5e6 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4338,7 +4338,7 @@ LangOptions getFormattingLangOpts(const FormatStyle 
&Style) {
   return LangOpts;
 }
 
-const char *StyleOptionHelpDescription =
+const char *const StyleOptionHelpDescription =
     "Set coding style. <string> can be:\n"
     "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
     "   Mozilla, WebKit.\n"
@@ -4449,9 +4449,9 @@ FormatStyle::LanguageKind guessLanguage(StringRef 
FileName, StringRef Code) {
 }
 
 // Update StyleOptionHelpDescription above when changing this.
-const char *DefaultFormatStyle = "file";
+const char *const DefaultFormatStyle = "file";
 
-const char *DefaultFallbackStyle = "LLVM";
+const char *const DefaultFallbackStyle = "LLVM";
 
 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
diff --git a/clang/lib/InstallAPI/DirectoryScanner.cpp 
b/clang/lib/InstallAPI/DirectoryScanner.cpp
index f8f708fda4ca4..bdf375bbdbda4 100644
--- a/clang/lib/InstallAPI/DirectoryScanner.cpp
+++ b/clang/lib/InstallAPI/DirectoryScanner.cpp
@@ -275,9 +275,9 @@ llvm::Error DirectoryScanner::scanForFrameworks(StringRef 
Directory) {
 
   // Expect a certain directory structure and naming convention to find
   // frameworks.
-  static const char *SubDirectories[] = {"System/Library/Frameworks/",
-                                         "System/Library/PrivateFrameworks/",
-                                         "System/Library/SubFrameworks"};
+  constexpr const char *const SubDirectories[] = {
+      "System/Library/Frameworks/", "System/Library/PrivateFrameworks/",
+      "System/Library/SubFrameworks"};
 
   // Check if the directory is already a framework.
   if (isFramework(Directory)) {
@@ -288,7 +288,7 @@ llvm::Error DirectoryScanner::scanForFrameworks(StringRef 
Directory) {
   }
 
   // Check known sub-directory locations.
-  for (const auto *SubDir : SubDirectories) {
+  for (const auto *const SubDir : SubDirectories) {
     SmallString<PATH_MAX> Path(Directory);
     sys::path::append(Path, SubDir);
 
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 98d78d2a461f1..5c1031cbf69fa 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10471,8 +10471,8 @@ void 
SemaCodeCompletion::CodeCompleteAvailabilityPlatformName() {
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
   Results.EnterNewScope();
-  static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
-  for (const char *Platform : llvm::ArrayRef(Platforms)) {
+  constexpr const char *const Platforms[] = {"macOS", "iOS", "watchOS", 
"tvOS"};
+  for (const char *const Platform : llvm::ArrayRef(Platforms)) {
     Results.AddResult(CodeCompletionResult(Platform));
     Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
         Twine(Platform) + "ApplicationExtension")));
diff --git a/clang/lib/Serialization/ObjectFilePCHContainerReader.cpp 
b/clang/lib/Serialization/ObjectFilePCHContainerReader.cpp
index 59fc46960dc60..08634bf9fe15e 100644
--- a/clang/lib/Serialization/ObjectFilePCHContainerReader.cpp
+++ b/clang/lib/Serialization/ObjectFilePCHContainerReader.cpp
@@ -13,7 +13,7 @@
 using namespace clang;
 
 ArrayRef<StringRef> ObjectFilePCHContainerReader::getFormats() const {
-  static StringRef Formats[] = {"obj", "raw"};
+  static const StringRef Formats[] = {"obj", "raw"};
   return Formats;
 }
 
diff --git a/clang/lib/Serialization/PCHContainerOperations.cpp 
b/clang/lib/Serialization/PCHContainerOperations.cpp
index 4aedb7debcff2..881f59ba4ab0e 100644
--- a/clang/lib/Serialization/PCHContainerOperations.cpp
+++ b/clang/lib/Serialization/PCHContainerOperations.cpp
@@ -56,7 +56,7 @@ std::unique_ptr<ASTConsumer> 
RawPCHContainerWriter::CreatePCHContainerGenerator(
 }
 
 ArrayRef<llvm::StringRef> RawPCHContainerReader::getFormats() const {
-  static StringRef Raw("raw");
+  static const StringRef Raw("raw");
   return ArrayRef(Raw);
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index be61eceeb62e7..51b2fa8299c33 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -399,7 +399,7 @@ namespace llvm {
 template <> struct format_provider<ValueDescStr> {
   static void format(const ValueDescStr &V, raw_ostream &Stream,
                      StringRef Style) {
-    static const char *ValueStr[2][3] = {
+    constexpr const char *const ValueStr[2][3] = {
         {"zero", "nonzero integer value", "probably nonzero integer value"},
         {"null pointer", "non-null pointer", "probably non-null pointer"},
     };
diff --git a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
index 46c7a6cd9a4dc..108f215944b94 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp
@@ -36,7 +36,7 @@ namespace {
 
 // Name of the "errno" variable.
 // FIXME: Is there a system where it is not called "errno" but is a variable?
-const char *ErrnoVarName = "errno";
+constexpr char ErrnoVarName[] = "errno";
 
 // Names of functions that return a location of the "errno" value.
 // FIXME: Are there other similar function names?
diff --git a/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
index 5637941a58f02..b719613e8ddcc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -43,7 +43,7 @@ using namespace ast_matchers;
 namespace {
 
 // ID of a node at which the diagnostic would be emitted.
-const char *WarnAtNode = "waitcall";
+constexpr char WarnAtNode[] = "waitcall";
 
 class GCDAntipatternChecker : public Checker<check::ASTCodeBody> {
 public:
diff --git a/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp 
b/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
index 46690dd886b2b..c12f0d070dfc3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
@@ -24,8 +24,8 @@ using namespace ento;
 using namespace ast_matchers;
 
 namespace {
-static constexpr const char *const WarnAtNode = "WarnAtNode";
-static constexpr const char *const WarnRecordDecl = "WarnRecordDecl";
+constexpr char WarnAtNode[] = "WarnAtNode";
+constexpr char WarnRecordDecl[] = "WarnRecordDecl";
 
 class OSObjectCStyleCastChecker : public Checker<check::ASTCodeBody> {
 public:
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
index e7fd14d4558b2..c595bb0deafc0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -41,11 +41,11 @@ using namespace ast_matchers;
 
 namespace {
 
-const char *ProblematicWriteBind = "problematicwrite";
-const char *CapturedBind = "capturedbind";
-const char *ParamBind = "parambind";
-const char *IsMethodBind = "ismethodbind";
-const char *IsARPBind = "isautoreleasepoolbind";
+constexpr char ProblematicWriteBind[] = "problematicwrite";
+constexpr char CapturedBind[] = "capturedbind";
+constexpr char ParamBind[] = "parambind";
+constexpr char IsMethodBind[] = "ismethodbind";
+constexpr char IsARPBind[] = "isautoreleasepoolbind";
 
 class ObjCAutoreleaseWriteChecker : public Checker<check::ASTCodeBody> {
 public:
diff --git 
a/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
index 2cf6c6ff47f1d..66565fa579707 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
@@ -40,11 +40,11 @@ using namespace ast_matchers;
 
 namespace {
 
-const char * RunLoopBind = "NSRunLoopM";
-const char * RunLoopRunBind = "RunLoopRunM";
-const char * OtherMsgBind = "OtherMessageSentM";
-const char * AutoreleasePoolBind = "AutoreleasePoolM";
-const char * OtherStmtAutoreleasePoolBind = "OtherAutoreleasePoolM";
+constexpr char RunLoopBind[] = "NSRunLoopM";
+constexpr char RunLoopRunBind[] = "RunLoopRunM";
+constexpr char OtherMsgBind[] = "OtherMessageSentM";
+constexpr char AutoreleasePoolBind[] = "AutoreleasePoolM";
+constexpr char OtherStmtAutoreleasePoolBind[] = "OtherAutoreleasePoolM";
 
 class RunLoopAutoreleaseLeakChecker : public Checker<check::ASTCodeBody> {
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 6481b76e69171..feada75dd1b1a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -198,8 +198,8 @@ using FnCheck = std::function<void(const StreamChecker *, 
const FnDescription *,
 using ArgNoTy = unsigned int;
 static const ArgNoTy ArgNone = std::numeric_limits<ArgNoTy>::max();
 
-const char *FeofNote = "Assuming stream reaches end-of-file here";
-const char *FerrorNote = "Assuming this stream operation fails";
+constexpr char FeofNote[] = "Assuming stream reaches end-of-file here";
+constexpr char FerrorNote[] = "Assuming this stream operation fails";
 
 struct FnDescription {
   FnCheck PreFn;
@@ -1923,7 +1923,7 @@ ProgramStateRef StreamChecker::ensureStreamOpened(SVal 
StreamVal,
 
 ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate(
     SVal StreamVal, CheckerContext &C, ProgramStateRef State) const {
-  static const char *BugMessage =
+  constexpr char BugMessage[] =
       "File position of the stream might be 'indeterminate' "
       "after a failed operation. "
       "Can cause undefined behavior.";
diff --git a/clang/lib/Tooling/AllTUsExecution.cpp 
b/clang/lib/Tooling/AllTUsExecution.cpp
index 9cad8680447be..69291bbbc9fa8 100644
--- a/clang/lib/Tooling/AllTUsExecution.cpp
+++ b/clang/lib/Tooling/AllTUsExecution.cpp
@@ -16,8 +16,6 @@
 namespace clang {
 namespace tooling {
 
-const char *AllTUsToolExecutor::ExecutorName = "AllTUsToolExecutor";
-
 namespace {
 llvm::Error make_string_error(const llvm::Twine &Message) {
   return llvm::make_error<llvm::StringError>(Message,
diff --git a/clang/lib/Tooling/StandaloneExecution.cpp 
b/clang/lib/Tooling/StandaloneExecution.cpp
index 09094c3c23f34..706ee3f3d8d28 100644
--- a/clang/lib/Tooling/StandaloneExecution.cpp
+++ b/clang/lib/Tooling/StandaloneExecution.cpp
@@ -17,8 +17,6 @@ static llvm::Error make_string_error(const llvm::Twine 
&Message) {
                                              llvm::inconvertibleErrorCode());
 }
 
-const char *StandaloneToolExecutor::ExecutorName = "StandaloneToolExecutor";
-
 static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
   return combineAdjusters(
       getClangStripOutputAdjuster(),
diff --git a/clang/unittests/Tooling/ExecutionTest.cpp 
b/clang/unittests/Tooling/ExecutionTest.cpp
index c81049308f706..284965a66cb64 100644
--- a/clang/unittests/Tooling/ExecutionTest.cpp
+++ b/clang/unittests/Tooling/ExecutionTest.cpp
@@ -87,7 +87,7 @@ class ReportResultActionFactory : public 
FrontendActionFactory {
 
 class TestToolExecutor : public ToolExecutor {
 public:
-  static const char *ExecutorName;
+  static constexpr char ExecutorName[] = "test-executor";
 
   TestToolExecutor(CommonOptionsParser Options)
       : OptionsParser(std::move(Options)) {}
@@ -118,8 +118,6 @@ class TestToolExecutor : public ToolExecutor {
   std::map<std::string, std::string> VFS;
 };
 
-const char *TestToolExecutor::ExecutorName = "test-executor";
-
 class TestToolExecutorPlugin : public ToolExecutorPlugin {
 public:
   llvm::Expected<std::unique_ptr<ToolExecutor>>

>From 0c5cd45417ce1faaba33294e82d5328c3e5a9803 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 25 Feb 2026 06:36:47 -0600
Subject: [PATCH 2/4] Revert format changes

The strings in Format.cpp and Format.h are currently used as mutable
global state, so they cannot be declared as const for now.
This commit reverts the changes to these strings.

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/include/clang/Format/Format.h | 6 +++---
 clang/lib/Format/Format.cpp         | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 8dba796126f18..2028c963ac306 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -6174,16 +6174,16 @@ LangOptions getFormattingLangOpts(const FormatStyle 
&Style = getLLVMStyle());
 /// Description to be used for help text for a ``llvm::cl`` option for
 /// specifying format style. The description is closely related to the 
operation
 /// of ``getStyle()``.
-extern const char *const StyleOptionHelpDescription;
+extern const char *StyleOptionHelpDescription;
 
 /// The suggested format style to use by default. This allows tools using
 /// ``getStyle`` to have a consistent default style.
 /// Different builds can modify the value to the preferred styles.
-extern const char *const DefaultFormatStyle;
+extern const char *DefaultFormatStyle;
 
 /// The suggested predefined style to use as the fallback style in 
``getStyle``.
 /// Different builds can modify the value to the preferred styles.
-extern const char *const DefaultFallbackStyle;
+extern const char *DefaultFallbackStyle;
 
 /// Construct a FormatStyle based on ``StyleName``.
 ///
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 6a069778fa5e6..2f67ec86b101a 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4338,7 +4338,7 @@ LangOptions getFormattingLangOpts(const FormatStyle 
&Style) {
   return LangOpts;
 }
 
-const char *const StyleOptionHelpDescription =
+const char *StyleOptionHelpDescription =
     "Set coding style. <string> can be:\n"
     "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
     "   Mozilla, WebKit.\n"
@@ -4449,9 +4449,9 @@ FormatStyle::LanguageKind guessLanguage(StringRef 
FileName, StringRef Code) {
 }
 
 // Update StyleOptionHelpDescription above when changing this.
-const char *const DefaultFormatStyle = "file";
+const char *DefaultFormatStyle = "file";
 
-const char *const DefaultFallbackStyle = "LLVM";
+const char *DefaultFallbackStyle = "LLVM";
 
 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,

>From a850bbd811e165b70690f893953eb42c0a0e77e9 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 25 Feb 2026 06:41:17 -0600
Subject: [PATCH 3/4] Add missing const

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/lib/CodeGen/CGNonTrivialStruct.cpp | 2 +-
 clang/lib/Driver/ToolChains/Clang.cpp    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp 
b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index 4e171691029eb..52345ec212b64 100644
--- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -32,7 +32,7 @@ static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
 
 namespace {
 enum { DstIdx = 0, SrcIdx = 1 };
-constexpr char *const ValNameStr[2] = {"dst", "src"};
+constexpr const char *const ValNameStr[2] = {"dst", "src"};
 
 template <class Derived> struct StructVisitor {
   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index be9cb19149da7..186f228740b17 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6518,7 +6518,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     CmdArgs.push_back("-relocatable-pch");
 
   if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
-    constexpr char *const kCFABIs[] = {
+    constexpr const char *const kCFABIs[] = {
         "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
     };
 

>From 0334cd9117b9414bda2d16f261ab362985639b99 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 25 Feb 2026 07:04:15 -0600
Subject: [PATCH 4/4] Remove rendundant const

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/lib/AST/NSAPI.cpp                       | 36 +++++++++----------
 clang/lib/CodeGen/CGNonTrivialStruct.cpp      |  2 +-
 clang/lib/Driver/ToolChains/Clang.cpp         |  2 +-
 clang/lib/InstallAPI/DirectoryScanner.cpp     |  6 ++--
 clang/lib/Sema/SemaCodeComplete.cpp           |  2 +-
 .../Checkers/DereferenceChecker.cpp           |  2 +-
 6 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index f0973a716e19b..d8dd96f7ae7fa 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -21,7 +21,7 @@ NSAPI::NSAPI(ASTContext &ctx)
     NSUTF8StringEncodingId(nullptr) {}
 
 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
-  constexpr const char *const ClassName[NumClassIds] = {
+  constexpr const char *ClassName[NumClassIds] = {
       "NSObject",       "NSString",     "NSArray",
       "NSMutableArray", "NSDictionary", "NSMutableDictionary",
       "NSNumber",       "NSMutableSet", "NSMutableOrderedSet",
@@ -277,7 +277,7 @@ std::optional<NSAPI::NSSetMethodKind> 
NSAPI::getNSSetMethodKind(Selector Sel) {
 
 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
                                            bool Instance) const {
-  constexpr const char *const ClassSelectorName[NumNSNumberLiteralMethods] = {
+  constexpr const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
       "numberWithChar",
       "numberWithUnsignedChar",
       "numberWithShort",
@@ -293,22 +293,22 @@ Selector 
NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
       "numberWithBool",
       "numberWithInteger",
       "numberWithUnsignedInteger"};
-  constexpr const char *const InstanceSelectorName[NumNSNumberLiteralMethods] =
-      {"initWithChar",
-       "initWithUnsignedChar",
-       "initWithShort",
-       "initWithUnsignedShort",
-       "initWithInt",
-       "initWithUnsignedInt",
-       "initWithLong",
-       "initWithUnsignedLong",
-       "initWithLongLong",
-       "initWithUnsignedLongLong",
-       "initWithFloat",
-       "initWithDouble",
-       "initWithBool",
-       "initWithInteger",
-       "initWithUnsignedInteger"};
+  constexpr const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
+      "initWithChar",
+      "initWithUnsignedChar",
+      "initWithShort",
+      "initWithUnsignedShort",
+      "initWithInt",
+      "initWithUnsignedInt",
+      "initWithLong",
+      "initWithUnsignedLong",
+      "initWithLongLong",
+      "initWithUnsignedLongLong",
+      "initWithFloat",
+      "initWithDouble",
+      "initWithBool",
+      "initWithInteger",
+      "initWithUnsignedInteger"};
 
   Selector *Sels;
   const char *const *Names;
diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp 
b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index 52345ec212b64..c9e863439d1eb 100644
--- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -32,7 +32,7 @@ static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
 
 namespace {
 enum { DstIdx = 0, SrcIdx = 1 };
-constexpr const char *const ValNameStr[2] = {"dst", "src"};
+constexpr const char *ValNameStr[2] = {"dst", "src"};
 
 template <class Derived> struct StructVisitor {
   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 186f228740b17..6a7b7d543adfb 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6518,7 +6518,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     CmdArgs.push_back("-relocatable-pch");
 
   if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
-    constexpr const char *const kCFABIs[] = {
+    constexpr const char *kCFABIs[] = {
         "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
     };
 
diff --git a/clang/lib/InstallAPI/DirectoryScanner.cpp 
b/clang/lib/InstallAPI/DirectoryScanner.cpp
index bdf375bbdbda4..77eb244e8112d 100644
--- a/clang/lib/InstallAPI/DirectoryScanner.cpp
+++ b/clang/lib/InstallAPI/DirectoryScanner.cpp
@@ -275,9 +275,9 @@ llvm::Error DirectoryScanner::scanForFrameworks(StringRef 
Directory) {
 
   // Expect a certain directory structure and naming convention to find
   // frameworks.
-  constexpr const char *const SubDirectories[] = {
-      "System/Library/Frameworks/", "System/Library/PrivateFrameworks/",
-      "System/Library/SubFrameworks"};
+  constexpr const char *SubDirectories[] = {"System/Library/Frameworks/",
+                                            
"System/Library/PrivateFrameworks/",
+                                            "System/Library/SubFrameworks"};
 
   // Check if the directory is already a framework.
   if (isFramework(Directory)) {
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 5c1031cbf69fa..d7b3fca2e92ac 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -10471,7 +10471,7 @@ void 
SemaCodeCompletion::CodeCompleteAvailabilityPlatformName() {
                         CodeCompleter->getCodeCompletionTUInfo(),
                         CodeCompletionContext::CCC_Other);
   Results.EnterNewScope();
-  constexpr const char *const Platforms[] = {"macOS", "iOS", "watchOS", 
"tvOS"};
+  constexpr const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
   for (const char *const Platform : llvm::ArrayRef(Platforms)) {
     Results.AddResult(CodeCompletionResult(Platform));
     Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 51b2fa8299c33..efaf21a842c32 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -399,7 +399,7 @@ namespace llvm {
 template <> struct format_provider<ValueDescStr> {
   static void format(const ValueDescStr &V, raw_ostream &Stream,
                      StringRef Style) {
-    constexpr const char *const ValueStr[2][3] = {
+    constexpr const char *ValueStr[2][3] = {
         {"zero", "nonzero integer value", "probably nonzero integer value"},
         {"null pointer", "non-null pointer", "probably non-null pointer"},
     };

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to