[clang] fdcb1f4 - [Clang] Make members with exclude_from_explicit_instantiation never be exported or imported (#185140)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 17 02:53:04 PDT 2026
Author: Tomohiro Kashiwada
Date: 2026-03-17T10:52:58+01:00
New Revision: fdcb1f4ab19fce575a2ecd165ea476c09152b93e
URL: https://github.com/llvm/llvm-project/commit/fdcb1f4ab19fce575a2ecd165ea476c09152b93e
DIFF: https://github.com/llvm/llvm-project/commit/fdcb1f4ab19fce575a2ecd165ea476c09152b93e.diff
LOG: [Clang] Make members with exclude_from_explicit_instantiation never be exported or imported (#185140)
This patch extends the `exclude_from_explicit_instantiation` attribute
to work in non-template contexts, despite of its name.
The attribute now has a simple semantics: "Excluded members will never
be exported or imported."
Added:
Modified:
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.ignore-dllattr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 0c5a15e610114..815ed11ee3b22 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6013,6 +6013,25 @@ TUs where it is used.
This attribute can be used on static and non-static member functions of class
templates, static data members of class templates and member classes of class
templates.
+
+**Interaction with __declspec(dllexport/dllimport)**
+
+For a DLL platform (i.e., Windows), this attribute also means "this member will
+never be exported or imported". Despite its name, this semantics applies to
+implicit instantiations and non-template entities as well.
+
+ .. code-block:: c++
+
+ // in <exception>
+ class __declspec(dllimport) nested_exception {
+ ...
+ public:
+ __attribute__((exclude_from_explicit_instantiation))
+ exception_ptr nested_ptr() const noexcept { ... }
+ };
+
+In this case, ``nested_exception::nested_ptr`` will never be attempted to be
+imported.
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e49f8d3ea54f8..d4d09a8ecef36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3799,12 +3799,6 @@ def warn_nothrow_attribute_ignored : Warning<"'nothrow' attribute conflicts with
def warn_dllattr_ignored_exclusion_takes_precedence : Warning<
"%0 attribute ignored; %1 takes precedence">,
InGroup<IgnoredAttributes>;
-def warn_attribute_ignored_on_non_member :
- Warning<"%0 attribute ignored on a non-member declaration">,
- InGroup<IgnoredAttributes>;
-def warn_attribute_ignored_in_non_template :
- Warning<"%0 attribute ignored in a non-template context">,
- InGroup<IgnoredAttributes>;
def warn_attribute_ignored_on_non_definition :
Warning<"%0 attribute ignored on a non-definition declaration">,
InGroup<IgnoredAttributes>;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 6fc749464586d..8da694d09e4b4 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -708,20 +708,9 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
}
if (auto *DA = getDLLAttr(D); DA && !DA->isInherited()) {
- if (auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
- if (RD->isTemplated()) {
- S.Diag(DA->getLoc(),
- diag::warn_dllattr_ignored_exclusion_takes_precedence)
- << DA << AL;
- D->dropAttrs<DLLExportAttr, DLLImportAttr>();
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored_in_non_template) << AL;
- return;
- }
- } else {
- S.Diag(AL.getLoc(), diag::warn_attribute_ignored_on_non_member) << AL;
- return;
- }
+ S.Diag(DA->getLoc(), diag::warn_dllattr_ignored_exclusion_takes_precedence)
+ << DA << AL;
+ D->dropAttrs<DLLExportAttr, DLLImportAttr>();
}
D->addAttr(::new (S.Context)
@@ -6489,19 +6478,10 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
}
if (auto *EA = D->getAttr<ExcludeFromExplicitInstantiationAttr>()) {
- if (auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
- if (RD->isTemplated()) {
- S.Diag(A.getRange().getBegin(),
- diag::warn_dllattr_ignored_exclusion_takes_precedence)
- << A << EA;
- return;
- }
- S.Diag(EA->getLoc(), diag::warn_attribute_ignored_in_non_template) << EA;
- D->dropAttr<ExcludeFromExplicitInstantiationAttr>();
- } else {
- S.Diag(EA->getLoc(), diag::warn_attribute_ignored_on_non_member) << EA;
- D->dropAttr<ExcludeFromExplicitInstantiationAttr>();
- }
+ S.Diag(A.getRange().getBegin(),
+ diag::warn_dllattr_ignored_exclusion_takes_precedence)
+ << A << EA;
+ return;
}
Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 56f315e005320..20e4663d670b2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6616,8 +6616,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// seem to be true in practice?
for (Decl *Member : Class->decls()) {
- if (isTemplateInstantiation(TSK) &&
- Member->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+ if (Member->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
VarDecl *VD = dyn_cast<VarDecl>(Member);
diff --git a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
index f041e587f5ace..7048d32feb9e3 100644
--- a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
+++ b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
@@ -149,15 +149,15 @@ void usePolymorphic() {
// GNU-DAG: define linkonce_odr dso_local void @_ZN11PolymorphicI11ImplicitTagE29excludedExportedVirtualMethodEv
}
-/// Test that the DLL attrribute wins over the exclude attribute on a
-/// non-template context.
+/// Test that the exclude attibute takes precedence over the DLL attrribute in
+/// a non-template context also.
struct NonTemplateClass {
EXCLUDE_ATTR __declspec(dllexport) void excludedExportedMethod();
};
void NonTemplateClass::excludedExportedMethod() {}
-// MSC-DAG: define dso_local dllexport void @"?excludedExportedMethod at NonTemplateClass@@QEAAXXZ"
-// GNU-DAG: define dso_local dllexport void @_ZN16NonTemplateClass22excludedExportedMethodEv
+// MSC-DAG: define dso_local void @"?excludedExportedMethod at NonTemplateClass@@QEAAXXZ"
+// GNU-DAG: define dso_local void @_ZN16NonTemplateClass22excludedExportedMethodEv
/// The same, but exporting whole class.
struct __declspec(dllexport) NonTemplateExportedClass {
@@ -165,5 +165,5 @@ struct __declspec(dllexport) NonTemplateExportedClass {
};
void NonTemplateExportedClass::excludedMethod() {}
-// MSC-DAG: define dso_local dllexport void @"?excludedMethod at NonTemplateExportedClass@@QEAAXXZ"
-// GNU-DAG: define dso_local dllexport void @_ZN24NonTemplateExportedClass14excludedMethodEv
+// MSC-DAG: define dso_local void @"?excludedMethod at NonTemplateExportedClass@@QEAAXXZ"
+// GNU-DAG: define dso_local void @_ZN24NonTemplateExportedClass14excludedMethodEv
diff --git a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
index d445d0252d905..05e0a6efadf7b 100644
--- a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
+++ b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
@@ -171,23 +171,25 @@ void usePolymorphic() {
// GNU-DAG: define linkonce_odr dso_local void @_ZN11PolymorphicI11ImplicitTagE29excludedImportedVirtualMethodEv
}
-/// Test that the DLL attrribute wins over the exclude attribute on a
-/// non-template context.
+/// Test that the exclude attibute takes precedence over the DLL attrribute in
+/// a non-template context also.
struct NonTemplateClass {
EXCLUDE_ATTR __declspec(dllimport) void excludedImportedMethod();
};
+void NonTemplateClass::excludedImportedMethod() {}
struct __declspec(dllimport) NonTemplateImportedClass {
EXCLUDE_ATTR void excludedMethod();
};
+void NonTemplateImportedClass::excludedMethod() {}
void useNonTemplateClass() {
NonTemplateClass().excludedImportedMethod();
- // MSC-DAG: declare dllimport void @"?excludedImportedMethod at NonTemplateClass@@QEAAXXZ"
- // GNU-DAG: declare dllimport void @_ZN16NonTemplateClass22excludedImportedMethodEv
+ // MSC-DAG: define dso_local void @"?excludedImportedMethod at NonTemplateClass@@QEAAXXZ"
+ // GNU-DAG: define dso_local void @_ZN16NonTemplateClass22excludedImportedMethodEv
NonTemplateImportedClass().excludedMethod();
- // MSC-DAG: declare dllimport void @"?excludedMethod at NonTemplateImportedClass@@QEAAXXZ"
- // GNU-DAG: declare dllimport void @_ZN24NonTemplateImportedClass14excludedMethodEv
+ // MSC-DAG: define dso_local void @"?excludedMethod at NonTemplateImportedClass@@QEAAXXZ"
+ // GNU-DAG: define dso_local void @_ZN24NonTemplateImportedClass14excludedMethodEv
}
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.ignore-dllattr.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.ignore-dllattr.cpp
index 5943f99e14cad..00e1c74c34bc3 100644
--- a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.ignore-dllattr.cpp
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.ignore-dllattr.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple x86_64-mingw -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple x86_64-cygwin -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -fsyntax-only -verify=expected,msc %s
+// RUN: %clang_cc1 -triple x86_64-mingw -fsyntax-only -verify=expected,gnu %s
+// RUN: %clang_cc1 -triple x86_64-cygwin -fsyntax-only -verify=expected,gnu %s
// Test that attaching the exclude_from_explicit_instantiation attribute and
// either the dllexport or dllimport attribute together causes a warning.
@@ -92,30 +92,30 @@ template struct __declspec(dllexport) class_tmpl_explicit_inst<int>;
// Test that exclude_from_explicit_instantiation is ignored in a non-template context.
struct class_nontmpl {
- EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- EXCLUDE_ATTR __declspec(dllimport) void fn_excluded_imported(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- __declspec(dllexport) EXCLUDE_ATTR void fn_exported_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- __declspec(dllimport) EXCLUDE_ATTR void fn_imported_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ EXCLUDE_ATTR __declspec(dllimport) void fn_excluded_imported(); // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ __declspec(dllexport) EXCLUDE_ATTR void fn_exported_excluded(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ __declspec(dllimport) EXCLUDE_ATTR void fn_imported_excluded(); // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
- EXCLUDE_ATTR __declspec(dllexport) static int var_excluded_exported; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- EXCLUDE_ATTR __declspec(dllimport) static int var_excluded_imported; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- __declspec(dllexport) EXCLUDE_ATTR static int var_exported_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- __declspec(dllimport) EXCLUDE_ATTR static int var_imported_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ EXCLUDE_ATTR __declspec(dllexport) static int var_excluded_exported; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ EXCLUDE_ATTR __declspec(dllimport) static int var_excluded_imported; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ __declspec(dllexport) EXCLUDE_ATTR static int var_exported_excluded; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ __declspec(dllimport) EXCLUDE_ATTR static int var_imported_excluded; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
- struct EXCLUDE_ATTR __declspec(dllexport) nested_excluded_exported {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- struct EXCLUDE_ATTR __declspec(dllimport) nested_excluded_imported {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- struct __declspec(dllexport) EXCLUDE_ATTR nested_exported_excluded {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
- struct __declspec(dllimport) EXCLUDE_ATTR nested_imported_excluded {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ struct EXCLUDE_ATTR __declspec(dllexport) nested_excluded_exported {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ struct EXCLUDE_ATTR __declspec(dllimport) nested_excluded_imported {}; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ struct __declspec(dllexport) EXCLUDE_ATTR nested_exported_excluded {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+ struct __declspec(dllimport) EXCLUDE_ATTR nested_imported_excluded {}; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
- struct EXCLUDE_ATTR __declspec(dllexport) class_template_excluded {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ struct EXCLUDE_ATTR __declspec(dllexport) class_template_excluded {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
- EXCLUDE_ATTR __declspec(dllexport) static T var_template_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ EXCLUDE_ATTR __declspec(dllexport) static T var_template_excluded; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
- EXCLUDE_ATTR __declspec(dllexport) void fn_template_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ EXCLUDE_ATTR __declspec(dllexport) void fn_template_excluded(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
struct nested {
- EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored in a non-template context}}
+ EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
};
struct EXCLUDE_ATTR nested_excluded {
@@ -135,27 +135,27 @@ struct class_nontmpl {
};
// Test that exclude_from_explicit_instantiation is ignored on a non-member entity.
-EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-EXCLUDE_ATTR __declspec(dllimport) void fn_excluded_imported(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-__declspec(dllexport) EXCLUDE_ATTR void fn_exported_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-__declspec(dllimport) EXCLUDE_ATTR void fn_imported_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+EXCLUDE_ATTR __declspec(dllexport) void fn_excluded_exported(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+EXCLUDE_ATTR __declspec(dllimport) void fn_excluded_imported(); // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+__declspec(dllexport) EXCLUDE_ATTR void fn_exported_excluded(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+__declspec(dllimport) EXCLUDE_ATTR void fn_imported_excluded(); // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
-EXCLUDE_ATTR __declspec(dllexport) int var_excluded_exported; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-EXCLUDE_ATTR __declspec(dllimport) int var_excluded_imported; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-__declspec(dllexport) EXCLUDE_ATTR int var_exported_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-__declspec(dllimport) EXCLUDE_ATTR int var_imported_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+EXCLUDE_ATTR __declspec(dllexport) int var_excluded_exported; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+EXCLUDE_ATTR __declspec(dllimport) int var_excluded_imported; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+__declspec(dllexport) EXCLUDE_ATTR int var_exported_excluded; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+__declspec(dllimport) EXCLUDE_ATTR int var_imported_excluded; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
-struct EXCLUDE_ATTR __declspec(dllexport) class_excluded_exported {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-struct EXCLUDE_ATTR __declspec(dllimport) class_excluded_imported {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-struct __declspec(dllexport) EXCLUDE_ATTR class_exported_excluded {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
-struct __declspec(dllimport) EXCLUDE_ATTR class_imported_excluded {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+struct EXCLUDE_ATTR __declspec(dllexport) class_excluded_exported {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+struct EXCLUDE_ATTR __declspec(dllimport) class_excluded_imported {}; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+struct __declspec(dllexport) EXCLUDE_ATTR class_exported_excluded {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
+struct __declspec(dllimport) EXCLUDE_ATTR class_imported_excluded {}; // expected-warning{{'dllimport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
-struct EXCLUDE_ATTR __declspec(dllexport) class_tmpl_excluded_exported {}; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+struct EXCLUDE_ATTR __declspec(dllexport) class_tmpl_excluded_exported {}; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
-EXCLUDE_ATTR __declspec(dllexport) T var_template_excluded; // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+EXCLUDE_ATTR __declspec(dllexport) T var_template_excluded; // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
template <class T>
-EXCLUDE_ATTR __declspec(dllexport) void fn_template_excluded(); // expected-warning{{'exclude_from_explicit_instantiation' attribute ignored on a non-member declaration}}
+EXCLUDE_ATTR __declspec(dllexport) void fn_template_excluded(); // expected-warning{{'dllexport' attribute ignored; 'exclude_from_explicit_instantiation' takes precedence}}
EXCLUDE_ATTR void fn_excluded();
@@ -167,6 +167,24 @@ struct EXCLUDE_ATTR class_excluded {
struct __declspec(dllexport) class_exported {
EXCLUDE_ATTR void fn_excluded();
};
-struct __declspec(dllimport) class_imported {
+
+// Test that an excluded member in an imported class can have its definition without any warning.
+struct __declspec(dllimport) class_imported { // #import
+ void fn(); // expected-note{{previous declaration is here}}
EXCLUDE_ATTR void fn_excluded();
+ static int var;
+ EXCLUDE_ATTR static int var_excluded;
};
+
+void class_imported::fn() {}
+ // msc-warning at -1{{'class_imported::fn' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
+ // gnu-warning at -2{{'class_imported::fn' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+ // gnu-note@#import {{previous attribute is here}}
+
+void class_imported::fn_excluded() {}
+
+int class_imported::var = 0;
+ // expected-error at -1{{definition of dllimport static field not allowed}}
+ // expected-note@#import{{attribute is here}}
+
+int class_imported::var_excluded = 0;
More information about the cfe-commits
mailing list