summaryrefslogtreecommitdiff
path: root/test/SemaCXX/unaddressable-functions.cpp
blob: 286cbee5ea9bc8f26003674d6a094da69137da20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14

namespace access_control {
class Private {
  void check(int *) __attribute__((enable_if(false, "")));
  void check(double *) __attribute__((enable_if(true, "")));

  static void checkStatic(int *) __attribute__((enable_if(false, "")));
  static void checkStatic(double *) __attribute__((enable_if(true, "")));
};

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}}

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}}

class Protected {
protected:
  void check(int *) __attribute__((enable_if(false, "")));
  void check(double *) __attribute__((enable_if(true, "")));

  static void checkStatic(int *) __attribute__((enable_if(false, "")));
  static void checkStatic(double *) __attribute__((enable_if(true, "")));
};

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}}

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}}
}

namespace unavailable {
// Ensure that we check that the function can be called
void foo() __attribute__((unavailable("don't call this")));
void foo(int) __attribute__((enable_if(false, "")));

void *Ptr = reinterpret_cast<void*>(foo); // expected-error{{'foo' is unavailable: don't call this}} expected-note@-3{{explicitly marked unavailable here}}
}

namespace template_deduction {
void foo() __attribute__((enable_if(false, "")));

void bar() __attribute__((enable_if(true, "")));
void bar() __attribute__((enable_if(false, "")));

void baz(int a) __attribute__((enable_if(true, "")));
void baz(int a) __attribute__((enable_if(a, "")));
void baz(int a) __attribute__((enable_if(false, "")));

void qux(int a) __attribute__((enable_if(1, "")));
void qux(int a) __attribute__((enable_if(true, "")));
void qux(int a) __attribute__((enable_if(a, "")));
void qux(int a) __attribute__((enable_if(false, "")));

template <typename Fn, typename... Args> void call(Fn F, Args... As) {
  F(As...);
}

void test() {
  call(foo); // expected-error{{cannot take address of function 'foo'}}
  call(bar);
  call(baz, 0);
  call(qux, 0); // expected-error{{no matching function for call to 'call'}} expected-note@53{{candidate template ignored: couldn't infer template argument 'Fn'}}

  auto Ptr1 = foo; // expected-error{{cannot take address of function 'foo'}}
  auto Ptr2 = bar;
  auto Ptr3 = baz;
  auto Ptr4 = qux; // expected-error{{variable 'Ptr4' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
}

template <typename Fn, typename T, typename... Args>
void callMem(Fn F, T t, Args... As) {
  (t.*F)(As...);
}

class Foo {
  void bar() __attribute__((enable_if(true, "")));
  void bar() __attribute__((enable_if(false, "")));

  static void staticBar() __attribute__((enable_if(true, "")));
  static void staticBar() __attribute__((enable_if(false, "")));
};

void testAccess() {
  callMem(&Foo::bar, Foo()); // expected-error{{'bar' is a private member of 'template_deduction::Foo'}} expected-note@-8{{implicitly declared private here}}
  call(&Foo::staticBar); // expected-error{{'staticBar' is a private member of 'template_deduction::Foo'}} expected-note@-6{{implicitly declared private here}}
}
}

namespace template_template_deduction {
void foo() __attribute__((enable_if(false, "")));
template <typename T>
T foo() __attribute__((enable_if(true, "")));

template <typename Fn, typename... Args> auto call(Fn F, Args... As) {
  return F(As...);
}

auto Ok = call(&foo<int>);
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'}}

auto PtrOk = &foo<int>;
auto PtrFail = &foo; // expected-error{{variable 'PtrFail' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
}

namespace pointer_equality {
  using FnTy = void (*)();

  void bothEnableIf() __attribute__((enable_if(false, "")));
  void bothEnableIf() __attribute__((enable_if(true, "")));

  void oneEnableIf() __attribute__((enable_if(false, "")));
  void oneEnableIf();

  void test() {
    FnTy Fn;
    (void)(Fn == bothEnableIf);
    (void)(Fn == &bothEnableIf);
    (void)(Fn == oneEnableIf);
    (void)(Fn == &oneEnableIf);
  }

  void unavailableEnableIf() __attribute__((enable_if(false, "")));
  void unavailableEnableIf() __attribute__((unavailable("noooo"))); // expected-note 2{{marked unavailable here}}

  void testUnavailable() {
    FnTy Fn;
    (void)(Fn == unavailableEnableIf); // expected-error{{is unavailable}}
    (void)(Fn == &unavailableEnableIf); // expected-error{{is unavailable}}
  }

  class Foo {
    static void staticAccessEnableIf(); // expected-note 2{{declared private here}}
    void accessEnableIf(); // expected-note{{declared private here}}

  public:
    static void staticAccessEnableIf() __attribute__((enable_if(false, "")));
    void accessEnableIf() __attribute__((enable_if(false, "")));
  };

  void testAccess() {
    FnTy Fn;
    (void)(Fn == Foo::staticAccessEnableIf); // expected-error{{is a private member}}
    (void)(Fn == &Foo::staticAccessEnableIf); // expected-error{{is a private member}}

    void (Foo::*MemFn)();
    (void)(MemFn == &Foo::accessEnableIf); // expected-error{{is a private member}}
  }
}