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