[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
rjodinchr wrote: @aviralg are you able to merge it? https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
rjodinchr wrote: Can anyone merge it? I don't have permission to do it myself. https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
rjodinchr wrote: @aviralg could you please have a second look at this PR? Thank you in advance 🙏 https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
rjodinchr wrote: CI is green ✅, I have updated the PR description https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
https://github.com/rjodinchr edited https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
https://github.com/rjodinchr updated
https://github.com/llvm/llvm-project/pull/196571
>From 97d98f922be0f3ccf1fec99daef82cf40992531e Mon Sep 17 00:00:00 2001
From: Romaric Jodin
Date: Fri, 8 May 2026 16:14:06 +0200
Subject: [PATCH] Fix MSVC template parsing error in SerializationFormat
This commit fixes a hard compilation error on Windows (when building with
Clang's MSVC compatibility mode) and a subsequent access violation that
occurred during Windows CI testing.
Root Causes:
1. When compiling with `-fms-compatibility`, Clang's two-phase template
lookup fails to resolve function-local static variables (`SavedSerialize`
and `SavedDeserialize`) captured by a local class (`ConcreteCodec`) inside
an uninstantiated template. It incorrectly assumes they are members of a
dependent base class.
2. Originally, `TypedSerializerFn` and `DeserializerFn` were typed as
`llvm::function_ref`. Storing these in static variables created dangling
pointers, as `function_ref` is a non-owning wrapper that only referenced
the temporaries decaying on the constructor's stack, causing an 0xC005
access violation on x64 Windows.
The Fix:
* Hoisted `SavedSerialize` and `SavedDeserialize` out of the constructor
scope to be `static inline` members of the `Add` class template. This allows
Clang's Phase 1 parser to correctly resolve the symbols.
* Redefined `TypedSerializerFn` and `DeserializerFn` to raw function pointers
instead of `llvm::function_ref`. This ensures the static registry variables
safely capture the persistent addresses of the global functions being
registered, eliminating the dangling pointers.
Safety note: The original concern regarding `dlopen` symbol visibility on
Linux is preserved. `ConcreteCodec` continues to store the functions strictly
as instance members, snapshotting the plugin's local copy of the static
variables at instantiation.
---
.../Core/Serialization/SerializationFormat.h | 30 +++
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git
a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
index fd261c6d9a723..080628a700ba1 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,
llvm::function_ref> {
-using DeserializerFn = llvm::function_ref;
+using DeserializerFn = DesRet (*)(DesArgs...);
public:
/// Abstract base type stored in \c llvm::Registry.
@@ -130,8 +130,10 @@ class SerializationFormat {
};
template struct Add {
- using TypedSerializerFn =
- llvm::function_ref;
+ using TypedSerializerFn = 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.
@@ -147,15 +149,19 @@ class SerializationFormat {
Registered = true;
/// The plugin's serializer and deserializer are captured in
-/// function-local statics so that the \c ConcreteCodec default
-/// constructor (required by \c llvm::Registry) can read them.
-/// They are stored as instance members of \c ConcreteCodec rather
-/// than \c static \c inline class members to avoid symbol
-/// 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;
+/// static inline members of the Add template so that the
+/// \c ConcreteCodec default constructor (required by \c
llvm::Registry)
+/// can read them. They use raw function pointers to prevent dangling
+/// references to temporary stack variables during registration.
+///
+/// Once read by the constructor, they are stored as instance members
+/// of \c ConcreteCodec rather than directly executed from the \c
static
+/// \c inline class members. This prevents symbol 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).
+SavedSerialize = TypedSerialize;
+SavedDeserialize = Deserialize;
/// Concrete subclass of \c Codec for \c AnalysisResultT.
/// The \c serialize() override performs the downcast from
___
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
github-actions[bot] wrote: # :window: Windows x64 Test Results * 53875 tests passed * 1200 tests skipped * 2 tests failed ## Failed Tests (click on a test name to see its output) ### Clang Clang.Analysis/Scalable/PointerFlow/wpa-result-serialization.test ``` Exit Code: 3221225477 Command Output (stdout): -- # RUN: at line 1 rm -rf C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp # executed command: rm -rf 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp' # note: command had no output on stdout or stderr # RUN: at line 2 mkdir -p C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp # executed command: mkdir -p 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp' # note: command had no output on stdout or stderr # RUN: at line 6 c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe --type wpa C:\_work\llvm-project\llvm-project\clang\test\Analysis\Scalable\PointerFlow/Inputs/wpa-result.json -o C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp/wpa-result.json # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe' --type wpa 'C:\_work\llvm-project\llvm-project\clang\test\Analysis\Scalable\PointerFlow/Inputs/wpa-result.json' -o 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\PointerFlow\Output\wpa-result-serialization.test.tmp/wpa-result.json' # .---command stderr # | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug. # | Stack dump: # | 0. Program arguments: c:\\_work\\llvm-project\\llvm-project\\build\\bin\\clang-ssaf-format.exe --type wpa C:\\_work\\llvm-project\\llvm-project\\clang\\test\\Analysis\\Scalable\\PointerFlow/Inputs/wpa-result.json -o C:\\_work\\llvm-project\\llvm-project\\build\\tools\\clang\\test\\Analysis\\Scalable\\PointerFlow\\Output\\wpa-result-serialization.test.tmp/wpa-result.json # | Exception Code: 0xC005 # | #0 0x # | #1 0x7ff6f680eb82 (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0x2eb82) # | #2 0x7ff6f68cdfd9 (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0xedfd9) # | #3 0x7ff6f68ceb6b (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0xeeb6b) # | #4 0x7ff6f68cff24 (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0xeff24) # | #5 0x7ff6f67e2830 (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0x2830) # | #6 0x7ff6f70e067c (c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe+0x90067c) # | #7 0x7ffb813c4cb0 (C:\Windows\System32\KERNEL32.DLL+0x14cb0) # | #8 0x7ffb8d79edcb (C:\Windows\SYSTEM32\ntdll.dll+0x7edcb) # `- # error: command failed with exit status: 0xc005 -- ``` Clang.Analysis/Scalable/UnsafeBufferUsage/wpa-result-serialization.test ``` Exit Code: 3221225477 Command Output (stdout): -- # RUN: at line 1 rm -rf C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp # executed command: rm -rf 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp' # note: command had no output on stdout or stderr # RUN: at line 2 mkdir -p C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp # executed command: mkdir -p 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp' # note: command had no output on stdout or stderr # RUN: at line 6 c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe --type wpa C:\_work\llvm-project\llvm-project\clang\test\Analysis\Scalable\UnsafeBufferUsage/Inputs/wpa-result.json -o C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp/wpa-result.json # executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang-ssaf-format.exe' --type wpa 'C:\_work\llvm-project\llvm-project\clang\test\Analysis\Scalable\UnsafeBufferUsage/Inputs/wpa-result.json' -o 'C:\_work\llvm-project\llvm-project\build\tools\clang\test\Analysis\Scalable\UnsafeBufferUsage\Output\wpa-result-serialization.test.tmp/wpa-result.json' # .---command stderr # | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
llvmorg-github-actions[bot] wrote:
@llvm/pr-subscribers-clang
Author: Romaric Jodin (rjodinchr)
Changes
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/196571.diff
1 Files Affected:
- (modified)
clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
(+5-2)
``diff
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;
+ static inline TypedSerializerFn SavedSerialize;
+ static inline DeserializerFn SavedDeserialize;
+
/// Takes the plugin's typed serializer and the deserializer, and
/// inserts them into \c llvm::Registry.
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
``
https://github.com/llvm/llvm-project/pull/196571
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
rjodinchr wrote: > ~Thank you for the detailed explanation of this fix! Please update the code > comments too.~ Looks like the change does not work? I'm not able to reproduce on my machine, but I'm suspecting an issue regarding `llvm::function_ref` as it is a non-owning wrapper. I still need to update the comments. I'll do that once all CI checks are green. https://github.com/llvm/llvm-project/pull/196571 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
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
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;
+ static inline TypedSerializerFn SavedSerialize;
+ static inline DeserializerFn SavedDeserialize;
+
/// Takes the plugin's typed serializer and the deserializer, and
/// inserts them into \c llvm::Registry.
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
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 0xC005 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/Serializatio
[clang] Fix MSVC template parsing error in SerializationFormat (PR #196571)
https://github.com/rjodinchr created
https://github.com/llvm/llvm-project/pull/196571
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.
>From 3a1a1f869091943822da9ba301f2d223840f11f9 Mon Sep 17 00:00:00 2001
From: Romaric Jodin
Date: Fri, 8 May 2026 16:14:06 +0200
Subject: [PATCH] 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;
+ static inline TypedSerializerFn SavedSerialize;
+ static inline DeserializerFn SavedDeserialize;
+
/// Takes the plugin's typed serializer and the deserializer, and
/// inserts them into \c ll
