llvm-project/clang/test/SemaTemplate/friend-template.cpp

145 lines
3.1 KiB
C++
Raw Normal View History

// RUN: %clang_cc1 -fsyntax-only -verify %s
// 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-12-12 04:51:23 +08:00
namespace test1 {
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}}
}
// 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-12-12 04:51:23 +08:00
template<> struct X0<int> {
template<typename U> friend struct X0;
};
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-12-12 04:51:23 +08:00
template<typename U> void f2(U);
2009-12-12 04:51:23 +08:00
X1<int> x1i;
X0<int*> x0ip;
2009-12-12 04:51:23 +08:00
template<> void f2(int);
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-12-12 04:51:23 +08:00
template<> void f3(int);
}
// PR5332
2009-12-12 04:51:23 +08:00
namespace test3 {
template <typename T> class Foo {
template <typename U>
friend class Foo;
};
2009-12-12 04:51:23 +08:00
Foo<int> foo;
2009-12-12 04:51:23 +08:00
template<typename T, T Value> struct X2a;
2009-12-12 04:51:23 +08:00
template<typename T, int Size> struct X2b;
2009-12-12 04:51:23 +08:00
template<typename T>
class X3 {
template<typename U, U Value> friend struct X2a;
// 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-12-12 04:51:23 +08:00
X3<int> x3i; // okay
X3<long> x3l; // expected-note {{in instantiation}}
2009-12-12 04:51:23 +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>&) {
int a[sizeof(T) ? -1 : -1]; // expected-error {{array size is negative}}
}
void f() {
f(A<int>()); // expected-note {{in instantiation of function template specialization}}
}
}
namespace test5 {
class outer {
class foo;
template <typename T> friend struct cache;
};
class outer::foo {
template <typename T> friend struct cache;
};
}
// 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);
};
}
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);
}
}