[clang] [Clang][Sema] Warn when 'exclude_from_explicit_instantiation' attribute is used on local classes and members thereof (PR #88777)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 17 06:27:37 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/88777
>From 5f19ff4e34c3e3153157cfb06ba1022e982b4f2d Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 12 Apr 2024 14:33:30 -0400
Subject: [PATCH 1/3] [Clang][Sema] Ignore
'exclude_from_explicit_instantiation' attribute for members of local classes
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 7cd428de0bb32d..bf6501bfeb3f0c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -4124,7 +4124,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
- if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
+ !Instantiation->isLocalClass())
continue;
MemberSpecializationInfo *MSInfo =
@@ -4169,7 +4170,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
if (Var->isStaticDataMember()) {
- if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
+ !Instantiation->isLocalClass())
continue;
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
@@ -4203,7 +4205,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
- if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
+ !Instantiation->isLocalClass())
continue;
// Always skip the injected-class-name, along with any
>From 695e618cb5fb20bee4d24a440fb4fe1a7d428e78 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 15 Apr 2024 14:15:28 -0400
Subject: [PATCH 2/3] [FOLD] add warning + tests
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 +
clang/lib/Sema/SemaDeclAttr.cpp | 18 ++++++
clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 +--
...rom_explicit_instantiation.local-class.cpp | 64 +++++++++++++++++++
4 files changed, 88 insertions(+), 6 deletions(-)
create mode 100644 clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 44f802c0c28e84..604699231645c3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3669,6 +3669,9 @@ def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
def warn_attribute_dllexport_explicit_instantiation_def : Warning<
"'dllexport' attribute ignored on explicit instantiation definition">,
InGroup<IgnoredAttributes>;
+def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning<
+ "%0 attribute ignored on local class%select{| member}1">,
+ InGroup<IgnoredAttributes>;
def warn_invalid_initializer_from_system_header : Warning<
"invalid constructor from class in system header, should not be explicit">,
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c3bf18a3f79e23..363ae93cb62df1 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -984,6 +984,21 @@ static void handleErrorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(EA);
}
+static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ const auto *PD = isa<CXXRecordDecl>(D)
+ ? cast<DeclContext>(D)
+ : D->getDeclContext()->getRedeclContext();
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(PD); RD && RD->isLocalClass()) {
+ S.Diag(AL.getLoc(),
+ diag::warn_attribute_exclude_from_explicit_instantiation_local_class)
+ << AL << /*IsMember=*/!isa<CXXRecordDecl>(D);
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ ExcludeFromExplicitInstantiationAttr(S.Context, AL));
+}
+
namespace {
/// Determines if a given Expr references any of the given function's
/// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
@@ -9339,6 +9354,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_Error:
handleErrorAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
+ handleExcludeFromExplicitInstantiationAttr(S, D, AL);
+ break;
case ParsedAttr::AT_DiagnoseIf:
handleDiagnoseIfAttr(S, D, AL);
break;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index bf6501bfeb3f0c..7cd428de0bb32d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -4124,8 +4124,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
- if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
- !Instantiation->isLocalClass())
+ if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
MemberSpecializationInfo *MSInfo =
@@ -4170,8 +4169,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
if (Var->isStaticDataMember()) {
- if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
- !Instantiation->isLocalClass())
+ if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
@@ -4205,8 +4203,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
- if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>() &&
- !Instantiation->isLocalClass())
+ if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
// Always skip the injected-class-name, along with any
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp
new file mode 100644
index 00000000000000..f0b2cec095c97f
--- /dev/null
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.local-class.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Test that the exclude_from_explicit_instantiation attribute is ignored
+// for local classes and members thereof.
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) // expected-note 0+{{expanded from macro}}
+
+namespace N0 {
+
+ template<typename T>
+ void f() {
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION A { // expected-warning {{attribute ignored on local class}}
+ // expected-note at -1 2{{in instantiation of}}
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION void g(T t) { // expected-warning {{attribute ignored on local class member}}
+ *t; // expected-error {{indirection requires pointer operand ('int' invalid)}}
+ }
+
+ struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION B { // expected-warning {{attribute ignored on local class}}
+ void h(T t) {
+ *t; // expected-error {{indirection requires pointer operand ('int' invalid)}}
+ }
+ };
+ };
+ }
+
+ template void f<int>(); // expected-note 2{{in instantiation of}}
+
+}
+
+// This is a reduced example from libc++ which required that 'value'
+// be prefixed with 'this->' because the definition of 'Local::operator A'
+// was not instantiated when the definition of 'g' was.
+namespace N1 {
+
+ struct A { };
+
+ struct B {
+ operator A() {
+ return A();
+ }
+ };
+
+ template<typename T>
+ auto f(T t) {
+ return A(t);
+ }
+
+ template<typename T>
+ auto g(T t) {
+ struct Local {
+ T value;
+
+ EXCLUDE_FROM_EXPLICIT_INSTANTIATION // expected-warning {{attribute ignored on local class member}}
+ operator A() {
+ return A(value);
+ }
+ };
+
+ return f(Local(t));
+ }
+
+ auto x = g(B());
+
+}
>From 2cb78154b7bcde44ecfc08b56fdb95198ff55109 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 17 Apr 2024 09:27:19 -0400
Subject: [PATCH 3/3] [FOLD] add release note
---
clang/docs/ReleaseNotes.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 96ad92b540b47f..d2af0254b08594 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -287,6 +287,9 @@ Attribute Changes in Clang
This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
apply to this class.
+- Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
+ is ignored when applied to a local class or a member thereof.
+
Improvements to Clang's diagnostics
-----------------------------------
- Clang now applies syntax highlighting to the code snippets it
More information about the cfe-commits
mailing list