hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Last use of an object resulting in `std::move` is incompatible with CTAD

bluetarpmedia opened this issue · comments

Describe the bug
Cppfront generates a std::move for the last-use of an object, but this can cause problems if that last-use is an argument passed to a constructor which is relying on CTAD.

To Reproduce
Run Cppfront on this code:

main: () -> int = {
    m: std::mutex = ();
    _: std::scoped_lock = (m);
    return 0;
}

It lowers to:

[[nodiscard]] auto main() -> int{
    std::mutex m {}; 
    std::scoped_lock auto_1 {std::move(m)}; 
    return 0; 
}

This results in a compilation error, e.g. with Clang:

main.cpp2:3:22: error: no viable constructor or deduction guide for deduction of template arguments of 'scoped_lock'
    3 |     std::scoped_lock auto_1 {std::move(m)}; 
      | 

(Similar errors with MSVC and GCC.)

See Godbolt

I found another example except this time it's not with CTAD:

main: () -> int = {
    m: std::mutex = ();
    _: std::unique_lock<std::mutex> = (m);
    return 0;
}

(Skipping the lowering.)

GCC error:

unique_lock.h:66:16: note:   conversion of argument 1 would be ill-formed:
<source>:5:51: error: cannot bind non-const lvalue reference of type 'std::unique_lock<std::mutex>::mutex_type&' {aka 'std::mutex&'} to an rvalue of type 'std::remove_reference<std::mutex&>::type' {aka 'std::mutex'}
    5 |     std::unique_lock<std::mutex> auto_1 (std::move(m));
      |                                          ~~~~~~~~~^~~

Thanks! See #1030, this should now be fixed in the above commit.

Both code examples above will now work.