aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/friend.cpp
blob: 4f27f4df6c907672057f49af06100cd51a82e483 (plain) (blame)
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14

friend class A; // expected-error {{'friend' used outside of class}}
void f() { friend class A; } // expected-error {{'friend' used outside of class}}
class C { friend class A; };
class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}}

// PR5760
namespace test0 {
  namespace ns {
    void f(int);
  }

  struct A {
    friend void ns::f(int a);
  };
}

// Test derived from LLVM's Registry.h
namespace test1 {
  template <class T> struct Outer {
    void foo(T);
    struct Inner {
      friend void Outer::foo(T);
    };
  };

  void test() {
    (void) Outer<int>::Inner();
  }
}

// PR5476
namespace test2 {
  namespace foo {
    void Func(int x);
  }

  class Bar {
    friend void ::test2::foo::Func(int x);
  };
}

// PR5134
namespace test3 {
  class Foo {
    friend const int getInt(int inInt = 0) {}

  };
}

namespace test4 {
  class T4A {
    friend class T4B;
  
  public:
    T4A(class T4B *);

  protected:
    T4B *mB;          // error here
  };
 
  class T4B {};
}

namespace rdar8529993 {
struct A { ~A(); };

struct B : A
{
  template<int> friend A::~A(); // expected-error {{destructor cannot be declared as a template}}
};
}

// PR7915
namespace test5 {
  struct A;
  struct A1 { friend void A(); };

  struct B { friend void B(); };
}

// PR8479
namespace test6_1 {
  class A {
   public:
   private:
    friend class vectorA;
    A() {}
  };
  class vectorA {
   public:
    vectorA(int i, const A& t = A()) {}
  };
  void f() {
    vectorA v(1);
  }
}
namespace test6_2 {
  template<class T>
  class vector {
   public:
    vector(int i, const T& t = T()) {}
  };
  class A {
   public:
   private:
    friend class vector<A>;
    A() {}
  };
  void f() {
    vector<A> v(1);
  }
}
namespace test6_3 {
  template<class T>
  class vector {
   public:
    vector(int i) {}
    void f(const T& t = T()) {}
  };
  class A {
   public:
   private:
    friend void vector<A>::f(const A&);
    A() {}
  };
  void f() {
    vector<A> v(1);
    v.f();
  }
}

namespace test7 {
  extern "C" {
    class X {
      friend int test7_f() { return 42; }
    };
  }
}

// PR15485
namespace test8 {
  namespace ns1 {
    namespace ns2 {
      template<class T> void f(T t); // expected-note {{target of using declaration}}
    }
    using ns2::f; // expected-note {{using declaration}}
  }
  struct A { void f(); }; // expected-note 2{{target of using declaration}}
  struct B : public A { using A::f; }; // expected-note {{using declaration}}
  template<typename T> struct C : A { using A::f; }; // expected-note {{using declaration}}
  struct X {
    template<class T> friend void ns1::f(T t); // expected-error {{cannot befriend target of using declaration}}
    friend void B::f(); // expected-error {{cannot befriend target of using declaration}}
    friend void C<int>::f(); // expected-error {{cannot befriend target of using declaration}}
  };
}

// PR16423
namespace test9 {
  class C {
  };
  struct A {
    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}}
  };
}

namespace test10 {
  struct X {};
  extern void f10_a();
  extern void f10_a(X);
  struct A {
    friend void f10_a();
    friend void f10_b();
    friend void f10_c();
    friend void f10_d();
    friend void f10_a(X);
    friend void f10_b(X);
    friend void f10_c(X);
    friend void f10_d(X);
  };
  extern void f10_b();
  extern void f10_b(X);
  struct B {
    friend void f10_a();
    friend void f10_b();
    friend void f10_c();
    friend void f10_d();
    friend void f10_a(X);
    friend void f10_b(X);
    friend void f10_c(X);
    friend void f10_d(X);
  };
  extern void f10_c();
  extern void f10_c(X);

  // FIXME: Give a better diagnostic for the case where a function exists but is
  // not visible.
  void g(X x) {
    f10_a();
    f10_b();
    f10_c();
    f10_d(); // expected-error {{undeclared identifier}}

    ::test10::f10_a();
    ::test10::f10_b();
    ::test10::f10_c();
    ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}

    f10_a(x);
    f10_b(x);
    f10_c(x);
    f10_d(x); // PR16597: expected-error {{undeclared identifier}}

    ::test10::f10_a(x);
    ::test10::f10_b(x);
    ::test10::f10_c(x);
    ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
  }

  struct Y : X {
    friend void f10_d();
    friend void f10_d(X);
  };

  struct Z {
    operator X();
    friend void f10_d();
    friend void f10_d(X);
  };

  void g(X x, Y y, Z z) {
    f10_d(); // expected-error {{undeclared identifier}}
    ::test10::f10_d(); // expected-error {{no member named 'f10_d'}}

    // f10_d is visible to ADL in the second and third cases.
    f10_d(x); // expected-error {{undeclared identifier}}
    f10_d(y);
    f10_d(z);

    // No ADL here.
    ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}}
    ::test10::f10_d(y); // expected-error {{no type named 'f10_d'}}
    ::test10::f10_d(z); // expected-error {{no type named 'f10_d'}}
  }

  void local_externs(X x, Y y) {
    extern void f10_d();
    extern void f10_d(X);
    f10_d();
    f10_d(x);
    // FIXME: This lookup should fail, because the local extern declaration
    // should suppress ADL.
    f10_d(y);
    {
      int f10_d;
      f10_d(); // expected-error {{not a function}}
      f10_d(x); // expected-error {{not a function}}
      f10_d(y); // expected-error {{not a function}}
    }
  }

  void i(X x, Y y) {
    f10_d(); // expected-error {{undeclared identifier}}
    f10_d(x); // expected-error {{undeclared identifier}}
    f10_d(y);
  }

  struct C {
    friend void f10_d();
    friend void f10_d(X);
  };

  void j(X x, Y y) {
    f10_d(); // expected-error {{undeclared identifier}}
    f10_d(x); // expected-error {{undeclared identifier}}
    f10_d(y);
  }

  extern void f10_d();
  extern void f10_d(X);
  void k(X x, Y y, Z z) {
    // All OK now.
    f10_d();
    f10_d(x);
    ::test10::f10_d();
    ::test10::f10_d(x);
    ::test10::f10_d(y);
    ::test10::f10_d(z);
  }
}

namespace test11 {
  class __attribute__((visibility("hidden"))) B;

  class A {
    friend class __attribute__((visibility("hidden"), noreturn)) B; // expected-warning {{'noreturn' attribute only applies to functions and methods}}
  };
}

namespace pr21851 {
// PR21851 was a problem where we assumed that when the friend function redecl
// lookup found a C++ method, it would necessarily have a qualifier. Below we
// have some test cases where unqualified lookup finds C++ methods without using
// qualifiers. Unfortunately, we can't exercise the case of an access check
// failure because nested classes always have access to the members of outer
// classes.

void friend_own_method() {
  class A {
    void m() {}
    friend void m();
  };
}

void friend_enclosing_method() {
  class A;
  class C {
    int p;
    friend class A;
  };
  class A {
    void enclosing_friend() {
      (void)b->p;
      (void)c->p;
    }
    class B {
      void b(A *a) {
        (void)a->c->p;
      }
      int p;
      friend void enclosing_friend();
    };
    B *b;
    C *c;
  };
}

static auto friend_file_func() {
  extern void file_scope_friend();
  class A {
    int p;
    friend void file_scope_friend();
  };
  return A();
}

void file_scope_friend() {
  auto a = friend_file_func();
  (void)a.p;
}
}

template<typename T>
struct X_pr6954 {
  operator int();
  friend void f_pr6954(int x);
};

int array0_pr6954[sizeof(X_pr6954<int>)];
int array1_pr6954[sizeof(X_pr6954<float>)];

void g_pr6954() {
  f_pr6954(5); // expected-error{{undeclared identifier 'f_pr6954'}}
}

namespace tag_redecl {
  namespace N {
    struct X *p;
    namespace {
      class K {
        friend struct X;
      };
    }
  }
  namespace N {
    struct X;
    X *q = p;
  }
}