rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.48k stars 699 forks source link

Bad bindings for empty C struct on windows #1683

Open colindr opened 5 years ago

colindr commented 5 years ago

Input C Header

struct mystruct {
};

Bindgen Invocation

This is specifically for windows. I've installed LLVM according to the documentation, and I'm setting my LIBCLANG_PATH like so (in powershell):

$env:LIBCLANG_PATH="C:\Program Files\LLVM\bin\"

Then I invoke bindgen like so:

bindgen test.h  -o src/bindings.rs

Actual Results

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct mystruct {
    pub _address: u8,
}
#[test]
fn bindgen_test_layout_mystruct() {
    assert_eq!(
        ::std::mem::size_of::<mystruct>(),
        4usize,
        concat!("Size of: ", stringify!(mystruct))
    );
    assert_eq!(
        ::std::mem::align_of::<mystruct>(),
        1usize,
        concat!("Alignment of ", stringify!(mystruct))
    );
}

Expected Results

I expected it to generate an empty rust struct, like so:

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct mystruct {}
#[test]
fn bindgen_test_layout_mystruct() {
    assert_eq!(
        ::std::mem::size_of::<mystruct>(),
        0usize,
        concat!("Size of: ", stringify!(mystruct))
    );
    assert_eq!(
        ::std::mem::align_of::<mystruct>(),
        1usize,
        concat!("Alignment of ", stringify!(mystruct))
    );
}

From this issue I understand that the _address field is supposed to be added for C++ structs, but this is a C struct. Also, the tests that are generated are incorrect, the u8 _address field is 1usize not 4usize.

I've tested this on linux and it's not a problem there.

Here are the debugging logs:

[2019-11-20T23:44:04Z INFO  bindgen] Clang Version: clang version 8.0.1 (tags/RELEASE_801/final)
[2019-11-20T23:44:04Z WARN  bindgen] Using clang (8, 0), expected (3, 9)
[2019-11-20T23:44:04Z DEBUG bindgen] Generating bindings, libclang at C:\Program Files\LLVM\bin\libclang.dll
[2019-11-20T23:44:04Z DEBUG bindgen] Trying to find clang with flags: []
[2019-11-20T23:44:05Z DEBUG bindgen] Found clang: Clang { path: "C:\\Program Files\\LLVM\\bin\\clang.exe", version: Some(CXVersion { Major: 8, Minor: 0, Subminor: 1 }), c_search_paths: Some(["C:\\Program Files\\LLVM\\lib\\clang\\8.0.1\\include", "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.23.28105\\include", "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt"]), cpp_search_paths: Some(["C:\\Program Files\\LLVM\\lib\\clang\\8.0.1\\include", "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.23.28105\\include", "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt"]) }
[2019-11-20T23:44:05Z DEBUG bindgen] Fixed-up options: BindgenOptions { blacklisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blacklisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blacklisted_items: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, opaque_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustfmt_path: None, whitelisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, whitelisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, whitelisted_vars: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_enum_style: Consts, bitfield_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_non_exhaustive_enums: RegexSet { items: [], matched: [], set: None, record_matches: false }, constified_enum_modules: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, builtins: false, emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, enable_function_attribute_detection: false, disable_name_namespacing: false, layout_tests: true, impl_debug: false, impl_partialeq: false, derive_copy: true, derive_debug: true, derive_default: false, derive_hash: false, derive_partialord: false, derive_ord: false, derive_partialeq: false, derive_eq: false, use_core: false, ctypes_prefix: None, time_phases: false, namespaced_constants: true, msvc_mangling: false, convert_floats: true, raw_lines: [], module_lines: {}, clang_args: ["-isystem", "C:\\Program Files\\LLVM\\lib\\clang\\8.0.1\\include", "-isystem", "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.23.28105\\include", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt", "test.h"], input_header: Some("test.h"), input_unsaved_files: [], parse_callbacks: None, codegen_config: FUNCTIONS | TYPES | VARS | METHODS | CONSTRUCTORS | DESTRUCTORS, conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, whitelist_recursively: true, objc_extern_crate: false, generate_block: false, block_extern_crate: false, enable_mangling: true, detect_include_paths: true, prepend_enum_name: true, rust_target: Stable_1_33, rust_features: RustFeatures { untagged_union: true, associated_const: true, builtin_clone_impls: true, repr_align: true, i128_and_u128: true, must_use_function: true, repr_transparent: true, min_const_fn: true, repr_packed_n: true, thiscall_abi: false, non_exhaustive: false }, record_matches: true, rustfmt_bindings: true, rustfmt_configuration_file: None, no_partialeq_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_copy_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_hash_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, array_pointers_in_arguments: false }
[2019-11-20T23:44:05Z DEBUG bindgen::ir::item] Item::from_ty_with_id: ItemId(1)
        ty = Type(struct mystruct, kind: Record, cconv: 100, decl: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")), canon: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))),
        location = Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] builtin_or_resolved_ty: Type(struct mystruct, kind: Record, cconv: 100, decl: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")), canon: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), Some(Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), Some(ItemId(0))
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] Not resolved, maybe builtin?
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] builtin_or_resolved_ty: Type(struct mystruct, kind: Record, cconv: 100, decl: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")), canon: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), Some(Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), Some(ItemId(0))
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] Not resolved, maybe builtin?
[2019-11-20T23:44:05Z DEBUG bindgen::ir::ty] from_clang_ty: ItemId(1), ty: Type(struct mystruct, kind: Record, cconv: 100, decl: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")), canon: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), loc: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))
[2019-11-20T23:44:05Z DEBUG bindgen::ir::ty] currently_parsed_types: [PartialType { decl: Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")), id: ItemId(1) }]
[2019-11-20T23:44:05Z DEBUG bindgen::ir::comp] CompInfo::from_ty(Struct, Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")))
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Type(Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: BeforeComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }) }, declaration: Some(Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct"))), loc: Some(Cursor(mystruct kind: StructDecl, loc: test.h:1:8, usr: Some("c:@S@mystruct")))
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] add_item_to_module: adding ItemId(1) as child of parent module ItemId(0)
[2019-11-20T23:44:05Z DEBUG bindgen::ir::context] No replacements to process
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_vtable] constrain ItemId(1)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_vtable]     comp considers its own methods and bases
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_vtable] constrain ItemId(0)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::sizedness] constrain TypeId(ItemId(1))
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::sizedness]     comp considers its own fields and bases
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::sizedness] inserting ZeroSized for TypeId(ItemId(1))
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params] constrain ItemId(1)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]   initially, used set is {}
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]     other item: join with successors' usage
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]   finally, used set is {}
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params] constrain ItemId(0)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]   initially, used set is {}
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]     other item: join with successors' usage
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::template_params]   finally, used set is {}
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] constrain: ItemId(1)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] ty: Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive]     can derive Debug because there are no members
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] inserting ItemId(1) can_derive<Debug>=Yes
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] constrain: ItemId(0)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive]     can derive Debug because there are no members
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] inserting ItemId(0) can_derive<Debug>=Yes
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] constrain: ItemId(1)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] ty: Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive]     can derive Copy because there are no members
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] inserting ItemId(1) can_derive<Copy>=Yes
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] constrain: ItemId(0)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive]     can derive Copy because there are no members
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::derive] inserting ItemId(0) can_derive<Copy>=Yes
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_type_param_in_array] constrain: ItemId(1)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_type_param_in_array]     comp doesn't have array
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_type_param_in_array] constrain: ItemId(0)
[2019-11-20T23:44:05Z TRACE bindgen::ir::analysis::has_type_param_in_array]     not a type; ignoring
[2019-11-20T23:44:05Z DEBUG bindgen::codegen] codegen: BindgenOptions { blacklisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blacklisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, blacklisted_items: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, opaque_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustfmt_path: None, whitelisted_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, whitelisted_functions: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, whitelisted_vars: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, default_enum_style: Consts, bitfield_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, rustified_non_exhaustive_enums: RegexSet { items: [], matched: [], set: None, record_matches: false }, constified_enum_modules: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, constified_enums: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, builtins: false, emit_ast: false, emit_ir: false, emit_ir_graphviz: None, enable_cxx_namespaces: false, enable_function_attribute_detection: false, disable_name_namespacing: false, layout_tests: true, impl_debug: false, impl_partialeq: false, derive_copy: true, derive_debug: true, derive_default: false, derive_hash: false, derive_partialord: false, derive_ord: false, derive_partialeq: false, derive_eq: false, use_core: false, ctypes_prefix: None, time_phases: false, namespaced_constants: true, msvc_mangling: false, convert_floats: true, raw_lines: [], module_lines: {}, clang_args: ["-isystem", "C:\\Program Files\\LLVM\\lib\\clang\\8.0.1\\include", "-isystem", "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.23.28105\\include", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.18362.0\\ucrt", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\um", "-isystem", "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\winrt", "test.h"], input_header: Some("test.h"), input_unsaved_files: [], parse_callbacks: None, codegen_config: FUNCTIONS | TYPES | VARS | METHODS | CONSTRUCTORS | DESTRUCTORS, conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, whitelist_recursively: true, objc_extern_crate: false, generate_block: false, block_extern_crate: false, enable_mangling: true, detect_include_paths: true, prepend_enum_name: true, rust_target: Stable_1_33, rust_features: RustFeatures { untagged_union: true, associated_const: true, builtin_clone_impls: true, repr_align: true, i128_and_u128: true, must_use_function: true, repr_transparent: true, min_const_fn: true, repr_packed_n: true, thiscall_abi: false, non_exhaustive: false }, record_matches: true, rustfmt_bindings: true, rustfmt_configuration_file: None, no_partialeq_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_copy_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, no_hash_types: RegexSet { items: [], matched: [], set: Some(RegexSet([])), record_matches: true }, array_pointers_in_arguments: false }
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children: {ItemId(1)} }) }
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Module(Module { name: Some("root"), kind: Normal, children: {ItemId(1)} }) }
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Type(Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }) }
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Type(Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }) }
[2019-11-20T23:44:05Z 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, derives: [] }, parent_id: ItemId(0), kind: Type(Type { name: Some("mystruct"), layout: Some(Layout { size: 4, align: 1, packed: false }), kind: Comp(CompInfo { kind: Struct, fields: AfterComputingBitfieldUnits([]), template_params: [], methods: [], constructors: [], destructor: None, base_members: [], inner_types: [], inner_vars: [], has_own_virtual_method: false, has_destructor: false, has_nonempty_base: false, has_non_type_template_params: false, packed_attr: false, found_unknown_attr: false, is_forward_declaration: false }), is_const: false }) }
emilio commented 5 years ago

In C all structs need to have a different address. It is unexpected that the size is four in windows though...

colindr commented 5 years ago

I was expecting it to not have an _address field because that is what is generated on Linux. The "Expected Results" in the issue is the output that I get when I run bindgen on Linux with the same input.

emilio commented 5 years ago

Ah, I didn't notice that... That's weird indeed, probably MSVC has a different ABI than gcc for empty structs and we're choking on it.

LunarLambda commented 3 years ago

It is worth mentioning that the C standard makes empty structs UB.

(C11, 6.7.2.1 Structure and union specifiers p8) "If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined."

MSVC seems to reject this outright, GCC makes it size zero. In C++, however, empty structs are valid and always 1 byte. (MSVC, GCC)

Not sure what clang says on Windows. Might mimick GCC's behaviour. It'd probably be best to reject empty C structs altogether

Dushistov commented 3 years ago

rustc also has problems with repr(C) and MSVC: rust-lang/rust#81996