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
