rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

__attribute__((aligned(__alignof__(struct {...})))) will trigger size check error

Open versaloon opened this issue 3 months ago • 1 comments

bindgen version and cargo build output:

PS C:\Users\admin\Desktop\rust_test\bindgen_bug> cargo build
   Compiling bindgen_bug v0.1.0 (C:\Users\admin\Desktop\rust_test\bindgen_bug)
warning: unused import: `bugtest::*`
 --> src\main.rs:2:5
  |
2 | use bugtest::*;
  |     ^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0080]: index out of bounds: the length is 1 but the index is 4
  --> src\bugtest.rs:30:5
   |
30 |     ["Size of base_t__bindgen_ty_1"][::std::mem::size_of::<base_t__bindgen_ty_1>() - 4usize];
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `bugtest::_` failed here

error[E0080]: index out of bounds: the length is 1 but the index is 4
  --> src\bugtest.rs:37:5
   |
37 |     ["Size of base_t"][::std::mem::size_of::<base_t>() - 4usize];
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `bugtest::_` failed here

For more information about this error, try `rustc --explain E0080`.
warning: `bindgen_bug` (bin "bindgen_bug") generated 1 warning
error: could not compile `bindgen_bug` (bin "bindgen_bug") due to 2 previous errors; 1 warning emitted
PS C:\Users\admin\Desktop\rust_test\bindgen_bug> bindgen --version
bindgen 0.72.1

C header:

typedef struct base_t {
    struct {
        int aaa;
    } __attribute__((aligned(
        __alignof__(
            struct {int aaa;}
        )
    )));
} base_t;

build.rs

use std::path::Path;
use std::env;

fn main() {
    let bindings = bindgen::Builder::default()
                    .header("./test.h")
                    .generate().expect("Fail to convert test.h to rust header");
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let pathbuf = Path::new(&manifest_dir).join("./src/bugtest.rs");
    bindings.write_to_file(&pathbuf).unwrap();
}

Cargo.toml:

[package]
name = "bindgen_bug"
version = "0.1.0"
edition = "2024"

[dependencies]

[build-dependencies]
bindgen = "0.72.1"

main.rs

mod bugtest;
use bugtest::*;

fn main() {
    println!("Hello, world!");
}

versaloon avatar Sep 18 '25 18:09 versaloon

With the CLI, a bit easier:

t.h

typedef struct base_t {
    struct {
        int aaa;
    } __attribute__((aligned(
        __alignof__(
            struct {int aaa;}
        )
    )));
} base_t;

output:

/* automatically generated by rust-bindgen 0.72.0 */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct base_t {
    pub __bindgen_anon_1: base_t__bindgen_ty_1,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct base_t__bindgen_ty_1 {
    pub aaa: ::std::os::raw::c_int,
    pub __bindgen_anon_1: base_t__bindgen_ty_1__bindgen_ty_1,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct base_t__bindgen_ty_1__bindgen_ty_1 {
    pub aaa: ::std::os::raw::c_int,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of base_t__bindgen_ty_1__bindgen_ty_1"]
        [::std::mem::size_of::<base_t__bindgen_ty_1__bindgen_ty_1>() - 4usize];
    ["Alignment of base_t__bindgen_ty_1__bindgen_ty_1"]
        [::std::mem::align_of::<base_t__bindgen_ty_1__bindgen_ty_1>() - 4usize];
    ["Offset of field: base_t__bindgen_ty_1__bindgen_ty_1::aaa"][::std::mem::offset_of!(
        base_t__bindgen_ty_1__bindgen_ty_1,
        aaa
    ) - 0usize];
};
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of base_t__bindgen_ty_1"]
        [::std::mem::size_of::<base_t__bindgen_ty_1>() - 4usize];
    ["Alignment of base_t__bindgen_ty_1"]
        [::std::mem::align_of::<base_t__bindgen_ty_1>() - 4usize];
    ["Offset of field: base_t__bindgen_ty_1::aaa"]
        [::std::mem::offset_of!(base_t__bindgen_ty_1, aaa) - 0usize];
};
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of base_t"][::std::mem::size_of::<base_t>() - 4usize];
    ["Alignment of base_t"][::std::mem::align_of::<base_t>() - 4usize];
};

It seems we're incorrectly treating the struct declaration inside the attribute as a member itself...

This is the relevant code:

https://github.com/rust-lang/rust-bindgen/blob/50ec3ee0d9436ff0d6e50c5ff59bf05ef137b386/bindgen/ir/comp.rs#L1400-L1410

That condition needs to get more subtle, probably.

emilio avatar Sep 18 '25 18:09 emilio