Open JohelEGP opened 1 year ago
My reading of https://eel.is/c++draft/expr.const#8
tells me that g(0);
will continue failing
whereas g(std::identity());
would be well-formed.
The same can be done here to resolve this #788. The alternative is to just embrace #550 and #788 as limitations of Cppfront, and require users to not name such variables like the function in a UFCS call.
I have potential solutions in mind for this one. But they also bring complexity to the code of Cppfront.
Maybe trial constant evaluation can be leveraged for a seamless user experience.
An alternative would be to disable UFCS
when in a constant expression (so Cppfront has to know about those)
and f
isn't part of the constant expression (determined by lexical name lookup).
// g(std::identity()); // Might be OK since P2280R4 (unimplemented).
Yes, it works: https://cpp2.godbolt.org/z/1vrf534qG.
(Now?) g(0)
also works with GCC (https://cpp2.godbolt.org/z/8v13hM44h).
I'd expect Clang to work, by choosing the member, since that works, before even trying the object.
Maybe there's a Clang bug lurking,
or some constant expression quirk where Clang is strict and GCC is loose.
It's worth debugging the UFCS macro to see exactly what triggers Clang for further investigation.
Title: UFCS fails during constant evaluation only.
Description:
Given a parameter named after the function being called, UFCS will fail during constant evaluation only in the case UFCS would call a member function.
Minimal reproducer (https://cpp2.godbolt.org/z/jKWG4boaq, https://compiler-explorer.com/z/zeqW6MEPK):
Commands:
```bash 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: A well-formed program that calls the member function.
Actual result and error:
Cpp2 lowered to Cpp1:
```C++ //=== Cpp2 type declarations ==================================================== #include "cpp2util.h" class t; //=== Cpp2 type definitions and function declarations =========================== class t { public: [[nodiscard]] constexpr auto f() const& -> int; }; auto g(auto const& f) -> void; auto main() -> int; //=== Cpp2 function definitions ================================================= [[nodiscard]] constexpr auto t::f() const& -> int { return 0; } auto g(auto const& f) -> void{ cpp2::Default.expects(CPP2_UFCS_0(f, t()) == 0, "");// OK. static_assert(CPP2_UFCS_0(f, t()) == 0);// Error: Argument `f` isn't "`constexpr`". } auto main() -> int{ g(0); // g(std::identity()); // Might be OK since P2280R4 (unimplemented). } ```Output:
```output main.cpp2:7:17: error: static assertion expression is not an integral constant expression 7 | static_assert(CPP2_UFCS_0(f, t()) == 0);// Error: Argument `f` isn't "`constexpr`". | ^~~~~~~~~~~~~~~~~~~~~~~~ raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:790:38: note: expanded from macro 'CPP2_UFCS_0' 790 | #define CPP2_UFCS_0(FUNCNAME,PARAM1) \ | ^ main.cpp2:11:3: note: in instantiation of function template specialization 'g