rust-lang / rust-lang/rust-bindgen

C++20 `enum class : char8_t` enumerators are signed `i8` (`-1` instead of `255`)

Open
#3,464 0 comments 0 reactions 0 assignees View on GitHub

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_Char16u16 and CXType_Char32u32.

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.