https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/194693

From 64bc65d2d282cf35c80bd71895f95fd7b5a32174 Mon Sep 17 00:00:00 2001
From: Balazs Benics <[email protected]>
Date: Tue, 28 Apr 2026 17:48:07 +0100
Subject: [PATCH 1/2] Reapply "[clang][ssaf][NFC] Rework how the Force linker
 anchors are defined and used" (#193451)

This reverts commit 582958c4337f539e650096c0257a322315298e1a.
---
 .../developer-docs/ForceLinkerHeaders.rst     | 34 ++++++----
 .../developer-docs/HowToExtend.rst            | 27 +++++---
 .../BuiltinAnchorSources.def                  | 30 +++++++++
 .../SerializationFormatRegistry.h             | 10 ++-
 .../Core/TUSummary/ExtractorRegistry.h        | 10 ++-
 .../WholeProgramAnalysis/AnalysisRegistry.h   | 14 ++--
 .../SSAFBuiltinForceLinker.h                  | 65 +++++--------------
 .../Analyses/CallGraph/CallGraphExtractor.cpp |  6 +-
 .../CallGraph/CallGraphJSONFormat.cpp         |  6 +-
 .../PointerFlow/PointerFlowAnalysis.cpp       |  4 +-
 .../PointerFlow/PointerFlowExtractor.cpp      |  4 +-
 .../PointerFlow/PointerFlowFormat.cpp         |  4 +-
 .../UnsafeBufferUsageAnalysis.cpp             |  4 +-
 .../UnsafeBufferUsageExtractor.cpp            |  5 +-
 .../UnsafeBufferUsageFormat.cpp               |  4 +-
 .../JSONFormat/JSONFormatImpl.cpp             | 14 ++--
 .../WholeProgramAnalysis/AnalysisRegistry.cpp | 11 ++--
 .../TUSummaryExtractorFrontendActionTest.cpp  |  4 --
 .../Registries/FancyAnalysisData.cpp          |  2 -
 .../Registries/MockSerializationFormat.cpp    |  2 -
 .../Registries/MockSummaryExtractor1.cpp      |  2 -
 .../Registries/MockSummaryExtractor2.cpp      |  2 -
 .../SSAFBuiltinTestForceLinker.h              | 51 ---------------
 .../SSAFTestForceLinker.h                     | 23 -------
 .../TestFixture.cpp                           |  1 -
 .../AnalysisDriverTest.cpp                    |  4 --
 26 files changed, 136 insertions(+), 207 deletions(-)
 create mode 100644 
clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
 delete mode 100644 
clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
 delete mode 100644 
clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h

diff --git 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
index c04b2b786308f..d4504aa5a793a 100644
--- 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
+++ 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
@@ -33,26 +33,29 @@ constructors unconditionally.
 The solution: anchor symbols
 ****************************
 
-Each registration translation unit defines a ``volatile int`` **anchor 
symbol**:
+Each registration translation unit defines a ``const volatile int`` **anchor 
symbol**:
 
 .. code-block:: c++
 
-  // In MyExtractor.cpp — next to the registry Add<> object
+  // In MyExtractor.cpp - next to the registry Add<> object in the 
``clang::ssaf`` namespace
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  volatile int SSAFMyExtractorAnchorSource = 0;
+  const volatile int MyExtractorAnchorSource = 0;
 
-A **force-linker header** declares the symbol as ``extern`` and reads it into a
-``[[maybe_unused]] static int`` destination:
+For **in-tree** anchors, add a single ``ANCHOR(...)`` entry to
+``BuiltinAnchorSources.def`` (in alphabetical order):
 
 .. code-block:: c++
 
-  // In SSAFBuiltinForceLinker.h
-  extern volatile int SSAFMyExtractorAnchorSource;
-  [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
-      SSAFMyExtractorAnchorSource;
+  // In 
clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
+  ANCHOR(JSONFormatAnchorSource)
+  ANCHOR(MyExtractorAnchorSource) // <-- Add here, in alphabetical order
+
+``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically to
+generate the ``extern`` declarations and the ``AnchorSources`` array — there is
+no need to edit that header directly.
 
 Any translation unit that ``#include``\s this header now has a reference to
-``SSAFMyExtractorAnchorSource``, which forces the linker to pull in
+``MyExtractorAnchorSource``, which forces the linker to pull in
 ``MyExtractor.o`` — and with it, the static ``Add<>`` registration object.
 
 The ``volatile`` qualifier is essential: without it the compiler could
@@ -85,11 +88,14 @@ point of a binary that uses 
``clangScalableStaticAnalysisFrameworkCore``:
 Naming convention
 =================
 
-Anchor symbols follow the pattern ``SSAF<Component>AnchorSource`` and
-``SSAF<Component>AnchorDestination``.  For example:
+Anchor symbols follow the pattern ``<Component>AnchorSource`` in the 
``clang::ssaf`` namespace.
+For example:
+
+- ``JSONFormatAnchorSource``
+- ``MyExtractorAnchorSource``
 
-- ``SSAFJSONFormatAnchorSource`` / ``SSAFJSONFormatAnchorDestination``
-- ``SSAFMyExtractorAnchorSource`` / ``SSAFMyExtractorAnchorDestination``
+All anchor sources are aggregated into a single ``BuiltinAnchorDestination``
+lambda in the force-linker header (see ``SSAFBuiltinForceLinker.h``).
 
 Considered alternatives
 ***********************
diff --git 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
index e5c717bec0892..761ee0eeb92ba 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
@@ -53,8 +53,10 @@ Step 2: Register the extractor
 
   using namespace clang::ssaf;
 
+  namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  volatile int SSAFMyExtractorAnchorSource = 0;
+  const volatile int MyExtractorAnchorSource = 0;
+  } // namespace clang::ssaf
 
   static TUSummaryExtractorRegistry::Add<MyExtractor>
       RegisterExtractor("MyExtractor", "My awesome summary extractor");
@@ -65,16 +67,17 @@ Step 3: Add the force-linker anchor
 ===================================
 
 See :doc:`ForceLinkerHeaders` for a full explanation of why this is needed.
-Add the following to the appropriate force-linker header:
+
+For **in-tree** additions, add one line to
+``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def``
+(in alphabetical order):
 
 .. code-block:: c++
 
-  extern volatile int SSAFMyExtractorAnchorSource;
-  [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
-      SSAFMyExtractorAnchorSource;
+  ANCHOR(MyExtractorAnchorSource)
 
-For **in-tree** additions, add this to
-``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
+``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically — no
+need to edit it directly.
 
 For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
 
@@ -122,8 +125,10 @@ Step 2: Register the format
 
   using namespace clang::ssaf;
 
+  namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  volatile int SSAFMyFormatAnchorSource = 0;
+  const volatile int MyFormatAnchorSource = 0;
+  } // namespace clang::ssaf
 
   static SerializationFormatRegistry::Add<MyFormat>
       RegisterFormat("myformat", "My awesome serialization format");
@@ -158,7 +163,9 @@ For each analysis that should be serializable in your 
format, register a ``Forma
 Step 4: Add the force-linker anchor
 ===================================
 
-Same pattern as for extractors — see `Adding a summary extractor`_ Step 3, and 
:doc:`ForceLinkerHeaders`.
+Same pattern as for extractors — add the anchor to ``BuiltinAnchorSources.def``
+(in alphabetical order). See `Adding a summary extractor`_ Step 3,
+and :doc:`ForceLinkerHeaders`.
 
 
 Static extensibility
@@ -169,7 +176,7 @@ In-tree extensions
 
 For extensions that are part of the upstream LLVM/Clang tree:
 
-#. Add the anchor to 
``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
+#. Add the anchor to 
``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def``
 (in alphabetical order).
 #. Add the source files to the ``clangScalableStaticAnalysisFrameworkCore`` 
CMake library target.
 #. That's it — the ``SSAFForceLinker.h`` umbrella includes 
``SSAFBuiltinForceLinker.h``
    transitively, so any binary that includes the umbrella will pull in the 
registration.
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def 
b/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
new file mode 100644
index 0000000000000..7dd866047f556
--- /dev/null
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
@@ -0,0 +1,30 @@
+//===- BuiltinAnchorSources.def ---------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file lists all the SSAF Anchor source names.
+/// This file should be exclusively used by SSAFBuiltinForceLinker.h
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ANCHOR
+#define ANCHOR(NAME)
+#endif
+
+ANCHOR(AnalysisRegistryAnchorSource)
+ANCHOR(CallGraphExtractorAnchorSource)
+ANCHOR(CallGraphJSONFormatAnchorSource)
+ANCHOR(JSONFormatAnchorSource)
+ANCHOR(PointerFlowAnalysisAnchorSource)
+ANCHOR(PointerFlowExtractorAnchorSource)
+ANCHOR(PointerFlowJSONFormatAnchorSource)
+ANCHOR(UnsafeBufferUsageAnalysisAnchorSource)
+ANCHOR(UnsafeBufferUsageExtractorAnchorSource)
+ANCHOR(UnsafeBufferUsageJSONFormatAnchorSource)
+
+#undef ANCHOR
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
index 61b08b4c0a1bd..24bfa554a3b77 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
@@ -21,8 +21,10 @@
 //
 // Insert this code to the cpp file:
 //
+//   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   volatile int SSAFMyFormatAnchorSource = 0;
+//   const volatile int MyFormatAnchorSource = 0;
+//   } // namespace clang::ssaf
 //   static SerializationFormatRegistry::Add<MyFormat>
 //     RegisterFormat("MyFormat", "My awesome serialization format");
 //   LLVM_DEFINE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
@@ -47,15 +49,11 @@
 //         "The MyFormat format info implementation for MyAnalysis"
 //       );
 //
-// Finally, insert a use of the new anchor symbol into the force-linker header:
+// Finally, extend the `AnchorSources` list in the force-linker header:
 // 
clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
 //
 // This anchor is used to force the linker to link the MyFormat registration.
 //
-//   extern volatile int SSAFMyFormatAnchorSource;
-//   [[maybe_unused]] static int SSAFMyFormatAnchorDestination =
-//       SSAFMyFormatAnchorSource;
-//
 
//===----------------------------------------------------------------------===//
 
 #ifndef 
LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
index 8639439dc1616..e96d7da11b750 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
@@ -9,18 +9,16 @@
 // Registry for TUSummaryExtractors, and some helper functions.
 // To register some custom extractor, insert this code:
 //
+//   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   volatile int SSAFMyExtractorAnchorSource = 0;
+//   const volatile int MyExtractorAnchorSource = 0;
+//   } // namespace clang::ssaf
 //   static TUSummaryExtractorRegistry::Add<MyExtractor>
 //     X("MyExtractor", "My awesome extractor");
 //
-// Finally, insert a use of the new anchor symbol into the force-linker header:
+// Finally, extend the `AnchorSources` list in the force-linker header:
 // 
clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
 //
-//   extern volatile int SSAFMyExtractorAnchorSource;
-//   [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
-//       SSAFMyExtractorAnchorSource;
-//
 
//===----------------------------------------------------------------------===//
 
 #ifndef 
LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
index c1698db05abbb..5612b092f6faf 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
@@ -9,19 +9,19 @@
 // Unified registry for both SummaryAnalysis and DerivedAnalysis subclasses.
 //
 // To register an analysis, add a static Add<AnalysisT> and an anchor source
-// in its translation unit, then add the matching anchor destination to the
-// relevant force-linker header:
+// in its translation unit, then add the anchor source to the `AnchorSources`
+// list in the relevant force-linker header:
 //
 //   // MyAnalysis.cpp
 //   static AnalysisRegistry::Add<MyAnalysis>
 //       Registered("One-line description of MyAnalysis");
 //
-//   volatile int SSAFMyAnalysisAnchorSource = 0;
+//   namespace clang::ssaf {
+//   // NOLINTNEXTLINE(misc-use-internal-linkage)
+//   const volatile int MyAnalysisAnchorSource = 0;
+//   } // namespace clang::ssaf
 //
-//   // SSAFBuiltinForceLinker.h (or the relevant force-linker header)
-//   extern volatile int SSAFMyAnalysisAnchorSource;
-//   [[maybe_unused]] static int SSAFMyAnalysisAnchorDestination =
-//       SSAFMyAnalysisAnchorSource;
+//   // Extend SSAFBuiltinForceLinker.h (or the relevant force-linker header)
 //
 // The registry entry name is derived automatically from
 // MyAnalysis::analysisName(), so name-mismatch bugs are impossible.
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h 
b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 26b1fe4a47840..0bfc4356969a5 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -20,59 +20,24 @@
 #ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
 #define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
 
-// TODO: Move these to the `clang::ssaf` namespace.
+namespace clang::ssaf {
 
-// This anchor is used to force the linker to link the JSONFormat registration.
-extern volatile int SSAFJSONFormatAnchorSource;
-[[maybe_unused]] static int SSAFJSONFormatAnchorDestination =
-    SSAFJSONFormatAnchorSource;
+#define ANCHOR(NAME) extern const volatile int NAME;
+#include "BuiltinAnchorSources.def"
 
-// This anchor is used to force the linker to link the AnalysisRegistry.
-extern volatile int SSAFAnalysisRegistryAnchorSource;
-[[maybe_unused]] static int SSAFAnalysisRegistryAnchorDestination =
-    SSAFAnalysisRegistryAnchorSource;
+// Force the linker to link in the built-in SSAF registrations.
+[[maybe_unused]] static const int BuiltinAnchorDestination = [] {
+  int AnchorSources[]{
+#define ANCHOR(NAME) NAME,
+#include "BuiltinAnchorSources.def"
+  };
 
-// This anchor is used to force the linker to link the UnsafeBufferUsage
-// JSON format.
-extern volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource;
-[[maybe_unused]] static int UnsafeBufferUsageSSAFJSONFormatAnchorDestination =
-    UnsafeBufferUsageSSAFJSONFormatAnchorSource;
+  int SomeUse = 0;
+  for (int V : AnchorSources)
+    SomeUse |= V;
+  return SomeUse;
+}();
 
-// This anchor is used to force the linker to link the
-// UnsafeBufferUsageTUSummaryExtractor.
-extern volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource;
-[[maybe_unused]] static int
-    UnsafeBufferUsageTUSummaryExtractorAnchorDestination =
-        UnsafeBufferUsageTUSummaryExtractorAnchorSource;
-
-extern volatile int UnsafeBufferUsageAnalysisAnchorSource;
-[[maybe_unused]] static int UnsafeBufferUsageAnalysisAnchorDestination =
-    UnsafeBufferUsageAnalysisAnchorSource;
-
-// This anchor is used to force the linker to link the PointerFlow
-// JSONFormat registration:
-extern volatile int PointerFlowSSAFJSONFormatAnchorSource;
-[[maybe_unused]] static int PointerFlowSSAFJSONFormatAnchorDestination =
-    PointerFlowSSAFJSONFormatAnchorSource;
-
-// This anchor is used to force the linker to link the PointerFlow
-// TUSummaryExtractor registration.
-extern volatile int PointerFlowTUSummaryExtractorAnchorSource;
-[[maybe_unused]] static int PointerFlowTUSummaryExtractorAnchorDestination =
-    PointerFlowTUSummaryExtractorAnchorSource;
-
-extern volatile int PointerFlowAnalysisAnchorSource;
-[[maybe_unused]] static int PointerFlowAnalysisAnchorDestination =
-    PointerFlowAnalysisAnchorSource;
-
-// This anchor is used to force the linker to link the CallGraphExtractor.
-extern volatile int CallGraphExtractorAnchorSource;
-[[maybe_unused]] static int CallGraphExtractorAnchorDestination =
-    CallGraphExtractorAnchorSource;
-
-// This anchor is used to force the linker to link the CallGraph JSON format.
-extern volatile int CallGraphJSONFormatAnchorSource;
-[[maybe_unused]] static int CallGraphJSONFormatAnchorDestination =
-    CallGraphJSONFormatAnchorSource;
+} // namespace clang::ssaf
 
 #endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index 3436da7c2244b..d7fa4d5434979 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -98,7 +98,7 @@ static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
     RegisterExtractor(CallGraphSummary::Name,
                       "Extracts static call-graph information");
 
-// This anchor is used to force the linker to link in the generated object file
-// and thus register the CallGraphExtractor.
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int CallGraphExtractorAnchorSource = 0;
+const volatile int CallGraphExtractorAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
index 860e26417eb55..209b05bdb0efb 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
@@ -168,7 +168,7 @@ static 
llvm::Registry<JSONFormat::FormatInfo>::Add<CallGraphJSONFormatInfo>
     RegisterFormatInfo(CallGraphSummary::Name,
                        "JSON Format info for CallGraph summary");
 
-// This anchor is used to force the linker to link in the generated object file
-// and thus register the JSON format for CallGraphSummary.
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int CallGraphJSONFormatAnchorSource = 0;
+const volatile int CallGraphJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
index cf606a76bbe0a..23ffe9fc365fb 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
@@ -116,5 +116,7 @@ AnalysisRegistry::Add<PointerFlowAnalysis>
 
 } // namespace
 
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowAnalysisAnchorSource = 0;
+const volatile int PointerFlowAnalysisAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index e1130a2c52e4c..0559f43a5592e 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -350,8 +350,10 @@ class PointerFlowTUSummaryExtractor : public 
TUSummaryExtractor {
 };
 } // namespace
 
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowTUSummaryExtractorAnchorSource = 0;
+const volatile int PointerFlowExtractorAnchorSource = 0;
+} // namespace clang::ssaf
 
 static TUSummaryExtractorRegistry::Add<PointerFlowTUSummaryExtractor>
     RegisterExtractor(PointerFlowEntitySummary::Name,
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
index 928d98d4c9efd..5d910ae1d4fb7 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
@@ -126,5 +126,7 @@ static 
llvm::Registry<JSONFormat::FormatInfo>::Add<PointerFlowJSONFormatInfo>
     RegisterPointerFlowJSONFormatInfo(
         "PointerFlow", "JSON Format info for PointerFlowEntitySummary");
 
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowSSAFJSONFormatAnchorSource = 0;
+const volatile int PointerFlowJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
index b7a913d627022..507494af68444 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
@@ -193,5 +193,7 @@ AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
 
 } // namespace
 
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
+const volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 9103778d585fb..1005dae980e05 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -93,9 +93,10 @@ void 
clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
     assert(InsertionSucceeded && "duplicated contributor extraction");
   }
 }
-
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource = 0;
+const volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
+} // namespace clang::ssaf
 
 static clang::ssaf::TUSummaryExtractorRegistry::Add<
     UnsafeBufferUsageTUSummaryExtractor>
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
index ad67b804eab82..4196ff7cce19d 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
@@ -80,5 +80,7 @@ static llvm::Registry<JSONFormat::FormatInfo>::Add<
         UnsafeBufferUsageEntitySummary::Name,
         "JSON Format info for UnsafeBufferUsageEntitySummary");
 
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource = 0;
+const volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
index 5d8d11dd47ea4..e8f42ac6b7a1c 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -11,17 +11,21 @@
 #include 
"clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
 #include "llvm/Support/Registry.h"
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFJSONFormatAnchorSource = 0;
-LLVM_DEFINE_REGISTRY(llvm::Registry<clang::ssaf::JSONFormat::FormatInfo>)
+using namespace clang;
+using namespace ssaf;
+
+LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
 LLVM_DEFINE_REGISTRY(
-    llvm::Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>)
+    llvm::Registry<JSONFormat::AnalysisResultRegistry::Codec>)
 
-static clang::ssaf::SerializationFormatRegistry::Add<clang::ssaf::JSONFormat>
+static SerializationFormatRegistry::Add<JSONFormat>
     RegisterJSONFormat("json", "JSON serialization format");
 
 namespace clang::ssaf {
 
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+const volatile int JSONFormatAnchorSource = 0;
+
 //----------------------------------------------------------------------------
 // JSON Reader and Writer
 //----------------------------------------------------------------------------
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
index 01a95a85b705a..86d379ae693aa 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -13,11 +13,12 @@
 using namespace clang;
 using namespace ssaf;
 
-using RegistryT = llvm::Registry<AnalysisBase>;
-
+namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFAnalysisRegistryAnchorSource = 0;
-LLVM_DEFINE_REGISTRY(RegistryT)
+const volatile int AnalysisRegistryAnchorSource = 0;
+} // namespace clang::ssaf
+
+LLVM_DEFINE_REGISTRY(llvm::Registry<AnalysisBase>)
 
 std::vector<AnalysisName> &AnalysisRegistry::getAnalysisNames() {
   static std::vector<AnalysisName> Names;
@@ -34,7 +35,7 @@ const std::vector<AnalysisName> &AnalysisRegistry::names() {
 
 llvm::Expected<std::unique_ptr<AnalysisBase>>
 AnalysisRegistry::instantiate(const AnalysisName &Name) {
-  for (const auto &Entry : RegistryT::entries()) {
+  for (const auto &Entry : llvm::Registry<AnalysisBase>::entries()) {
     if (Entry.getName() == Name.str()) {
       return std::unique_ptr<AnalysisBase>(Entry.instantiate());
     }
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
index 5d2392c9236a9..0635d2f8c0782 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
@@ -48,8 +48,6 @@ class NoOpExtractor : public TUSummaryExtractor {
 };
 } // namespace
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFNoOpExtractorAnchorSource = 0;
 static TUSummaryExtractorRegistry::Add<NoOpExtractor>
     RegisterNoOp("NoOpExtractor", "No-op extractor for frontend action tests");
 
@@ -114,8 +112,6 @@ class FailingSerializationFormat final : public 
SerializationFormat {
 };
 } // namespace
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFFailingSerializationFormatAnchorSource = 0;
 static SerializationFormatRegistry::Add<FailingSerializationFormat>
     RegisterFormat(
         "FailingSerializationFormat",
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
index 313c53518dfe8..084835190f7bd 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
@@ -54,8 +54,6 @@ struct FancyAnalysisFormatInfo final : FormatInfo {
 };
 } // namespace
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFFancyAnalysisDataAnchorSource = 0;
 static llvm::Registry<FormatInfo>::Add<FancyAnalysisFormatInfo>
     RegisterFormatInfo("FancyAnalysisData",
                        "Format info for FancyAnalysisData for the "
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
index 0ec7eb44c5755..3fe6efeaf957a 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
@@ -160,8 +160,6 @@ llvm::Error MockSerializationFormat::writeTUSummary(const 
TUSummary &Summary,
   return llvm::Error::success();
 }
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFMockSerializationFormatAnchorSource = 0;
 static SerializationFormatRegistry::Add<MockSerializationFormat>
     RegisterFormat("MockSerializationFormat",
                    "A serialization format for testing");
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
index 1bce78c8b1030..1d5a33900d3c2 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
@@ -40,7 +40,5 @@ class MockSummaryExtractor1 : public TUSummaryExtractor {
 
 } // namespace
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFMockSummaryExtractor1AnchorSource = 0;
 static TUSummaryExtractorRegistry::Add<MockSummaryExtractor1>
     RegisterExtractor("MockSummaryExtractor1", "Mock summary extractor 1");
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
index 242f427f5e346..ab78b5c135faa 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
@@ -40,7 +40,5 @@ class MockSummaryExtractor2 : public TUSummaryExtractor {
 
 } // namespace
 
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFMockSummaryExtractor2AnchorSource = 0;
 static TUSummaryExtractorRegistry::Add<MockSummaryExtractor2>
     RegisterExtractor("MockSummaryExtractor2", "Mock summary extractor 2");
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h 
b/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
deleted file mode 100644
index 05d96af80cb27..0000000000000
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- SSAFBuiltinTestForceLinker.h -----------------------------*- C++ 
-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file pulls in all test-only SSAF mock extractor and format
-/// registrations by referencing their anchor symbols.
-///
-/// Include this header (with IWYU pragma: keep) in a translation unit that
-/// is compiled into the SSAF unittest binary.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
-#define 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
-
-// Force the linker to link NoOpExtractor registration.
-extern volatile int SSAFNoOpExtractorAnchorSource;
-[[maybe_unused]] static int SSAFNoOpExtractorAnchorDestination =
-    SSAFNoOpExtractorAnchorSource;
-
-// Force the linker to link MockSummaryExtractor1 registration.
-extern volatile int SSAFMockSummaryExtractor1AnchorSource;
-[[maybe_unused]] static int SSAFMockSummaryExtractor1AnchorDestination =
-    SSAFMockSummaryExtractor1AnchorSource;
-
-// Force the linker to link MockSummaryExtractor2 registration.
-extern volatile int SSAFMockSummaryExtractor2AnchorSource;
-[[maybe_unused]] static int SSAFMockSummaryExtractor2AnchorDestination =
-    SSAFMockSummaryExtractor2AnchorSource;
-
-// Force the linker to link FailingSerializationFormat registration.
-extern volatile int SSAFFailingSerializationFormatAnchorSource;
-[[maybe_unused]] static int SSAFFailingSerializationFormatAnchorDestination =
-    SSAFFailingSerializationFormatAnchorSource;
-
-// Force the linker to link MockSerializationFormat registration.
-extern volatile int SSAFMockSerializationFormatAnchorSource;
-[[maybe_unused]] static int SSAFMockSerializationFormatAnchorDestination =
-    SSAFMockSerializationFormatAnchorSource;
-
-// Force the linker to link FancyAnalysisData format info registration.
-extern volatile int SSAFFancyAnalysisDataAnchorSource;
-[[maybe_unused]] static int SSAFFancyAnalysisDataAnchorDestination =
-    SSAFFancyAnalysisDataAnchorSource;
-
-#endif // 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h 
b/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
deleted file mode 100644
index dd2077569a4eb..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- SSAFTestForceLinker.h ------------------------------------*- C++ 
-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file pulls in all test-only SSAF mock extractor and format
-/// registrations by referencing their anchor symbols.
-///
-/// Include this header (with IWYU pragma: keep) in a translation unit that
-/// is compiled into the SSAF unittest binary.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
-#define 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
-
-#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
-
-#endif // 
LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp 
b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
index 772eaf069a350..c1c41997abcf2 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
@@ -7,7 +7,6 @@
 
//===----------------------------------------------------------------------===//
 
 #include "TestFixture.h"
-#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
diff --git 
a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
 
b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
index e8290a7c3cd1f..8b2c910711024 100644
--- 
a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
@@ -180,10 +180,6 @@ class Analysis1 final
   }
 };
 
-// These static registrations are safe without SSAFBuiltinTestForceLinker.h
-// because this translation unit is compiled directly into the test binary -
-// the linker cannot dead-strip it, so all static initializers are guaranteed
-// to run.
 static AnalysisRegistry::Add<Analysis1> RegAnalysis1("Analysis for Analysis1");
 
 class Analysis2 final

From 840021f34e2604490140137ab2867fdbc4429a7f Mon Sep 17 00:00:00 2001
From: Balazs Benics <[email protected]>
Date: Tue, 28 Apr 2026 18:39:47 +0100
Subject: [PATCH 2/2] Drop "const" from these anchor variables - like they are
 in clang-tidy

Turns out, MSVC likely doesn't conform with the C++ standard and makes
`const volatile` global variables have *internal* linkage - while they
should have *external* linkage.

https://eel.is/c++draft/basic.link#3.2
```
(3) The name of an entity that belongs to a namespace scope has internal 
linkage if it is the name of
(3.1) a variable, variable template, function, or function template that is 
explicitly declared static; or
(3.2) a non-template variable of non-volatile const-qualified type, unless
(3.2.1) it is declared in the purview of a module interface unit (outside the 
private-module-fragment, if any) or module partition, or
(3.2.2) it is explicitly declared extern, or
(3.2.3) it is inline, or
(3.2.4) it was previously declared and the prior declaration did not have 
internal linkage; or
```

Consequently, `const volatile` globals should NOT have *internal*
linkage, because `volatile` variables are exempt by (3.2).
---
 .../developer-docs/ForceLinkerHeaders.rst                 | 8 ++++++--
 .../developer-docs/HowToExtend.rst                        | 4 ++--
 .../Core/Serialization/SerializationFormatRegistry.h      | 2 +-
 .../Core/TUSummary/ExtractorRegistry.h                    | 2 +-
 .../Core/WholeProgramAnalysis/AnalysisRegistry.h          | 2 +-
 .../SSAFBuiltinForceLinker.h                              | 2 +-
 .../Analyses/CallGraph/CallGraphExtractor.cpp             | 2 +-
 .../Analyses/CallGraph/CallGraphJSONFormat.cpp            | 2 +-
 .../Analyses/PointerFlow/PointerFlowAnalysis.cpp          | 2 +-
 .../Analyses/PointerFlow/PointerFlowExtractor.cpp         | 2 +-
 .../Analyses/PointerFlow/PointerFlowFormat.cpp            | 2 +-
 .../UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp       | 2 +-
 .../UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp      | 2 +-
 .../UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp         | 2 +-
 .../Core/Serialization/JSONFormat/JSONFormatImpl.cpp      | 2 +-
 .../Core/WholeProgramAnalysis/AnalysisRegistry.cpp        | 2 +-
 16 files changed, 22 insertions(+), 18 deletions(-)

diff --git 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
index d4504aa5a793a..fb113824217ea 100644
--- 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
+++ 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
@@ -33,13 +33,13 @@ constructors unconditionally.
 The solution: anchor symbols
 ****************************
 
-Each registration translation unit defines a ``const volatile int`` **anchor 
symbol**:
+Each registration translation unit defines a ``volatile int`` **anchor 
symbol**:
 
 .. code-block:: c++
 
   // In MyExtractor.cpp - next to the registry Add<> object in the 
``clang::ssaf`` namespace
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyExtractorAnchorSource = 0;
+  volatile int MyExtractorAnchorSource = 0;
 
 For **in-tree** anchors, add a single ``ANCHOR(...)`` entry to
 ``BuiltinAnchorSources.def`` (in alphabetical order):
@@ -61,6 +61,10 @@ Any translation unit that ``#include``\s this header now has 
a reference to
 The ``volatile`` qualifier is essential: without it the compiler could
 constant-fold the ``0`` and eliminate the reference entirely.
 
+These anchor symbols must be mutable (not ``const``), because otherwise on MSVC
+``const volatile`` variables would still have **internal linkage** — despite
+that the standard specifies that these should have **external linkage**.
+
 Header hierarchy
 ================
 
diff --git 
a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst 
b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
index 761ee0eeb92ba..4b5194f2b0a0b 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
@@ -55,7 +55,7 @@ Step 2: Register the extractor
 
   namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyExtractorAnchorSource = 0;
+  volatile int MyExtractorAnchorSource = 0;
   } // namespace clang::ssaf
 
   static TUSummaryExtractorRegistry::Add<MyExtractor>
@@ -127,7 +127,7 @@ Step 2: Register the format
 
   namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyFormatAnchorSource = 0;
+  volatile int MyFormatAnchorSource = 0;
   } // namespace clang::ssaf
 
   static SerializationFormatRegistry::Add<MyFormat>
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
index 24bfa554a3b77..664e9c6245546 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
@@ -23,7 +23,7 @@
 //
 //   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyFormatAnchorSource = 0;
+//   volatile int MyFormatAnchorSource = 0;
 //   } // namespace clang::ssaf
 //   static SerializationFormatRegistry::Add<MyFormat>
 //     RegisterFormat("MyFormat", "My awesome serialization format");
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
index e96d7da11b750..f0ef920a719c8 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
@@ -11,7 +11,7 @@
 //
 //   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyExtractorAnchorSource = 0;
+//   volatile int MyExtractorAnchorSource = 0;
 //   } // namespace clang::ssaf
 //   static TUSummaryExtractorRegistry::Add<MyExtractor>
 //     X("MyExtractor", "My awesome extractor");
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
index 5612b092f6faf..f3e0327227889 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
@@ -18,7 +18,7 @@
 //
 //   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyAnalysisAnchorSource = 0;
+//   volatile int MyAnalysisAnchorSource = 0;
 //   } // namespace clang::ssaf
 //
 //   // Extend SSAFBuiltinForceLinker.h (or the relevant force-linker header)
diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h 
b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 0bfc4356969a5..354379645a8de 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -22,7 +22,7 @@
 
 namespace clang::ssaf {
 
-#define ANCHOR(NAME) extern const volatile int NAME;
+#define ANCHOR(NAME) extern volatile int NAME;
 #include "BuiltinAnchorSources.def"
 
 // Force the linker to link in the built-in SSAF registrations.
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index d7fa4d5434979..6e0b0ee8fe834 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -100,5 +100,5 @@ static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int CallGraphExtractorAnchorSource = 0;
+volatile int CallGraphExtractorAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
index 209b05bdb0efb..6f2414280bfaa 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
@@ -170,5 +170,5 @@ static 
llvm::Registry<JSONFormat::FormatInfo>::Add<CallGraphJSONFormatInfo>
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int CallGraphJSONFormatAnchorSource = 0;
+volatile int CallGraphJSONFormatAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
index 23ffe9fc365fb..de8490601cccc 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
@@ -118,5 +118,5 @@ AnalysisRegistry::Add<PointerFlowAnalysis>
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int PointerFlowAnalysisAnchorSource = 0;
+volatile int PointerFlowAnalysisAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index 0559f43a5592e..951a05bd26496 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -352,7 +352,7 @@ class PointerFlowTUSummaryExtractor : public 
TUSummaryExtractor {
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int PointerFlowExtractorAnchorSource = 0;
+volatile int PointerFlowExtractorAnchorSource = 0;
 } // namespace clang::ssaf
 
 static TUSummaryExtractorRegistry::Add<PointerFlowTUSummaryExtractor>
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
index 5d910ae1d4fb7..146a815e0e55d 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
@@ -128,5 +128,5 @@ static 
llvm::Registry<JSONFormat::FormatInfo>::Add<PointerFlowJSONFormatInfo>
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int PointerFlowJSONFormatAnchorSource = 0;
+volatile int PointerFlowJSONFormatAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
index 507494af68444..43ca3f1984ba0 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
@@ -195,5 +195,5 @@ AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
+volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 1005dae980e05..f0d43c5968d05 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -95,7 +95,7 @@ void 
clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
 }
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
+volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
 } // namespace clang::ssaf
 
 static clang::ssaf::TUSummaryExtractorRegistry::Add<
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
index 4196ff7cce19d..ff6ab3886941d 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
@@ -82,5 +82,5 @@ static llvm::Registry<JSONFormat::FormatInfo>::Add<
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
+volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
 } // namespace clang::ssaf
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
index e8f42ac6b7a1c..179e3fa989f6e 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -24,7 +24,7 @@ static SerializationFormatRegistry::Add<JSONFormat>
 namespace clang::ssaf {
 
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int JSONFormatAnchorSource = 0;
+volatile int JSONFormatAnchorSource = 0;
 
 //----------------------------------------------------------------------------
 // JSON Reader and Writer
diff --git 
a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
 
b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
index 86d379ae693aa..55b4f36a1764f 100644
--- 
a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ 
b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -15,7 +15,7 @@ using namespace ssaf;
 
 namespace clang::ssaf {
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int AnalysisRegistryAnchorSource = 0;
+volatile int AnalysisRegistryAnchorSource = 0;
 } // namespace clang::ssaf
 
 LLVM_DEFINE_REGISTRY(llvm::Registry<AnalysisBase>)

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

Reply via email to