Open
Description
Input C/C++ Header
namespace std {
template <typename _Tp, _Tp __v> struct integral_constant {
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const noexcept { return value; }
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
constexpr value_type operator()() const noexcept { return value; }
#endif
};
template <typename _Tp, _Tp __v>
constexpr _Tp integral_constant<_Tp, __v>::value;
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
template <bool __v> using __bool_constant = integral_constant<bool, __v>;
template <typename _Tp>
struct is_enum : public integral_constant<bool, __is_enum(_Tp)> {};
template <typename _Tp, bool = is_enum<_Tp>::value>
struct __underlying_type_impl {
using type = __underlying_type(_Tp);
};
template <typename _Tp> struct __underlying_type_impl<_Tp, false> {};
template <typename _Tp>
struct underlying_type : public __underlying_type_impl<_Tp> {};
template <typename _Tp>
using underlying_type_t = typename underlying_type<_Tp>::type;
} // namespace std
enum MyEnum : int { A, B, C };
class EnumWrapper {
std::underlying_type_t<MyEnum> inner;
};
Bindgen Invocation
bindgen::Builder::default()
.clang_args(&["-std=c++20"])
.allowlist_type("EnumWrapper")
// The input header we would like to generate
// bindings for.
.header("header.hpp")
.enable_cxx_namespaces()
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
Actual Results
running 3 tests
test root::__bindgen_test_layout_underlying_type_t_open0_MyEnum_close0_instantiation ... FAILED
test root::bindgen_test_layout_EnumWrapper ... FAILED
test test ... ok
failures:
---- root::__bindgen_test_layout_underlying_type_t_open0_MyEnum_close0_instantiation stdout ----
thread 'root::__bindgen_test_layout_underlying_type_t_open0_MyEnum_close0_instantiation' panicked at 'assertion failed: `(left == right)`
left: `1`,
right: `4`: Size of template specialization: root :: std :: underlying_type_t', /run/media/aleok/data/programming/bindgen-mre/target/debug/build/bindgen-mre-b0317d4ce440433c/out/bindings.rs:52:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- root::bindgen_test_layout_EnumWrapper stdout ----
thread 'root::bindgen_test_layout_EnumWrapper' panicked at 'assertion failed: `(left == right)`
left: `1`,
right: `4`: Size of: EnumWrapper', /run/media/aleok/data/programming/bindgen-mre/target/debug/build/bindgen-mre-b0317d4ce440433c/out/bindings.rs:29:9
This is because the bindings are incorrect and underlying_type
is incorrectly opaque:
/* automatically generated by rust-bindgen 0.59.2 */
#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
#[allow(unused_imports)]
use self::super::root;
pub mod std {
#[allow(unused_imports)]
use self::super::super::root;
pub type __underlying_type_impl_type<_Tp> = _Tp;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct underlying_type {
pub _address: u8,
}
pub type underlying_type_t = root::std::underlying_type;
}
pub const MyEnum_A: root::MyEnum = 0;
pub const MyEnum_B: root::MyEnum = 1;
pub const MyEnum_C: root::MyEnum = 2;
pub type MyEnum = ::std::os::raw::c_int;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EnumWrapper {
pub inner: root::std::underlying_type_t,
}
/* ... tests ... */
}
Expected Results
/* automatically generated by rust-bindgen 0.59.2 */
#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
#[allow(unused_imports)]
use self::super::root;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EnumWrapper {
pub inner: root::EnumWrapper_type,
}
pub type EnumWrapper_type = ::std::os::raw::c_int;
}
Note that these are actually the bindings generated if we use std::underlying_type<MyEnum>::type
instead of std::underlying_type_t<MyEnum>
! The issue happens with std::underlying_type_t
.