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