2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
2009-09-26 14:47:28 +08:00
|
|
|
// PR5057
|
2009-12-12 04:51:23 +08:00
|
|
|
namespace test0 {
|
|
|
|
namespace std {
|
|
|
|
class X {
|
|
|
|
public:
|
|
|
|
template<typename T> friend struct Y;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace std {
|
|
|
|
template<typename T> struct Y {};
|
|
|
|
}
|
2009-09-26 14:47:28 +08:00
|
|
|
}
|
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
namespace test1 {
|
2009-09-28 08:08:27 +08:00
|
|
|
template<typename T> void f1(T) { } // expected-note{{here}}
|
|
|
|
|
|
|
|
class X {
|
|
|
|
template<typename T> friend void f0(T);
|
|
|
|
template<typename T> friend void f1(T);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> void f0(T) { }
|
|
|
|
template<typename T> void f1(T) { } // expected-error{{redefinition}}
|
|
|
|
}
|
2009-10-10 05:11:42 +08:00
|
|
|
|
|
|
|
// PR4768
|
2009-12-12 04:51:23 +08:00
|
|
|
namespace test2 {
|
|
|
|
template<typename T> struct X0 {
|
|
|
|
template<typename U> friend struct X0;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> struct X0<T*> {
|
|
|
|
template<typename U> friend struct X0;
|
|
|
|
};
|
2009-10-10 05:11:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<> struct X0<int> {
|
|
|
|
template<typename U> friend struct X0;
|
|
|
|
};
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<typename T> struct X1 {
|
|
|
|
template<typename U> friend void f2(U);
|
|
|
|
template<typename U> friend void f3(U);
|
|
|
|
};
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<typename U> void f2(U);
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
X1<int> x1i;
|
|
|
|
X0<int*> x0ip;
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<> void f2(int);
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
// FIXME: Should this declaration of f3 be required for the specialization of
|
|
|
|
// f3<int> (further below) to work? GCC and EDG don't require it, we do...
|
|
|
|
template<typename U> void f3(U);
|
2009-10-13 22:39:41 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<> void f3(int);
|
|
|
|
}
|
2009-10-31 05:07:27 +08:00
|
|
|
|
|
|
|
// PR5332
|
2009-12-12 04:51:23 +08:00
|
|
|
namespace test3 {
|
|
|
|
template <typename T> class Foo {
|
|
|
|
template <typename U>
|
|
|
|
friend class Foo;
|
|
|
|
};
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
Foo<int> foo;
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<typename T, T Value> struct X2a;
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<typename T, int Size> struct X2b;
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
template<typename T>
|
|
|
|
class X3 {
|
|
|
|
template<typename U, U Value> friend struct X2a;
|
2010-03-25 14:39:04 +08:00
|
|
|
|
|
|
|
// FIXME: the redeclaration note ends up here because redeclaration
|
|
|
|
// lookup ends up finding the friend target from X3<int>.
|
|
|
|
template<typename U, T Value> 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}}
|
2009-12-12 04:51:23 +08:00
|
|
|
};
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2009-12-12 04:51:23 +08:00
|
|
|
X3<int> x3i; // okay
|
2009-10-31 06:42:42 +08:00
|
|
|
|
2010-03-25 14:39:04 +08:00
|
|
|
X3<long> x3l; // expected-note {{in instantiation}}
|
2009-12-12 04:51:23 +08:00
|
|
|
}
|
2009-12-15 07:19:40 +08:00
|
|
|
|
|
|
|
// PR5716
|
|
|
|
namespace test4 {
|
|
|
|
template<typename> struct A {
|
|
|
|
template<typename T> friend void f(const A<T>&);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> void f(const A<T>&) {
|
2011-01-04 12:44:35 +08:00
|
|
|
int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}}
|
2009-12-15 07:19:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void f() {
|
|
|
|
f(A<int>()); // expected-note {{in instantiation of function template specialization}}
|
|
|
|
}
|
|
|
|
}
|
2009-12-18 19:25:59 +08:00
|
|
|
|
|
|
|
namespace test5 {
|
|
|
|
class outer {
|
|
|
|
class foo;
|
|
|
|
template <typename T> friend struct cache;
|
|
|
|
};
|
|
|
|
class outer::foo {
|
|
|
|
template <typename T> friend struct cache;
|
|
|
|
};
|
|
|
|
}
|
2010-01-17 02:09:52 +08:00
|
|
|
|
|
|
|
// PR6022
|
|
|
|
namespace PR6022 {
|
|
|
|
template <class T1, class T2 , class T3 > class A;
|
|
|
|
|
|
|
|
namespace inner {
|
|
|
|
template<class T1, class T2, class T3, class T>
|
|
|
|
A<T1, T2, T3>& f0(A<T1, T2, T3>&, T);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T1, class T2, class T3>
|
|
|
|
class A {
|
|
|
|
template<class U1, class U2, class U3, class T>
|
|
|
|
friend A<U1, U2, U3>& inner::f0(A<U1, U2, U3>&, T);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2010-04-28 12:52:24 +08:00
|
|
|
namespace FriendTemplateDefinition {
|
|
|
|
template<unsigned > struct int_c { };
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct X {
|
|
|
|
template<unsigned N>
|
|
|
|
friend void f(X, int_c<N>) {
|
|
|
|
int value = N;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
void test_X(X<int> x, int_c<5> i5) {
|
|
|
|
f(x, i5);
|
|
|
|
}
|
|
|
|
}
|
2010-05-04 07:29:10 +08:00
|
|
|
|
|
|
|
namespace PR7013a {
|
|
|
|
template<class > struct X0
|
|
|
|
{
|
|
|
|
typedef int type;
|
|
|
|
};
|
|
|
|
template<typename > struct X1
|
|
|
|
{
|
|
|
|
};
|
|
|
|
template<typename , typename T> struct X2
|
|
|
|
{
|
|
|
|
typename T::type e;
|
|
|
|
};
|
|
|
|
namespace N
|
|
|
|
{
|
|
|
|
template <typename = int, typename = X1<int> > struct X3
|
|
|
|
{
|
|
|
|
template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
|
|
|
|
};
|
|
|
|
template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
|
|
|
|
{
|
|
|
|
X2<int, Tr> s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int n()
|
|
|
|
{
|
|
|
|
X2<int, X0<int> > ngs;
|
|
|
|
N::X3<> b;
|
|
|
|
op(ngs, b);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace PR7013b {
|
|
|
|
template<class > struct X0
|
|
|
|
{
|
|
|
|
typedef int type;
|
|
|
|
};
|
|
|
|
template<typename > struct X1
|
|
|
|
{
|
|
|
|
};
|
|
|
|
template<typename , typename T> struct X2
|
|
|
|
{
|
|
|
|
typename T::type e;
|
|
|
|
};
|
|
|
|
namespace N
|
|
|
|
{
|
|
|
|
template <typename = X1<int> > struct X3
|
|
|
|
{
|
|
|
|
template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
|
|
|
|
};
|
|
|
|
template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
|
|
|
|
{
|
|
|
|
X2<int, Tr> s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int n()
|
|
|
|
{
|
|
|
|
X2<int, X0<int> > ngs;
|
|
|
|
N::X3<> b;
|
|
|
|
op(ngs, b);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-12-21 16:14:57 +08:00
|
|
|
|
|
|
|
namespace PR8649 {
|
|
|
|
template<typename T, typename U, unsigned N>
|
|
|
|
struct X {
|
|
|
|
template<unsigned M> friend class X<T, U, M>; // expected-error{{partial specialization cannot be declared as a friend}}
|
|
|
|
};
|
|
|
|
|
|
|
|
X<int, float, 7> x;
|
|
|
|
}
|
2011-05-04 02:35:10 +08:00
|
|
|
|
|
|
|
// Don't crash, and error on invalid friend type template.
|
|
|
|
namespace friend_type_template_no_tag {
|
|
|
|
template <typename T> struct S {
|
|
|
|
template <typename U> friend S<U>; // expected-error{{friend type templates must use an elaborated type}}
|
|
|
|
};
|
|
|
|
template struct S<int>;
|
|
|
|
}
|
2011-10-20 23:58:54 +08:00
|
|
|
|
|
|
|
namespace PR10660 {
|
|
|
|
struct A {
|
|
|
|
template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}}
|
|
|
|
};
|
|
|
|
}
|
2012-03-31 00:20:47 +08:00
|
|
|
|
|
|
|
namespace rdar11147355 {
|
|
|
|
template <class T>
|
|
|
|
struct A {
|
|
|
|
template <class U> class B;
|
|
|
|
template <class S> template <class U> friend class A<S>::B;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class S> template <class U> class A<S>::B {
|
|
|
|
};
|
|
|
|
|
|
|
|
A<double>::B<double> ab;
|
|
|
|
}
|