https://github.com/keepyixiao updated https://github.com/llvm/llvm-project/pull/222523
>From d5b96615e43b04cc6be70cd80627f6969fd511fa Mon Sep 17 00:00:00 2001 From: nudt_yixiao <[email protected]> Date: Fri, 25 Sep 2026 10:13:26 +0800 Subject: [PATCH] [Clang] Fix stale linkage cache when merging redeclarations A linkage query before a declaration is connected to a preceding static declaration may leave stale cached linkage and trigger an assertion. Invalidate cached linkage in Redeclarable::setPreviousDecl() so it is recomputed from the complete redeclaration chain. Add regression tests for C variables and functions and C++ variable templates. --- clang/docs/ReleaseNotes.md | 3 ++- clang/include/clang/AST/Decl.h | 3 +++ clang/test/Sema/redefine_extname.c | 11 +++++++++++ clang/test/Sema/redefine_extname.cpp | 8 ++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 78eb1aab3ed66..d824dab47adbd 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -580,7 +580,8 @@ features cannot lower the translation-unit ABI level; (e.g. `({ s.b; })`) was not subject to integer promotion, unlike an ordinary bit-field access. (#GH221542) - No longer crashing due to follow-on diagnostics when there is an invalid operand in a logical operator involving a vector operand. (#GH227588) - +- Fixed assertion failures caused by stale linkage information when an extern variable or function declaration is merged with a preceding static declaration. (#GH204759, #GH204754) + #### Bug Fixes to Compiler Builtins - Fixed a crash when classifying a call to a builtin with dependent arguments, diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index c64dc8c02d40e..f809b475eea5c 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -5472,6 +5472,9 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { "setPreviousDecl on a decl already in a redeclaration chain"); if (PrevDecl) { + // Linking this declaration to a previous one may change its linkage. + static_cast<decl_type *>(this)->invalidateCachedLinkage(); + // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. 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}} diff --git a/clang/test/Sema/redefine_extname.cpp b/clang/test/Sema/redefine_extname.cpp index 7a0066b887d0e..16a436fdfb996 100644 --- a/clang/test/Sema/redefine_extname.cpp +++ b/clang/test/Sema/redefine_extname.cpp @@ -22,6 +22,14 @@ int foo_cppfunc() { return 1; } // expected-warning {{#pragma redefine_extname i int foo_cppvar = 1; // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to variable 'foo_cppvar'}} // CHECK-DAG: {{@[^ ]*foo_cppvar}} +/// Check that merging variable template declarations does not leave stale +/// linkage information. +#pragma redefine_extname a alias +template <typename> +static int a; // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to variable 'a'}} +template <typename> +extern int a; // expected-warning {{#pragma redefine_extname is applicable to external C declarations only; not applied to variable 'a'}} + /// Check that the warning goes away when doing it in a namespace. /// Such uses are clearly scoped and need no warning (and often can be intentional). #pragma redefine_extname foo_nsfunc check_not_bar_nsfunc _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
