// RUN: %clang_cc1 -fsyntax-only -verify %s // PR5057 namespace test0 { namespace std { class X { public: template friend struct Y; }; } namespace std { template struct Y {}; } } namespace test1 { template void f1(T) { } // expected-note{{here}} class X { template friend void f0(T); template friend void f1(T); }; template void f0(T) { } template void f1(T) { } // expected-error{{redefinition}} } // PR4768 namespace test2 { template struct X0 { template friend struct X0; }; template struct X0 { template friend struct X0; }; template<> struct X0 { template friend struct X0; }; template struct X1 { template friend void f2(U); template friend void f3(U); }; template void f2(U); X1 x1i; X0 x0ip; template<> void f2(int); // FIXME: Should this declaration of f3 be required for the specialization of // f3 (further below) to work? GCC and EDG don't require it, we do... template void f3(U); template<> void f3(int); } // PR5332 namespace test3 { template class Foo { template friend class Foo; }; Foo foo; template struct X2a; template struct X2b; template class X3 { template friend struct X2a; // FIXME: the redeclaration note ends up here because redeclaration // lookup ends up finding the friend target from X3. template friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \ // expected-note {{previous non-type template parameter with type 'int' is here}} }; X3 x3i; // okay X3 x3l; // expected-note {{in instantiation}} } // PR5716 namespace test4 { template struct A { template friend void f(const A&); }; template void f(const A&) { int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}} } void f() { f(A()); // expected-note {{in instantiation of function template specialization}} } } namespace test5 { class outer { class foo; template friend struct cache; }; class outer::foo { template friend struct cache; }; } // PR6022 namespace PR6022 { template class A; namespace inner { template A& f0(A&, T); } template class A { template friend A& inner::f0(A&, T); }; } namespace FriendTemplateDefinition { template struct int_c { }; template struct X { template friend void f(X, int_c) { int value = N; }; }; void test_X(X x, int_c<5> i5) { f(x, i5); } } namespace PR7013a { template struct X0 { typedef int type; }; template struct X1 { }; template struct X2 { typename T::type e; }; namespace N { template > struct X3 { template friend void op(X2& , B); }; template void op(X2& , B) { X2 s; } } int n() { X2 > ngs; N::X3<> b; op(ngs, b); return 0; } } namespace PR7013b { template struct X0 { typedef int type; }; template struct X1 { }; template struct X2 { typename T::type e; }; namespace N { template > struct X3 { template friend void op(X2& , B); }; template void op(X2& , B) { X2 s; } } int n() { X2 > ngs; N::X3<> b; op(ngs, b); return 0; } } namespace PR8649 { template struct X { template friend class X; // expected-error{{partial specialization cannot be declared as a friend}} }; X x; } // Don't crash, and error on invalid friend type template. namespace friend_type_template_no_tag { template struct S { template friend S; // expected-error{{friend type templates must use an elaborated type}} }; template struct S; } namespace PR10660 { struct A { template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}} }; } namespace rdar11147355 { template struct A { template class B; template template friend class A::B; }; template template class A::B { }; A::B ab; }