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