1 | // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++14 -fms-extensions -o - %s | FileCheck %s --check-prefix=IMPORT |
2 | // RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++14 -fms-extensions -o - %s -DTEST_EXPORT | FileCheck %s --check-prefix=EXPORT |
3 | |
4 | #ifndef TEST_EXPORT |
5 | #define DLLATTR __declspec(dllimport) |
6 | #else |
7 | #define DLLATTR __declspec(dllexport) |
8 | #endif |
9 | |
10 | // PR37232: When a dllimport attribute is propagated from a derived class to a |
11 | // base class that happens to be a template specialization, it is only applied |
12 | // to template *methods*, and not static data members. If a dllexport attribute |
13 | // is propagated, it still applies to static data members. |
14 | |
15 | // IMPORT-DAG: @"?sdm@Exporter@@2HB" = available_externally dllimport constant i32 2, align 4 |
16 | // IMPORT-DAG: @"?csdm@?$A@H@@2HB" = linkonce_odr dso_local constant i32 2, comdat, align 4 |
17 | // IMPORT-DAG: @"?sdm@?$A@H@@2HA" = linkonce_odr dso_local global i32 1, comdat, align 4 |
18 | // IMPORT-DAG: @"?sdm@?$B@H@@2HB" = available_externally dllimport constant i32 2, align 4 |
19 | // IMPORT-DAG: @"?sdm@?$C@H@@2HB" = available_externally dllimport constant i32 2, align 4 |
20 | |
21 | // EXPORT-DAG: @"?sdm@Exporter@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4 |
22 | // EXPORT-DAG: @"?csdm@?$A@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4 |
23 | // EXPORT-DAG: @"?sdm@?$A@H@@2HA" = weak_odr dso_local dllexport global i32 1, comdat, align 4 |
24 | // EXPORT-DAG: @"?sdm@?$B@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4 |
25 | // EXPORT-DAG: @"?sdm@?$C@H@@2HB" = weak_odr dso_local dllexport constant i32 2, comdat, align 4 |
26 | |
27 | |
28 | template <typename T> struct A { |
29 | static constexpr int csdm = 2; |
30 | static int sdm; |
31 | }; |
32 | template <typename T> int A<T>::sdm = 1; |
33 | |
34 | struct DLLATTR Exporter : A<int> { |
35 | static constexpr int sdm = 2; |
36 | }; |
37 | |
38 | template <typename T> struct DLLATTR B { static constexpr int sdm = 2; }; |
39 | |
40 | template <typename T> struct DLLATTR C; |
41 | template <typename T> struct C { static constexpr int sdm = 2; }; |
42 | |
43 | void takeRef(const int &_Args) {} |
44 | |
45 | int main() { |
46 | takeRef(Exporter::sdm); |
47 | takeRef(A<int>::csdm); |
48 | takeRef(A<int>::sdm); |
49 | takeRef(B<int>::sdm); |
50 | takeRef(C<int>::sdm); |
51 | |
52 | return 1; |
53 | } |
54 | |