Input C/C++ Header
enum class E : char8_t { HEX = u8'\xFF', A = u8'A' };
enum class U : unsigned char { HEX = 255 };
int takeE(E e, int t);
int takeU(U e, int t);
unsigned sz(void);
Bindgen Invocation
$ bindgen input.h --no-rustfmt-bindings --enable-cxx-namespaces -- -x c++ -std=c++20
Actual Results
char8_t is unsigned in C++20. A char8_t parameter is already u8. enum class : unsigned char with value 255 is 255 / c_uchar on both sides.
Only enum underlying char8_t is signed:
pub const E_HEX: E = -1;
pub const E_A: E = 65;
pub type E = i8;
pub const U_HEX: U = 255;
pub type U = ::std::os::raw::c_uchar;
C++ (int)E::HEX is 255. Rust E_HEX as i32 is -1. sizeof is 1 on both sides. bindgen exit 0, rustc exit 0.
takeE(E::HEX, 10) is 265 on both sides (the callee still sees bits 0xFF). The generated constant is the silent C-to-Rust meaning error.
libclang has no CXType_Char8; char8_t is CXType_Unexposed. clang_getEnumConstantDeclUnsignedValue for HEX is already 255; bindgen takes the signed API because Enum::from_ty defaults is_signed = true when the Unexposed underlying type does not resolve to an Int. build_builtin_ty already maps CXType_Char16 → u16 and CXType_Char32 → u32.
This is not #2475 (unicode character macros failing to parse).
Expected Results
enum class : char8_t should be an unsigned 8-bit type, with E_HEX = 255, matching C++ and matching how bindgen already treats char16_t / char32_t / unsigned char.
Environment
bindgen current main: 77cbc72
bindgen: 0.73.1
clang: Apple clang 21.0.0
rustc: 1.97.1
target: aarch64-apple-darwin
Input C/C++ Header
Bindgen Invocation
$ bindgen input.h --no-rustfmt-bindings --enable-cxx-namespaces -- -x c++ -std=c++20Actual Results
char8_tis unsigned in C++20. Achar8_tparameter is alreadyu8.enum class : unsigned charwith value 255 is255/c_ucharon both sides.Only enum underlying
char8_tis signed:C++
(int)E::HEXis 255. RustE_HEX as i32is -1.sizeofis 1 on both sides. bindgen exit 0, rustc exit 0.takeE(E::HEX, 10)is 265 on both sides (the callee still sees bits0xFF). The generated constant is the silent C-to-Rust meaning error.libclang has no
CXType_Char8;char8_tisCXType_Unexposed.clang_getEnumConstantDeclUnsignedValueforHEXis already 255; bindgen takes the signed API becauseEnum::from_tydefaultsis_signed = truewhen the Unexposed underlying type does not resolve to anInt.build_builtin_tyalready mapsCXType_Char16→u16andCXType_Char32→u32.This is not #2475 (unicode character macros failing to parse).
Expected Results
enum class : char8_tshould be an unsigned 8-bit type, withE_HEX = 255, matching C++ and matching how bindgen already treatschar16_t/char32_t/unsigned char.Environment