rust-bindgen
rust-bindgen copied to clipboard
__attribute__((aligned(__alignof__(struct {...})))) will trigger size check error
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!");
}
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.