diff options
Diffstat (limited to 'test/SemaTemplate/friend.cpp')
-rw-r--r-- | test/SemaTemplate/friend.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/test/SemaTemplate/friend.cpp b/test/SemaTemplate/friend.cpp index ef1aed50e6266..777682be3f1b8 100644 --- a/test/SemaTemplate/friend.cpp +++ b/test/SemaTemplate/friend.cpp @@ -47,3 +47,78 @@ 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?! +} |