1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
2*67e74705SXin Li
3*67e74705SXin Li namespace access_control {
4*67e74705SXin Li class Private {
5*67e74705SXin Li void check(int *) __attribute__((enable_if(false, "")));
6*67e74705SXin Li void check(double *) __attribute__((enable_if(true, "")));
7*67e74705SXin Li
8*67e74705SXin Li static void checkStatic(int *) __attribute__((enable_if(false, "")));
9*67e74705SXin Li static void checkStatic(double *) __attribute__((enable_if(true, "")));
10*67e74705SXin Li };
11*67e74705SXin Li
12*67e74705SXin Li auto Priv = reinterpret_cast<void (Private::*)(char *)>(&Private::check); // expected-error{{'check' is a private member of 'access_control::Private'}} expected-note@6{{implicitly declared private here}}
13*67e74705SXin Li
14*67e74705SXin Li auto PrivStatic = reinterpret_cast<void (*)(char *)>(&Private::checkStatic); // expected-error{{'checkStatic' is a private member of 'access_control::Private'}} expected-note@9{{implicitly declared private here}}
15*67e74705SXin Li
16*67e74705SXin Li class Protected {
17*67e74705SXin Li protected:
18*67e74705SXin Li void check(int *) __attribute__((enable_if(false, "")));
19*67e74705SXin Li void check(double *) __attribute__((enable_if(true, "")));
20*67e74705SXin Li
21*67e74705SXin Li static void checkStatic(int *) __attribute__((enable_if(false, "")));
22*67e74705SXin Li static void checkStatic(double *) __attribute__((enable_if(true, "")));
23*67e74705SXin Li };
24*67e74705SXin Li
25*67e74705SXin Li auto Prot = reinterpret_cast<void (Protected::*)(char *)>(&Protected::check); // expected-error{{'check' is a protected member of 'access_control::Protected'}} expected-note@19{{declared protected here}}
26*67e74705SXin Li
27*67e74705SXin Li auto ProtStatic = reinterpret_cast<void (*)(char *)>(&Protected::checkStatic); // expected-error{{'checkStatic' is a protected member of 'access_control::Protected'}} expected-note@22{{declared protected here}}
28*67e74705SXin Li }
29*67e74705SXin Li
30*67e74705SXin Li namespace unavailable {
31*67e74705SXin Li // Ensure that we check that the function can be called
32*67e74705SXin Li void foo() __attribute__((unavailable("don't call this")));
33*67e74705SXin Li void foo(int) __attribute__((enable_if(false, "")));
34*67e74705SXin Li
35*67e74705SXin Li void *Ptr = reinterpret_cast<void*>(foo); // expected-error{{'foo' is unavailable: don't call this}} expected-note@-3{{explicitly marked unavailable here}}
36*67e74705SXin Li }
37*67e74705SXin Li
38*67e74705SXin Li namespace template_deduction {
39*67e74705SXin Li void foo() __attribute__((enable_if(false, "")));
40*67e74705SXin Li
41*67e74705SXin Li void bar() __attribute__((enable_if(true, "")));
42*67e74705SXin Li void bar() __attribute__((enable_if(false, "")));
43*67e74705SXin Li
44*67e74705SXin Li void baz(int a) __attribute__((enable_if(true, "")));
45*67e74705SXin Li void baz(int a) __attribute__((enable_if(a, "")));
46*67e74705SXin Li void baz(int a) __attribute__((enable_if(false, "")));
47*67e74705SXin Li
48*67e74705SXin Li void qux(int a) __attribute__((enable_if(1, "")));
49*67e74705SXin Li void qux(int a) __attribute__((enable_if(true, "")));
50*67e74705SXin Li void qux(int a) __attribute__((enable_if(a, "")));
51*67e74705SXin Li void qux(int a) __attribute__((enable_if(false, "")));
52*67e74705SXin Li
call(Fn F,Args...As)53*67e74705SXin Li template <typename Fn, typename... Args> void call(Fn F, Args... As) {
54*67e74705SXin Li F(As...);
55*67e74705SXin Li }
56*67e74705SXin Li
test()57*67e74705SXin Li void test() {
58*67e74705SXin Li call(foo); // expected-error{{cannot take address of function 'foo'}}
59*67e74705SXin Li call(bar);
60*67e74705SXin Li call(baz, 0);
61*67e74705SXin Li call(qux, 0); // expected-error{{no matching function for call to 'call'}} expected-note@53{{candidate template ignored: couldn't infer template argument 'Fn'}}
62*67e74705SXin Li
63*67e74705SXin Li auto Ptr1 = foo; // expected-error{{cannot take address of function 'foo'}}
64*67e74705SXin Li auto Ptr2 = bar;
65*67e74705SXin Li auto Ptr3 = baz;
66*67e74705SXin Li auto Ptr4 = qux; // expected-error{{variable 'Ptr4' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
67*67e74705SXin Li }
68*67e74705SXin Li
69*67e74705SXin Li template <typename Fn, typename T, typename... Args>
callMem(Fn F,T t,Args...As)70*67e74705SXin Li void callMem(Fn F, T t, Args... As) {
71*67e74705SXin Li (t.*F)(As...);
72*67e74705SXin Li }
73*67e74705SXin Li
74*67e74705SXin Li class Foo {
75*67e74705SXin Li void bar() __attribute__((enable_if(true, "")));
76*67e74705SXin Li void bar() __attribute__((enable_if(false, "")));
77*67e74705SXin Li
78*67e74705SXin Li static void staticBar() __attribute__((enable_if(true, "")));
79*67e74705SXin Li static void staticBar() __attribute__((enable_if(false, "")));
80*67e74705SXin Li };
81*67e74705SXin Li
testAccess()82*67e74705SXin Li void testAccess() {
83*67e74705SXin Li callMem(&Foo::bar, Foo()); // expected-error{{'bar' is a private member of 'template_deduction::Foo'}} expected-note@-8{{implicitly declared private here}}
84*67e74705SXin Li call(&Foo::staticBar); // expected-error{{'staticBar' is a private member of 'template_deduction::Foo'}} expected-note@-6{{implicitly declared private here}}
85*67e74705SXin Li }
86*67e74705SXin Li }
87*67e74705SXin Li
88*67e74705SXin Li namespace template_template_deduction {
89*67e74705SXin Li void foo() __attribute__((enable_if(false, "")));
90*67e74705SXin Li template <typename T>
91*67e74705SXin Li T foo() __attribute__((enable_if(true, "")));
92*67e74705SXin Li
call(Fn F,Args...As)93*67e74705SXin Li template <typename Fn, typename... Args> auto call(Fn F, Args... As) {
94*67e74705SXin Li return F(As...);
95*67e74705SXin Li }
96*67e74705SXin Li
97*67e74705SXin Li auto Ok = call(&foo<int>);
98*67e74705SXin Li auto Fail = call(&foo); // expected-error{{no matching function for call to 'call'}} expected-note@-5{{candidate template ignored: couldn't infer template argument 'Fn'}}
99*67e74705SXin Li
100*67e74705SXin Li auto PtrOk = &foo<int>;
101*67e74705SXin Li auto PtrFail = &foo; // expected-error{{variable 'PtrFail' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
102*67e74705SXin Li }
103*67e74705SXin Li
104*67e74705SXin Li namespace pointer_equality {
105*67e74705SXin Li using FnTy = void (*)();
106*67e74705SXin Li
107*67e74705SXin Li void bothEnableIf() __attribute__((enable_if(false, "")));
108*67e74705SXin Li void bothEnableIf() __attribute__((enable_if(true, "")));
109*67e74705SXin Li
110*67e74705SXin Li void oneEnableIf() __attribute__((enable_if(false, "")));
111*67e74705SXin Li void oneEnableIf();
112*67e74705SXin Li
test()113*67e74705SXin Li void test() {
114*67e74705SXin Li FnTy Fn;
115*67e74705SXin Li (void)(Fn == bothEnableIf);
116*67e74705SXin Li (void)(Fn == &bothEnableIf);
117*67e74705SXin Li (void)(Fn == oneEnableIf);
118*67e74705SXin Li (void)(Fn == &oneEnableIf);
119*67e74705SXin Li }
120*67e74705SXin Li
121*67e74705SXin Li void unavailableEnableIf() __attribute__((enable_if(false, "")));
122*67e74705SXin Li void unavailableEnableIf() __attribute__((unavailable("noooo"))); // expected-note 2{{marked unavailable here}}
123*67e74705SXin Li
testUnavailable()124*67e74705SXin Li void testUnavailable() {
125*67e74705SXin Li FnTy Fn;
126*67e74705SXin Li (void)(Fn == unavailableEnableIf); // expected-error{{is unavailable}}
127*67e74705SXin Li (void)(Fn == &unavailableEnableIf); // expected-error{{is unavailable}}
128*67e74705SXin Li }
129*67e74705SXin Li
130*67e74705SXin Li class Foo {
131*67e74705SXin Li static void staticAccessEnableIf(); // expected-note 2{{declared private here}}
132*67e74705SXin Li void accessEnableIf(); // expected-note{{declared private here}}
133*67e74705SXin Li
134*67e74705SXin Li public:
135*67e74705SXin Li static void staticAccessEnableIf() __attribute__((enable_if(false, "")));
136*67e74705SXin Li void accessEnableIf() __attribute__((enable_if(false, "")));
137*67e74705SXin Li };
138*67e74705SXin Li
testAccess()139*67e74705SXin Li void testAccess() {
140*67e74705SXin Li FnTy Fn;
141*67e74705SXin Li (void)(Fn == Foo::staticAccessEnableIf); // expected-error{{is a private member}}
142*67e74705SXin Li (void)(Fn == &Foo::staticAccessEnableIf); // expected-error{{is a private member}}
143*67e74705SXin Li
144*67e74705SXin Li void (Foo::*MemFn)();
145*67e74705SXin Li (void)(MemFn == &Foo::accessEnableIf); // expected-error{{is a private member}}
146*67e74705SXin Li }
147*67e74705SXin Li }
148