https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/209873

>From 6684e01c8bdd9db554e45cf3acdb59604def64fa Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Wed, 15 Jul 2026 12:39:15 -0700
Subject: [PATCH 1/2] Ensure that we properly propagate template decl
 attributes to redecls

Variable and class templates weren't forwarding their declaration
attributes that were attached directly to them (at the moment, the only
one I could find that had this issue is the no_specialization attr).
The result was that intermediate redeclarations would prevent the
diagnostics from happening.

This patch ensures we propagate them properly for variable and class
templates.  It seems our function templates already do the right thing.

Fixes: #101469
---
 clang/docs/ReleaseNotes.md                    |  2 ++
 clang/lib/Sema/SemaDecl.cpp                   |  4 ++++
 clang/lib/Sema/SemaTemplate.cpp               |  4 +++-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  2 ++
 .../test/SemaCXX/attr-no-specializations.cpp  | 22 +++++++++++++++++++
 5 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index cda3b1ee62f2b..c6c7026b51985 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -121,6 +121,8 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 
 ### Attribute Changes in Clang
 
+- Clang now properly propagates attributes on class and variable templates to 
their redeclarations, which will result in redeclarations not interfering with 
diagnostics. (#GH101469)
+
 ### Improvements to Clang's diagnostics
 
 ### Improvements to Clang's time-trace
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7e1b23c971a9c..bf902010523dd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4768,7 +4768,11 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
     New->setInvalidDecl();
   }
 
+  if (NewTemplate && OldTemplate)
+    mergeDeclAttributes(NewTemplate, OldTemplate);
+
   mergeDeclAttributes(New, Old);
+
   // Warn if an already-defined variable is made a weak_import in a subsequent
   // declaration
   if (New->hasAttr<WeakImportAttr>())
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7286a0c2f6fbf..91946c0519562 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2288,8 +2288,10 @@ DeclResult Sema::CheckClassTemplate(
 
   ProcessDeclAttributeList(S, NewClass, Attr);
 
-  if (PrevClassTemplate)
+  if (PrevClassTemplate) {
+    mergeDeclAttributes(NewTemplate, PrevClassTemplate);
     mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
+  }
 
   AddPushedVisibilityAttribute(NewClass);
   inferGslOwnerPointerAttribute(NewClass);
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c2e90624b8a6e..80206b6829d86 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2539,6 +2539,8 @@ Decl 
*TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
   }
 
   Owner->addDecl(Inst);
+  SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Inst, LateAttrs,
+                                  StartingScope);
 
   if (!PrevVarTemplate) {
     // Queue up any out-of-line partial specializations of this member
diff --git a/clang/test/SemaCXX/attr-no-specializations.cpp 
b/clang/test/SemaCXX/attr-no-specializations.cpp
index 1fb57db14a446..4ff23bb6e8a04 100644
--- a/clang/test/SemaCXX/attr-no-specializations.cpp
+++ b/clang/test/SemaCXX/attr-no-specializations.cpp
@@ -60,3 +60,25 @@ template <class T>
 [[clang::no_specializations]] void func(); // expected-note {{marked 
'clang::no_specializations' here}}
 
 template <> void func<int>(); // expected-error {{'func' cannot be 
specialized}}
+
+namespace DeclBetween {
+template <class T>
+[[clang::no_specializations]] void func(); // expected-note {{marked 
'clang::no_specializations' here}}
+template<class t> void func(){}
+template <> void func<int>(); // expected-error {{'func' cannot be 
specialized}}
+
+template<typename T>
+struct HasVarDecl {
+template<typename U> static int var_decl[[clang::no_specializations]];// 
expected-note {{marked 'clang::no_specializations' here}}
+};
+
+template<typename T>
+template<typename U> int HasVarDecl<T>::var_decl = 5;
+template<>
+template<>
+int HasVarDecl<int>::var_decl<int>; // expected-error{{'var_decl' cannot be 
specialized}}
+
+template<typename> struct [[clang::no_specializations]] ClassTempl; // 
expected-note {{marked 'clang::no_specializations' here}}
+template<typename> struct ClassTempl { };
+template<> struct ClassTempl<int> { }; // expected-error{{'ClassTempl' cannot 
be specialized}}
+};

>From aed9eb221b05a3918244afac883e43e4cf5c12f7 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Wed, 15 Jul 2026 12:51:34 -0700
Subject: [PATCH 2/2] Fix issue number... I'm a dummy

---
 clang/docs/ReleaseNotes.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c6c7026b51985..efc7bb7b4660e 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -121,7 +121,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 
 ### Attribute Changes in Clang
 
-- Clang now properly propagates attributes on class and variable templates to 
their redeclarations, which will result in redeclarations not interfering with 
diagnostics. (#GH101469)
+- Clang now properly propagates attributes on class and variable templates to 
their redeclarations, which will result in redeclarations not interfering with 
diagnostics. (#GH209812)
 
 ### Improvements to Clang's diagnostics
 

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

Reply via email to