| // RUN: %clang_cc1 -fsyntax-only -verify %s |
| template<typename T> struct A { |
| struct B { }; |
| |
| friend struct B; |
| }; |
| |
| void f() { |
| A<int>::B b; |
| } |
| |
| struct C0 { |
| friend struct A<int>; |
| }; |
| |
| namespace PR6770 { |
| namespace N { |
| int f1(int); |
| } |
| using namespace N; |
| |
| namespace M { |
| float f1(float); |
| } |
| using M::f1; |
| |
| template<typename T> void f1(T, T); |
| template <class T> |
| void f() { |
| friend class f; // expected-error{{'friend' used outside of class}} |
| friend class f1; // expected-error{{'friend' used outside of class}} |
| } |
| } |
| |
| namespace friend_redecl_inline { |
| // We had a bug where instantiating the foo friend declaration would check the |
| // defined-ness of the most recent decl while checking if the canonical decl was |
| // inlined. |
| void foo(); |
| void bar(); |
| template <typename T> |
| class C { |
| friend void foo(); |
| friend inline void bar(); |
| }; |
| inline void foo() {} |
| inline void bar() {} |
| C<int> c; |
| } |
| |
| namespace qualified_friend { |
| void f(int); // expected-note 2{{type mismatch at 1st parameter}} |
| template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}} |
| template<typename T> void nondep(); |
| |
| template<typename> struct X1 { |
| friend void qualified_friend::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}} |
| friend void qualified_friend::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend'}} |
| }; |
| template<typename T> struct X2 { |
| friend void qualified_friend::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend'}} |
| }; |
| X1<int> xi; |
| X2<double> xd; // expected-note {{in instantiation of}} |
| X2<int> x2i; |
| |
| struct Y { |
| void f(int); // expected-note 2{{type mismatch at 1st parameter}} |
| template<typename T> void f(T*); // expected-note 2{{could not match 'type-parameter-0-0 *' against 'double'}} |
| template<typename T> void nondep(); |
| }; |
| |
| template<typename> struct Z1 { |
| friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}} |
| friend void Y::g(); // expected-error {{friend declaration of 'g' does not match any declaration in 'qualified_friend::Y'}} |
| }; |
| template<typename T> struct Z2 { |
| friend void Y::f(T); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend::Y'}} |
| }; |
| Z1<int> zi; |
| Z2<double> zd; // expected-note {{in instantiation of}} |
| Z2<int> z2i; |
| |
| template<typename T> |
| struct OK { |
| friend void qualified_friend::f(int); |
| friend void qualified_friend::f(int*); |
| friend void qualified_friend::f(T*); |
| friend void qualified_friend::f<T>(T*); |
| friend void qualified_friend::nondep<int>(); |
| friend void qualified_friend::nondep<T>(); |
| |
| friend void Y::f(int); |
| friend void Y::f(int*); |
| friend void Y::f(T*); |
| friend void Y::f<T>(T*); |
| friend void Y::nondep<int>(); |
| friend void Y::nondep<T>(); |
| }; |
| OK<float> ok; |
| } |
| |
| namespace qualified_friend_finds_nothing { |
| // FIXME: The status of this example is unclear. For now, we diagnose if the |
| // qualified declaration has nothing it can redeclare, but allow qualified |
| // lookup to find later-declared function templates during instantiation. |
| // |
| // This matches the behavior of GCC, EDG, ICC, and MSVC (except that GCC and |
| // ICC bizarrely accept the instantiation of B<float>). |
| namespace N {} |
| |
| template<typename T> struct A { |
| friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}} |
| }; |
| namespace N { void f(); } // expected-note {{different number of parameters}} |
| |
| template<typename T> struct B { |
| friend void N::f(T); // expected-error {{friend declaration of 'f' does not match}} |
| }; |
| B<float> bf; // expected-note {{in instantiation of}} |
| |
| namespace N { void f(int); } |
| B<int> bi; // ok?! |
| } |