cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] cppfront generates illegal code in an inspect returning a struct

Open threeifbyair opened this issue 1 year ago • 3 comments

If I declare a struct, and then use it as the result of an inspect, cppfront generates code constructing the struct with no arguments -- and there's no way to declare an operator= with no arguments in a struct!

Steps to reproduce the behavior:

https://cpp2.godbolt.org/z/K6f9h9qjx

action: @struct type = {
    dx: int;
    dy: int;
}

testfn: (x: int, y: int) -> action = {
    return inspect (x,y) -> action {
        is (0, 0) = action(1, 0);
        is (0, 1) = action(0, 1);
        is _      = action(1, 1);
    };
}

cppfront generates this as the definition of action:

class action {
    public: int dx; 
    public: int dy; 
    public: action(auto&& dx_, auto&& dy_)
CPP2_REQUIRES_ (std::is_convertible_v<CPP2_TYPEOF(dx_), std::add_const_t<int>&> && std::is_convertible_v<CPP2_TYPEOF(dy_), std::add_const_t<int>&>) ;

};

and this as the definition of testfn:

[[nodiscard]] auto testfn(cpp2::impl::in<int> x, cpp2::impl::in<int> y) -> action{
    return [&] () -> action { auto&& _expr = (x, y);
        if (cpp2::impl::is(_expr, (0, 0))) { if constexpr( requires{action(1, 0);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((action(1, 0))),action> ) return action(1, 0); else return action{}; else return action{}; }
        else if (cpp2::impl::is(_expr, 0, 1)) { if constexpr( requires{action(0, 1);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((action(0, 1))),action> ) return action(0, 1); else return action{}; else return action{}; }
        else return action(1, 1); }
    (); 
}

Obviously action{} is a zero-parameter constructor, and action doesn't have any zero-argument constructors. (And even if I ensure that action{} is on a code path never taken, both gcc 14 and Clang 19 try to compile it and throw an error.)

threeifbyair avatar Dec 07 '24 01:12 threeifbyair