1 // RUN: %clang_cc1 -fsyntax-only -verify %s 2 template<typename T> struct A { 3 struct B { }; 4 5 friend struct B; 6 }; 7 8 void f() { 9 A<int>::B b; 10 } 11 12 struct C0 { 13 friend struct A<int>; 14 }; 15 16 namespace 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 35 namespace 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. 39 void foo(); 40 void bar(); 41 template <typename T> 42 class C { 43 friend void foo(); 44 friend inline void bar(); 45 }; 46 inline void foo() {} 47 inline void bar() {} 48 C<int> c; 49 } 50 51 namespace 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 103 namespace 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 126 namespace PR37556 { 127 inline namespace N { int x1, x2, y1, y2; } // expected-note 2{{previous}} 128 struct X { 129 friend void x1(int); 130 friend void PR37556::x2(int); // expected-error {{different kind}} 131 }; 132 template<typename T> struct Y { 133 friend void y1(T); 134 friend void PR37556::y2(T); // expected-error {{different kind}} 135 }; 136 template struct Y<int>; 137 template<typename T> struct Z { 138 friend void z1(T); 139 friend void PR37556::z2(T); // expected-error {{does not match any}} 140 }; 141 inline namespace N { int z1, z2; } 142 template struct Z<int>; 143 } 144 145 namespace PR42513_comment3 { 146 template<typename X> struct T { friend auto f(X*) { return nullptr; } }; 147 struct X1 { friend auto f(X1*); }; 148 template struct T<X1>; 149 int n = f((X1*)nullptr); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'nullptr_t'}} 150 } 151