Skip to content

enum class : unsigned __int128 enumerator constants are truncated to u64 #3465

Description

@lwz23

Input C/C++ Header

enum class E : unsigned __int128 { HEX = ~(unsigned __int128)0 };
int take(E e, int t);
unsigned sz(void);

Bindgen Invocation

$ bindgen input.h --no-rustfmt-bindings --enable-cxx-namespaces -- -x c++ -std=c++17

Actual Results

The generated type is correct (u128). The generated constant is u64::MAX, not u128::MAX:

pub const E_HEX: E = 18446744073709551615;
pub type E = u128;

C++ E::HEX is all-ones in both halves. Rust E_HEX has hi = 0.

take returns (hi != 0) + (lo != 0) + t. sizeof is 16 on both sides. bindgen exit 0, rustc exit 0:

C:    v=12 lo=18446744073709551615 hi=18446744073709551615 sz=16
Rust: v=11 lo=18446744073709551615 hi=0                    sz=16

build_builtin_ty already maps CXType_UInt128IntKind::U128. enum_val_unsigned() is Option<u64> via clang_getEnumConstantDeclUnsignedValue, so the high half is dropped while still emitting a typed u128 constant.

This is not #3416 (packed bitfield accessors shifting a 65-bit window in u64).

Expected Results

E_HEX should be ~(unsigned __int128)0 as u128 (all-ones), or bindgen should not emit a silently truncated value as a u128 constant.

Environment

bindgen current main: 77cbc72
bindgen:              0.73.1
clang:                Apple clang 21.0.0
rustc:                1.97.1
target:               aarch64-apple-darwin

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions