| // 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>'}} |
| } |