1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s |
3 | // RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s |
4 | |
5 | struct pr12960 { |
6 | int begin; |
7 | void foo(int x) { |
8 | for (int& it : x) { // expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}} |
9 | } |
10 | } |
11 | }; |
12 | |
13 | struct null_t { |
14 | operator int*(); |
15 | }; |
16 | |
17 | namespace X { |
18 | template<typename T> |
19 | auto begin(T &&t) -> decltype(t.begin()) { return t.begin(); } // expected-note 2{{ignored: substitution failure}} |
20 | template<typename T> |
21 | auto end(T &&t) -> decltype(t.end()) { return t.end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} |
22 | |
23 | template<typename T> |
24 | auto begin(T &&t) -> decltype(t.alt_begin()) { return t.alt_begin(); } // expected-note {{selected 'begin' template [with T = }} \ |
25 | expected-note 2{{candidate template ignored: substitution failure [with T = }} |
26 | template<typename T> |
27 | auto end(T &&t) -> decltype(t.alt_end()) { return t.alt_end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} |
28 | |
29 | namespace inner { |
30 | // These should never be considered. |
31 | int begin(int); |
32 | int end(int); |
33 | } |
34 | |
35 | using namespace inner; |
36 | |
37 | struct A { // expected-note 2 {{candidate constructor}} |
38 | A(); |
39 | int *begin(); // expected-note 3{{selected 'begin' function with iterator type 'int *'}} expected-note {{'begin' declared here}} |
40 | int *end(); |
41 | }; |
42 | |
43 | struct B { |
44 | B(); |
45 | int *alt_begin(); |
46 | int *alt_end(); |
47 | }; |
48 | |
49 | struct NoBeginADL { |
50 | null_t alt_end(); |
51 | }; |
52 | struct NoEndADL { |
53 | null_t alt_begin(); |
54 | }; |
55 | |
56 | struct C { |
57 | C(); |
58 | struct It { |
59 | int val; |
60 | operator int &() { return val; } |
61 | }; |
62 | It begin(); |
63 | It end(); |
64 | }; |
65 | |
66 | constexpr int operator*(const C::It &) { return 0; } |
67 | } |
68 | |
69 | using X::A; |
70 | |
71 | void f(); |
72 | void f(int); |
73 | |
74 | void g() { |
75 | for (int a : A()) |
76 | A __begin; |
77 | for (char *a : A()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} |
78 | } |
79 | for (char *a : X::B()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} |
80 | } |
81 | // FIXME: Terrible diagnostic here. auto deduction should fail, but does not! |
82 | for (double a : f) { // expected-error {{cannot use type '<overloaded function type>' as a range}} |
83 | } |
84 | for (auto a : A()) { |
85 | } |
86 | for (auto a : X::B()) { |
87 | } |
88 | for (auto *a : A()) { // expected-error {{variable 'a' with type 'auto *' has incompatible initializer of type 'int'}} |
89 | } |
90 | // : is not a typo for :: here. |
91 | for (A NS:A()) { // expected-error {{no viable conversion from 'int' to 'X::A'}} |
92 | } |
93 | for (auto not_in_scope : not_in_scope) { // expected-error {{use of undeclared identifier 'not_in_scope'}} |
94 | } |
95 | |
96 | for (auto a : A()) |
97 | for (auto b : A()) { |
98 | __range.begin(); // expected-error {{use of undeclared identifier '__range'}} |
99 | ++__begin; // expected-error {{use of undeclared identifier '__begin'}} |
100 | --__end; // expected-error {{use of undeclared identifier '__end'}} |
101 | } |
102 | |
103 | for (char c : "test") |
104 | ; |
105 | for (auto a : f()) // expected-error {{cannot use type 'void' as a range}} |
106 | ; |
107 | |
108 | extern int incomplete[]; |
109 | for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}} |
110 | ; |
111 | extern struct Incomplete also_incomplete[2]; // expected-note 2{{forward declaration}} |
112 | for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}} |
113 | ; |
114 | |
115 | struct VoidBegin { |
116 | void begin(); // expected-note {{selected 'begin' function with iterator type 'void'}} |
117 | void end(); |
118 | }; |
119 | for (auto a : VoidBegin()) // expected-error {{cannot use type 'void' as an iterator}} |
120 | ; |
121 | |
122 | struct Differ { |
123 | int *begin(); |
124 | null_t end(); |
125 | }; |
126 | for (auto a : Differ()) |
127 | #if __cplusplus <= 201402L |
128 | // expected-warning@-2 {{'begin' and 'end' returning different types ('int *' and 'null_t') is a C++17 extension}} |
129 | // expected-note@-6 {{selected 'begin' function with iterator type 'int *'}} |
130 | // expected-note@-6 {{selected 'end' function with iterator type 'null_t'}} |
131 | #endif |
132 | ; |
133 | |
134 | for (void f() : "error") // expected-error {{for range declaration must declare a variable}} |
135 | ; |
136 | |
137 | for (extern int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'extern'}} |
138 | for (static int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'static'}} |
139 | for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}} expected-warning 0-1{{register}} expected-error 0-1{{register}} |
140 | for (constexpr int a : X::C()) {} // OK per CWG issue #1204. |
141 | |
142 | for (auto u : X::NoBeginADL()) { // expected-error {{invalid range expression of type 'X::NoBeginADL'; no viable 'begin' function available}} |
143 | } |
144 | for (auto u : X::NoEndADL()) { // expected-error {{invalid range expression of type 'X::NoEndADL'; no viable 'end' function available}} |
145 | } |
146 | |
147 | struct NoBegin { |
148 | null_t end(); |
149 | }; |
150 | struct NoEnd { |
151 | null_t begin(); |
152 | }; |
153 | for (auto u : NoBegin()) { // expected-error {{no viable 'begin' function available}} |
154 | } |
155 | for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}} |
156 | } |
157 | |
158 | struct NoIncr { |
159 | void *begin(); // expected-note {{selected 'begin' function with iterator type 'void *'}} |
160 | void *end(); |
161 | }; |
162 | for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}}\ |
163 | expected-note {{in implicit call to 'operator++' for iterator of type 'NoIncr'}} |
164 | } |
165 | |
166 | struct NoNotEq { |
167 | NoNotEq begin(); // expected-note {{selected 'begin' function with iterator type 'NoNotEq'}} |
168 | NoNotEq end(); |
169 | void operator++(); |
170 | }; |
171 | for (auto u : NoNotEq()) { // expected-error {{invalid operands to binary expression}}\ |
172 | expected-note {{in implicit call to 'operator!=' for iterator of type 'NoNotEq'}} |
173 | } |
174 | |
175 | struct NoDeref { |
176 | NoDeref begin(); // expected-note {{selected 'begin' function}} |
177 | NoDeref end(); |
178 | void operator++(); |
179 | bool operator!=(NoDeref &); |
180 | }; |
181 | |
182 | for (auto u : NoDeref()) { // expected-error {{indirection requires pointer operand}} \ |
183 | expected-note {{in implicit call to 'operator*' for iterator of type 'NoDeref'}} |
184 | } |
185 | |
186 | struct NoCopy { |
187 | NoCopy(); |
188 | NoCopy(const NoCopy &) = delete; |
189 | int *begin(); |
190 | int *end(); |
191 | }; |
192 | for (int n : NoCopy()) { // ok |
193 | } |
194 | |
195 | for (int n : 42) { // expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}} |
196 | } |
197 | |
198 | for (auto a : *also_incomplete) { // expected-error {{cannot use incomplete type 'struct Incomplete' as a range}} |
199 | } |
200 | } |
201 | |
202 | template<typename T, typename U> |
203 | void h(T t) { |
204 | for (U u : t) { // expected-error {{no viable conversion from 'X::A' to 'int'}} |
205 | } |
206 | for (auto u : t) { |
207 | } |
208 | } |
209 | |
210 | template void h<A, int>(A); |
211 | template void h<A(&)[4], A &>(A(&)[4]); |
212 | template void h<A(&)[13], A>(A(&)[13]); |
213 | template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}} |
214 | |
215 | template<typename T> |
216 | void i(T t) { |
217 | for (auto u : t) { // expected-error {{invalid range expression of type 'X::A *'; no viable 'begin' function available}} \ |
218 | expected-error {{'this' argument to member function 'begin' has type 'const X::A', but function is not marked const}} \ |
219 | expected-note {{when looking up 'begin' function}} |
220 | |
221 | } |
222 | } |
223 | template void i<A[13]>(A*); // expected-note {{requested here}} |
224 | template void i<const A>(const A); // expected-note {{requested here}} |
225 | |
226 | struct StdBeginEnd {}; |
227 | namespace std { |
228 | int *begin(StdBeginEnd); |
229 | int *end(StdBeginEnd); |
230 | } |
231 | void DR1442() { |
232 | for (auto a : StdBeginEnd()) {} // expected-error {{invalid range expression of type 'StdBeginEnd'; no viable 'begin'}} |
233 | } |
234 | |
235 | namespace NS { |
236 | class ADL {}; |
237 | int *begin(ADL); // expected-note {{no known conversion from 'NS::NoADL' to 'NS::ADL'}} |
238 | int *end(ADL); |
239 | |
240 | class NoADL {}; |
241 | } |
242 | int *begin(NS::NoADL); |
243 | int *end(NS::NoADL); |
244 | |
245 | struct VoidBeginADL {}; |
246 | void begin(VoidBeginADL); // expected-note {{selected 'begin' function with iterator type 'void'}} |
247 | void end(VoidBeginADL); |
248 | |
249 | void j() { |
250 | for (auto u : NS::ADL()) { |
251 | } |
252 | for (auto u : NS::NoADL()) { // expected-error {{invalid range expression of type 'NS::NoADL'; no viable 'begin' function available}} |
253 | } |
254 | for (auto a : VoidBeginADL()) { // expected-error {{cannot use type 'void' as an iterator}} |
255 | |
256 | } |
257 | } |
258 | |
259 | void example() { |
260 | int array[5] = { 1, 2, 3, 4, 5 }; |
261 | for (int &x : array) |
262 | x *= 2; |
263 | } |
264 | |
265 | namespace rdar13712739 { |
266 | template<typename T> |
267 | void foo(const T& t) { |
268 | auto &x = t.get(); // expected-error{{member reference base type 'const int' is not a structure or union}} |
269 | for (auto &blah : x) { } |
270 | } |
271 | |
272 | template void foo(const int&); // expected-note{{in instantiation of function template specialization}} |
273 | } |
274 | |
275 | namespace p0962r1 { |
276 | namespace NA { |
277 | struct A { |
278 | void begin(); |
279 | }; |
280 | int *begin(A); |
281 | int *end(A); |
282 | } |
283 | |
284 | namespace NB { |
285 | struct B { |
286 | void end(); |
287 | }; |
288 | int *begin(B); |
289 | int *end(B); |
290 | } |
291 | |
292 | namespace NC { |
293 | struct C { |
294 | void begin(); |
295 | }; |
296 | int *begin(C); |
297 | } |
298 | |
299 | namespace ND { |
300 | struct D { |
301 | void end(); |
302 | }; |
303 | int *end(D); |
304 | } |
305 | |
306 | namespace NE { |
307 | struct E { |
308 | void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}} |
309 | }; |
310 | int *end(E); |
311 | } |
312 | |
313 | namespace NF { |
314 | struct F { |
315 | void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}} |
316 | }; |
317 | int *begin(F); |
318 | } |
319 | |
320 | void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) { |
321 | for (auto x : a) {} |
322 | for (auto x : b) {} |
323 | for (auto x : c) {} // expected-error {{no viable 'end' function}} |
324 | for (auto x : d) {} // expected-error {{no viable 'begin' function}} |
325 | for (auto x : e) {} // expected-error {{no viable 'begin' function}} |
326 | for (auto x : f) {} // expected-error {{no viable 'end' function}} |
327 | } |
328 | } |
329 | |