https://github.com/kikairoya updated 
https://github.com/llvm/llvm-project/pull/183514

>From 9bb00dde5e8c9c0bcfc73daefd9b31ceb9cb714f Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 26 Feb 2026 21:50:15 +0900
Subject: [PATCH 1/3] [Clang] Drop `exclude_from_explicit_instantiation` on a
 non-template context

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  6 ++
 clang/lib/Sema/SemaDeclAttr.cpp               | 12 ++++
 ...rom_explicit_instantiation.nontemplate.cpp | 68 +++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 
clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8a3b9de19ad32..b35c0694cf518 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3796,6 +3796,12 @@ def warn_attribute_ignored_on_non_definition :
 def warn_attribute_ignored_on_inline :
   Warning<"%0 attribute ignored on inline function">,
   InGroup<IgnoredAttributes>;
+def warn_attribute_ignored_on_non_member :
+  Warning<"%0 attribute ignored on a non-member declaration">,
+  InGroup<IgnoredAttributes>;
+def warn_attribute_ignored_on_non_template :
+  Warning<"%0 attribute ignored on a non-template context">,
+  InGroup<IgnoredAttributes>;
 def warn_nocf_check_attribute_ignored :
   Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the 
attribute">,
   InGroup<IgnoredAttributes>;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3abc69d0e4b96..680f24dde5143 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -705,6 +705,18 @@ static void 
handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
         << AL << /*IsMember=*/!isa<CXXRecordDecl>(D);
     return;
   }
+  if (const auto *RD = dyn_cast_if_present<CXXRecordDecl>(
+          D->getDeclContext()->getRedeclContext())) {
+    if (!isa<TemplateDecl>(RD) && !RD->isDependentType() &&
+        !isTemplateInstantiation(RD->getTemplateSpecializationKind())) {
+      S.Diag(AL.getLoc(), diag::warn_attribute_ignored_on_non_template) << AL;
+      return;
+    }
+  } else {
+    S.Diag(AL.getLoc(), diag::warn_attribute_ignored_on_non_member) << AL;
+    return;
+  }
+
   D->addAttr(::new (S.Context)
                  ExcludeFromExplicitInstantiationAttr(S.Context, AL));
 }
diff --git 
a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
new file mode 100644
index 0000000000000..0196869117ed8
--- /dev/null
+++ 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Test that exclude_from_explicit_instantiation is warned if attached
+// on a non-template context or on a non-member entity.
+
+#define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
+
+struct C {
+  EXCLUDE_ATTR void fn_excluded();
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  EXCLUDE_ATTR static int var_excluded;
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  struct EXCLUDE_ATTR nested_excluded {
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+    EXCLUDE_ATTR void fn_excluded();
+    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+    EXCLUDE_ATTR static int var_excluded;
+    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  };
+  struct nested {
+    EXCLUDE_ATTR void fn_excluded();
+    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+    EXCLUDE_ATTR static int var_excluded;
+    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  };
+  template <class T>
+  struct EXCLUDE_ATTR class_template_excluded {};
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  template <class T>
+  EXCLUDE_ATTR static T var_template_excluded;
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  template <class T>
+  EXCLUDE_ATTR void fn_template_excluded();
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+};
+
+struct EXCLUDE_ATTR class_excluded {};
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+EXCLUDE_ATTR int var_excluded;
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+EXCLUDE_ATTR void fn_excluded();
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+
+template <class T>
+struct EXCLUDE_ATTR class_template_excluded {};
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+template <class T>
+EXCLUDE_ATTR T var_template_excluded;
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+template <class T>
+EXCLUDE_ATTR void fn_template_excluded();
+// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+
+void fn () {
+  EXCLUDE_ATTR static int var_excluded;
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+}
+
+auto lambda = [](auto x) {
+  EXCLUDE_ATTR static int var_excluded;
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+};
+
+template <class T>
+void fn_template() {
+  EXCLUDE_ATTR static T var_excluded;
+  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+};

>From 557eeec2ff67f8ed0466749ac7d725d93b2b01a1 Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Fri, 27 Feb 2026 19:22:23 +0900
Subject: [PATCH 2/3] unfold

---
 ...rom_explicit_instantiation.nontemplate.cpp | 57 +++++++------------
 1 file changed, 19 insertions(+), 38 deletions(-)

diff --git 
a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
index 0196869117ed8..2a9c3fbef037f 100644
--- 
a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
+++ 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
@@ -6,63 +6,44 @@
 #define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
 
 struct C {
-  EXCLUDE_ATTR void fn_excluded();
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
-  EXCLUDE_ATTR static int var_excluded;
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
-  struct EXCLUDE_ATTR nested_excluded {
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
-    EXCLUDE_ATTR void fn_excluded();
-    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
-    EXCLUDE_ATTR static int var_excluded;
-    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  struct EXCLUDE_ATTR nested_excluded { // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+    EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
   };
   struct nested {
-    EXCLUDE_ATTR void fn_excluded();
-    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
-    EXCLUDE_ATTR static int var_excluded;
-    // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+    EXCLUDE_ATTR static int var_excluded;  // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
   };
   template <class T>
-  struct EXCLUDE_ATTR class_template_excluded {};
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  struct EXCLUDE_ATTR class_template_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
   template <class T>
-  EXCLUDE_ATTR static T var_template_excluded;
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  EXCLUDE_ATTR static T var_template_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
   template <class T>
-  EXCLUDE_ATTR void fn_template_excluded();
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-template context}}
+  EXCLUDE_ATTR void fn_template_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
 };
 
-struct EXCLUDE_ATTR class_excluded {};
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
-EXCLUDE_ATTR int var_excluded;
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
-EXCLUDE_ATTR void fn_excluded();
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+struct EXCLUDE_ATTR class_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
+EXCLUDE_ATTR int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
+EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 
 template <class T>
-struct EXCLUDE_ATTR class_template_excluded {};
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+struct EXCLUDE_ATTR class_template_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 template <class T>
-EXCLUDE_ATTR T var_template_excluded;
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+EXCLUDE_ATTR T var_template_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 template <class T>
-EXCLUDE_ATTR void fn_template_excluded();
-// expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+EXCLUDE_ATTR void fn_template_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 
 void fn () {
-  EXCLUDE_ATTR static int var_excluded;
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+  EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 }
 
 auto lambda = [](auto x) {
-  EXCLUDE_ATTR static int var_excluded;
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+  EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 };
 
 template <class T>
 void fn_template() {
-  EXCLUDE_ATTR static T var_excluded;
-  // expected-warning@-1{{'exclude_from_explicit_instantiation' attribute 
ignored on a non-member declaration}}
+  EXCLUDE_ATTR static T var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}
 };

>From 28b051d1a9634c4504aec2a87fd8227e8b0a493e Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Fri, 27 Feb 2026 20:53:25 +0900
Subject: [PATCH 3/3] *in* a non-template context

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 ++--
 clang/lib/Sema/SemaDeclAttr.cpp               |  2 +-
 ...rom_explicit_instantiation.nontemplate.cpp | 20 +++++++++----------
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b35c0694cf518..18b4d697d82a5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3799,8 +3799,8 @@ def warn_attribute_ignored_on_inline :
 def warn_attribute_ignored_on_non_member :
   Warning<"%0 attribute ignored on a non-member declaration">,
   InGroup<IgnoredAttributes>;
-def warn_attribute_ignored_on_non_template :
-  Warning<"%0 attribute ignored on a non-template context">,
+def warn_attribute_ignored_in_non_template :
+  Warning<"%0 attribute ignored in a non-template context">,
   InGroup<IgnoredAttributes>;
 def warn_nocf_check_attribute_ignored :
   Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the 
attribute">,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 680f24dde5143..508341f801f0b 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -709,7 +709,7 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema 
&S, Decl *D,
           D->getDeclContext()->getRedeclContext())) {
     if (!isa<TemplateDecl>(RD) && !RD->isDependentType() &&
         !isTemplateInstantiation(RD->getTemplateSpecializationKind())) {
-      S.Diag(AL.getLoc(), diag::warn_attribute_ignored_on_non_template) << AL;
+      S.Diag(AL.getLoc(), diag::warn_attribute_ignored_in_non_template) << AL;
       return;
     }
   } else {
diff --git 
a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
index 2a9c3fbef037f..4823a12e7c2a7 100644
--- 
a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
+++ 
b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.nontemplate.cpp
@@ -6,22 +6,22 @@
 #define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
 
 struct C {
-  EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
-  EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
-  struct EXCLUDE_ATTR nested_excluded { // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
-    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
-    EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
+  EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
+  struct EXCLUDE_ATTR nested_excluded { // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
+    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
+    EXCLUDE_ATTR static int var_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
   };
   struct nested {
-    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
-    EXCLUDE_ATTR static int var_excluded;  // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+    EXCLUDE_ATTR void fn_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
+    EXCLUDE_ATTR static int var_excluded;  // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
   };
   template <class T>
-  struct EXCLUDE_ATTR class_template_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  struct EXCLUDE_ATTR class_template_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
   template <class T>
-  EXCLUDE_ATTR static T var_template_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  EXCLUDE_ATTR static T var_template_excluded; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
   template <class T>
-  EXCLUDE_ATTR void fn_template_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-template context}}
+  EXCLUDE_ATTR void fn_template_excluded(); // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a 
non-template context}}
 };
 
 struct EXCLUDE_ATTR class_excluded {}; // 
expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a 
non-member declaration}}

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

Reply via email to