Skip to content

Commit faf57af

Browse files
fknaufhsutter
andauthored
Bugfix #778: Flag for entry into for loop after range has been processed (#795)
* #778: Flag for entry into for loop after range has been processed * Add regression test * Added requested regression tests * Changing style to `_tag` For better or worse, I've been using `_tag` types instead of adding to the `start`/`end` names, so just staying consistent for now. --------- Co-authored-by: Herb Sutter <[email protected]>
1 parent 6224e2f commit faf57af

File tree

5 files changed

+91
-1
lines changed

5 files changed

+91
-1
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
first: (forward f, forward _...) -> forward _ = f;
2+
3+
main: (args) = {
4+
ints: const std::array = (1, 2, 3, 4, 5);
5+
// OK
6+
for ints.first() do (i) {
7+
std::cout << i;
8+
}
9+
10+
// OK
11+
for ints.first(1) do (i) {
12+
std::cout << i;
13+
}
14+
15+
// Used to cause Error
16+
for ints.first(:(x) x) do (i) {
17+
std::cout << i;
18+
}
19+
20+
// OK
21+
temp := ints.first(:(x) x);
22+
for temp do (i) {
23+
std::cout << i;
24+
}
25+
26+
for :() args$;() do (i) _ = i;
27+
for :(x) x;(args) do (j) _ = j;
28+
for :(x) x;(args) next _ = :() args$;() do (k) _ = k;
29+
for :(x) x;(args) next _ = :(x) x;(args) do (l) _ = l;
30+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-for-loop-range-with-lambda.cpp2"
10+
11+
12+
//=== Cpp2 type definitions and function declarations ===========================
13+
14+
#line 1 "pure2-for-loop-range-with-lambda.cpp2"
15+
[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...unnamed_param_2) -> auto&&;
16+
17+
#line 3 "pure2-for-loop-range-with-lambda.cpp2"
18+
auto main(int const argc_, char** argv_) -> int;
19+
20+
//=== Cpp2 function definitions =================================================
21+
22+
#line 1 "pure2-for-loop-range-with-lambda.cpp2"
23+
[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...unnamed_param_2) -> auto&& { return CPP2_FORWARD(f); }
24+
25+
#line 3 "pure2-for-loop-range-with-lambda.cpp2"
26+
auto main(int const argc_, char** argv_) -> int{
27+
auto const args = cpp2::make_args(argc_, argv_);
28+
#line 4 "pure2-for-loop-range-with-lambda.cpp2"
29+
std::array const ints {1, 2, 3, 4, 5};
30+
// OK
31+
for ( auto const& i : CPP2_UFCS(first)(ints) ) {
32+
std::cout << i;
33+
}
34+
35+
// OK
36+
for ( auto const& i : CPP2_UFCS(first)(ints, 1) ) {
37+
std::cout << i;
38+
}
39+
40+
// Used to cause Error
41+
for ( auto const& i : CPP2_UFCS(first)(ints, [](auto const& x) mutable -> auto { return x; }) ) {
42+
std::cout << i;
43+
}
44+
45+
// OK
46+
auto temp {CPP2_UFCS(first)(std::move(ints), [](auto const& x) mutable -> auto { return x; })};
47+
for ( auto const& i : temp ) {
48+
std::cout << i;
49+
}
50+
51+
for ( auto const& i : [_0 = args]() mutable -> auto { return _0; }() ) static_cast<void>(i);
52+
for ( auto const& j : [](auto const& x) mutable -> auto { return x; }(args) ) static_cast<void>(j);
53+
for ( auto const& k : [](auto const& x) mutable -> auto { return x; }(args) ) { do static_cast<void>(k); while (false); static_cast<void>([_0 = args]() mutable -> auto { return _0; }()); }
54+
for ( auto const& l : [](auto const& x) mutable -> auto { return x; }(args) ) { do static_cast<void>(l); while (false); static_cast<void>([](auto const& x) mutable -> auto { return x; }(args)); }
55+
}
56+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-for-loop-range-with-lambda.cpp2... ok (all Cpp2, passes safety checks)
2+

source/parse.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4028,6 +4028,7 @@ auto primary_expression_node::visit(auto& v, int depth)
40284028

40294029

40304030
struct next_expression_tag { };
4031+
struct loop_body_tag { token const* identifier; };
40314032

40324033
auto iteration_statement_node::visit(auto& v, int depth)
40334034
-> void
@@ -4054,6 +4055,7 @@ auto iteration_statement_node::visit(auto& v, int depth)
40544055
else {
40554056
assert(range && parameter && body);
40564057
range->visit(v, depth+1);
4058+
v.start(loop_body_tag{identifier}, depth);
40574059
parameter->visit(v, depth+1);
40584060
body->visit(v, depth+1);
40594061
}

source/sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,7 @@ class sema
16911691
inside_returns_list = false;
16921692
}
16931693

1694-
auto start(iteration_statement_node const& n, int) -> void
1694+
auto start(loop_body_tag const &n, int) -> void
16951695
{
16961696
if (*n.identifier == "for") {
16971697
just_entered_for = true;

0 commit comments

Comments
 (0)