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

>From 949abf8addb865099cb92b2f58abc885144965f5 Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 21:37:35 +0900
Subject: [PATCH 1/6] pretest

---
 ...t_instantiation.exclude_from_dllexport.cpp | 206 ++++++++++++++++++
 ...t_instantiation.exclude_from_dllimport.cpp | 205 +++++++++++++++++
 2 files changed, 411 insertions(+)
 create mode 100644 
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
 create mode 100644 
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp

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
new file mode 100644
index 0000000000000..f417140b0301e
--- /dev/null
+++ 
b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
@@ -0,0 +1,206 @@
+// RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir
+//
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
+// RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
+// RUN: FileCheck %s --check-prefixes=UNDESIRED-MSC 
--implicit-check-not=notToBeInstantiated < x86_64-win32.ll
+//
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
+// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
+// RUN: FileCheck %s --check-prefixes=UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
+//
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
+// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
+// RUN: FileCheck %s --check-prefixes=UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
+
+// Because --implicit-check-not doesn't work with -DAG checks, negative checks
+// are performed on another independent path.
+// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$BasicCase@UWithExportTag@@@@QEAAXXZ" = comdat any
+// UNDESIRED-GNU: $_ZN9BasicCaseI13WithExportTagE19notToBeInstantiatedEv = 
comdat any
+// UNDESIRED-MSC: 
$"?notToBeInstantiated_withExport@?$BasicCase@UWithExportTag@@@@QEAAXXZ" = 
comdat any
+// UNDESIRED-GNU: 
$_ZN9BasicCaseI13WithExportTagE30notToBeInstantiated_withExportEv = comdat any
+// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ" = comdat any
+// UNDESIRED-GNU: $_ZN19ExportWholeTemplateI9NoAttrTagE19notToBeInstantiatedEv 
= comdat any
+// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$Polymorphic@UWithExportTag@@@@QEAAXXZ" = comdat any
+// UNDESIRED-GNU: $_ZN11PolymorphicI13WithExportTagE19notToBeInstantiatedEv = 
comdat any
+// UNDESIRED-MSC: 
$"?notToBeInstantiated_withExport@?$Polymorphic@UWithExportTag@@@@QEAAXXZ" = 
comdat any
+// UNDESIRED-GNU: 
$_ZN11PolymorphicI13WithExportTagE30notToBeInstantiated_withExportEv = comdat 
any
+
+#define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
+
+struct NoAttrTag {};
+struct WithExportTag {};
+struct ImplicitTag {};
+
+// Test that __declspec(dllexport) doesn't instantiate entities marked with
+// the exclude_from_explicit_instantiation attribute.
+template <class T>
+struct BasicCase {
+  void noAttrMethod() {}
+  EXCLUDE_ATTR void excludedMethod() {}
+  EXCLUDE_ATTR __declspec(dllexport) void excludedExportedMethod() {}
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+  EXCLUDE_ATTR __declspec(dllexport) void notToBeInstantiated_withExport() {}
+};
+
+/// Test that an exported explicit instantiation definition causes to export
+/// non-exclued methods (i.e., noAttrMethod) only.
+template struct __declspec(dllexport) BasicCase<WithExportTag>;
+// MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE12noAttrMethodEv
+
+// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE19notToBeInstantiatedEv
+
+// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated_withExport@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE30notToBeInstantiated_withExportEv
+
+/// Test that a non-exported explicit instantiation definition instantiates
+/// non-exclued methods but not exports.
+template struct BasicCase<NoAttrTag>;
+// MSC-DAG: define weak_odr dso_local void 
@"?noAttrMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+// GNU-DAG: define weak_odr dso_local void 
@_ZN9BasicCaseI9NoAttrTagE12noAttrMethodEv
+
+/// Test that an excluded method isn't exported even if the previous explicit
+/// instantiation definition or the method itself is exported.
+/// A never-called method `notToBeInstantiated` makes sure that an excluded
+/// method isn't instantiated unexpectedly.
+void useBasicCase() {
+  BasicCase<WithExportTag>().excludedMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE14excludedMethodEv
+
+  BasicCase<WithExportTag>().excludedExportedMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedExportedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE22excludedExportedMethodEv
+
+  BasicCase<NoAttrTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI9NoAttrTagE14excludedMethodEv
+
+  BasicCase<NoAttrTag>().excludedExportedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI9NoAttrTagE22excludedExportedMethodEv
+
+  BasicCase<ImplicitTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI11ImplicitTagE14excludedMethodEv
+
+  BasicCase<ImplicitTag>().excludedExportedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedMethod@?$BasicCase@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI11ImplicitTagE22excludedExportedMethodEv
+}
+
+// Test that a class-level dllexport attribute won't affect to excluded 
methods.
+template <class T>
+struct __declspec(dllexport) ExportWholeTemplate {
+  void noAttrMethod() {}
+  EXCLUDE_ATTR void excludedMethod() {}
+  EXCLUDE_ATTR void excludedNoinlineMethod();
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+};
+
+// MSVC and MinGW disagree on whether an inline method of a class-level 
exported
+// template should be exported.
+template <typename T> void ExportWholeTemplate<T>::excludedNoinlineMethod() {}
+
+template struct ExportWholeTemplate<NoAttrTag>;
+// MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE12noAttrMethodEv
+
+// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE19notToBeInstantiatedEv
+
+void useExportWholeTemplate() {
+  ExportWholeTemplate<NoAttrTag>().excludedMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE14excludedMethodEv
+
+  ExportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
+
+  ExportWholeTemplate<ImplicitTag>().excludedMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE14excludedMethodEv
+
+  ExportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
+  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
+}
+
+// Interaction with VTables.
+template <class T>
+struct Polymorphic {
+  EXCLUDE_ATTR explicit Polymorphic() = default;
+  virtual void noAttrVirtualMethod() {}
+  EXCLUDE_ATTR virtual void excludedVirtualMethod() {}
+  EXCLUDE_ATTR __declspec(dllexport) virtual void 
excludedExportedVirtualMethod() {}
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+  EXCLUDE_ATTR __declspec(dllexport) void notToBeInstantiated_withExport() {}
+};
+
+template struct __declspec(dllexport) Polymorphic<WithExportTag>;
+// MSC-DAG: @"??_7?$Polymorphic@UWithExportTag@@@@6B@" = dllexport unnamed_addr
+// GNU-DAG: @_ZTV11PolymorphicI13WithExportTagE = weak_odr dso_local dllexport 
unnamed_addr
+
+// MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE19noAttrVirtualMethodEv
+
+// MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE21excludedVirtualMethodEv
+
+// MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedExportedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE29excludedExportedVirtualMethodEv
+
+// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$Polymorphic@UWithExportTag@@@@QEAAXXZ"
+// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE19notToBeInstantiatedEv
+
+// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated_withExport@?$Polymorphic@UWithExportTag@@@@QEAAXXZ"
+// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE30notToBeInstantiated_withExportEv
+
+template struct Polymorphic<NoAttrTag>;
+// MSC-DAG: @"??_7?$Polymorphic@UNoAttrTag@@@@6B@" = unnamed_addr
+// GNU-DAG: @_ZTV11PolymorphicI9NoAttrTagE = weak_odr dso_local unnamed_addr
+
+// MSC-DAG: define weak_odr dso_local void 
@"?noAttrVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+// GNU-DAG: define weak_odr dso_local void 
@_ZN11PolymorphicI9NoAttrTagE19noAttrVirtualMethodEv
+
+// MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+// GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI9NoAttrTagE21excludedVirtualMethodEv
+
+// MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+// GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI9NoAttrTagE29excludedExportedVirtualMethodEv
+
+void usePolymorphic() {
+  new Polymorphic<ImplicitTag>();
+  // MSC-DAG: @"??_7?$Polymorphic@UImplicitTag@@@@6B@" = unnamed_addr
+  // GNU-DAG: @_ZTV11PolymorphicI11ImplicitTagE = linkonce_odr dso_local 
unnamed_addr
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?noAttrVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE19noAttrVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE21excludedVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE29excludedExportedVirtualMethodEv
+}
+
+/// Test that the DLL attrribute wins over the exclude attribute on a
+/// non-template context.
+struct NonTemplateClass {
+  EXCLUDE_ATTR __declspec(dllexport) void excludedExportedMethod();
+};
+
+void NonTemplateClass::excludedExportedMethod() {}
+// MSC-DAG: define dso_local dllexport void 
@"?excludedExportedMethod@NonTemplateClass@@QEAAXXZ"
+// GNU-DAG: define dso_local dllexport void 
@_ZN16NonTemplateClass22excludedExportedMethodEv
+
+/// The same, but exporting whole class.
+struct __declspec(dllexport) NonTemplateExportedClass {
+  EXCLUDE_ATTR void excludedMethod();
+};
+
+void NonTemplateExportedClass::excludedMethod() {}
+// MSC-DAG: define dso_local dllexport void 
@"?excludedMethod@NonTemplateExportedClass@@QEAAXXZ"
+// GNU-DAG: define dso_local dllexport 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
new file mode 100644
index 0000000000000..dd9347f27cbfc
--- /dev/null
+++ 
b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
@@ -0,0 +1,205 @@
+// RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir
+//
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
+// RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
+// RUN: FileCheck %s --check-prefixes=UNDESIRED-MSC 
--implicit-check-not=notToBeInstantiated < x86_64-win32.ll
+//
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
+// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
+// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU,UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
+//
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
+// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
+// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU,UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
+
+// Because --implicit-check-not doesn't work with -DAG checks, negative checks
+// are performed on another independent path.
+
+#define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
+
+struct NoAttrTag {};
+struct WithImportTag {};
+struct ImplicitTag {};
+
+// Test that __declspec(dllimport) doesn't instantiate entities marked with
+// the exclude_from_explicit_instantiation attribute.
+template <class T>
+struct BasicCase {
+  void noAttrMethod() {}
+  EXCLUDE_ATTR void excludedMethod() {}
+  EXCLUDE_ATTR __declspec(dllimport) void excludedImportedMethod() {}
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+  EXCLUDE_ATTR __declspec(dllimport) void notToBeInstantiated_withImport() {}
+  void notToBeInstantiated_noAttr() {}
+};
+
+extern template struct __declspec(dllimport) BasicCase<WithImportTag>;
+extern template struct BasicCase<NoAttrTag>;
+
+/// Test that an excluded method isn't imported even if the previous explicit
+/// instantiation declaration or the method itself is imported.
+/// A never-called method `notToBeInstantiated` makes sure that an excluded
+/// method isn't instantiated unexpectedly.
+void useBaseCase() {
+  BasicCase<WithImportTag>().noAttrMethod();
+  // MSC-DAG: declare dllimport void 
@"?noAttrMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE12noAttrMethodEv
+
+  BasicCase<WithImportTag>().excludedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE14excludedMethodEv
+
+  BasicCase<WithImportTag>().excludedImportedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedImportedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE22excludedImportedMethodEv
+
+  BasicCase<NoAttrTag>().noAttrMethod();
+  // MSC-DAG: declare dso_local void 
@"?noAttrMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dso_local void @_ZN9BasicCaseI9NoAttrTagE12noAttrMethodEv
+
+  BasicCase<NoAttrTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI9NoAttrTagE14excludedMethodEv
+
+  BasicCase<NoAttrTag>().excludedImportedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI9NoAttrTagE22excludedImportedMethodEv
+
+  BasicCase<ImplicitTag>().noAttrMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?noAttrMethod@?$BasicCase@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI11ImplicitTagE12noAttrMethodEv
+
+  BasicCase<ImplicitTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI11ImplicitTagE14excludedMethodEv
+
+  BasicCase<ImplicitTag>().excludedImportedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedMethod@?$BasicCase@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI11ImplicitTagE22excludedImportedMethodEv
+}
+
+// Test that a class-level dllimport attribute won't affect to excluded 
methods.
+template <class T>
+struct __declspec(dllimport) ImportWholeTemplate {
+  void noAttrMethod() {}
+  EXCLUDE_ATTR void excludedMethod() {}
+  EXCLUDE_ATTR void excludedNoinlineMethod();
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+  void notToBeInstantiated_noAttr() {}
+};
+
+// MSVC and MinGW disagree on whether an inline method of a class-level 
imported
+// template should be imported.
+template <typename T> void ImportWholeTemplate<T>::excludedNoinlineMethod() {}
+
+extern template struct ImportWholeTemplate<NoAttrTag>;
+
+void useImportWholeTemplate() {
+  ImportWholeTemplate<NoAttrTag>().excludedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI9NoAttrTagE14excludedMethodEv
+
+  ImportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
+
+  ImportWholeTemplate<ImplicitTag>().excludedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE14excludedMethodEv
+
+  ImportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
+}
+
+template <class T>
+struct Polymorphic {
+  EXCLUDE_ATTR explicit Polymorphic() {}
+  virtual void noAttrVirtualMethod() {}
+  EXCLUDE_ATTR virtual void excludedVirtualMethod() {}
+  EXCLUDE_ATTR __declspec(dllimport) virtual void 
excludedImportedVirtualMethod() {}
+  EXCLUDE_ATTR void notToBeInstantiated() {}
+  EXCLUDE_ATTR __declspec(dllimport) void notToBeInstantiated_withImport() {}
+  void notToBeInstantiated_noAttr() {}
+};
+
+extern template struct __declspec(dllimport) Polymorphic<WithImportTag>;
+extern template struct Polymorphic<NoAttrTag>;
+
+/// For the MSVC ABI:
+/// A call to an excluded constructor implicitly instantiates the VTable, which
+/// triggers the instantiation of all virtual methods, regardless of the 
exclude
+/// attribute. Therefore, the `MSC-DAG` checks are repeated four times for each
+/// specialization: once for the VTable and three times for the all three
+/// virtual methods of the class template.
+///
+/// For the Itanium ABI:
+/// An implicit instantiation declaration suppresses emitting the VTable, so
+/// virtual member functions won't be instantiated. Therefore, for 
`WithImportTag`
+/// and `NoAttrTag` specializations, that have an explicit instantiation
+/// declaration, only one `GNU-DAG` check to verify the VTable and three
+/// `NEGATIVE-GNU-NOT` checks to ensure the virtual methods are not emitted
+/// anywhere are placed. For the `ImplicitTag` specialization, `GNU-DAG` checks
+/// are placed four times, since the virtual methods are implicitly 
instantiated.
+///
+void usePolymorphic() {
+  new Polymorphic<WithImportTag>();
+  // UNDESIRED-MSC-NOT: @"??_{{.}}?$Polymorphic@UWithImportTag@@@@6B@" = 
unnamed_addr
+  // UNDESIRED-GNU-NOT: @_ZTV11PolymorphicI13WithImportTagE = external 
dllimport unnamed_addr
+
+  // UNDESIRED-MSC-NOT: 
@"?noAttrVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE19noAttrVirtualMethodEv
+
+  // UNDESIRED-MSC-NOT: 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE21excludedVirtualMethodEv
+
+  // UNDESIRED-MSC-NOT: 
@"?excludedImportedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE29excludedImportedVirtualMethodEv
+
+  new Polymorphic<NoAttrTag>();
+  // MSC-DAG: @"??_7?$Polymorphic@UNoAttrTag@@@@6B@" = unnamed_addr
+  // GNU-DAG: @_ZTV11PolymorphicI9NoAttrTagE = external unnamed_addr
+
+  // MSC-DAG: declare dso_local void 
@"?noAttrVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: @_ZN11PolymorphicI9NoAttrTagE19noAttrVirtualMethodEv
+
+  // MSC-DAG: declare dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: @_ZN11PolymorphicI9NoAttrTagE21excludedVirtualMethodEv
+
+  // MSC-DAG: declare dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI9NoAttrTagE29excludedImportedVirtualMethodEv
+
+  new Polymorphic<ImplicitTag>();
+  // MSC-DAG: @"??_7?$Polymorphic@UImplicitTag@@@@6B@" = unnamed_addr
+  // GNU-DAG: @_ZTV11PolymorphicI11ImplicitTagE = linkonce_odr dso_local 
unnamed_addr
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?noAttrVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE19noAttrVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE21excludedVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UImplicitTag@@@@UEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI11ImplicitTagE29excludedImportedVirtualMethodEv
+}
+
+/// Test that the DLL attrribute wins over the exclude attribute on a
+/// non-template context.
+struct NonTemplateClass {
+  EXCLUDE_ATTR __declspec(dllimport) void excludedImportedMethod();
+};
+
+struct __declspec(dllimport) NonTemplateImportedClass {
+  EXCLUDE_ATTR void excludedMethod();
+};
+
+void useNonTemplateClass() {
+  NonTemplateClass().excludedImportedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedImportedMethod@NonTemplateClass@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN16NonTemplateClass22excludedImportedMethodEv
+
+  NonTemplateImportedClass().excludedMethod();
+  // MSC-DAG: declare dllimport void 
@"?excludedMethod@NonTemplateImportedClass@@QEAAXXZ"
+  // GNU-DAG: declare dllimport void 
@_ZN24NonTemplateImportedClass14excludedMethodEv
+}
+

>From b892bb596e6a0d9548b49c8d1026405349b618ff Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 21:37:36 +0900
Subject: [PATCH 2/6] [Clang] Apply exclude_from_explicit_instantiation to
 dllimport/dllexport

Attaching `__declspec(dllexport/dllimport)` to explicit instantiation
declaration made its whole member instantiated even if they were
`__attribute__((__exclude_from_explicit_instantation__))`.
Such members should not be instantiated nor be exported to avoid
symbol leakage or duplication.
---
 clang/lib/Sema/SemaDeclCXX.cpp                |  5 ++
 ...t_instantiation.exclude_from_dllexport.cpp | 55 +++++--------------
 ...t_instantiation.exclude_from_dllimport.cpp | 32 +++++------
 3 files changed, 36 insertions(+), 56 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5837ecd6b9163..fdf3898ba52e5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6592,6 +6592,11 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl 
*Class) {
   // seem to be true in practice?
 
   for (Decl *Member : Class->decls()) {
+    if ((TSK == TSK_ExplicitInstantiationDeclaration ||
+         TSK == TSK_ExplicitInstantiationDefinition) &&
+        Member->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+      continue;
+
     VarDecl *VD = dyn_cast<VarDecl>(Member);
     CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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 f417140b0301e..7ee64a2c75b6c 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
@@ -2,28 +2,18 @@
 //
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
 // RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
-// RUN: FileCheck %s --check-prefixes=UNDESIRED-MSC 
--implicit-check-not=notToBeInstantiated < x86_64-win32.ll
+// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-win32.ll
 //
 // RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
 // RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
-// RUN: FileCheck %s --check-prefixes=UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
+// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-mingw.ll
 //
 // RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
 // RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
-// RUN: FileCheck %s --check-prefixes=UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
+// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-cygwin.ll
 
 // Because --implicit-check-not doesn't work with -DAG checks, negative checks
 // are performed on another independent path.
-// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$BasicCase@UWithExportTag@@@@QEAAXXZ" = comdat any
-// UNDESIRED-GNU: $_ZN9BasicCaseI13WithExportTagE19notToBeInstantiatedEv = 
comdat any
-// UNDESIRED-MSC: 
$"?notToBeInstantiated_withExport@?$BasicCase@UWithExportTag@@@@QEAAXXZ" = 
comdat any
-// UNDESIRED-GNU: 
$_ZN9BasicCaseI13WithExportTagE30notToBeInstantiated_withExportEv = comdat any
-// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ" = comdat any
-// UNDESIRED-GNU: $_ZN19ExportWholeTemplateI9NoAttrTagE19notToBeInstantiatedEv 
= comdat any
-// UNDESIRED-MSC: 
$"?notToBeInstantiated@?$Polymorphic@UWithExportTag@@@@QEAAXXZ" = comdat any
-// UNDESIRED-GNU: $_ZN11PolymorphicI13WithExportTagE19notToBeInstantiatedEv = 
comdat any
-// UNDESIRED-MSC: 
$"?notToBeInstantiated_withExport@?$Polymorphic@UWithExportTag@@@@QEAAXXZ" = 
comdat any
-// UNDESIRED-GNU: 
$_ZN11PolymorphicI13WithExportTagE30notToBeInstantiated_withExportEv = comdat 
any
 
 #define EXCLUDE_ATTR __attribute__((exclude_from_explicit_instantiation))
 
@@ -48,12 +38,6 @@ template struct __declspec(dllexport) 
BasicCase<WithExportTag>;
 // MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
 // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE12noAttrMethodEv
 
-// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
-// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE19notToBeInstantiatedEv
-
-// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated_withExport@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
-// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE30notToBeInstantiated_withExportEv
-
 /// Test that a non-exported explicit instantiation definition instantiates
 /// non-exclued methods but not exports.
 template struct BasicCase<NoAttrTag>;
@@ -66,12 +50,12 @@ template struct BasicCase<NoAttrTag>;
 /// method isn't instantiated unexpectedly.
 void useBasicCase() {
   BasicCase<WithExportTag>().excludedMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
-  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE14excludedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithExportTagE14excludedMethodEv
 
   BasicCase<WithExportTag>().excludedExportedMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedExportedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
-  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN9BasicCaseI13WithExportTagE22excludedExportedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithExportTagE22excludedExportedMethodEv
 
   BasicCase<NoAttrTag>().excludedMethod();
   // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
@@ -107,17 +91,14 @@ template struct ExportWholeTemplate<NoAttrTag>;
 // MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
 // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE12noAttrMethodEv
 
-// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE19notToBeInstantiatedEv
-
 void useExportWholeTemplate() {
   ExportWholeTemplate<NoAttrTag>().excludedMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE14excludedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE14excludedMethodEv
 
   ExportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
 
   ExportWholeTemplate<ImplicitTag>().excludedMethod();
   // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
@@ -146,17 +127,11 @@ template struct __declspec(dllexport) 
Polymorphic<WithExportTag>;
 // MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
 // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE19noAttrVirtualMethodEv
 
-// MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
-// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE21excludedVirtualMethodEv
-
-// MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedExportedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
-// GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE29excludedExportedVirtualMethodEv
-
-// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated@?$Polymorphic@UWithExportTag@@@@QEAAXXZ"
-// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE19notToBeInstantiatedEv
+// MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI13WithExportTagE21excludedVirtualMethodEv
 
-// UNDESIRED-MSC: define weak_odr dso_local dllexport void 
@"?notToBeInstantiated_withExport@?$Polymorphic@UWithExportTag@@@@QEAAXXZ"
-// UNDESIRED-GNU: define weak_odr dso_local dllexport void 
@_ZN11PolymorphicI13WithExportTagE30notToBeInstantiated_withExportEv
+// MSC-DAG: define linkonce_odr dso_local void 
@"?excludedExportedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI13WithExportTagE29excludedExportedVirtualMethodEv
 
 template struct Polymorphic<NoAttrTag>;
 // MSC-DAG: @"??_7?$Polymorphic@UNoAttrTag@@@@6B@" = unnamed_addr
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 dd9347f27cbfc..f6ca73d4cb847 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
@@ -2,15 +2,15 @@
 //
 // RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
 // RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
-// RUN: FileCheck %s --check-prefixes=UNDESIRED-MSC 
--implicit-check-not=notToBeInstantiated < x86_64-win32.ll
+// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-win32.ll
 //
 // RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
 // RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
-// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU,UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
+// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
 //
 // RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
 // RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
-// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU,UNDESIRED-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
+// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
 
 // Because --implicit-check-not doesn't work with -DAG checks, negative checks
 // are performed on another independent path.
@@ -46,12 +46,12 @@ void useBaseCase() {
   // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE12noAttrMethodEv
 
   BasicCase<WithImportTag>().excludedMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
-  // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE14excludedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithImportTagE14excludedMethodEv
 
   BasicCase<WithImportTag>().excludedImportedMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedImportedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
-  // GNU-DAG: declare dllimport void 
@_ZN9BasicCaseI13WithImportTagE22excludedImportedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithImportTagE22excludedImportedMethodEv
 
   BasicCase<NoAttrTag>().noAttrMethod();
   // MSC-DAG: declare dso_local void 
@"?noAttrMethod@?$BasicCase@UNoAttrTag@@@@QEAAXXZ"
@@ -96,12 +96,12 @@ extern template struct ImportWholeTemplate<NoAttrTag>;
 
 void useImportWholeTemplate() {
   ImportWholeTemplate<NoAttrTag>().excludedMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI9NoAttrTagE14excludedMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE14excludedMethodEv
 
   ImportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
 
   ImportWholeTemplate<ImplicitTag>().excludedMethod();
   // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
@@ -144,16 +144,16 @@ extern template struct Polymorphic<NoAttrTag>;
 ///
 void usePolymorphic() {
   new Polymorphic<WithImportTag>();
-  // UNDESIRED-MSC-NOT: @"??_{{.}}?$Polymorphic@UWithImportTag@@@@6B@" = 
unnamed_addr
-  // UNDESIRED-GNU-NOT: @_ZTV11PolymorphicI13WithImportTagE = external 
dllimport unnamed_addr
+  // MSC-DAG: @"??_S?$Polymorphic@UWithImportTag@@@@6B@" = unnamed_addr
+  // GNU-DAG: @_ZTV11PolymorphicI13WithImportTagE = external dllimport 
unnamed_addr
 
-  // UNDESIRED-MSC-NOT: 
@"?noAttrVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // MSC-DAG: declare dllimport void 
@"?noAttrVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE19noAttrVirtualMethodEv
 
-  // UNDESIRED-MSC-NOT: 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // MSC-DAG: declare dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE21excludedVirtualMethodEv
 
-  // UNDESIRED-MSC-NOT: 
@"?excludedImportedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // MSC-DAG: declare dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE29excludedImportedVirtualMethodEv
 
   new Polymorphic<NoAttrTag>();

>From baafdd7160e22e17bd3cf24a7c9bf32148cef4e7 Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 21:37:37 +0900
Subject: [PATCH 3/6] instantiate vtable

---
 clang/lib/Sema/SemaDeclCXX.cpp                   | 16 ++++++++++++++--
 ...icit_instantiation.exclude_from_dllimport.cpp |  8 ++++----
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index fdf3898ba52e5..8173a4b53a679 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -19124,8 +19124,20 @@ bool Sema::DefineUsedVTables() {
         }
       }
 
-      if (IsExplicitInstantiationDeclaration)
-        DefineVTable = false;
+      if (IsExplicitInstantiationDeclaration) {
+        const bool HasExcludeFromExplicitInstantiation =
+            llvm::any_of(Class->methods(), [](CXXMethodDecl *method) {
+              // If the class has a member function declared with
+              // `__attribute__((exclude_from_explicit_instantiation))`, the
+              // explicit instantiation declaration should not suppress 
emitting
+              // the vtable, since the corresponding explicit instantiation
+              // definition might not emit the vtable if a triggering method is
+              // excluded.
+              return method->hasAttr<ExcludeFromExplicitInstantiationAttr>();
+            });
+        if (!HasExcludeFromExplicitInstantiation)
+          DefineVTable = false;
+      }
     }
 
     // The exception specifications for all virtual members may be needed even
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 f6ca73d4cb847..f2dd22f53ac08 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
@@ -150,10 +150,10 @@ void usePolymorphic() {
   // MSC-DAG: declare dllimport void 
@"?noAttrVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE19noAttrVirtualMethodEv
 
-  // MSC-DAG: declare dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE21excludedVirtualMethodEv
 
-  // MSC-DAG: declare dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE29excludedImportedVirtualMethodEv
 
   new Polymorphic<NoAttrTag>();
@@ -163,10 +163,10 @@ void usePolymorphic() {
   // MSC-DAG: declare dso_local void 
@"?noAttrVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: @_ZN11PolymorphicI9NoAttrTagE19noAttrVirtualMethodEv
 
-  // MSC-DAG: declare dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: @_ZN11PolymorphicI9NoAttrTagE21excludedVirtualMethodEv
 
-  // MSC-DAG: declare dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedImportedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
   // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI9NoAttrTagE29excludedImportedVirtualMethodEv
 
   new Polymorphic<ImplicitTag>();

>From c642266f1574870db7509ac10d14544b8e96c289 Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 23:25:11 +0900
Subject: [PATCH 4/6] not to use temporaries in %t.dir

---
 ...t_instantiation.exclude_from_dllexport.cpp | 23 ++++++++++---------
 ...t_instantiation.exclude_from_dllimport.cpp | 23 ++++++++++---------
 2 files changed, 24 insertions(+), 22 deletions(-)

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 7ee64a2c75b6c..d958db5f5cf78 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
@@ -1,16 +1,17 @@
-// RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=MSC
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --implicit-check-not=notToBeInstantiated
 //
-// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
-// RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
-// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-win32.ll
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --implicit-check-not=notToBeInstantiated
 //
-// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
-// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
-// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-mingw.ll
-//
-// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
-// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
-// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-cygwin.ll
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --implicit-check-not=notToBeInstantiated
 
 // Because --implicit-check-not doesn't work with -DAG checks, negative checks
 // are performed on another independent path.
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 f2dd22f53ac08..87439af227393 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
@@ -1,16 +1,17 @@
-// RUN: rm -rf %t.dir && mkdir %t.dir && cd %t.dir
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=MSC
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --implicit-check-not=notToBeInstantiated
 //
-// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s > 
x86_64-win32.ll
-// RUN: FileCheck %s --check-prefixes=MSC                                  < 
x86_64-win32.ll
-// RUN: FileCheck %s --implicit-check-not=notToBeInstantiated              < 
x86_64-win32.ll
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated
 //
-// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s > 
x86_64-mingw.ll
-// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-mingw.ll
-// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-mingw.ll
-//
-// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s > 
x86_64-cygwin.ll
-// RUN: FileCheck %s --check-prefixes=GNU                                  < 
x86_64-cygwin.ll
-// RUN: FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated < x86_64-cygwin.ll
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=NEGATIVE-GNU 
--implicit-check-not=notToBeInstantiated
 
 // Because --implicit-check-not doesn't work with -DAG checks, negative checks
 // are performed on another independent path.

>From 2eec31bc919530c32cc691a0315e7df790e763db Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 23:26:42 +0900
Subject: [PATCH 5/6] exclude-attr affects class-level dll-attr also

---
 clang/lib/Sema/SemaDeclCXX.cpp                              | 3 +--
 ...e_from_explicit_instantiation.exclude_from_dllexport.cpp | 6 +++---
 ...e_from_explicit_instantiation.exclude_from_dllimport.cpp | 6 +++---
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8173a4b53a679..d5c207cd7481b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6592,8 +6592,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl 
*Class) {
   // seem to be true in practice?
 
   for (Decl *Member : Class->decls()) {
-    if ((TSK == TSK_ExplicitInstantiationDeclaration ||
-         TSK == TSK_ExplicitInstantiationDefinition) &&
+    if (isTemplateInstantiation(TSK) &&
         Member->hasAttr<ExcludeFromExplicitInstantiationAttr>())
       continue;
 
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 d958db5f5cf78..aa4165af975fe 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
@@ -102,12 +102,12 @@ void useExportWholeTemplate() {
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
 
   ExportWholeTemplate<ImplicitTag>().excludedMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE14excludedMethodEv
 
   ExportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
-  // MSC-DAG: define weak_odr dso_local dllexport void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
-  // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
 }
 
 // Interaction with VTables.
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 87439af227393..2bd64046d905e 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
@@ -105,12 +105,12 @@ void useImportWholeTemplate() {
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
 
   ImportWholeTemplate<ImplicitTag>().excludedMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE14excludedMethodEv
 
   ImportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
-  // MSC-DAG: declare dllimport void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
-  // GNU-DAG: declare dllimport void 
@_ZN19ImportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
 }
 
 template <class T>

>From ed72a85381f0583d5c5d63228944ee55f1f85c06 Mon Sep 17 00:00:00 2001
From: kikairoya <[email protected]>
Date: Thu, 5 Mar 2026 23:27:41 +0900
Subject: [PATCH 6/6] omit redundant noinline checks

---
 ...xplicit_instantiation.exclude_from_dllexport.cpp | 13 -------------
 ...xplicit_instantiation.exclude_from_dllimport.cpp | 13 -------------
 2 files changed, 26 deletions(-)

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 aa4165af975fe..f041e587f5ace 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
@@ -80,14 +80,9 @@ template <class T>
 struct __declspec(dllexport) ExportWholeTemplate {
   void noAttrMethod() {}
   EXCLUDE_ATTR void excludedMethod() {}
-  EXCLUDE_ATTR void excludedNoinlineMethod();
   EXCLUDE_ATTR void notToBeInstantiated() {}
 };
 
-// MSVC and MinGW disagree on whether an inline method of a class-level 
exported
-// template should be exported.
-template <typename T> void ExportWholeTemplate<T>::excludedNoinlineMethod() {}
-
 template struct ExportWholeTemplate<NoAttrTag>;
 // MSC-DAG: define weak_odr dso_local dllexport void 
@"?noAttrMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
 // GNU-DAG: define weak_odr dso_local dllexport void 
@_ZN19ExportWholeTemplateI9NoAttrTagE12noAttrMethodEv
@@ -97,17 +92,9 @@ void useExportWholeTemplate() {
   // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE14excludedMethodEv
 
-  ExportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
-  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
-
   ExportWholeTemplate<ImplicitTag>().excludedMethod();
   // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE14excludedMethodEv
-
-  ExportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
-  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
-  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
 }
 
 // Interaction with VTables.
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 2bd64046d905e..d445d0252d905 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
@@ -84,15 +84,10 @@ template <class T>
 struct __declspec(dllimport) ImportWholeTemplate {
   void noAttrMethod() {}
   EXCLUDE_ATTR void excludedMethod() {}
-  EXCLUDE_ATTR void excludedNoinlineMethod();
   EXCLUDE_ATTR void notToBeInstantiated() {}
   void notToBeInstantiated_noAttr() {}
 };
 
-// MSVC and MinGW disagree on whether an inline method of a class-level 
imported
-// template should be imported.
-template <typename T> void ImportWholeTemplate<T>::excludedNoinlineMethod() {}
-
 extern template struct ImportWholeTemplate<NoAttrTag>;
 
 void useImportWholeTemplate() {
@@ -100,17 +95,9 @@ void useImportWholeTemplate() {
   // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE14excludedMethodEv
 
-  ImportWholeTemplate<NoAttrTag>().excludedNoinlineMethod();
-  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
-  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE22excludedNoinlineMethodEv
-
   ImportWholeTemplate<ImplicitTag>().excludedMethod();
   // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
   // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE14excludedMethodEv
-
-  ImportWholeTemplate<ImplicitTag>().excludedNoinlineMethod();
-  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedNoinlineMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
-  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE22excludedNoinlineMethodEv
 }
 
 template <class T>

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

Reply via email to