1// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14
2
3friend class A; // expected-error {{'friend' used outside of class}}
4void f() { friend class A; } // expected-error {{'friend' used outside of class}}
5class C { friend class A; };
6class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}}
7
8// PR5760
9namespace test0 {
10  namespace ns {
11    void f(int);
12  }
13
14  struct A {
15    friend void ns::f(int a);
16  };
17}
18
19// Test derived from LLVM's Registry.h
20namespace test1 {
21  template <class T> struct Outer {
22    void foo(T);
23    struct Inner {
24      friend void Outer::foo(T);
25    };
26  };
27
28  void test() {
29    (void) Outer<int>::Inner();
30  }
31}
32
33// PR5476
34namespace test2 {
35  namespace foo {
36    void Func(int x);
37  }
38
39  class Bar {
40    friend void ::test2::foo::Func(int x);
41  };
42}
43
44// PR5134
45namespace test3 {
46  class Foo {
47    friend const int getInt(int inInt = 0) {}
48
49  };
50}
51
52namespace test4 {
53  class T4A {
54    friend class T4B;
55
56  public:
57    T4A(class T4B *);
58
59  protected:
60    T4B *mB;          // error here
61  };
62
63  class T4B {};
64}
65
66namespace rdar8529993 {
67struct A { ~A(); };
68
69struct B : A
70{
71  template<int> friend A::~A(); // expected-error {{destructor cannot be declared as a template}}
72};
73}
74
75// PR7915
76namespace test5 {
77  struct A;
78  struct A1 { friend void A(); };
79
80  struct B { friend void B(); };
81}
82
83// PR8479
84namespace test6_1 {
85  class A {
86   public:
87   private:
88    friend class vectorA;
89    A() {}
90  };
91  class vectorA {
92   public:
93    vectorA(int i, const A& t = A()) {}
94  };
95  void f() {
96    vectorA v(1);
97  }
98}
99namespace test6_2 {
100  template<class T>
101  class vector {
102   public:
103    vector(int i, const T& t = T()) {}
104  };
105  class A {
106   public:
107   private:
108    friend class vector<A>;
109    A() {}
110  };
111  void f() {
112    vector<A> v(1);
113  }
114}
115namespace test6_3 {
116  template<class T>
117  class vector {
118   public:
119    vector(int i) {}
120    void f(const T& t = T()) {}
121  };
122  class A {
123   public:
124   private:
125    friend void vector<A>::f(const A&);
126    A() {}
127  };
128  void f() {
129    vector<A> v(1);
130    v.f();
131  }
132}
133
134namespace test7 {
135  extern "C" {
136    class X {
137      friend int test7_f() { return 42; }
138    };
139  }
140}
141
142// PR15485
143namespace test8 {
144  namespace ns1 {
145    namespace ns2 {
146      template<class T> void f(T t); // expected-note {{target of using declaration}}
147    }
148    using ns2::f; // expected-note {{using declaration}}
149  }
150  struct A { void f(); }; // expected-note {{target of using declaration}}
151  struct B : public A { using A::f; }; // expected-note {{using declaration}}
152  struct X {
153    template<class T> friend void ns1::f(T t); // expected-error {{cannot befriend target of using declaration}}
154    friend void B::f(); // expected-error {{cannot befriend target of using declaration}}
155  };
156}
157
158// PR16423
159namespace test9 {
160  class C {
161  };
162  struct A {
163    friend void C::f(int, int, int) {}  // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}}
164  };
165}
166
167namespace test10 {
168  struct X {};
169  extern void f10_a();
170  extern void f10_a(X);
171  struct A {
172    friend void f10_a();
173    friend void f10_b();
174    friend void f10_c();
175    friend void f10_d();
176    friend void f10_a(X);
177    friend void f10_b(X);
178    friend void f10_c(X);
179    friend void f10_d(X);
180  };
181  extern void f10_b();
182  extern void f10_b(X);
183  struct B {
184    friend void f10_a();
185    friend void f10_b();
186    friend void f10_c();
187    friend void f10_d();
188    friend void f10_a(X);
189    friend void f10_b(X);
190    friend void f10_c(X);
191    friend void f10_d(X);
192  };
193  extern void f10_c();
194  extern void f10_c(X);
195
196  // FIXME: Give a better diagnostic for the case where a function exists but is
197  // not visible.
198  void g(X x) {
199    f10_a();
200    f10_b();
201    f10_c();
202    f10_d(); // expected-error {{undeclared identifier}}
203
204    ::test10::f10_a();
205    ::test10::f10_b();
206    ::test10::f10_c();
207    ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}
208
209    f10_a(x);
210    f10_b(x);
211    f10_c(x);
212    f10_d(x); // PR16597: expected-error {{undeclared identifier}}
213
214    ::test10::f10_a(x);
215    ::test10::f10_b(x);
216    ::test10::f10_c(x);
217    ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
218  }
219
220  struct Y : X {
221    friend void f10_d();
222    friend void f10_d(X);
223  };
224
225  struct Z {
226    operator X();
227    friend void f10_d();
228    friend void f10_d(X);
229  };
230
231  void g(X x, Y y, Z z) {
232    f10_d(); // expected-error {{undeclared identifier}}
233    ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}
234
235    // f10_d is visible to ADL in the second and third cases.
236    f10_d(x); // expected-error {{undeclared identifier}}
237    f10_d(y);
238    f10_d(z);
239
240    // No ADL here.
241    ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
242    ::test10::f10_d(y); // expected-error {{no type named 'f10_d'}}
243    ::test10::f10_d(z); // expected-error {{no type named 'f10_d'}}
244  }
245
246  void local_externs(X x, Y y) {
247    extern void f10_d();
248    extern void f10_d(X);
249    f10_d();
250    f10_d(x);
251    // FIXME: This lookup should fail, because the local extern declaration
252    // should suppress ADL.
253    f10_d(y);
254    {
255      int f10_d;
256      f10_d(); // expected-error {{not a function}}
257      f10_d(x); // expected-error {{not a function}}
258      f10_d(y); // expected-error {{not a function}}
259    }
260  }
261
262  void i(X x, Y y) {
263    f10_d(); // expected-error {{undeclared identifier}}
264    f10_d(x); // expected-error {{undeclared identifier}}
265    f10_d(y);
266  }
267
268  struct C {
269    friend void f10_d();
270    friend void f10_d(X);
271  };
272
273  void j(X x, Y y) {
274    f10_d(); // expected-error {{undeclared identifier}}
275    f10_d(x); // expected-error {{undeclared identifier}}
276    f10_d(y);
277  }
278
279  extern void f10_d();
280  extern void f10_d(X);
281  void k(X x, Y y, Z z) {
282    // All OK now.
283    f10_d();
284    f10_d(x);
285    ::test10::f10_d();
286    ::test10::f10_d(x);
287    ::test10::f10_d(y);
288    ::test10::f10_d(z);
289  }
290}
291
292namespace test11 {
293  class __attribute__((visibility("hidden"))) B;
294
295  class A {
296    friend class __attribute__((visibility("hidden"), noreturn)) B; // expected-warning {{'noreturn' attribute only applies to functions and methods}}
297  };
298}
299
300namespace pr21851 {
301// PR21851 was a problem where we assumed that when the friend function redecl
302// lookup found a C++ method, it would necessarily have a qualifier. Below we
303// have some test cases where unqualified lookup finds C++ methods without using
304// qualifiers. Unfortunately, we can't exercise the case of an access check
305// failure because nested classes always have access to the members of outer
306// classes.
307
308void friend_own_method() {
309  class A {
310    void m() {}
311    friend void m();
312  };
313}
314
315void friend_enclosing_method() {
316  class A;
317  class C {
318    int p;
319    friend class A;
320  };
321  class A {
322    void enclosing_friend() {
323      (void)b->p;
324      (void)c->p;
325    }
326    class B {
327      void b(A *a) {
328        (void)a->c->p;
329      }
330      int p;
331      friend void enclosing_friend();
332    };
333    B *b;
334    C *c;
335  };
336}
337
338static auto friend_file_func() {
339  extern void file_scope_friend();
340  class A {
341    int p;
342    friend void file_scope_friend();
343  };
344  return A();
345}
346
347void file_scope_friend() {
348  auto a = friend_file_func();
349  (void)a.p;
350}
351}
352
353template<typename T>
354struct X_pr6954 {
355  operator int();
356  friend void f_pr6954(int x);
357};
358
359int array0_pr6954[sizeof(X_pr6954<int>)];
360int array1_pr6954[sizeof(X_pr6954<float>)];
361
362void g_pr6954() {
363  f_pr6954(5); // expected-error{{undeclared identifier 'f_pr6954'}}
364}
365
366