diff --git a/ThunkLibs/include/common/Host.h b/ThunkLibs/include/common/Host.h index 3783dab569..d69cfd9f48 100644 --- a/ThunkLibs/include/common/Host.h +++ b/ThunkLibs/include/common/Host.h @@ -227,6 +227,13 @@ const host_layout& to_host_layout(const T& t) { return reinterpret_cast&>(t); } +template +constexpr bool is_long_or_longlong = + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v; + template struct host_layout { T* data; @@ -243,10 +250,12 @@ struct host_layout { // This is useful for handling "long"/"long long" on 64-bit, which are distinct types // but have equal data layout. template - explicit host_layout(const guest_layout& from) requires (std::is_integral_v && std::is_integral_v && sizeof(T) == sizeof(U) && std::is_same_v>, long> && std::is_convertible_v && std::is_signed_v == std::is_signed_v) : data { (T*)(uintptr_t)from.data } { - } - template - explicit host_layout(const guest_layout& from) requires (std::is_integral_v && std::is_integral_v && sizeof(T) == sizeof(U) && std::is_same_v>, long long> && std::is_convertible_v && std::is_signed_v == std::is_signed_v) : data { (T*)(uintptr_t)from.data } { + explicit host_layout(const guest_layout& from) requires (is_long_or_longlong> && std::is_integral_v && std::is_convertible_v && std::is_signed_v == std::is_signed_v +#if __clang_major__ >= 16 + // Old clang versions don't support using sizeof on incomplete types when evaluating requires() + && sizeof(T) == sizeof(U) +#endif + ) : data { (T*)(uintptr_t)from.data } { } // Allow conversion of pointers to 8-bit integer types to "char*". diff --git a/unittests/ThunkLibs/generator.cpp b/unittests/ThunkLibs/generator.cpp index d32bf53ff4..b2f6411085 100644 --- a/unittests/ThunkLibs/generator.cpp +++ b/unittests/ThunkLibs/generator.cpp @@ -305,12 +305,14 @@ SourceWithAST Fixture::run_thunkgen_host(std::string_view prelude, std::string_v " template explicit host_layout(const guest_layout&) requires (std::is_integral_v && sizeof(U) <= sizeof(T) && std::is_convertible_v && std::is_signed_v == std::is_signed_v);\n" "};\n" "\n" + "template constexpr bool is_long = std::is_same_v || std::is_same_v;\n" + "template constexpr bool is_longlong = std::is_same_v || std::is_same_v;\n" "template\n" "struct host_layout {\n" " T* data;\n" " explicit host_layout(const guest_layout&);\n" - " template explicit host_layout(const guest_layout&) requires (std::is_integral_v && std::is_integral_v && sizeof(T) == sizeof(U) && std::is_same_v>, long> && std::is_convertible_v && std::is_signed_v == std::is_signed_v);\n" - " template explicit host_layout(const guest_layout&) requires (std::is_integral_v && std::is_integral_v && sizeof(T) == sizeof(U) && std::is_same_v>, long long> && std::is_convertible_v && std::is_signed_v == std::is_signed_v);\n" + " template explicit host_layout(const guest_layout&) requires (std::is_integral_v && sizeof(U) == sizeof(long) && sizeof(long) == 8 && is_long> && std::is_convertible_v && std::is_signed_v == std::is_signed_v);\n" + " template explicit host_layout(const guest_layout&) requires (std::is_integral_v && sizeof(U) == sizeof(long long) && is_longlong> && std::is_convertible_v && std::is_signed_v == std::is_signed_v);\n" " template explicit host_layout(const guest_layout&) requires (std::is_same_v, char> && std::is_integral_v && std::is_convertible_v && sizeof(U) == 1);\n" " template explicit host_layout(const guest_layout&) requires (std::is_same_v, wchar_t> && std::is_integral_v && std::is_convertible_v && sizeof(U) == sizeof(wchar_t));\n" "};\n"