Skip to content

[BUG] Need decltype(auto) for perfect backwarding #876

Closed
@JohelEGP

Description

@JohelEGP

Title: Need decltype(auto) for perfect backwarding.

Description:

At first, a Cpp2 -> forward _ return-list lowered to the Cpp1 return type auto&&.

#175 noted this was unsafe,
and commit b59f539 changed it to decltype(auto).

#274 noted that this makes accessors return by copy,
then commit 413de0e changed it back to auto&&,
and commit 43cdf3e addressed some safety concerns of #175.

Now perfect backwarding doesn't work or returns a temporary.
This means we can't implement std::invoke or simpler equivalents.
For example, implementing a simple function_ref: https://cpp2.godbolt.org/z/r53zfnxbT.

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

f: (x: int) x;
f: (x: long) _ = x;
g: (x) -> forward _ = f(x);
main: () = {
  _ = g(0);
  _ = g(0L);
}
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: Perfect backwarding to work.

Actual result and error:

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 f(cpp2::in<int> x) -> auto;
#line 2 "/app/example.cpp2"
[[nodiscard]] auto f(cpp2::in<long> x) -> auto;
[[nodiscard]] auto g(auto const& x) -> auto&&;
auto main() -> int;

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

#line 1 "/app/example.cpp2"
[[nodiscard]] auto f(cpp2::in<int> x) -> auto { return x;  }
#line 2 "/app/example.cpp2"
[[nodiscard]] auto f(cpp2::in<long> x) -> auto { return static_cast<void>(x);  }
[[nodiscard]] auto g(auto const& x) -> auto&& { return f(x);  }
auto main() -> int{
  static_cast<void>(g(0));
  static_cast<void>(g(0L));
}
Output:
main.cpp2:3:56: warning: returning reference to local temporary object [-Wreturn-stack-address]
    3 | [[nodiscard]] auto g(auto const& x) -> auto&& { return f(x);  }
      |                                                        ^~~~
main.cpp2:5:21: note: in instantiation of function template specialization 'g<int>' requested here
    5 |   static_cast<void>(g(0));
      |                     ^
main.cpp2:3:44: error: cannot form a reference to 'void'
    3 | [[nodiscard]] auto g(auto const& x) -> auto&& { return f(x);  }
      |                                            ^
main.cpp2:6:21: note: in instantiation of function template specialization 'g<long>' requested here
    6 |   static_cast<void>(g(0L));
      |                     ^
1 warning and 1 error generated.

See also:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions