[clang] [clang] Don't inherit dllimport/dllexport to exclude_from_explicit_in… (PR #65961)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 11 06:19:22 PDT 2023


llvmbot wrote:

@llvm/pr-subscribers-clang

<details>
<summary>Changes</summary>

…stantiation members during explicit instantiation.

This is a continuation of https://reviews.llvm.org/D155713

Fixes https://github.com/llvm/llvm-project/issues/40363
--
Full diff: https://github.com/llvm/llvm-project/pull/65961.diff

3 Files Affected:

- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+7) 
- (added) clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp (+48) 
- (added) clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp (+27) 


<pre>
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2b2b7391f88fd54..1f2bb1edd3b7be5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6602,6 +6602,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
     if (!VD && !MD)
       continue;
 
+    if ((TSK == TSK_ExplicitInstantiationDeclaration ||
+         TSK == TSK_ExplicitInstantiationDefinition) &&
+        Member->hasAttr<ExcludeFromExplicitInstantiationAttr>()) {
+      // Skip members excluded from instantiation.
+      continue;
+    }
+
     if (MD) {
       // Don't process deleted methods.
       if (MD->isDeleted())
diff --git a/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
new file mode 100644
index 000000000000000..b3c804839be1ee4
--- /dev/null
+++ b/clang/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
+
+// Test that dllimport and exclude_from_explicit_instantiation work properly
+// together. Specifically, we check that when exclude_from_explicit_instantiation
+// is used on a method, the compiler doesn't expect it to be provided externally
+// even if it is marked with dllimport.
+//
+// https://github.com/llvm/llvm-project/issues/40363
+
+#define DLLIMPORT __declspec(dllimport)
+#define DLLEXPORT __declspec(dllexport)
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct DLLIMPORT Foo {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
+};
+
+template <class T>
+struct Bar {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
+};
+
+extern template struct Foo<int>;
+extern template struct DLLIMPORT Bar<int>;
+
+
+template <class T>
+struct Baz {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void f() {}
+};
+
+template struct DLLEXPORT Baz<int>;
+
+
+void test(Foo<int>& foo, Bar<int>& bar, Baz<int>& baz) {
+  // Not imported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Foo at H@@QEAAXXZ"
+  foo.x();
+
+  // Not imported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Bar at H@@QEAAXXZ"
+  bar.x();
+
+  // Not exported.
+  // CHECK-DAG: define linkonce_odr dso_local void @"?f@?$Baz at H@@QEAAXXZ"
+  baz.f();
+}
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
new file mode 100644
index 000000000000000..bdca2d8895f516c
--- /dev/null
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.dllimport.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -verify %s
+
+// Test that an entity marked as both dllimport and exclude_from_explicit_instantiation
+// isn't instantiated.
+
+#define DLLIMPORT __declspec(dllimport)
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct DLLIMPORT Foo {
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x();
+};
+
+template <class T>
+struct Bar {
+  DLLIMPORT EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void x();
+};
+
+template <class T>
+void Foo<T>::x() { using Fail = typename T::fail; }
+
+template <class T>
+DLLIMPORT inline void Bar<T>::x() { using Fail = typename T::fail; }
+
+// expected-no-diagnostics
+template struct Foo<int>;
+template struct Bar<int>;
</pre>

</details>

https://github.com/llvm/llvm-project/pull/65961


More information about the cfe-commits mailing list