1*1a840d29SReid Kleckner // RUN: %clang_cc1 -std=c++14 %s -verify -fms-extensions -triple x86_64-windows-msvc 2*1a840d29SReid Kleckner // RUN: %clang_cc1 -std=c++17 %s -verify -fms-extensions -triple x86_64-windows-msvc 3*1a840d29SReid Kleckner 4*1a840d29SReid Kleckner __declspec(dllimport) void imported_func(); 5*1a840d29SReid Kleckner __declspec(dllimport) int imported_int; 6*1a840d29SReid Kleckner struct Foo { 7*1a840d29SReid Kleckner void __declspec(dllimport) imported_method(); 8*1a840d29SReid Kleckner }; 9*1a840d29SReid Kleckner 10*1a840d29SReid Kleckner // Instantiation is OK. 11*1a840d29SReid Kleckner template <void (*FP)()> struct TemplateFnPtr { getitTemplateFnPtr12*1a840d29SReid Kleckner static void getit() { FP(); } 13*1a840d29SReid Kleckner }; 14*1a840d29SReid Kleckner template <void (&FP)()> struct TemplateFnRef { getitTemplateFnRef15*1a840d29SReid Kleckner static void getit() { FP(); } 16*1a840d29SReid Kleckner }; instantiate1()17*1a840d29SReid Klecknervoid instantiate1() { 18*1a840d29SReid Kleckner TemplateFnPtr<&imported_func>::getit(); 19*1a840d29SReid Kleckner TemplateFnRef<imported_func>::getit(); 20*1a840d29SReid Kleckner } 21*1a840d29SReid Kleckner 22*1a840d29SReid Kleckner // Check variable template instantiation. 23*1a840d29SReid Kleckner template <int *GI> struct TemplateIntPtr { getitTemplateIntPtr24*1a840d29SReid Kleckner static int getit() { return *GI; } 25*1a840d29SReid Kleckner }; 26*1a840d29SReid Kleckner template <int &GI> struct TemplateIntRef { getitTemplateIntRef27*1a840d29SReid Kleckner static int getit() { return GI; } 28*1a840d29SReid Kleckner }; instantiate2()29*1a840d29SReid Klecknerint instantiate2() { 30*1a840d29SReid Kleckner int r = 0; 31*1a840d29SReid Kleckner r += TemplateIntPtr<&imported_int>::getit(); 32*1a840d29SReid Kleckner r += TemplateIntRef<imported_int>::getit(); 33*1a840d29SReid Kleckner return r; 34*1a840d29SReid Kleckner } 35*1a840d29SReid Kleckner 36*1a840d29SReid Kleckner // Member pointer instantiation. 37*1a840d29SReid Kleckner template <void (Foo::*MP)()> struct TemplateMemPtr { }; 38*1a840d29SReid Kleckner TemplateMemPtr<&Foo::imported_method> instantiate_mp; 39*1a840d29SReid Kleckner 40*1a840d29SReid Kleckner // constexpr initialization doesn't work for dllimport things. 41*1a840d29SReid Kleckner // expected-error@+1{{must be initialized by a constant expression}} 42*1a840d29SReid Kleckner constexpr void (*constexpr_import_func)() = &imported_func; 43*1a840d29SReid Kleckner // expected-error@+1{{must be initialized by a constant expression}} 44*1a840d29SReid Kleckner constexpr int *constexpr_import_int = &imported_int; 45*1a840d29SReid Kleckner // expected-error@+1{{must be initialized by a constant expression}} 46*1a840d29SReid Kleckner constexpr void (Foo::*constexpr_memptr)() = &Foo::imported_method; 47*1a840d29SReid Kleckner 48*1a840d29SReid Kleckner // We make dynamic initializers for 'const' globals, but not constexpr ones. 49*1a840d29SReid Kleckner void (*const const_import_func)() = &imported_func; 50*1a840d29SReid Kleckner int *const const_import_int = &imported_int; 51*1a840d29SReid Kleckner void (Foo::*const const_memptr)() = &Foo::imported_method; 52*1a840d29SReid Kleckner 53*1a840d29SReid Kleckner // Check that using a non-type template parameter for constexpr global 54*1a840d29SReid Kleckner // initialization is correctly diagnosed during template instantiation. 55*1a840d29SReid Kleckner template <void (*FP)()> struct StaticConstexpr { 56*1a840d29SReid Kleckner // expected-error@+1{{must be initialized by a constant expression}} 57*1a840d29SReid Kleckner static constexpr void (*g_fp)() = FP; 58*1a840d29SReid Kleckner }; instantiate3()59*1a840d29SReid Klecknervoid instantiate3() { 60*1a840d29SReid Kleckner // expected-note@+1 {{requested here}} 61*1a840d29SReid Kleckner StaticConstexpr<imported_func>::g_fp(); 62*1a840d29SReid Kleckner } 63