Clang Project

clang_source_code/test/SemaTemplate/friend.cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s
2template<typename T> struct A {
3  struct B { };
4  
5  friend struct B;
6};
7
8void f() {
9  A<int>::B b;
10}
11
12struct C0 {
13  friend struct A<int>;
14};
15
16namespace PR6770 {
17  namespace N {
18    int f1(int);
19  }
20  using namespace N;
21
22  namespace M { 
23    float f1(float);
24  }
25  using M::f1;
26
27  template<typename T> void f1(T, T);
28  template <class T>
29  void f() {
30    friend class f; // expected-error{{'friend' used outside of class}}
31    friend class f1; // expected-error{{'friend' used outside of class}}
32  }
33}
34
35namespace friend_redecl_inline {
36// We had a bug where instantiating the foo friend declaration would check the
37// defined-ness of the most recent decl while checking if the canonical decl was
38// inlined.
39void foo();
40void bar();
41template <typename T>
42class C {
43  friend void foo();
44  friend inline void bar();
45};
46inline void foo() {}
47inline void bar() {}
48C<int> c;
49}
50
51namespace qualified_friend {
52  void f(int); // expected-note 2{{type mismatch at 1st parameter}}
53  template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
54  template<typename T> void nondep();
55
56  template<typename> struct X1 {
57    friend void qualified_friend::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}}
58    friend void qualified_friend::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend'}}
59  };
60  template<typename T> struct X2 {
61    friend void qualified_friend::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}}
62  };
63  X1<int> xi;
64  X2<double> xd; // expected-note {{in instantiation of}}
65  X2<int> x2i;
66
67  struct Y {
68    void f(int); // expected-note 2{{type mismatch at 1st parameter}}
69    template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}}
70    template<typename T> void nondep();
71  };
72
73  template<typename> struct Z1 {
74    friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}}
75    friend void Y::g(); // expected-error {{friend declaration of 'g' does not match any declaration in 'qualified_friend::Y'}}
76  };
77  template<typename T> struct Z2 {
78    friend void Y::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}}
79  };
80  Z1<int> zi;
81  Z2<double> zd; // expected-note {{in instantiation of}}
82  Z2<int> z2i;
83
84  template<typename T>
85  struct OK {
86    friend void qualified_friend::f(int);
87    friend void qualified_friend::f(int*);
88    friend void qualified_friend::f(T*);
89    friend void qualified_friend::f<T>(T*);
90    friend void qualified_friend::nondep<int>();
91    friend void qualified_friend::nondep<T>();
92
93    friend void Y::f(int);
94    friend void Y::f(int*);
95    friend void Y::f(T*);
96    friend void Y::f<T>(T*);
97    friend void Y::nondep<int>();
98    friend void Y::nondep<T>();
99  };
100  OK<float> ok;
101}
102
103namespace qualified_friend_finds_nothing {
104  // FIXME: The status of this example is unclear. For now, we diagnose if the
105  // qualified declaration has nothing it can redeclare, but allow qualified
106  // lookup to find later-declared function templates during instantiation.
107  //
108  // This matches the behavior of GCC, EDG, ICC, and MSVC (except that GCC and
109  // ICC bizarrely accept the instantiation of B<float>).
110  namespace N {}
111
112  template<typename T> struct A {
113    friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}}
114  };
115  namespace N { void f(); } // expected-note {{different number of parameters}}
116
117  template<typename T> struct B {
118    friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}}
119  };
120  B<float> bf; // expected-note {{in instantiation of}}
121
122  namespace N { void f(int); }
123  B<int> bi; // ok?!
124}
125