169 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s2template<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 the37// defined-ness of the most recent decl while checking if the canonical decl was38// 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 'T *' 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 'T *' 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 the105 // qualified declaration has nothing it can redeclare, but allow qualified106 // lookup to find later-declared function templates during instantiation.107 //108 // This matches the behavior of GCC, EDG, ICC, and MSVC (except that GCC and109 // 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 126namespace 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 145namespace 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 'std::nullptr_t'}}150}151 152namespace GH61851 {153namespace A {154inline namespace B {155 constexpr struct {} foo;156}157 158template <typename T>159class Bar {160 template <typename U>161 friend void foo(U &&arg) {} // no diagnostic expected162};163}164 165void foobar() {166 A::Bar<int> b;167}168}169