rust-lang / rust-lang/rust-bindgen
C++20 `enum class : char8_t` enumerators are signed `i8` (`-1` instead of `255`)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with input.h using the shown bindgen invocation, then inspect Enum::from_ty and the existing build_builtin_ty handling for char16_t and char32_t. Update the enum underlying-type handling so char8_t produces unsigned 8-bit values, and verify that E_HEX is 255 while the generated bindings still compile and preserve the reported behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100