hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.39k stars 232 forks source link

[BUG] `@enum` value can't be interpolated #872

Open JohelEGP opened 8 months ago

JohelEGP commented 8 months ago

Title: @enum value can't be interpolated.

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

command: @enum type = {
  count;
  filter;
}
main: () = {
  _ = "(command::count)$";
}

Commands: ```bash 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: Interpolation to use the generated to_string member function.

Actual result and error:

main.cpp2:6:37: error: cannot pass object of non-trivial type 'const command' through variadic function; call will abort at runtime [-Wnon-pod-varargs]
    6 |   static_cast<void>(cpp2::to_string(command::count));
      |                                     ^
1 error generated.

Cpp2 lowered to Cpp1: ```C++ //=== Cpp2 type declarations ==================================================== #include "cpp2util.h" #line 1 "/app/example.cpp2" class command; #line 2 "/app/example.cpp2" //=== Cpp2 type definitions and function declarations =========================== #line 1 "/app/example.cpp2" class command { private: cpp2::i8 _value; private: constexpr command(cpp2::in _val); private: constexpr auto operator=(cpp2::in _val) -> command& ; public: [[nodiscard]] constexpr auto get_raw_value() const& -> cpp2::i8; public: constexpr command(command const& that); public: constexpr auto operator=(command const& that) -> command& ; public: constexpr command(command&& that) noexcept; public: constexpr auto operator=(command&& that) noexcept -> command& ; public: [[nodiscard]] auto operator<=>(command const& that) const& -> std::strong_ordering = default; public: static const command count; public: static const command filter; public: [[nodiscard]] auto to_string() const& -> std::string; #line 4 "/app/example.cpp2" }; auto main() -> int; //=== Cpp2 function definitions ================================================= #line 1 "/app/example.cpp2" #line 1 "/app/example.cpp2" constexpr command::command(cpp2::in _val) : _value{ cpp2::unsafe_narrow(_val) } { } constexpr auto command::operator=(cpp2::in _val) -> command& { _value = cpp2::unsafe_narrow(_val); return *this; } [[nodiscard]] constexpr auto command::get_raw_value() const& -> cpp2::i8 { return _value; } constexpr command::command(command const& that) : _value{ that._value }{} constexpr auto command::operator=(command const& that) -> command& { _value = that._value; return *this;} constexpr command::command(command&& that) noexcept : _value{ std::move(that)._value }{} constexpr auto command::operator=(command&& that) noexcept -> command& { _value = std::move(that)._value; return *this;} inline CPP2_CONSTEXPR command command::count = 0; inline CPP2_CONSTEXPR command command::filter = 1; [[nodiscard]] auto command::to_string() const& -> std::string{ if ((*this) == count) {return "count"; } if ((*this) == filter) {return "filter"; } return "invalid command value"; } #line 5 "/app/example.cpp2" auto main() -> int{ static_cast(cpp2::to_string(command::count)); } ```
JohelEGP commented 8 months ago

There is a way to make @enum able to be interpolated (https://cpp2.godbolt.org/z/xa8oo74qK):

command: @enum type = {
  count;
  filter;
}

template<> struct std::formatter<command> : formatter<string> {
  auto format(command c, auto&& ctx) const {
    return formatter<string>::format(c.to_string(), CPP2_FORWARD(ctx));
  }
};

main: () = {
  std::cout << "(command::count:)$\n";
}

But you need contextual knowledge to add the : to the string.