1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
4 template<typename T, typename U>
5 struct is_same {
6   static const bool value = false;
7 };
8 
9 template<typename T>
10 struct is_same<T, T> {
11   static const bool value = true;
12 };
13 
14 template<typename MetaFun, typename T1, typename T2>
15 struct metafun_apply2 {
16   typedef typename MetaFun::template apply<T1, T2> inner;
17   typedef typename inner::type type;
18 };
19 
20 template<typename T, typename U> struct pair;
21 
22 struct make_pair {
23   template<typename T1, typename T2>
24   struct apply {
25     typedef pair<T1, T2> type;
26   };
27 };
28 
29 int a0[is_same<metafun_apply2<make_pair, int, float>::type,
30                pair<int, float> >::value? 1 : -1];
31 int a1[is_same<
32          typename make_pair::template apply<int, float>,
33 #if __cplusplus <= 199711L // C++03 and earlier modes
34          // expected-warning@-2 {{'template' keyword outside of a template}}
35          // expected-warning@-3 {{'typename' occurs outside of a template}}
36 #endif
37          make_pair::apply<int, float>
38        >::value? 1 : -1];
39 
40 template<typename MetaFun>
41 struct swap_and_apply2 {
42   template<typename T1, typename T2>
43   struct apply {
44     typedef typename MetaFun::template apply<T2, T1> new_metafun;
45     typedef typename new_metafun::type type;
46   };
47 };
48 
49 int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type,
50                pair<float, int> >::value? 1 : -1];
51 
52 template<typename MetaFun>
53 struct swap_and_apply2b {
54   template<typename T1, typename T2>
55   struct apply {
56     typedef typename MetaFun::template apply<T2, T1>::type type;
57   };
58 };
59 
60 int a3[is_same<swap_and_apply2b<make_pair>::apply<int, float>::type,
61                pair<float, int> >::value? 1 : -1];
62 
63 template<typename T>
64 struct X0 {
65   template<typename U, typename V>
66   struct Inner;
67 
68   void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}}
69   void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}}
70 
71   void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}}
72   void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}}
73 
74   void f2(typename X0<T>::Inner<T*, T&>::type); // expected-note{{here}}
75   void f2(typename X0<T>::template Inner<T*, T&>::type); // expected-error{{redecl}}
76 };
77 
78 namespace PR6236 {
79   template<typename T, typename U> struct S { };
80 
81   template<typename T> struct S<T, T> {
82     template<typename U> struct K { };
83 
fPR6236::S84     void f() {
85       typedef typename S<T, T>::template K<T> Foo;
86     }
87   };
88 }
89 
90 namespace PR6268 {
91   template <typename T>
92   struct Outer {
93     template <typename U>
94     struct Inner {};
95 
96     template <typename U>
97     typename Outer<T>::template Inner<U>
98     foo(typename Outer<T>::template Inner<U>);
99   };
100 
101   template <typename T>
102   template <typename U>
103   typename Outer<T>::template Inner<U>
foo(typename Outer<T>::template Inner<U>)104   Outer<T>::foo(typename Outer<T>::template Inner<U>) {
105     return Inner<U>();
106   }
107 }
108 
109 namespace PR6463 {
110   struct B { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}
111   struct C { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}
112 
113   template<typename T>
114   struct A : B, C {
115     type& a(); // expected-error{{found in multiple base classes}}
116     int x;
117   };
118 
119   // FIXME: Improve source location info here.
120   template<typename T>
a()121   typename A<T>::type& A<T>::a() { // expected-error{{found in multiple base classes}}
122     return x;
123   }
124 }
125 
126 namespace PR7419 {
127   template <typename T> struct S {
128     typedef typename T::Y T2;
129     typedef typename T2::Z T3;
130     typedef typename T3::W T4;
131     T4 *f();
132 
133     typedef typename T::template Y<int> TT2;
134     typedef typename TT2::template Z<float> TT3;
135     typedef typename TT3::template W<double> TT4;
136     TT4 g();
137   };
138 
f()139   template <typename T> typename T::Y::Z::W *S<T>::f() { }
g()140   template <typename T> typename T::template Y<int>::template Z<float>::template W<double> S<T>::g() { }
141 }
142 
143 namespace rdar8740998 {
144   template<typename T>
145   struct X : public T {
146     using T::iterator; // expected-note{{add 'typename' to treat this using declaration as a type}} \
147     // expected-error{{dependent using declaration resolved to type without 'typename'}}
148 
frdar8740998::X149     void f() {
150       typename X<T>::iterator i; // expected-error{{typename specifier refers to a dependent using declaration for a value 'iterator' in 'X<T>'}}
151     }
152   };
153 
154   struct HasIterator {
155     typedef int *iterator; // expected-note{{target of using declaration}}
156   };
157 
test_X(X<HasIterator> xi)158   void test_X(X<HasIterator> xi) { // expected-note{{in instantiation of template class}}
159     xi.f();
160   }
161 }
162 
163 namespace rdar9068589 {
164   // From GCC PR c++/13950
165   template <class T> struct Base {};
166   template <class T> struct Derived: public Base<T> {
167     typename Derived::template Base<double>* p1;
168   };
169 }
170