250 lines
7.2 KiB
C++
250 lines
7.2 KiB
C++
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||
|
|
||
|
// This test concerns the identity of dependent types within the
|
||
|
// canonical type system, specifically focusing on the difference
|
||
|
// between members of the current instantiation and members of an
|
||
|
// unknown specialization. This considers C++ [temp.type], which
|
||
|
// specifies type equivalence within a template, and C++0x
|
||
|
// [temp.dep.type], which defines what it means to be a member of the
|
||
|
// current instantiation.
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
struct X0 {
|
||
|
typedef T T_type;
|
||
|
typedef U U_type;
|
||
|
|
||
|
void f0(T&); // expected-note{{previous}}
|
||
|
void f0(typename X0::U_type&);
|
||
|
void f0(typename X0::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f1(T&); // expected-note{{previous}}
|
||
|
void f1(typename X0::U_type&);
|
||
|
void f1(typename X0<T, U>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f2(T&); // expected-note{{previous}}
|
||
|
void f2(typename X0::U_type&);
|
||
|
void f2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f3(T&); // expected-note{{previous}}
|
||
|
void f3(typename X0::U_type&);
|
||
|
void f3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
struct X1 {
|
||
|
typedef T my_T_type;
|
||
|
|
||
|
void g0(T&); // expected-note{{previous}}
|
||
|
void g0(typename X0::U_type&);
|
||
|
void g0(typename X0::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g1(T&); // expected-note{{previous}}
|
||
|
void g1(typename X0::U_type&);
|
||
|
void g1(typename X0<T, U>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g2(T&); // expected-note{{previous}}
|
||
|
void g2(typename X0::U_type&);
|
||
|
void g2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g3(T&); // expected-note{{previous}}
|
||
|
void g3(typename X0::U_type&);
|
||
|
void g3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g4(T&); // expected-note{{previous}}
|
||
|
void g4(typename X0::U_type&);
|
||
|
void g4(typename X1::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g5(T&); // expected-note{{previous}}
|
||
|
void g5(typename X0::U_type&);
|
||
|
void g5(typename X0::X1::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g6(T&); // expected-note{{previous}}
|
||
|
void g6(typename X0::U_type&);
|
||
|
void g6(typename X0<T, U>::X1::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g7(T&); // expected-note{{previous}}
|
||
|
void g7(typename X0::U_type&);
|
||
|
void g7(typename ::X0<typename X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g8(T&); // expected-note{{previous}}
|
||
|
void g8(typename X0<U, T_type>::T_type&);
|
||
|
void g8(typename ::X0<typename X0<T_type, U>::X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
struct X0<T*, U*> {
|
||
|
typedef T T_type;
|
||
|
typedef U U_type;
|
||
|
typedef T* Tptr;
|
||
|
typedef U* Uptr;
|
||
|
|
||
|
void f0(T&); // expected-note{{previous}}
|
||
|
void f0(typename X0::U_type&);
|
||
|
void f0(typename X0::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f1(T&); // expected-note{{previous}}
|
||
|
void f1(typename X0::U_type&);
|
||
|
void f1(typename X0<T*, U*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f2(T&); // expected-note{{previous}}
|
||
|
void f2(typename X0::U_type&);
|
||
|
void f2(typename X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f3(T&); // expected-note{{previous}}
|
||
|
void f3(typename X0::U_type&);
|
||
|
void f3(typename ::X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f4(T&); // expected-note{{previous}}
|
||
|
void f4(typename X0::U_type&);
|
||
|
void f4(typename ::X0<Tptr, Uptr>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void f5(X0*); // expected-note{{previous}}
|
||
|
void f5(::X0<T, U>*);
|
||
|
void f5(::X0<T*, U*>*); // expected-error{{redecl}}
|
||
|
|
||
|
struct X2 {
|
||
|
typedef T my_T_type;
|
||
|
|
||
|
void g0(T&); // expected-note{{previous}}
|
||
|
void g0(typename X0::U_type&);
|
||
|
void g0(typename X0::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g1(T&); // expected-note{{previous}}
|
||
|
void g1(typename X0::U_type&);
|
||
|
void g1(typename X0<T*, U*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g2(T&); // expected-note{{previous}}
|
||
|
void g2(typename X0::U_type&);
|
||
|
void g2(typename X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g3(T&); // expected-note{{previous}}
|
||
|
void g3(typename X0::U_type&);
|
||
|
void g3(typename ::X0<T_type*, U_type*>::T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g4(T&); // expected-note{{previous}}
|
||
|
void g4(typename X0::U_type&);
|
||
|
void g4(typename X2::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g5(T&); // expected-note{{previous}}
|
||
|
void g5(typename X0::U_type&);
|
||
|
void g5(typename X0::X2::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g6(T&); // expected-note{{previous}}
|
||
|
void g6(typename X0::U_type&);
|
||
|
void g6(typename X0<T*, U*>::X2::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g7(T&); // expected-note{{previous}}
|
||
|
void g7(typename X0::U_type&);
|
||
|
void g7(typename ::X0<typename X2::my_T_type*, U_type*>::X2::my_T_type&); // expected-error{{redecl}}
|
||
|
|
||
|
void g8(T&); // expected-note{{previous}}
|
||
|
void g8(typename X0<U, T_type>::T_type&);
|
||
|
void g8(typename ::X0<typename X0<T_type*, U*>::X2::my_T_type*, U_type*>::X2::my_T_type&); // expected-error{{redecl}}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct X1 {
|
||
|
static int *a;
|
||
|
void f(float *b) {
|
||
|
X1<T>::a = b; // expected-error{{incompatible}}
|
||
|
X1<T*>::a = b;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
namespace ConstantInCurrentInstantiation {
|
||
|
template<typename T>
|
||
|
struct X {
|
||
|
static const int value = 2;
|
||
|
static int array[value];
|
||
|
};
|
||
|
|
||
|
template<typename T> const int X<T>::value;
|
||
|
|
||
|
template<typename T>
|
||
|
int X<T>::array[X<T>::value] = { 1, 2 };
|
||
|
}
|
||
|
|
||
|
namespace Expressions {
|
||
|
template <bool b>
|
||
|
struct Bool {
|
||
|
enum anonymous_enum { value = b };
|
||
|
};
|
||
|
struct True : public Bool<true> {};
|
||
|
struct False : public Bool<false> {};
|
||
|
|
||
|
template <typename T1, typename T2>
|
||
|
struct Is_Same : public False {};
|
||
|
template <typename T>
|
||
|
struct Is_Same<T, T> : public True {};
|
||
|
|
||
|
template <bool b, typename T = void>
|
||
|
struct Enable_If {};
|
||
|
template <typename T>
|
||
|
struct Enable_If<true, T> {
|
||
|
typedef T type;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
class Class {
|
||
|
public:
|
||
|
template <typename U>
|
||
|
typename Enable_If<Is_Same<U, Class>::value, void>::type
|
||
|
foo();
|
||
|
};
|
||
|
|
||
|
|
||
|
template <typename T>
|
||
|
template <typename U>
|
||
|
typename Enable_If<Is_Same<U, Class<T> >::value, void>::type
|
||
|
Class<T>::foo() {}
|
||
|
}
|
||
|
|
||
|
namespace PR9255 {
|
||
|
template<typename T>
|
||
|
class X0 {
|
||
|
public:
|
||
|
class Inner1;
|
||
|
|
||
|
class Inner2 {
|
||
|
public:
|
||
|
void f()
|
||
|
{
|
||
|
Inner1::f.g();
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
}
|
||
|
|
||
|
namespace rdar10194295 {
|
||
|
template<typename XT>
|
||
|
class X {
|
||
|
public:
|
||
|
enum Enum { Yes, No };
|
||
|
template<Enum> void foo();
|
||
|
template<Enum> class Inner;
|
||
|
};
|
||
|
|
||
|
template<typename XT>
|
||
|
template<typename X<XT>::Enum>
|
||
|
void X<XT>::foo()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template<typename XT>
|
||
|
template<typename X<XT>::Enum>
|
||
|
class X<XT>::Inner { };
|
||
|
}
|
||
|
|
||
|
namespace RebuildDependentScopeDeclRefExpr {
|
||
|
template<int> struct N {};
|
||
|
template<typename T> struct X {
|
||
|
static const int thing = 0;
|
||
|
N<thing> data();
|
||
|
N<thing> foo();
|
||
|
};
|
||
|
template<typename T> N<X<T>::thing> X<T>::data() {}
|
||
|
// FIXME: We should issue a typo-correction here.
|
||
|
template<typename T> N<X<T>::think> X<T>::foo() {} // expected-error {{no member named 'think' in 'X<T>'}}
|
||
|
}
|