Skip to content

Generate sensible code for long double / stuff that has more than 64-bit alignment. #550

Closed
@tov

Description

@tov

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 }) }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions