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