Skip to content

[BUG] Last use of copy/move/forward in for _expression_ not exercised #847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JohelEGP opened this issue Nov 22, 2023 · 3 comments · Fixed by #887
Closed

[BUG] Last use of copy/move/forward in for _expression_ not exercised #847

JohelEGP opened this issue Nov 22, 2023 · 3 comments · Fixed by #887
Labels
bug Something isn't working

Comments

@JohelEGP
Copy link
Contributor

Title: Last use of copy/move/forward in for expression not exercised.

Minimal reproducer (https://cpp2.godbolt.org/z/4PE6dTY8f):

f: (copy v: std::vector<int>) = { for v do (_) { } } // Doesn't move.
f: (move v: std::vector<int>) = { for v do (_) { } } // Doesn't move.
f: (forward r) = { for r do (_) { } } // Doesn't forward.
main: () = { }
Commands:
cppfront main.cpp2
clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -I . main.cpp

Expected result:

auto f(std::vector<int> v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : std::move(v) ) {}}// Doesn't move.
#line 2 "/app/example.cpp2"
auto f(std::vector<int>&& v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : std::move(v) ) {}}// Doesn't move.
auto f(auto&& r) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_FORWARD(r) ) {}}// Doesn't forward.

Actual result and error:

auto f(std::vector<int> v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : v ) {}}// Doesn't move.
#line 2 "/app/example.cpp2"
auto f(std::vector<int>&& v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : v ) {}}// Doesn't move.
auto f(auto&& r) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : r ) {}}// Doesn't forward.
Cpp2 lowered to Cpp1:
//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

#line 1 "/app/example.cpp2"


//=== Cpp2 type definitions and function declarations ===========================

#line 1 "/app/example.cpp2"
auto f(std::vector<int> v) -> void;
#line 2 "/app/example.cpp2"
auto f(std::vector<int>&& v) -> void;
auto f(auto&& r) -> void;
auto main() -> int;

//=== Cpp2 function definitions =================================================

#line 1 "/app/example.cpp2"
auto f(std::vector<int> v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : v ) {}}// Doesn't move.
#line 2 "/app/example.cpp2"
auto f(std::vector<int>&& v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : v ) {}}// Doesn't move.
auto f(auto&& r) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : r ) {}}// Doesn't forward.
auto main() -> int{}
Output:
Program returned: 0

See also:

@JohelEGP JohelEGP added the bug Something isn't working label Nov 22, 2023
@JohelEGP
Copy link
Contributor Author

When I reported this, I think I was hoping to get a container cleared on move.
That can't happen because it initializes a auto&& variable (https://eel.is/c++draft/stmt.ranged).

It uses the variable as an lvalue to access the iterators, so const is already propagated.
Propagating rvalueness does nothing.
Except perhaps not confusing users in rare error messages
where the variable appears declared as an lvalue reference instead of an rvalue reference.
That might led users astray in their development process.

@JohelEGP
Copy link
Contributor Author

Description:

Even if the expression isn't just the parameter name,
move/forward on last use doesn't happen.

Minimal reproducer (https://cpp2.godbolt.org/z/Tvana63M9):

copy: (copy x) x;
f: (copy v: std::vector<int>) = { for v.copy() do (_) { } } // Doesn't move.
f: (move v: std::vector<int>) = { for v.copy() do (_) { } } // Doesn't move.
f: (forward r) = { for r.copy() do (_) { } } // Doesn't forward.
main: () = { }
Commands:
cppfront main.cpp2
clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -Werror=unused-value -Werror=unused-parameter -I . main.cpp

Expected result: Move/forward on last use in the expression of the for.

Actual result and error:

auto f(std::vector<int> v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, v) ) {}}// Doesn't move.
auto f(std::vector<int>&& v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, v) ) {}}// Doesn't move.
auto f(auto&& r) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, r) ) {}}// Doesn't forward.
auto main() -> int{}
Cpp2 lowered to Cpp1:
//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

#line 1 "/app/example.cpp2"


//=== Cpp2 type definitions and function declarations ===========================

#line 1 "/app/example.cpp2"
[[nodiscard]] auto copy(auto x) -> auto;
#line 2 "/app/example.cpp2"
auto f(std::vector<int> v) -> void;
auto f(std::vector<int>&& v) -> void;
auto f(auto&& r) -> void;
auto main() -> int;

//=== Cpp2 function definitions =================================================

#line 1 "/app/example.cpp2"
[[nodiscard]] auto copy(auto x) -> auto { return std::move(x);  }
#line 2 "/app/example.cpp2"
auto f(std::vector<int> v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, v) ) {}}// Doesn't move.
auto f(std::vector<int>&& v) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, v) ) {}}// Doesn't move.
auto f(auto&& r) -> void{for ( [[maybe_unused]] auto const& unnamed_param_1 : CPP2_UFCS_0(copy, r) ) {}}// Doesn't forward.
auto main() -> int{}

@JohelEGP
Copy link
Contributor Author

The same is true for the loop variable (https://cpp2.godbolt.org/z/KsYen7Y7h):

main: (args) = {
  for args do (copy x) _ = x; // Doesn't move.
  for args do (move x) _ = x; // Doesn't move.
  for args do (forward x) _ = x; // Doesn't forward.
}
auto main(int const argc_, char** argv_) -> int{
  auto const args = cpp2::make_args(argc_, argv_); 
  for ( auto x : args ) static_cast<void>(x); // Doesn't move.
  for ( auto&& x : args ) static_cast<void>(x); // Doesn't move.
  for ( auto&& x : args ) static_cast<void>(x); // Doesn't forward.
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant