Reid Kleckner | df6dbf6 | 2018-05-11 01:26:11 +0000 | [diff] [blame] | 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 | } |