| 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 | |