xref: /llvm-project/clang/test/SemaCXX/dllimport-constexpr.cpp (revision 1a840d29b417e393c3d229706c912a97d015ed41)
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 Kleckner void 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 Kleckner int 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 Kleckner void instantiate3() {
60*1a840d29SReid Kleckner   // expected-note@+1 {{requested here}}
61*1a840d29SReid Kleckner   StaticConstexpr<imported_func>::g_fp();
62*1a840d29SReid Kleckner }
63