1// RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-unused
2// RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-unused -fms-compatibility -DMSVC
3namespace N {
4  struct A {
5    typedef int type;
6  };
7
8  struct B {
9  };
10
11  struct C {
12    struct type { };
13    int type; // expected-note 2{{referenced member 'type' is declared here}}
14  };
15}
16
17int i;
18
19typename N::A::type *ip1 = &i; // expected-warning{{'typename' occurs outside of a template}}
20typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} \
21// expected-warning{{'typename' occurs outside of a template}}
22typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} \
23// expected-warning{{'typename' occurs outside of a template}}
24
25void test(double d) {
26  typename N::A::type f(typename N::A::type(a)); // expected-warning{{disambiguated as a function declaration}} \
27  // expected-note{{add a pair of parentheses}} expected-warning 2{{'typename' occurs outside of a template}}
28  int five = f(5);
29
30  using namespace N;
31  for (typename A::type i = 0; i < 10; ++i) // expected-warning{{'typename' occurs outside of a template}}
32    five += 1;
33
34  const typename N::A::type f2(d); // expected-warning{{'typename' occurs outside of a template}}
35}
36
37namespace N {
38  template<typename T>
39  struct X {
40    typedef typename T::type type; // expected-error {{no type named 'type' in 'N::B'}} \
41    // expected-error {{no type named 'type' in 'B'}} \
42    // FIXME: location info for error above isn't very good \
43    // expected-error 2{{typename specifier refers to non-type member 'type'}} \
44    // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
45  };
46}
47
48N::X<N::A>::type *ip4 = &i;
49N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'N::X<N::B>' requested here}}
50N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'N::X<N::C>' requested here}}
51
52N::X<int>::type fail1; // expected-note{{in instantiation of template class 'N::X<int>' requested here}}
53
54template<typename T>
55struct Y {
56  typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'N::X<B>' requested here}} \
57  // expected-note{{in instantiation of template class 'N::X<C>' requested here}}
58};
59
60struct A {
61  typedef int type;
62};
63
64struct B {
65};
66
67struct C {
68  struct type { };
69  int type; // expected-note{{referenced member 'type' is declared here}}
70};
71
72::Y<A>::type ip7 = &i;
73::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'Y<B>' requested here}}
74::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'Y<C>' requested here}}
75
76template<typename T> struct D {
77  typedef typename T::foo foo;  // expected-error {{type 'long' cannot be used prior to '::' because it has no members}}
78  typedef typename foo::bar bar;
79};
80
81D<long> struct_D;  // expected-note {{in instantiation of template class 'D<long>' requested here}}
82
83template<typename T> struct E {
84  typedef typename T::foo foo;
85  typedef typename foo::bar bar;  // expected-error {{type 'foo' (aka 'double') cannot be used prior to '::' because it has no members}}
86};
87
88struct F {
89  typedef double foo;
90};
91
92E<F> struct_E; // expected-note {{in instantiation of template class 'E<F>' requested here}}
93
94template<typename T> struct G {
95  typedef typename T::foo foo;
96  typedef typename foo::bar bar;
97};
98
99struct H {
100  struct foo {
101    typedef double bar;
102  };
103};
104
105G<H> struct_G;
106
107namespace PR10925 {
108  template< int mydim, typename Traits >
109  class BasicGeometry
110  {
111    typedef int some_type_t;
112  };
113
114  template<class ctype, int mydim, int coorddim>
115  class MockGeometry : BasicGeometry<mydim, int>{
116    using typename BasicGeometry<mydim, int>::operator[]; // expected-error {{typename is allowed for identifiers only}}
117  };
118}
119
120
121namespace missing_typename {
122template <class T1, class T2> struct pair {}; // expected-note 7 {{template parameter is declared here}}
123
124template <class T1, class T2>
125struct map {
126  typedef T1* iterator;
127};
128
129template <class T>
130class ExampleClass1 {
131  struct ExampleItem;
132
133
134  struct ExampleItemSet {
135    typedef ExampleItem* iterator;
136    ExampleItem* operator[](unsigned);
137  };
138
139  void foo() {
140#ifdef MSVC
141    // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
142#else
143    // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}}
144#endif
145    pair<ExampleItemSet::iterator, int> i;
146    pair<this->ExampleItemSet::iterator, int> i; // expected-error-re {{template argument for template type parameter must be a type{{$}}}}
147    pair<ExampleItemSet::operator[], int> i; // expected-error-re {{template argument for template type parameter must be a type{{$}}}}
148  }
149#ifdef MSVC
150    // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
151#else
152  // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}}
153#endif
154  pair<ExampleItemSet::iterator, int> elt;
155
156
157  typedef map<int, ExampleItem*> ExampleItemMap;
158
159  static void bar() {
160#ifdef MSVC
161    // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
162#else
163    // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}}
164#endif
165    pair<ExampleItemMap::iterator, int> i;
166  }
167#ifdef MSVC
168    // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
169#else
170  // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}}
171#endif
172  pair<ExampleItemMap::iterator, int> entry;
173  pair<bar, int> foobar; // expected-error {{template argument for template type parameter must be a type}}
174};
175} // namespace missing_typename
176
177namespace missing_typename_and_base {
178template <class T> struct Bar {}; // expected-note 1+ {{template parameter is declared here}}
179template <typename T>
180struct Foo : T {
181
182  // FIXME: MSVC accepts this code.
183  Bar<TypeInBase> x; // expected-error {{use of undeclared identifier 'TypeInBase'}}
184
185#ifdef MSVC
186  // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
187#else
188  // expected-error@+2 {{must be a type; did you forget 'typename'?}}
189#endif
190  Bar<T::TypeInBase> y;
191
192#ifdef MSVC
193  // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}}
194#else
195  // expected-error@+2 {{must be a type; did you forget 'typename'?}}
196#endif
197  Bar<T::NestedRD::TypeInNestedRD> z;
198
199};
200struct Base {
201  typedef int TypeInBase;
202  struct NestedRD {
203    typedef int TypeInNestedRD;
204  };
205};
206Foo<Base> x;
207} // namespace missing_typename_and_base
208
209namespace func_type_vs_construct_tmp {
210template <typename> struct S { typedef int type; };
211template <typename T> void f();
212template <int N> void f();
213
214// expected-error@+1 {{missing 'typename' prior to dependent type name 'S<int>::type'}}
215template <typename T> void g() { f</*typename*/ S<T>::type(int())>(); }
216
217// Adding typename does fix the diagnostic.
218template <typename T> void h() { f<typename S<T>::type(int())>(); }
219
220void j() {
221  g<int>(); // expected-note-re {{in instantiation {{.*}} requested here}}
222  h<int>();
223}
224} // namespace func_type_vs_construct_tmp
225
226namespace pointer_vs_multiply {
227int x;
228// expected-error@+1 {{missing 'typename' prior to dependent type name 'B::type_or_int'}}
229template <typename T> void g() { T::type_or_int * x; }
230// expected-error@+1 {{typename specifier refers to non-type member 'type_or_int' in 'pointer_vs_multiply::A'}}
231template <typename T> void h() { typename T::type_or_int * x; }
232
233struct A { static const int type_or_int = 5; }; // expected-note {{referenced member 'type_or_int' is declared here}}
234struct B { typedef int type_or_int; };
235
236void j() {
237  g<A>();
238  g<B>(); // expected-note-re {{in instantiation {{.*}} requested here}}
239  h<A>(); // expected-note-re {{in instantiation {{.*}} requested here}}
240  h<B>();
241}
242} // namespace pointer_vs_multiply
243