| // PR c++/94695 |
| // { dg-do compile { target c++11 } } |
| // { dg-options "-Wrange-loop-construct" } |
| |
| #include <initializer_list> |
| |
| struct Small { |
| char arr[64]; |
| }; |
| |
| struct Big_aggr { |
| char arr[65]; |
| }; |
| |
| struct Big_triv_copy { |
| char arr[65]; |
| Big_triv_copy() { } |
| }; |
| |
| struct Big { |
| char arr[65]; |
| Big () = default; |
| Big(const Big&); |
| }; |
| |
| struct Foo { }; |
| struct Bar { |
| char arr[100]; |
| Bar(Foo); |
| Bar(int); |
| operator int(); |
| }; |
| |
| template<typename T> |
| struct It { |
| T operator*(); |
| It operator++(); |
| bool operator!=(const It); |
| }; |
| |
| template<typename T> |
| struct Cont { |
| using I = It<T>; |
| I begin(); |
| I end(); |
| }; |
| |
| #define TEST \ |
| void fn_macro() \ |
| { \ |
| Cont<Bar &> cont_bar_ref; \ |
| for (const Bar x : cont_bar_ref) { (void) x; } \ |
| } |
| |
| TEST |
| |
| Cont<Bar &>& foo (); |
| Cont<Bar &> foo2 (); |
| |
| void |
| fn1 () |
| { |
| for (const auto x : foo () ) { (void) x; } // { dg-warning "creates a copy" } |
| for (const auto x : foo2 () ) { (void) x; } // { dg-warning "creates a copy" } |
| |
| Small s{}; |
| Small sa[5] = { }; |
| for (const auto x : sa) { (void) x; } |
| for (const auto x : { s, s, s }) { (void) x; } |
| |
| Big_aggr b{}; |
| Big_aggr ba[5] = { }; |
| for (const auto x : ba) { (void) x; } // { dg-warning "creates a copy" } |
| for (const auto x : { b, b, b }) { (void) x; } // { dg-warning "creates a copy" } |
| |
| Big_triv_copy bt{}; |
| Big_triv_copy bta[5]; |
| for (const auto x : bta) { (void) x; } // { dg-warning "creates a copy" } |
| for (const auto x : { bt, bt, bt }) { (void) x; } // { dg-warning "creates a copy" } |
| |
| Big b2; |
| Big ba2[5]; |
| for (const auto x : ba2) { (void) x; } // { dg-warning "creates a copy" } |
| for (const auto x : { b2, b2, b2 }) { (void) x; } // { dg-warning "creates a copy" } |
| } |
| |
| void |
| fn2 () |
| { |
| Cont<int> cont_int; |
| for (const auto x : cont_int) { (void) x; } |
| for (const int x : cont_int) { (void) x; } |
| for (int x : cont_int) { (void) x; } |
| for (const auto &x : cont_int) { (void) x; } |
| for (double x : cont_int) { (void) x; } |
| for (const double x : cont_int) { (void) x; } |
| for (const Bar x : cont_int) { (void) x; } |
| for (Bar x : cont_int) { (void) x; } |
| } |
| |
| void |
| fn3 () |
| { |
| Cont<int &> cont_int_ref; |
| for (const int x : cont_int_ref) { (void) x; } |
| for (int x : cont_int_ref) { (void) x; } |
| for (const double x : cont_int_ref) { (void) x; } |
| for (double x : cont_int_ref) { (void) x; } |
| for (const Bar x : cont_int_ref) { (void) x; } |
| for (Bar x : cont_int_ref) { (void) x; } |
| } |
| |
| void |
| fn4 () |
| { |
| Cont<Bar> cont_bar; |
| for (const Bar x : cont_bar) { (void) x; } |
| for (Bar x : cont_bar) { (void) x; } |
| for (const int x : cont_bar) { (void) x; } |
| for (int x : cont_bar) { (void) x; } |
| } |
| |
| void |
| fn5 () |
| { |
| Cont<Bar&> cont_bar_ref; |
| for (const Bar x : cont_bar_ref) { (void) x; } // { dg-warning "creates a copy" } |
| for (Bar x : cont_bar_ref) { (void) x; } |
| for (const int x : cont_bar_ref) { (void) x; } |
| for (int x : cont_bar_ref) { (void) x; } |
| } |
| |
| void |
| fn6 () |
| { |
| Cont<Foo> cont_foo; |
| for (const Bar x : cont_foo) { (void) x; } |
| for (Bar x : cont_foo) { (void) x; } |
| } |
| |
| void |
| fn7 () |
| { |
| Cont<Foo &> cont_foo_ref; |
| for (const Bar x : cont_foo_ref) { (void) x; } |
| for (Bar x : cont_foo_ref) { (void) x; } |
| } |
| |
| void |
| fn8 () |
| { |
| double arr[2]; |
| for (const double x : arr) { (void) x; } |
| for (double x : arr) { (void) x; } |
| for (const int x : arr) { (void) x; } |
| for (int x : arr) { (void) x; } |
| for (const Bar x : arr) { (void) x; } |
| for (Bar x : arr) { (void) x; } |
| } |
| |
| void |
| fn9 () |
| { |
| Foo foo[2]; |
| for (const Foo x : foo) { (void) x; } |
| for (Foo x : foo) { (void) x; } |
| for (const Bar x : foo) { (void) x; } |
| for (Bar x : foo) { (void) x; } |
| } |
| |
| void |
| fn10 () |
| { |
| Bar bar[2] = { 1, 2 }; |
| for (const Bar x : bar) { (void) x; } // { dg-warning "creates a copy" } |
| for (Bar x : bar) { (void) x; } |
| for (const int x : bar) { (void) x; } |
| for (int x : bar) { (void) x; } |
| } |
| |
| template<typename T> |
| void |
| fn11 () |
| { |
| Cont<Bar> cont_bar; |
| for (const Bar x : cont_bar) { (void) x; } |
| |
| Cont<Bar&> cont_bar_ref; |
| for (const Bar x : cont_bar_ref) { (void) x; } // { dg-warning "creates a copy" } |
| |
| Cont<T> cont_dep; |
| for (const T x : cont_dep) { (void) x; } |
| } |
| |
| template<typename T> |
| void |
| fn12 () |
| { |
| for (const auto x : { T{} }) { (void) x; } // { dg-warning "creates a copy" } |
| } |
| |
| void |
| invoke () |
| { |
| fn11<int> (); |
| fn12<Big> (); |
| } |