Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s
      2 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s
      3 
      4 template <typename return_type>
      5 struct Iterator {
      6   return_type operator*();
      7   Iterator operator++();
      8   bool operator!=(const Iterator);
      9 };
     10 
     11 template <typename T>
     12 struct Container {
     13   typedef Iterator<T> I;
     14 
     15   I begin();
     16   I end();
     17 };
     18 
     19 struct Foo {};
     20 struct Bar {
     21   Bar(Foo);
     22   Bar(int);
     23   operator int();
     24 };
     25 
     26 // Testing notes:
     27 // test0 checks that the full text of the warnings and notes is correct.  The
     28 //   rest of the tests checks a smaller portion of the text.
     29 // test1-6 are set in pairs, the odd numbers are the non-reference returning
     30 //   versions of the even numbers.
     31 // test7-9 use an array instead of a range object
     32 // tests use all four versions of the loop varaible, const &T, const T, T&, and
     33 //   T.  Versions producing errors and are commented out.
     34 //
     35 // Conversion chart:
     36 //   double <=> int
     37 //   int    <=> Bar
     38 //   double  => Bar
     39 //   Foo     => Bar
     40 //
     41 // Conversions during tests:
     42 // test1-2
     43 //   int => int
     44 //   int => double
     45 //   int => Bar
     46 // test3-4
     47 //   Bar => Bar
     48 //   Bar => int
     49 // test5-6
     50 //   Foo => Bar
     51 // test7
     52 //   double => double
     53 //   double => int
     54 //   double => Bar
     55 // test8
     56 //   Foo => Foo
     57 //   Foo => Bar
     58 // test9
     59 //   Bar => Bar
     60 //   Bar => int
     61 
     62 void test0() {
     63   Container<int> int_non_ref_container;
     64   Container<int&> int_container;
     65   Container<Bar&> bar_container;
     66 
     67   for (const int &x : int_non_ref_container) {}
     68   // expected-warning@-1 {{loop variable 'x' is always a copy because the range of type 'Container<int>' does not return a reference}}
     69   // expected-note@-2 {{use non-reference type 'int'}}
     70 
     71   for (const double &x : int_container) {}
     72   // expected-warning@-1 {{loop variable 'x' has type 'const double &' but is initialized with type 'int' resulting in a copy}}
     73   // expected-note@-2 {{use non-reference type 'double' to keep the copy or type 'const int &' to prevent copying}}
     74 
     75   for (const Bar x : bar_container) {}
     76   // expected-warning@-1 {{loop variable 'x' of type 'const Bar' creates a copy from type 'const Bar'}}
     77   // expected-note@-2 {{use reference type 'const Bar &' to prevent copying}}
     78 }
     79 
     80 void test1() {
     81   Container<int> A;
     82 
     83   for (const int &x : A) {}
     84   // expected-warning@-1 {{always a copy}}
     85   // expected-note@-2 {{'int'}}
     86   for (const int x : A) {}
     87   // No warning, non-reference type indicates copy is made
     88   //for (int &x : A) {}
     89   // Binding error
     90   for (int x : A) {}
     91   // No warning, non-reference type indicates copy is made
     92 
     93   for (const double &x : A) {}
     94   // expected-warning@-1 {{always a copy}}
     95   // expected-note@-2 {{'double'}}
     96   for (const double x : A) {}
     97   // No warning, non-reference type indicates copy is made
     98   //for (double &x : A) {}
     99   // Binding error
    100   for (double x : A) {}
    101   // No warning, non-reference type indicates copy is made
    102 
    103   for (const Bar &x : A) {}
    104   // expected-warning@-1 {{always a copy}}
    105   // expected-note@-2 {{'Bar'}}
    106   for (const Bar x : A) {}
    107   // No warning, non-reference type indicates copy is made
    108   //for (Bar &x : A) {}
    109   // Binding error
    110   for (Bar x : A) {}
    111   // No warning, non-reference type indicates copy is made
    112 }
    113 
    114 void test2() {
    115   Container<int&> B;
    116 
    117   for (const int &x : B) {}
    118   // No warning, this reference is not a temporary
    119   for (const int x : B) {}
    120   // No warning on POD copy
    121   for (int &x : B) {}
    122   // No warning
    123   for (int x : B) {}
    124   // No warning
    125 
    126   for (const double &x : B) {}
    127   // expected-warning@-1 {{resulting in a copy}}
    128   // expected-note-re@-2 {{'double'{{.*}}'const int &'}}
    129   for (const double x : B) {}
    130   //for (double &x : B) {}
    131   // Binding error
    132   for (double x : B) {}
    133   // No warning
    134 
    135   for (const Bar &x : B) {}
    136   // expected-warning@-1 {{resulting in a copy}}
    137   // expected-note@-2 {{'Bar'}}
    138   for (const Bar x : B) {}
    139   //for (Bar &x : B) {}
    140   // Binding error
    141   for (Bar x : B) {}
    142   // No warning
    143 }
    144 
    145 void test3() {
    146   Container<Bar> C;
    147 
    148   for (const Bar &x : C) {}
    149   // expected-warning@-1 {{always a copy}}
    150   // expected-note@-2 {{'Bar'}}
    151   for (const Bar x : C) {}
    152   // No warning, non-reference type indicates copy is made
    153   //for (Bar &x : C) {}
    154   // Binding error
    155   for (Bar x : C) {}
    156   // No warning, non-reference type indicates copy is made
    157 
    158   for (const int &x : C) {}
    159   // expected-warning@-1 {{always a copy}}
    160   // expected-note@-2 {{'int'}}
    161   for (const int x : C) {}
    162   // No warning, copy made
    163   //for (int &x : C) {}
    164   // Binding error
    165   for (int x : C) {}
    166   // No warning, copy made
    167 }
    168 
    169 void test4() {
    170   Container<Bar&> D;
    171 
    172   for (const Bar &x : D) {}
    173   // No warning, this reference is not a temporary
    174   for (const Bar x : D) {}
    175   // expected-warning@-1 {{creates a copy}}
    176   // expected-note@-2 {{'const Bar &'}}
    177   for (Bar &x : D) {}
    178   // No warning
    179   for (Bar x : D) {}
    180   // No warning
    181 
    182   for (const int &x : D) {}
    183   // expected-warning@-1 {{resulting in a copy}}
    184   // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
    185   for (const int x : D) {}
    186   // No warning
    187   //for (int &x : D) {}
    188   // Binding error
    189   for (int x : D) {}
    190   // No warning
    191 }
    192 
    193 void test5() {
    194   Container<Foo> E;
    195 
    196   for (const Bar &x : E) {}
    197   // expected-warning@-1 {{always a copy}}
    198   // expected-note@-2 {{'Bar'}}
    199   for (const Bar x : E) {}
    200   // No warning, non-reference type indicates copy is made
    201   //for (Bar &x : E) {}
    202   // Binding error
    203   for (Bar x : E) {}
    204   // No warning, non-reference type indicates copy is made
    205 }
    206 
    207 void test6() {
    208   Container<Foo&> F;
    209 
    210   for (const Bar &x : F) {}
    211   // expected-warning@-1 {{resulting in a copy}}
    212   // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
    213   for (const Bar x : F) {}
    214   // No warning.
    215   //for (Bar &x : F) {}
    216   // Binding error
    217   for (Bar x : F) {}
    218   // No warning
    219 }
    220 
    221 void test7() {
    222   double G[2];
    223 
    224   for (const double &x : G) {}
    225   // No warning
    226   for (const double x : G) {}
    227   // No warning on POD copy
    228   for (double &x : G) {}
    229   // No warning
    230   for (double x : G) {}
    231   // No warning
    232 
    233   for (const int &x : G) {}
    234   // expected-warning@-1 {{resulting in a copy}}
    235   // expected-note-re@-2 {{'int'{{.*}}'const double &'}}
    236   for (const int x : G) {}
    237   // No warning
    238   //for (int &x : G) {}
    239   // Binding error
    240   for (int x : G) {}
    241   // No warning
    242 
    243   for (const Bar &x : G) {}
    244   // expected-warning@-1 {{resulting in a copy}}
    245   // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}}
    246   for (const Bar x : G) {}
    247   // No warning
    248   //for (int &Bar : G) {}
    249   // Binding error
    250   for (int Bar : G) {}
    251   // No warning
    252 }
    253 
    254 void test8() {
    255   Foo H[2];
    256 
    257   for (const Foo &x : H) {}
    258   // No warning
    259   for (const Foo x : H) {}
    260   // No warning on POD copy
    261   for (Foo &x : H) {}
    262   // No warning
    263   for (Foo x : H) {}
    264   // No warning
    265 
    266   for (const Bar &x : H) {}
    267   // expected-warning@-1 {{resulting in a copy}}
    268   // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
    269   for (const Bar x : H) {}
    270   // No warning
    271   //for (Bar &x: H) {}
    272   // Binding error
    273   for (Bar x: H) {}
    274   // No warning
    275 }
    276 
    277 void test9() {
    278   Bar I[2] = {1,2};
    279 
    280   for (const Bar &x : I) {}
    281   // No warning
    282   for (const Bar x : I) {}
    283   // expected-warning@-1 {{creates a copy}}
    284   // expected-note@-2 {{'const Bar &'}}
    285   for (Bar &x : I) {}
    286   // No warning
    287   for (Bar x : I) {}
    288   // No warning
    289 
    290   for (const int &x : I) {}
    291   // expected-warning@-1 {{resulting in a copy}}
    292   // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
    293   for (const int x : I) {}
    294   // No warning
    295   //for (int &x : I) {}
    296   // Binding error
    297   for (int x : I) {}
    298   // No warning
    299 }
    300