[llvm-branch-commits] [clang] a7d2c50 - Revert "[clang][ssaf][NFC] Rework how the Force linker anchors are defined an…"

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Apr 22 03:00:30 PDT 2026


Author: Balázs Benics
Date: 2026-04-22T11:00:25+01:00
New Revision: a7d2c5098f3ee3b2ef0dd259e38ecb1ccc6e3a8a

URL: https://github.com/llvm/llvm-project/commit/a7d2c5098f3ee3b2ef0dd259e38ecb1ccc6e3a8a
DIFF: https://github.com/llvm/llvm-project/commit/a7d2c5098f3ee3b2ef0dd259e38ecb1ccc6e3a8a.diff

LOG: Revert "[clang][ssaf][NFC] Rework how the Force linker anchors are defined an…"

This reverts commit 8e56a89c8f28c2d8b1a952b0ee321c4953594b6b.

Added: 
    clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
    clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h

Modified: 
    clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
    clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
    clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
    clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
    clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
    clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
    clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
    clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
    clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
    clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
    clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
    clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
    clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
    clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
    clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
    clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
    clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
    clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
    clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp

Removed: 
    clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def


################################################################################
diff  --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
index d4504aa5a793a..c04b2b786308f 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
@@ -33,29 +33,26 @@ 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
+  // In MyExtractor.cpp — next to the registry Add<> object
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyExtractorAnchorSource = 0;
+  volatile int SSAFMyExtractorAnchorSource = 0;
 
-For **in-tree** anchors, add a single ``ANCHOR(...)`` entry to
-``BuiltinAnchorSources.def`` (in alphabetical order):
+A **force-linker header** declares the symbol as ``extern`` and reads it into a
+``[[maybe_unused]] static int`` destination:
 
 .. code-block:: c++
 
-  // 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.
+  // In SSAFBuiltinForceLinker.h
+  extern volatile int SSAFMyExtractorAnchorSource;
+  [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
+      SSAFMyExtractorAnchorSource;
 
 Any translation unit that ``#include``\s this header now has a reference to
-``MyExtractorAnchorSource``, which forces the linker to pull in
+``SSAFMyExtractorAnchorSource``, 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
@@ -88,14 +85,11 @@ point of a binary that uses ``clangScalableStaticAnalysisFrameworkCore``:
 Naming convention
 =================
 
-Anchor symbols follow the pattern ``<Component>AnchorSource`` in the ``clang::ssaf`` namespace.
-For example:
-
-- ``JSONFormatAnchorSource``
-- ``MyExtractorAnchorSource``
+Anchor symbols follow the pattern ``SSAF<Component>AnchorSource`` and
+``SSAF<Component>AnchorDestination``.  For example:
 
-All anchor sources are aggregated into a single ``BuiltinAnchorDestination``
-lambda in the force-linker header (see ``SSAFBuiltinForceLinker.h``).
+- ``SSAFJSONFormatAnchorSource`` / ``SSAFJSONFormatAnchorDestination``
+- ``SSAFMyExtractorAnchorSource`` / ``SSAFMyExtractorAnchorDestination``
 
 Considered alternatives
 ***********************

diff  --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
index ac377813986ec..7d92d7e6f2de7 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
@@ -53,10 +53,8 @@ Step 2: Register the extractor
 
   using namespace clang::ssaf;
 
-  namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyExtractorAnchorSource = 0;
-  } // namespace clang::ssaf
+  volatile int SSAFMyExtractorAnchorSource = 0;
 
   static TUSummaryExtractorRegistry::Add<MyExtractor>
       RegisterExtractor("MyExtractor", "My awesome summary extractor");
@@ -67,17 +65,16 @@ Step 3: Add the force-linker anchor
 ===================================
 
 See :doc:`ForceLinkerHeaders` for a full explanation of why this is needed.
-
-For **in-tree** additions, add one line to
-``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def``
-(in alphabetical order):
+Add the following to the appropriate force-linker header:
 
 .. code-block:: c++
 
-  ANCHOR(MyExtractorAnchorSource)
+  extern volatile int SSAFMyExtractorAnchorSource;
+  [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
+      SSAFMyExtractorAnchorSource;
 
-``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically — no
-need to edit it directly.
+For **in-tree** additions, add this to
+``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
 
 For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
 
@@ -128,10 +125,8 @@ Step 2: Register the format
 
   using namespace clang::ssaf;
 
-  namespace clang::ssaf {
   // NOLINTNEXTLINE(misc-use-internal-linkage)
-  const volatile int MyFormatAnchorSource = 0;
-  } // namespace clang::ssaf
+  volatile int SSAFMyFormatAnchorSource = 0;
 
   static SerializationFormatRegistry::Add<MyFormat>
       RegisterFormat("myformat", "My awesome serialization format");
@@ -166,9 +161,7 @@ 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 — add the anchor to ``BuiltinAnchorSources.def``
-(in alphabetical order). See `Adding a summary extractor`_ Step 3,
-and :doc:`ForceLinkerHeaders`.
+Same pattern as for extractors — see `Adding a summary extractor`_ Step 3, and :doc:`ForceLinkerHeaders`.
 
 
 Static extensibility
@@ -179,7 +172,7 @@ In-tree extensions
 
 For extensions that are part of the upstream LLVM/Clang tree:
 
-#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def`` (in alphabetical order).
+#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
 #. 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
deleted file mode 100644
index 63235f0630afc..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
+++ /dev/null
@@ -1,26 +0,0 @@
-//===- 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(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 bc146a5340339..a1955e64d5137 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
@@ -24,10 +24,8 @@
 //
 // Insert this code to the cpp file:
 //
-//   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyFormatAnchorSource = 0;
-//   } // namespace clang::ssaf
+//   volatile int SSAFMyFormatAnchorSource = 0;
 //   static SerializationFormatRegistry::Add<MyFormat>
 //     RegisterFormat("MyFormat", "My awesome serialization format");
 //   LLVM_INSTANTIATE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
@@ -52,11 +50,15 @@
 //         "The MyFormat format info implementation for MyAnalysis"
 //       );
 //
-// Finally, extend the `AnchorSources` list in the force-linker header:
+// Finally, insert a use of the new anchor symbol into 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 6af6f949a6af8..da57838c64b2f 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
@@ -9,16 +9,18 @@
 // Registry for TUSummaryExtractors, and some helper functions.
 // To register some custom extractor, insert this code:
 //
-//   namespace clang::ssaf {
 //   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyExtractorAnchorSource = 0;
-//   } // namespace clang::ssaf
+//   volatile int SSAFMyExtractorAnchorSource = 0;
 //   static TUSummaryExtractorRegistry::Add<MyExtractor>
 //     X("MyExtractor", "My awesome extractor");
 //
-// Finally, extend the `AnchorSources` list in the force-linker header:
+// Finally, insert a use of the new anchor symbol into 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 f747775c2c498..44eabce6c809c 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 anchor source to the `AnchorSources`
-// list in the relevant force-linker header:
+// in its translation unit, then add the matching anchor destination to the
+// relevant force-linker header:
 //
 //   // MyAnalysis.cpp
 //   static AnalysisRegistry::Add<MyAnalysis>
 //       Registered("One-line description of MyAnalysis");
 //
-//   namespace clang::ssaf {
-//   // NOLINTNEXTLINE(misc-use-internal-linkage)
-//   const volatile int MyAnalysisAnchorSource = 0;
-//   } // namespace clang::ssaf
+//   volatile int SSAFMyAnalysisAnchorSource = 0;
 //
-//   // Extend SSAFBuiltinForceLinker.h (or the relevant force-linker header)
+//   // SSAFBuiltinForceLinker.h (or the relevant force-linker header)
+//   extern volatile int SSAFMyAnalysisAnchorSource;
+//   [[maybe_unused]] static int SSAFMyAnalysisAnchorDestination =
+//       SSAFMyAnalysisAnchorSource;
 //
 // 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 0bfc4356969a5..5616976e10f77 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -20,24 +20,39 @@
 #ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
 #define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
 
-namespace clang::ssaf {
+// TODO: Move these to the `clang::ssaf` namespace.
 
-#define ANCHOR(NAME) extern const volatile int NAME;
-#include "BuiltinAnchorSources.def"
+// This anchor is used to force the linker to link the JSONFormat registration.
+extern volatile int SSAFJSONFormatAnchorSource;
+[[maybe_unused]] static int SSAFJSONFormatAnchorDestination =
+    SSAFJSONFormatAnchorSource;
 
-// 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 AnalysisRegistry.
+extern volatile int SSAFAnalysisRegistryAnchorSource;
+[[maybe_unused]] static int SSAFAnalysisRegistryAnchorDestination =
+    SSAFAnalysisRegistryAnchorSource;
 
-  int SomeUse = 0;
-  for (int V : AnchorSources)
-    SomeUse |= V;
-  return SomeUse;
-}();
+// This anchor is used to force the linker to link the UnsafeBufferUsage
+// JSON format.
+extern volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource;
+[[maybe_unused]] static int UnsafeBufferUsageSSAFJSONFormatAnchorDestination =
+    UnsafeBufferUsageSSAFJSONFormatAnchorSource;
 
-} // namespace clang::ssaf
+// This anchor is used to force the linker to link the
+// UnsafeBufferUsageTUSummaryExtractor.
+extern volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource;
+[[maybe_unused]] static int
+    UnsafeBufferUsageTUSummaryExtractorAnchorDestination =
+        UnsafeBufferUsageTUSummaryExtractorAnchorSource;
+
+// 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;
 
 #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 3651953a413e2..1dbed7e0b0d8a 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -101,7 +101,7 @@ static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
     RegisterExtractor(CallGraphSummary::Name,
                       "Extracts static call-graph information");
 
-namespace clang::ssaf {
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the CallGraphExtractor.
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int CallGraphExtractorAnchorSource = 0;
-} // namespace clang::ssaf
+volatile int CallGraphExtractorAnchorSource = 0;

diff  --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
index 209b05bdb0efb..860e26417eb55 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");
 
-namespace clang::ssaf {
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the JSON format for CallGraphSummary.
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int CallGraphJSONFormatAnchorSource = 0;
-} // namespace clang::ssaf
+volatile int CallGraphJSONFormatAnchorSource = 0;

diff  --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
index d7d4dae453e56..ea5d2297b9836 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
@@ -84,6 +84,9 @@ static llvm::Registry<JSONFormat::FormatInfo>::Add<
         UnsafeBufferUsageEntitySummary::Name,
         "JSON Format info for UnsafeBufferUsageEntitySummary");
 
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource = 0;
+
 // For unit test:
 llvm::Expected<std::unique_ptr<EntitySummary>>
 ssaf::serializeDeserializeRoundTrip(
@@ -105,8 +108,3 @@ ssaf::serializeDeserializeRoundTrip(
 
   return deserializeImpl(serialize(S, IdToJson), IdFromJson);
 }
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
-} // namespace clang::ssaf

diff  --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index ec9295d968561..550416c353fb7 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -98,10 +98,9 @@ void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
     assert(InsertionSucceeded && "duplicated contributor extraction");
   }
 }
-namespace clang::ssaf {
+
 // NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
-} // namespace clang::ssaf
+volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource = 0;
 
 static clang::ssaf::TUSummaryExtractorRegistry::Add<
     ssaf::UnsafeBufferUsageTUSummaryExtractor>

diff  --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
index 93850ad1f42b3..8db7480e683f5 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -11,22 +11,17 @@
 #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
 #include "llvm/Support/Registry.h"
 
-using namespace clang;
-using namespace ssaf;
-
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int SSAFJSONFormatAnchorSource = 0;
+LLVM_INSTANTIATE_REGISTRY(llvm::Registry<clang::ssaf::JSONFormat::FormatInfo>)
 LLVM_INSTANTIATE_REGISTRY(
-    llvm::Registry<JSONFormat::AnalysisResultRegistry::Codec>)
-
-LLVM_INSTANTIATE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
+    llvm::Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>)
 
-static SerializationFormatRegistry::Add<JSONFormat>
+static clang::ssaf::SerializationFormatRegistry::Add<clang::ssaf::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 94241afe08153..8e1ea954d9afd 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -13,12 +13,11 @@
 using namespace clang;
 using namespace ssaf;
 
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-const volatile int AnalysisRegistryAnchorSource = 0;
-} // namespace clang::ssaf
+using RegistryT = llvm::Registry<AnalysisBase>;
 
-LLVM_INSTANTIATE_REGISTRY(llvm::Registry<AnalysisBase>)
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int SSAFAnalysisRegistryAnchorSource = 0;
+LLVM_INSTANTIATE_REGISTRY(RegistryT)
 
 std::vector<AnalysisName> &AnalysisRegistry::getAnalysisNames() {
   static std::vector<AnalysisName> Names;
@@ -35,7 +34,7 @@ const std::vector<AnalysisName> &AnalysisRegistry::names() {
 
 llvm::Expected<std::unique_ptr<AnalysisBase>>
 AnalysisRegistry::instantiate(const AnalysisName &Name) {
-  for (const auto &Entry : llvm::Registry<AnalysisBase>::entries()) {
+  for (const auto &Entry : RegistryT::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 0635d2f8c0782..5d2392c9236a9 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
@@ -48,6 +48,8 @@ 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");
 
@@ -112,6 +114,8 @@ 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 084835190f7bd..313c53518dfe8 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
@@ -54,6 +54,8 @@ 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 48c2efb08338c..684249620e869 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
@@ -160,6 +160,8 @@ 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 1d5a33900d3c2..1bce78c8b1030 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
@@ -40,5 +40,7 @@ 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 ab78b5c135faa..242f427f5e346 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
@@ -40,5 +40,7 @@ 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
new file mode 100644
index 0000000000000..05d96af80cb27
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
@@ -0,0 +1,51 @@
+//===- 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
new file mode 100644
index 0000000000000..dd2077569a4eb
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
@@ -0,0 +1,23 @@
+//===- 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 c1c41997abcf2..772eaf069a350 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #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 8b2c910711024..e8290a7c3cd1f 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
@@ -180,6 +180,10 @@ 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


        


More information about the llvm-branch-commits mailing list