Author: Tomohiro Kashiwada
Date: 2026-03-06T11:45:14+01:00
New Revision: 9ce9e4e6c19bed1781db2c20fae7f24c905438e9

URL: 
https://github.com/llvm/llvm-project/commit/9ce9e4e6c19bed1781db2c20fae7f24c905438e9
DIFF: 
https://github.com/llvm/llvm-project/commit/9ce9e4e6c19bed1781db2c20fae7f24c905438e9.diff

LOG: [Clang] Apply exclude_from_explicit_instantiation to dllimport/dllexport 
(#168171)

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.

Fixes #40363
Fixes #66909

Added: 
    
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
    
clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp

Modified: 
    clang/lib/Sema/SemaDeclCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 68f27dce84fe3..2ae6e5de0e3ee 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6605,6 +6605,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl 
*Class) {
   // seem to be true in practice?
 
   for (Decl *Member : Class->decls()) {
+    if (isTemplateInstantiation(TSK) &&
+        Member->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+      continue;
+
     VarDecl *VD = dyn_cast<VarDecl>(Member);
     CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
 
@@ -19176,8 +19180,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_dllexport.cpp
 
b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
new file mode 100644
index 0000000000000..f041e587f5ace
--- /dev/null
+++ 
b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllexport.cpp
@@ -0,0 +1,169 @@
+// 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-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-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.
+
+#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
+
+/// 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 linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UWithExportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithExportTagE14excludedMethodEv
+
+  BasicCase<WithExportTag>().excludedExportedMethod();
+  // 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"
+  // 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 notToBeInstantiated() {}
+};
+
+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
+
+void useExportWholeTemplate() {
+  ExportWholeTemplate<NoAttrTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI9NoAttrTagE14excludedMethodEv
+
+  ExportWholeTemplate<ImplicitTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ExportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ExportWholeTemplateI11ImplicitTagE14excludedMethodEv
+}
+
+// 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 linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithExportTag@@@@UEAAXXZ"
+// GNU-DAG: define linkonce_odr dso_local void 
@_ZN11PolymorphicI13WithExportTagE21excludedVirtualMethodEv
+
+// 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
+// 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..d445d0252d905
--- /dev/null
+++ 
b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.exclude_from_dllimport.cpp
@@ -0,0 +1,193 @@
+// 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-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-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.
+
+#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: define linkonce_odr dso_local void 
@"?excludedMethod@?$BasicCase@UWithImportTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN9BasicCaseI13WithImportTagE14excludedMethodEv
+
+  BasicCase<WithImportTag>().excludedImportedMethod();
+  // 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"
+  // 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 notToBeInstantiated() {}
+  void notToBeInstantiated_noAttr() {}
+};
+
+extern template struct ImportWholeTemplate<NoAttrTag>;
+
+void useImportWholeTemplate() {
+  ImportWholeTemplate<NoAttrTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UNoAttrTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI9NoAttrTagE14excludedMethodEv
+
+  ImportWholeTemplate<ImplicitTag>().excludedMethod();
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedMethod@?$ImportWholeTemplate@UImplicitTag@@@@QEAAXXZ"
+  // GNU-DAG: define linkonce_odr dso_local void 
@_ZN19ImportWholeTemplateI11ImplicitTagE14excludedMethodEv
+}
+
+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>();
+  // MSC-DAG: @"??_S?$Polymorphic@UWithImportTag@@@@6B@" = unnamed_addr
+  // GNU-DAG: @_ZTV11PolymorphicI13WithImportTagE = external dllimport 
unnamed_addr
+
+  // MSC-DAG: declare dllimport void 
@"?noAttrVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE19noAttrVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UWithImportTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: 
@_ZN11PolymorphicI13WithImportTagE21excludedVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr dso_local void 
@"?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: define linkonce_odr dso_local void 
@"?excludedVirtualMethod@?$Polymorphic@UNoAttrTag@@@@UEAAXXZ"
+  // NEGATIVE-GNU-NOT: @_ZN11PolymorphicI9NoAttrTagE21excludedVirtualMethodEv
+
+  // MSC-DAG: define linkonce_odr 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
+}
+


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

Reply via email to