From 4e5b7e13e0e28b898b8e4fd3ce761376e9de2707 Mon Sep 17 00:00:00 2001 From: Florian Knauf Date: Wed, 1 Nov 2023 16:42:46 +0100 Subject: [PATCH 1/4] #778: Flag for entry into for loop after range has been processed --- source/parse.h | 6 ++++++ source/sema.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/source/parse.h b/source/parse.h index bedb265b65..b610c6b5bc 100644 --- a/source/parse.h +++ b/source/parse.h @@ -3906,6 +3906,7 @@ auto iteration_statement_node::visit(auto& v, int depth) else { assert(range && parameter && body); range->visit(v, depth+1); + v.prepare_for_loop_body(*this); parameter->visit(v, depth+1); body->visit(v, depth+1); } @@ -8963,6 +8964,11 @@ class parse_tree_printer : printing_visitor { // Ignore other node types } + + auto prepare_for_loop_body(iteration_statement_node const &n) -> void + { + // only important for sema + } }; diff --git a/source/sema.h b/source/sema.h index 21973839f2..464ad8bd4b 100644 --- a/source/sema.h +++ b/source/sema.h @@ -1592,7 +1592,7 @@ class sema inside_returns_list = false; } - auto start(iteration_statement_node const& n, int) -> void + auto prepare_for_loop_body(iteration_statement_node const &n) -> void { if (*n.identifier == "for") { just_entered_for = true; From 28cd98308abb7069ebc24a4e2218b18633dd3d8b Mon Sep 17 00:00:00 2001 From: Florian Knauf Date: Wed, 1 Nov 2023 16:50:03 +0100 Subject: [PATCH 2/4] Add regression test --- .../pure2-for-loop-range-with-lambda.cpp2 | 25 +++++++++++ .../pure2-for-loop-range-with-lambda.cpp | 44 +++++++++++++++++++ ...re2-for-loop-range-with-lambda.cpp2.output | 2 + 3 files changed, 71 insertions(+) create mode 100644 regression-tests/pure2-for-loop-range-with-lambda.cpp2 create mode 100644 regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp create mode 100644 regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output diff --git a/regression-tests/pure2-for-loop-range-with-lambda.cpp2 b/regression-tests/pure2-for-loop-range-with-lambda.cpp2 new file mode 100644 index 0000000000..56b49fc8fb --- /dev/null +++ b/regression-tests/pure2-for-loop-range-with-lambda.cpp2 @@ -0,0 +1,25 @@ +first: (forward f, forward _...) -> forward _ = f; + +main: () = { + ints: const std::array = (1, 2, 3, 4, 5); + // OK + for ints.first() do (i) { + std::cout << i; + } + + // OK + for ints.first(1) do (i) { + std::cout << i; + } + + // Used to cause Error + for ints.first(:(x) x) do (i) { + std::cout << i; + } + + // OK + temp := ints.first(:(x) x); + for temp do (i) { + std::cout << i; + } +} diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp new file mode 100644 index 0000000000..4e5b9f09f5 --- /dev/null +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp @@ -0,0 +1,44 @@ + + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + + + +//=== Cpp2 type definitions and function declarations =========================== + +[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&&; + +auto main() -> int; + + +//=== Cpp2 function definitions ================================================= + +[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&& { return CPP2_FORWARD(f); } + +auto main() -> int{ + std::array const ints {1, 2, 3, 4, 5}; + // OK + for ( auto const& i : CPP2_UFCS_0(first, ints) ) { + std::cout << i; + } + + // OK + for ( auto const& i : CPP2_UFCS(first, ints, 1) ) { + std::cout << i; + } + + // Used to cause Error + for ( auto const& i : CPP2_UFCS(first, ints, [](auto const& x) -> auto { return x; }) ) { + std::cout << i; + } + + // OK + auto temp {CPP2_UFCS(first, ints, [](auto const& x) -> auto { return x; })}; + for ( auto const& i : temp ) { + std::cout << i; + } +} + diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output new file mode 100644 index 0000000000..b2cb50984a --- /dev/null +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output @@ -0,0 +1,2 @@ +../pure2-for-loop-range-with-lambda.cpp2... ok (all Cpp2, passes safety checks) + From d2e52f41921e2940d8e6bc524b07d9e9fc1c2918 Mon Sep 17 00:00:00 2001 From: Florian Knauf Date: Wed, 13 Dec 2023 11:32:42 +0100 Subject: [PATCH 3/4] Added requested regression tests --- .../pure2-for-loop-range-with-lambda.cpp2 | 7 ++++++- .../pure2-for-loop-range-with-lambda.cpp | 12 ++++++++++-- .../pure2-for-loop-range-with-lambda.cpp2.output | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/regression-tests/pure2-for-loop-range-with-lambda.cpp2 b/regression-tests/pure2-for-loop-range-with-lambda.cpp2 index 56b49fc8fb..066771baa9 100644 --- a/regression-tests/pure2-for-loop-range-with-lambda.cpp2 +++ b/regression-tests/pure2-for-loop-range-with-lambda.cpp2 @@ -1,6 +1,6 @@ first: (forward f, forward _...) -> forward _ = f; -main: () = { +main: (args) = { ints: const std::array = (1, 2, 3, 4, 5); // OK for ints.first() do (i) { @@ -22,4 +22,9 @@ main: () = { for temp do (i) { std::cout << i; } + + for :() args$;() do (i) _ = i; + for :(x) x;(args) do (j) _ = j; + for :(x) x;(args) next _ = :() args$;() do (k) _ = k; + for :(x) x;(args) next _ = :(x) x;(args) do (l) _ = l; } diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp index 4e5b9f09f5..3aaef61e57 100644 --- a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp @@ -1,4 +1,5 @@ +#define CPP2_IMPORT_STD Yes //=== Cpp2 type declarations ==================================================== @@ -11,14 +12,16 @@ [[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&&; -auto main() -> int; +auto main(int const argc_, char** argv_) -> int; //=== Cpp2 function definitions ================================================= [[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&& { return CPP2_FORWARD(f); } -auto main() -> int{ +auto main(int const argc_, char** argv_) -> int{ + auto const args = cpp2::make_args(argc_, argv_); +#line 4 "pure2-for-loop-range-with-lambda.cpp2" std::array const ints {1, 2, 3, 4, 5}; // OK for ( auto const& i : CPP2_UFCS_0(first, ints) ) { @@ -40,5 +43,10 @@ auto main() -> int{ for ( auto const& i : temp ) { std::cout << i; } + + for ( auto const& i : [_0 = args]() -> auto { return _0; }() ) static_cast(i); + for ( auto const& j : [](auto const& x) -> auto { return x; }(args) ) static_cast(j); + for ( auto const& k : [](auto const& x) -> auto { return x; }(args) ) { do static_cast(k); while (false); static_cast([_0 = args]() -> auto { return _0; }()); } + for ( auto const& l : [](auto const& x) -> auto { return x; }(args) ) { do static_cast(l); while (false); static_cast([](auto const& x) -> auto { return x; }(args)); } } diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output index b2cb50984a..0a120379fb 100644 --- a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp2.output @@ -1,2 +1,2 @@ -../pure2-for-loop-range-with-lambda.cpp2... ok (all Cpp2, passes safety checks) +pure2-for-loop-range-with-lambda.cpp2... ok (all Cpp2, passes safety checks) From 2432e34f773b823f5223566ea3f7b15a375588df Mon Sep 17 00:00:00 2001 From: Herb Sutter Date: Fri, 15 Dec 2023 17:14:40 -1000 Subject: [PATCH 4/4] 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. --- .../pure2-for-loop-range-with-lambda.cpp | 26 +++++++++++-------- source/parse.h | 8 ++---- source/sema.h | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp index 3aaef61e57..3e2e505aed 100644 --- a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp @@ -6,47 +6,51 @@ #include "cpp2util.h" +#line 1 "pure2-for-loop-range-with-lambda.cpp2" //=== Cpp2 type definitions and function declarations =========================== -[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&&; +#line 1 "pure2-for-loop-range-with-lambda.cpp2" +[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...unnamed_param_2) -> auto&&; +#line 3 "pure2-for-loop-range-with-lambda.cpp2" auto main(int const argc_, char** argv_) -> int; - //=== Cpp2 function definitions ================================================= -[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...param2) -> auto&& { return CPP2_FORWARD(f); } +#line 1 "pure2-for-loop-range-with-lambda.cpp2" +[[nodiscard]] auto first(auto&& f, [[maybe_unused]] auto&& ...unnamed_param_2) -> auto&& { return CPP2_FORWARD(f); } +#line 3 "pure2-for-loop-range-with-lambda.cpp2" auto main(int const argc_, char** argv_) -> int{ auto const args = cpp2::make_args(argc_, argv_); #line 4 "pure2-for-loop-range-with-lambda.cpp2" std::array const ints {1, 2, 3, 4, 5}; // OK - for ( auto const& i : CPP2_UFCS_0(first, ints) ) { + for ( auto const& i : CPP2_UFCS(first)(ints) ) { std::cout << i; } // OK - for ( auto const& i : CPP2_UFCS(first, ints, 1) ) { + for ( auto const& i : CPP2_UFCS(first)(ints, 1) ) { std::cout << i; } // Used to cause Error - for ( auto const& i : CPP2_UFCS(first, ints, [](auto const& x) -> auto { return x; }) ) { + for ( auto const& i : CPP2_UFCS(first)(ints, [](auto const& x) mutable -> auto { return x; }) ) { std::cout << i; } // OK - auto temp {CPP2_UFCS(first, ints, [](auto const& x) -> auto { return x; })}; + auto temp {CPP2_UFCS(first)(std::move(ints), [](auto const& x) mutable -> auto { return x; })}; for ( auto const& i : temp ) { std::cout << i; } - for ( auto const& i : [_0 = args]() -> auto { return _0; }() ) static_cast(i); - for ( auto const& j : [](auto const& x) -> auto { return x; }(args) ) static_cast(j); - for ( auto const& k : [](auto const& x) -> auto { return x; }(args) ) { do static_cast(k); while (false); static_cast([_0 = args]() -> auto { return _0; }()); } - for ( auto const& l : [](auto const& x) -> auto { return x; }(args) ) { do static_cast(l); while (false); static_cast([](auto const& x) -> auto { return x; }(args)); } + for ( auto const& i : [_0 = args]() mutable -> auto { return _0; }() ) static_cast(i); + for ( auto const& j : [](auto const& x) mutable -> auto { return x; }(args) ) static_cast(j); + for ( auto const& k : [](auto const& x) mutable -> auto { return x; }(args) ) { do static_cast(k); while (false); static_cast([_0 = args]() mutable -> auto { return _0; }()); } + for ( auto const& l : [](auto const& x) mutable -> auto { return x; }(args) ) { do static_cast(l); while (false); static_cast([](auto const& x) mutable -> auto { return x; }(args)); } } diff --git a/source/parse.h b/source/parse.h index 7b3e0658f9..a2a5932ca1 100644 --- a/source/parse.h +++ b/source/parse.h @@ -4028,6 +4028,7 @@ auto primary_expression_node::visit(auto& v, int depth) struct next_expression_tag { }; +struct loop_body_tag { token const* identifier; }; auto iteration_statement_node::visit(auto& v, int depth) -> void @@ -4054,7 +4055,7 @@ auto iteration_statement_node::visit(auto& v, int depth) else { assert(range && parameter && body); range->visit(v, depth+1); - v.prepare_for_loop_body(*this); + v.start(loop_body_tag{identifier}, depth); parameter->visit(v, depth+1); body->visit(v, depth+1); } @@ -9141,11 +9142,6 @@ class parse_tree_printer : printing_visitor { // Ignore other node types } - - auto prepare_for_loop_body(iteration_statement_node const &n) -> void - { - // only important for sema - } }; diff --git a/source/sema.h b/source/sema.h index b4637ad82f..1f7e48ad2c 100644 --- a/source/sema.h +++ b/source/sema.h @@ -1691,7 +1691,7 @@ class sema inside_returns_list = false; } - auto prepare_for_loop_body(iteration_statement_node const &n) -> void + auto start(loop_body_tag const &n, int) -> void { if (*n.identifier == "for") { just_entered_for = true;