Closed
Description
Input C/C++ Header
typedef struct {
long double ld;
} max_align;
Bindgen Invokation
$ bindgen input.h > lib.rs
This is with both bindgen 0.22 and HEAD, on both of these:
- Linux stewie 4.4.0-57-generic Don't force users to manually install llvm/clang #78-Ubuntu SMP Fri Dec 9 23:50:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
- Darwin sublevel 16.4.0 Darwin Kernel Version 16.4.0: Thu Dec 22 22:53:21 PST 2016; root:xnu-3789.41.3~3/RELEASE_X86_64 x86_64
Actual Results
/* automatically generated by rust-bindgen */
#[repr(C)]
#[derive(Debug, Copy)]
pub struct max_align {
pub ld: f64,
}
#[test]
fn bindgen_test_layout_max_align() {
assert_eq!(::std::mem::size_of::<max_align>() , 16usize , concat ! (
"Size of: " , stringify ! ( max_align ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const max_align ) ) . ld as * const _ as usize
} , 0usize , concat ! (
"Alignment of field: " , stringify ! ( max_align ) , "::" ,
stringify ! ( ld ) ));
}
impl Clone for max_align {
fn clone(&self) -> Self { *self }
}
The generated test is that sizeof(max_align) == 16
. This may be true for the original C struct, but it's not true for the generated Rust struct.
Expected Results
I’m not sure how the struct should be translated, since Rust doesn’t have f80
or whatever, but even without a sane translation, the generated test should pass, right?
Does this have something to do with #468? That shows the same code (from <stddef.h>
) that led me to discover this problem. The translation that it shows includes padding that I'm not seeing.
RUST_LOG=bindgen
Output
INFO:bindgen: Clang Version: clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
WARN:bindgen: Using clang (3, 8), expected (3, 9)
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [] }) }, declaration: None, loc: None
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(max_align, kind: Record, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Some(Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(max_align, kind: Record, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Some(Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::ty: from_clang_ty: ItemId(1), ty: Type(max_align, kind: Record, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), loc: Some(Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")))
DEBUG:bindgen::ir::ty: currently_parsed_types: [PartialType { decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), id: ItemId(1) }]
DEBUG:bindgen::ir::comp: CompInfo::from_ty(Struct, Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")))
DEBUG:bindgen::ir::item: from_ty_or_ref_with_id: ItemId(2) Type(long double, kind: LongDouble, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(ld kind: FieldDecl, loc: ffi.h:2:17, usr: Some("c:@SA@max_align@FI@ld"))), Some(ItemId(1))
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(long double, kind: LongDouble, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), Some(Cursor(ld kind: FieldDecl, loc: ffi.h:2:17, usr: Some("c:@SA@max_align@FI@ld"))), Some(ItemId(1))
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: add_builtin_item: item = Item { id: ItemId(3), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("long double"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Float(LongDouble), is_const: false }) }
DEBUG:bindgen::ir::item: ItemId(3) already resolved: Some(Cursor(ld kind: FieldDecl, loc: ffi.h:2:17, usr: Some("c:@SA@max_align@FI@ld")))
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: [Field { name: Some("ld"), ty: ItemId(3), comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, bitfield: None, mutable: false, offset: Some(0) }], template_args: [], methods: [], constructors: [], base_members: [], ref_template: None, inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false }) }, declaration: Some(Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), loc: Some(Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")))
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(max_align, kind: Typedef, decl: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")), canon: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(max_align, kind: Typedef, decl: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")), canon: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), None
DEBUG:bindgen::ir::context: Not resolved, maybe builtin?
DEBUG:bindgen::ir::ty: from_clang_ty: ItemId(4), ty: Type(max_align, kind: Typedef, decl: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")), canon: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), loc: Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")))
DEBUG:bindgen::ir::ty: currently_parsed_types: [PartialType { decl: Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")), id: ItemId(4) }]
DEBUG:bindgen::ir::item: from_ty_or_ref_with_id: ItemId(5) Type(struct max_align, kind: Unexposed, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), None
DEBUG:bindgen::ir::context: builtin_or_resolved_ty: Type(struct max_align, kind: Unexposed, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), None
DEBUG:bindgen::ir::context: Already resolved ty ItemId(1), CanonicalTypeDeclaration(Type(struct max_align, kind: Unexposed, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))), Type(struct max_align, kind: Unexposed, decl: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align")), canon: Cursor( kind: StructDecl, loc: ffi.h:1:9, usr: Some("c:@SA@max_align"))) Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")))
DEBUG:bindgen::ir::context: add_builtin_item: item = Item { id: ItemId(5), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("struct max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: ResolvedTypeRef(ItemId(1)), is_const: false }) }
DEBUG:bindgen::ir::item: ItemId(5) already resolved: Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")))
DEBUG:bindgen::ir::context: BindgenContext::add_item(Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Alias(ItemId(5)), is_const: false }) }, declaration: Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align"))), loc: Some(Cursor(max_align kind: TypedefDecl, loc: ffi.h:3:3, usr: Some("c:ffi.h@T@max_align")))
DEBUG:bindgen::ir::context: No replacements to process
DEBUG:bindgen::codegen: codegen: BindgenOptions { hidden_types: RegexSet { items: [], set: Some(RegexSet([])) }, opaque_types: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_types: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_functions: RegexSet { items: [], set: Some(RegexSet([])) }, whitelisted_vars: RegexSet { items: [], set: Some(RegexSet([])) }, bitfield_enums: RegexSet { items: [], set: Some(RegexSet([])) }, constified_enums: RegexSet { items: [], set: Some(RegexSet([])) }, builtins: false, links: [], emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, disable_name_namespacing: false, derive_debug: true, derive_default: false, unstable_rust: true, use_core: false, ctypes_prefix: None, namespaced_constants: true, msvc_mangling: false, convert_floats: true, raw_lines: [], clang_args: ["-isystem", "/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0", "-isystem", "/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/x86_64-linux-gnu/c++/5.4.0", "-isystem", "/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/backward", "-isystem", "/usr/local/include", "-isystem", "/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/include", "-isystem", "/usr/include/x86_64-linux-gnu", "-isystem", "/usr/include", "ffi.h"], input_header: Some("ffi.h"), dummy_uses: None, type_chooser: None, codegen_config: CodegenConfig { functions: true, types: true, vars: true, methods: true, constructors: true }, conservative_inline_namespaces: false, generate_comments: true, whitelist_recursively: true, objc_extern_crate: false, enable_mangling: true, prepend_enum_name: true }
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [ItemId(1), ItemId(4)] }) }
DEBUG:bindgen::codegen: <Module as CodeGenerator>::codegen: item = Item { id: ItemId(0), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children_ids: [ItemId(1), ItemId(4)] }) }
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: [Field { name: Some("ld"), ty: ItemId(3), comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, bitfield: None, mutable: false, offset: Some(0) }], template_args: [], methods: [], constructors: [], base_members: [], ref_template: None, inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false }) }
DEBUG:bindgen::codegen: <Type as CodeGenerator>::codegen: item = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: [Field { name: Some("ld"), ty: ItemId(3), comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, bitfield: None, mutable: false, offset: Some(0) }], template_args: [], methods: [], constructors: [], base_members: [], ref_template: None, inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false }) }
DEBUG:bindgen::codegen: <CompInfo as CodeGenerator>::codegen: item = Item { id: ItemId(1), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: [Field { name: Some("ld"), ty: ItemId(3), comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, bitfield: None, mutable: false, offset: Some(0) }], template_args: [], methods: [], constructors: [], base_members: [], ref_template: None, inner_types: [], inner_vars: [], has_vtable: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed: false, found_unknown_attr: false, detect_derive_debug_cycle: Cell { value: false }, detect_derive_default_cycle: Cell { value: false }, detect_has_destructor_cycle: Cell { value: false }, is_forward_declaration: false }), is_const: false }) }
DEBUG:bindgen::codegen::struct_layout: Offset: <padding>: 0 -> 0
DEBUG:bindgen::codegen::struct_layout: align field ld to 0/0 with 0 padding bytes Layout { size: 16, align: 16, packed: false }
DEBUG:bindgen::codegen::struct_layout: Offset: ld: 0 -> 16
DEBUG:bindgen::codegen: <Item as CodeGenerator>::codegen: self = Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Alias(ItemId(5)), is_const: false }) }
DEBUG:bindgen::codegen: <Type as CodeGenerator>::codegen: item = Item { id: ItemId(4), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false }, parent_id: ItemId(0), kind: Type(Type { name: Some("max_align"), layout: Some(Layout { size: 16, align: 16, packed: false }), kind: Alias(ItemId(5)), is_const: false }) }