Clang Project

clang_source_code/test/SemaCXX/unaddressable-functions.cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
2
3namespace access_control {
4class 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
12auto 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
14auto 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
16class Protected {
17protected:
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
25auto 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
27auto 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
30namespace unavailable {
31// Ensure that we check that the function can be called
32void foo() __attribute__((unavailable("don't call this")));
33void foo(int) __attribute__((enable_if(false, "")));
34
35void *Ptr = reinterpret_cast<void*>(foo); // expected-error{{'foo' is unavailable: don't call this}} expected-note@-3{{explicitly marked unavailable here}}
36}
37
38namespace template_deduction {
39void foo() __attribute__((enable_if(false, "")));
40
41void bar() __attribute__((enable_if(true, "")));
42void bar() __attribute__((enable_if(false, "")));
43
44void baz(int a) __attribute__((enable_if(true, "")));
45void baz(int a) __attribute__((enable_if(a, "")));
46void baz(int a) __attribute__((enable_if(false, "")));
47
48void qux(int a) __attribute__((enable_if(1, "")));
49void qux(int a) __attribute__((enable_if(true, "")));
50void qux(int a) __attribute__((enable_if(a, "")));
51void qux(int a) __attribute__((enable_if(false, "")));
52
53template <typename Fn, typename... Args> void call(Fn F, Args... As) {
54  F(As...);
55}
56
57void 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
69template <typename Fn, typename T, typename... Args>
70void callMem(Fn F, T t, Args... As) {
71  (t.*F)(As...);
72}
73
74class 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
82void 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
88namespace template_template_deduction {
89void foo() __attribute__((enable_if(false, "")));
90template <typename T>
91T foo() __attribute__((enable_if(true, "")));
92
93template <typename Fn, typename... Args> auto call(Fn F, Args... As) {
94  return F(As...);
95}
96
97auto Ok = call(&foo<int>);
98auto 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
100auto PtrOk = &foo<int>;
101auto PtrFail = &foo; // expected-error{{variable 'PtrFail' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
102}
103
104namespace 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
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
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
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