Home | History | Annotate | Download | only in stmt.ranged
      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++1z -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 {{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++1z 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 {{range type 'NoBegin' has 'end' member but no 'begin' member}}
    154   }
    155   for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}}
    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 {{member function 'begin' not viable}} \
    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