https://github.com/keepyixiao created 
https://github.com/llvm/llvm-project/pull/222523

linkage before Sema connects it to a previous declaration. This can cache 
external linkage for an extern declaration that is later connected to a 
preceding static declaration.

The resulting stale cache disagrees with the effective internal linkage and can 
trigger an assertion while building the redeclaration chain.

Invalidate the cached linkage before connecting variable and function 
declarations to their previous declarations, allowing linkage to be recomputed 
from the completed redeclaration chain.

Add regression coverage for both variable and function declarations where an 
extern declaration follows a static declaration.

Fixes https://github.com/llvm/llvm-project/issues/204759

>From dd7c4f6d7a7ecf0fd4fe98b7472e24e50afdb5de Mon Sep 17 00:00:00 2001
From: yixiao <[email protected]>
Date: Thu, 10 Sep 2026 14:46:10 +0800
Subject: [PATCH] [Clang] Fix stale linkage cache when merging redeclarations

linkage before Sema connects it to a previous declaration. This can cache
external linkage for an extern declaration that is later connected to a
preceding static declaration.

The resulting stale cache disagrees with the effective internal linkage and
can trigger an assertion while building the redeclaration chain.

Invalidate the cached linkage before connecting variable and function
declarations to their previous declarations, allowing linkage to be
recomputed from the completed redeclaration chain.

Add regression coverage for both variable and function declarations where
an extern declaration follows a static declaration.
---
 clang/lib/AST/Decl.cpp             |  2 ++
 clang/lib/Sema/SemaDecl.cpp        |  3 +++
 clang/test/Sema/redefine_extname.c | 11 +++++++++++
 3 files changed, 16 insertions(+)

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a620e9f211ca6..84a1648c78c1c 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3775,6 +3775,8 @@ bool FunctionDecl::isTargetVersionMultiVersion() const {
 
 void
 FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
+  // Linking this declaration to a previous one may change its linkage.
+  invalidateCachedLinkage();
   redeclarable_base::setPreviousDecl(PrevDecl);
 
   if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a9047f61a8bf5..7a5f1cb6bddb6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4984,6 +4984,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
   if (Old->getMostRecentDecl()->isUsed(false))
     New->setIsUsed();
 
+  // Linking this declaration to a previous one may change its linkage.
+  New->invalidateCachedLinkage();
+
   // Keep a chain of previous declarations.
   New->setPreviousDecl(Old);
   if (NewTemplate)
diff --git a/clang/test/Sema/redefine_extname.c 
b/clang/test/Sema/redefine_extname.c
index 8ccac7ffcd413..c20d426295f1b 100644
--- a/clang/test/Sema/redefine_extname.c
+++ b/clang/test/Sema/redefine_extname.c
@@ -5,4 +5,15 @@
 #pragma redefine_extname foo_static bar_static
 static int foo_static(void) { return 1; } // expected-warning {{#pragma 
redefine_extname is applicable to external C declarations only; not applied to 
function 'foo_static'}}
 
+// Computing whether the declarations have external C linkage must not leave a
+// stale linkage cached before they are connected to the preceding static
+// declarations.
+#pragma redefine_extname variable_after_static variable_alias
+static int variable_after_static; // expected-warning {{#pragma 
redefine_extname is applicable to external C declarations only; not applied to 
variable 'variable_after_static'}}
+extern int variable_after_static;
+
+#pragma redefine_extname function_after_static function_alias
+static int function_after_static(void); // expected-warning {{#pragma 
redefine_extname is applicable to external C declarations only; not applied to 
function 'function_after_static'}}
+extern int function_after_static(void);
+
 unsigned __int128_t; // expected-error {{redefinition of '__int128_t' as 
different kind of symbol}}

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

Reply via email to