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