Skip to content

Commit dba7d73

Browse files
zmodemZijunZhaoCCK
authored andcommitted
[clang] Don't inherit dllimport/dllexport to exclude_from_explicit_instantiation members during explicit instantiation (llvm#65961)
This is a continuation of https://reviews.llvm.org/D155713 Fixes llvm#40363
1 parent 8f76645 commit dba7d73

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6602,6 +6602,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
66026602
if (!VD && !MD)
66036603
continue;
66046604

6605+
if ((TSK == TSK_ExplicitInstantiationDeclaration ||
6606+
TSK == TSK_ExplicitInstantiationDefinition) &&
6607+
Member->hasAttr<ExcludeFromExplicitInstantiationAttr>()) {
6608+
// Skip members excluded from instantiation.
6609+
continue;
6610+
}
6611+
66056612
if (MD) {
66066613
// Don't process deleted methods.
66076614
if (MD->isDeleted())
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
2+
3+
// Test that dllimport and exclude_from_explicit_instantiation work properly
4+
// together. Specifically, we check that when exclude_from_explicit_instantiation
5+
// is used on a method, the compiler doesn't expect it to be provided externally
6+
// even if it is marked with dllimport.
7+
//
8+
// https://github.com/llvm/llvm-project/issues/40363
9+
10+
#define DLLIMPORT __declspec(dllimport)
11+
#define DLLEXPORT __declspec(dllexport)
12+
#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
13+
14+
template <class T>
15+
struct DLLIMPORT Foo {
16+
EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
17+
};
18+
19+
template <class T>
20+
struct Bar {
21+
EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x() {}
22+
};
23+
24+
extern template struct Foo<int>;
25+
extern template struct DLLIMPORT Bar<int>;
26+
27+
28+
template <class T>
29+
struct Baz {
30+
EXCLUDE_FROM_EXPLICIT_INSTANTIATION void f() {}
31+
};
32+
33+
template struct DLLEXPORT Baz<int>;
34+
35+
36+
void test(Foo<int>& foo, Bar<int>& bar, Baz<int>& baz) {
37+
// Not imported.
38+
// CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Foo@H@@QEAAXXZ"
39+
foo.x();
40+
41+
// Not imported.
42+
// CHECK-DAG: define linkonce_odr dso_local void @"?x@?$Bar@H@@QEAAXXZ"
43+
bar.x();
44+
45+
// Not exported.
46+
// CHECK-DAG: define linkonce_odr dso_local void @"?f@?$Baz@H@@QEAAXXZ"
47+
baz.f();
48+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-windows -fms-extensions -verify %s
2+
3+
// Test that an entity marked as both dllimport and exclude_from_explicit_instantiation
4+
// isn't instantiated.
5+
6+
#define DLLIMPORT __declspec(dllimport)
7+
#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
8+
9+
template <class T>
10+
struct DLLIMPORT Foo {
11+
EXCLUDE_FROM_EXPLICIT_INSTANTIATION void x();
12+
};
13+
14+
template <class T>
15+
struct Bar {
16+
DLLIMPORT EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void x();
17+
};
18+
19+
template <class T>
20+
void Foo<T>::x() { using Fail = typename T::fail; }
21+
22+
template <class T>
23+
DLLIMPORT inline void Bar<T>::x() { using Fail = typename T::fail; }
24+
25+
// expected-no-diagnostics
26+
template struct Foo<int>;
27+
template struct Bar<int>;

0 commit comments

Comments
 (0)