https://github.com/rjodinchr updated 
https://github.com/llvm/llvm-project/pull/196571

>From 3a1a1f869091943822da9ba301f2d223840f11f9 Mon Sep 17 00:00:00 2001
From: Romaric Jodin <[email protected]>
Date: Fri, 8 May 2026 16:14:06 +0200
Subject: [PATCH 1/2] Fix MSVC template parsing error in SerializationFormat

This commit fixes a hard compilation error on Windows when building
translation units that instantiate the `Add` registry template
(such as `PointerFlowAnalysis.cpp`).

**Root Cause:**
When compiling on Windows, Clang defaults to MSVC compatibility mode
(`-fms-compatibility`). Under this mode, Clang's two-phase template
lookup struggles to resolve function-local static variables
(`SavedSerialize` and `SavedDeserialize`) captured by a local class
(`ConcreteCodec`) inside an uninstantiated template. During Phase 1
parsing, Clang incorrectly falls back to assuming these variables must
be members of a dependent base class, rewriting them to
`this->SavedSerialize`. During Phase 2 instantiation, compilation
fails because the base class (`Codec`) has no such members.

**The Fix:**
Hoisted `SavedSerialize` and `SavedDeserialize` out of the constructor
scope, making them `static inline` members of the `Add` class template.
This allows Clang's Phase 1 parser to perfectly resolve the symbols
without relying on broken MSVC fallbacks.

**Why this is safe (Addressing the `dlopen` comment):**
The original author explicitly commented that they avoided `static inline`
class members to prevent Linux symbol visibility issues across shared
library boundaries (`dlopen` with `RTLD_LOCAL`).

That concern is still honored by this fix. The visibility risk only applies
if the `ConcreteCodec`'s *own* execution state relied directly on static
members. By moving the static variables to the `Add` factory class,
`ConcreteCodec` continues to store `SerFn` and `DesFn` as strictly
**instance members**. The `ConcreteCodec` constructor safely snapshots
the plugin's local copy of `Add::SavedSerialize` at the moment of
instantiation. Since the virtual methods executed by the host still
read exclusively from the isolated instance state, the runtime behavior
remains completely identical and safe.
---
 .../Core/Serialization/SerializationFormat.h               | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
index fd261c6d9a723..9ab79dda3fc11 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
@@ -133,6 +133,9 @@ class SerializationFormat {
       using TypedSerializerFn =
           llvm::function_ref<SerRet(const AnalysisResultT &, SerArgs...)>;
 
+      static inline TypedSerializerFn SavedSerialize;
+      static inline DeserializerFn SavedDeserialize;
+
       /// Takes the plugin's typed serializer and the deserializer, and
       /// inserts them into \c llvm::Registry<Codec>.
       Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize) {
@@ -154,8 +157,8 @@ class SerializationFormat {
         /// visibility issues across shared library boundaries on Linux
         /// (where \c dlopen with \c RTLD_LOCAL can give the host and
         /// plugin separate copies of \c static \c inline members).
-        static TypedSerializerFn SavedSerialize = TypedSerialize;
-        static DeserializerFn SavedDeserialize = Deserialize;
+        SavedSerialize = TypedSerialize;
+        SavedDeserialize = Deserialize;
 
         /// Concrete subclass of \c Codec for \c AnalysisResultT.
         /// The \c serialize() override performs the downcast from

>From 71f74736a3ebeb2a59521f298523df17057a7555 Mon Sep 17 00:00:00 2001
From: Romaric Jodin <[email protected]>
Date: Sat, 9 May 2026 17:03:07 +0200
Subject: [PATCH 2/2] Fix Windows CI segfault by using function pointers

This commit fixes an 0xC0000005 access violation occurring during
Windows CI testing for `clang-ssaf-format.exe`.

* Root Cause:
Because `TypedSerializerFn` and `DeserializerFn` were typed as
`llvm::function_ref`, storing them in static
variables (`SavedSerialize` and `SavedDeserialize`) inadvertently
created dangling pointers. `llvm::function_ref` is a non-owning
wrapper; it only captured a reference to the temporary callables
decaying on the `Add` constructor's stack. Once the constructor
returned, those temporaries were destroyed. Dereferencing the stored
`function_ref` later caused an access violation on x64 Windows.

* The Fix:
Redefined `TypedSerializerFn` and `DeserializerFn` from
`llvm::function_ref` to standard raw function pointers. This ensures
the static registry variables safely capture and store the actual
persistent addresses of the global functions being registered,
completely eliminating the dangling pointers and resolving the crash.
---
 .../Core/Serialization/SerializationFormat.h                 | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
index 9ab79dda3fc11..af6a1ec98db78 100644
--- 
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
+++ 
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
@@ -111,7 +111,7 @@ class SerializationFormat {
       FormatT, llvm::function_ref<SerRet(const AnalysisResult &, SerArgs...)>,
       llvm::function_ref<DesRet(DesArgs...)>> {
 
-    using DeserializerFn = llvm::function_ref<DesRet(DesArgs...)>;
+    using DeserializerFn = DesRet (*)(DesArgs...);
 
   public:
     /// Abstract base type stored in \c llvm::Registry<Codec>.
@@ -130,8 +130,7 @@ class SerializationFormat {
     };
 
     template <class AnalysisResultT> struct Add {
-      using TypedSerializerFn =
-          llvm::function_ref<SerRet(const AnalysisResultT &, SerArgs...)>;
+      using TypedSerializerFn = SerRet (*)(const AnalysisResultT &, 
SerArgs...);
 
       static inline TypedSerializerFn SavedSerialize;
       static inline DeserializerFn SavedDeserialize;

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

Reply via email to