Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enum and define with the same name collide #687

Closed
deweerdt opened this issue May 3, 2017 · 26 comments
Closed

enum and define with the same name collide #687

deweerdt opened this issue May 3, 2017 · 26 comments

Comments

@deweerdt
Copy link

deweerdt commented May 3, 2017

Input C/C++ Header

enum {
        A =
#define A 0
                A,
} anenum;

Bindgen Invokation

bindgen::Builder::default()
    .header("input.h")
    .generate()
    .unwrap()

Actual Results

       Fresh bindgen v0.23.1                                                                                                                                                                                                                                                                                                        Compiling math_dot_h v0.1.0 (file:///home/def/p/rust/math_dot_h)
     Running `rustc --crate-name math_dot_h src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=93892b9e7e7b815c -C extra-filename=-93892b9e7e7b815c --out-dir /home/def/p/rust/math_dot_h/target/debug/deps -L dependency=/home/def/p/rust/math_dot_h/target/debug/deps`
error[E0428]: a value named `A` has already been defined in this module
 --> /home/def/p/rust/math_dot_h/target/debug/build/math_dot_h-7f0a85db403a8610/out/bindings.rs:4:1
  |
3 | pub const A: ::std::os::raw::c_uint = 0;
  | ---------------------------------------- previous definition of `A` here
4 | pub const A: _bindgen_ty_1 = _bindgen_ty_1::A;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` already defined

error: aborting due to previous error

error: Could not compile `math_dot_h`.

Caused by:
  process didn't exit successfully: `rustc --crate-name math_dot_h src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=93892b9e7e7b815c -C extra-filename=-93892b9e7e7b815c --out-dir /home/def/p/rust/math_dot_h/target/debug/deps -L dependency=/home/def/p/rust/math_dot_h/target/debug/deps` (exit code: 101)

Expected Results

No compilation error, both the enum and the define have their own name space.

This is problematic IRL because math.h uses this construct to define FP_* constants:
https://sourceware.org/git/?p=glibc.git;a=blob;f=math/math.h;h=cfaed0ed98013830421afdf1ba6f13c01702831d;hb=HEAD#l318

enum                                                                                                                                                                                                                                                                                                                               {                                                                                                                                                                                                                                                                                                                                  FP_NAN =                                                                                                                                                                                                                                                                                                                     # define FP_NAN 0                                                                                                                                                                                                                                                                                                                      FP_NAN,                                                                                                                                                                                                                                                                                                                        FP_INFINITE =                                                                                                                                                                                                                                                                                                                # define FP_INFINITE 1                                                                                                                                                                                                                                                                                                                 FP_INFINITE,
    FP_ZERO =
# define FP_ZERO 2
      FP_ZERO,
    FP_SUBNORMAL =
# define FP_SUBNORMAL 3
      FP_SUBNORMAL,
    FP_NORMAL =
# define FP_NORMAL 4
      FP_NORMAL
  };

RUST_LOG=bindgen Output

   Compiling math_dot_h v0.1.0 (file:///home/def/p/rust/math_dot_h)
error[E0428]: a value named `A` has already been defined in this module
 --> /home/def/p/rust/math_dot_h/target/debug/build/math_dot_h-7f0a85db403a8610/out/bindings.rs:4:1
  |
3 | pub const A: ::std::os::raw::c_uint = 0;
  | ---------------------------------------- previous definition of `A` here
4 | pub const A: _bindgen_ty_1 = _bindgen_ty_1::A;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` already defined

error: aborting due to previous error

error: Could not compile `math_dot_h`.

To learn more, run the command again with --verbose.
@emilio
Copy link
Contributor

emilio commented May 3, 2017

That's... nasty...

What would be a good solution for this? I can allow you to ignore a given macro by name with a new method in ParseCallbacks, would that work for you?

@emilio emilio added the bug label May 3, 2017
@emilio
Copy link
Contributor

emilio commented May 3, 2017

To be more clear, I'm thinking in something like macro_parsing_behavior(&self, name: &str) -> MacroParsingBehavior.

with something like:

enum MacroParsingBehavior {
    TryToEvaluate,
    Ignore,
}

Or something like that.

@deweerdt
Copy link
Author

deweerdt commented May 3, 2017

Thanks for your quick response!

If i understand correctly, you're suggesting that i return Ignore for the definitions I know will also be used as defines? I believe that will work for me, yes.

In general, it feels like the two definitions should belong to two different namespaces, but i don't know enough about bindgen to suggest anything beyond offering my opinion.

@emilio
Copy link
Contributor

emilio commented May 3, 2017

Yeah, it's a kind of unfortunate trade-off between ease to use and features... In general bindgen doesn't need to do a lot of deduplicating at the root level because rust allows to differentiate struct foo {} from fn foo, and similar stuff.

We could either mangle stuff like enum_foo, struct_bar, etc... but that'd be really annoying, specially for C++ users... Oh well.

@retrry
Copy link

retrry commented Jul 21, 2017

I've started seeing this behavior on bindgen 0.26. While bindgen 0.25 generated code without errors. Bindgen 0.26 started giving me errors:

error[E0428]: the name `FP_NAN` is defined multiple times
    --> /home/target/debug/build/ffmpeg-sys-026db31dcba0e79a/out/bindings.rs:2820:1
     |
491  | pub const FP_NAN: libc::c_int = 0;
     | ---------------------------------- previous definition of the value `FP_NAN` here
...
2820 | pub const FP_NAN: _bindgen_ty_1 = _bindgen_ty_1::FP_NAN;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_NAN` redefined here
     |
     = note: `FP_NAN` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_INFINITE` is defined multiple times
    --> /home/target/debug/build/ffmpeg-sys-026db31dcba0e79a/out/bindings.rs:2821:1
     |
492  | pub const FP_INFINITE: libc::c_int = 1;
     | --------------------------------------- previous definition of the value `FP_INFINITE` here
...
2821 | pub const FP_INFINITE: _bindgen_ty_1 = _bindgen_ty_1::FP_INFINITE;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_INFINITE` redefined here
     |
     = note: `FP_INFINITE` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_ZERO` is defined multiple times
    --> /home/target/debug/build/ffmpeg-sys-026db31dcba0e79a/out/bindings.rs:2822:1
     |
493  | pub const FP_ZERO: libc::c_int = 2;
     | ----------------------------------- previous definition of the value `FP_ZERO` here
...
2822 | pub const FP_ZERO: _bindgen_ty_1 = _bindgen_ty_1::FP_ZERO;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_ZERO` redefined here
     |
     = note: `FP_ZERO` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_SUBNORMAL` is defined multiple times
    --> /home/target/debug/build/ffmpeg-sys-026db31dcba0e79a/out/bindings.rs:2823:1
     |
494  | pub const FP_SUBNORMAL: libc::c_int = 3;
     | ---------------------------------------- previous definition of the value `FP_SUBNORMAL` here
...
2823 | pub const FP_SUBNORMAL: _bindgen_ty_1 = _bindgen_ty_1::FP_SUBNORMAL;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_SUBNORMAL` redefined here
     |
     = note: `FP_SUBNORMAL` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_NORMAL` is defined multiple times
    --> /home/target/debug/build/ffmpeg-sys-026db31dcba0e79a/out/bindings.rs:2824:1
     |
495  | pub const FP_NORMAL: libc::c_int = 4;
     | ------------------------------------- previous definition of the value `FP_NORMAL` here
...
2824 | pub const FP_NORMAL: _bindgen_ty_1 = _bindgen_ty_1::FP_NORMAL;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_NORMAL` redefined here
     |
     = note: `FP_NORMAL` must be defined only once in the value namespace of this module

error: aborting due to 5 previous errors

error: Could not compile `ffmpeg-sys`.

As a workaround I'm just ignoring those types:

        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL")

@gentoo90
Copy link

gentoo90 commented Aug 18, 2017

I've encountered the same error with bindgen-0.25.5 and clang-4.0.0 on linux.
Crate magick-rust.

$ LIBCLANG_PATH=/usr/lib/llvm/4/lib64 cargo build
   Compiling magick_rust v0.6.6 (file:///home/user/magick-rust)
    --> /home/user/magick-rust/target/debug/build/magick_rust-9bda580053656820/out/bindings.rs:4825:1
     |
747  | pub const FP_NAN: libc::c_uint = 0;
     | ----------------------------------- previous definition of the value `FP_NAN` here
...
4825 | pub const FP_NAN: _bindgen_ty_1 = _bindgen_ty_1::FP_NAN;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_NAN` redefined here
     |
     = note: `FP_NAN` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_INFINITE` is defined multiple times
    --> /home/user/magick-rust/target/debug/build/magick_rust-9bda580053656820/out/bindings.rs:4826:1
     |
748  | pub const FP_INFINITE: libc::c_uint = 1;
     | ---------------------------------------- previous definition of the value `FP_INFINITE` here
...
4826 | pub const FP_INFINITE: _bindgen_ty_1 = _bindgen_ty_1::FP_INFINITE;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_INFINITE` redefined here
     |
     = note: `FP_INFINITE` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_ZERO` is defined multiple times
    --> /home/user/magick-rust/target/debug/build/magick_rust-9bda580053656820/out/bindings.rs:4827:1
     |
749  | pub const FP_ZERO: libc::c_uint = 2;
     | ------------------------------------ previous definition of the value `FP_ZERO` here
...
4827 | pub const FP_ZERO: _bindgen_ty_1 = _bindgen_ty_1::FP_ZERO;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_ZERO` redefined here
     |
     = note: `FP_ZERO` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_SUBNORMAL` is defined multiple times
    --> /home/user/magick-rust/target/debug/build/magick_rust-9bda580053656820/out/bindings.rs:4828:1
     |
750  | pub const FP_SUBNORMAL: libc::c_uint = 3;
     | ----------------------------------------- previous definition of the value `FP_SUBNORMAL` here
...
4828 | pub const FP_SUBNORMAL: _bindgen_ty_1 = _bindgen_ty_1::FP_SUBNORMAL;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_SUBNORMAL` redefined here
     |
     = note: `FP_SUBNORMAL` must be defined only once in the value namespace of this module

error[E0428]: the name `FP_NORMAL` is defined multiple times
    --> /home/user/magick-rust/target/debug/build/magick_rust-9bda580053656820/out/bindings.rs:4829:1
     |
751  | pub const FP_NORMAL: libc::c_uint = 4;
     | -------------------------------------- previous definition of the value `FP_NORMAL` here
...
4829 | pub const FP_NORMAL: _bindgen_ty_1 = _bindgen_ty_1::FP_NORMAL;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `FP_NORMAL` redefined here
     |
     = note: `FP_NORMAL` must be defined only once in the value namespace of this module

@spacekookie
Copy link
Member

Is there any update or progress on fixing this issue? I'm only affected by it via an external dependency so manually tweaking bindgen settings isn't really an option for me. And this is currently blocking a project 😞

@fitzgen
Copy link
Member

fitzgen commented Dec 4, 2017

I could imagine the BindgenContext carrying a map of name -> counter and writing a new pass over the IR right before codegen that bumps the appropriate entry's counter for each definition of any kind, and then appending the counter to the definition's name when its not the first time we've seen that name.

Essentially, moving our method/function overloading strategy up and out of codegen and use it for all definitions.

This should also solve #840

If anyone is interested in trying their hand at this, I can help mentor (cc @spacekookie )

@spacekookie
Copy link
Member

Hey @fitzgen, I mean...I'd love to have a try at fixing this though I've only been writing Rust for ~2 months now and I'm rather green, especially when it comes to large Rust projects. If you're offering to mentor though, maybe get in touch with me via twitter or e-mail?

@emilio
Copy link
Contributor

emilio commented Jan 30, 2018

I just noticed that there's a way to properly handling this hiding the enum instead of the constant with ParseCallbacks::enum_variant_behavior. Will add the symmetric API for macros, and then I think we can call it fixed. Of course we may want to expose that to the cli somehow, but that can be another issue.

emilio added a commit to emilio/rust-bindgen that referenced this issue Jan 30, 2018
emilio added a commit to emilio/rust-bindgen that referenced this issue Jan 30, 2018
This is symmetric, yet less powerful, than enum_variant_behavior.

Fixes rust-lang#687.
emilio added a commit to emilio/rust-bindgen that referenced this issue Jan 30, 2018
This is symmetric, yet less powerful, than enum_variant_behavior.

Fixes rust-lang#687.
emilio added a commit to emilio/rust-bindgen that referenced this issue Jan 30, 2018
This is symmetric, yet less powerful, than enum_variant_behavior.

Fixes rust-lang#687.
bors-servo pushed a commit that referenced this issue Jan 31, 2018
callbacks: Introduce MacroParsingBehavior to allow ignoring macros.

This is symmetric, yet less powerful, than enum_variant_behavior.

Fixes #687.
@trsh
Copy link

trsh commented May 10, 2018

@bors-servo why is this closed? Still having those issues!

@emilio
Copy link
Contributor

emilio commented May 11, 2018

Yes, but now you have a way to avoid them, using MacroParsingBehavior to avoid the relevant macros.

@xxks-kkk
Copy link

Hello @emilio ,

Can you please shed some lights on how to use MacroParsingBehavior? I'm new to Rust and bindgen and I just followed the tutorial to generate the bindings. I got the two following definitions

pub const IPPORT_RESERVED: ::std::os::raw::c_uint = 1024;
pub const IPPORT_RESERVED: _bindgen_ty_7 = _bindgen_ty_7::IPPORT_RESERVED;

However, none of them are part of my orginal C code. I'm wondering how can I fix this issue?

Thanks much!

@emilio
Copy link
Contributor

emilio commented Aug 28, 2018

You can either add a ParseCallbacks implementation returning MacroParsingBehavior::Ignore like:

https://github.com/rust-lang-nursery/rust-bindgen/blob/14da023687b36db480c42f924ec8d236faf1577a/bindgen-integration/build.rs#L21

Or if you don't care about that particular enum either, you could do something like blacklist_type("IPPORT_.*"), which should work given it's an anonymous enum I'd think.

@xxks-kkk
Copy link

xxks-kkk commented Aug 28, 2018

Hello @emilio ,

Thanks for the response. Now, I use blacklist_type("IPPORT_.*") inside my build.rs but then I run cargo test, I got two test cases failure:

    bindgen_test_layout_spdk_nvme_feat_async_event_configuration
    bindgen_test_layout_spdk_nvme_feat_async_event_configuration__bindgen_ty_1

I take a look at the bindings generated:

/// Data used by Set Features / Get Features \ref SPDK_NVME_FEAT_ASYNC_EVENT_CONFIGURATION
#[repr(C)]
#[derive(Copy, Clone)]
pub union spdk_nvme_feat_async_event_configuration { pub raw: u32, pub bits: spdk_nvme_feat_async_event_configuration__bindgen_ty_1, _bindgen_union_align: u32 }

#[repr(C)]
#[derive(Copy, Clone)]
pub struct spdk_nvme_feat_async_event_configuration__bindgen_ty_1 { pub crit_warn: spdk_nvme_critical_warning_state, pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u32>, pub __bindgen_align: [u32; 0usize] }

The original data structure in C looks like

/**
 * Data used by Set Features / Get Features \ref SPDK_NVME_FEAT_ASYNC_EVENT_CONFIGURATION
 */
union spdk_nvme_feat_async_event_configuration {
	uint32_t raw;
	struct {
		union spdk_nvme_critical_warning_state crit_warn;
		uint32_t ns_attr_notice		: 1;
		uint32_t fw_activation_notice	: 1;
		uint32_t telemetry_log_notice	: 1;
		uint32_t reserved		: 21;
	} bits;
};

There is also an assertion immediately follows the struct definition above:

SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_async_event_configuration) == 4, "Incorrect size");

The full stacktrace I got for the error:

   0:     0x559d9711d3be - std::sys::unix::backtrace::tracing::imp::unwind_backtrace::h845003dfd4057b58test bindgen_test_layout_spdk_nvme_feat_async_event_configuration ... 
FAILED
                               at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x559d971101b6 - std::sys_common::backtrace::print::he21204c91f031ba1
                               at libstd/sys_common/backtrace.rs:71
                               at libstd/sys_common/backtrace.rs:59
   2:     0x559d9710e24d - std::panicking::default_hook::{{closure}}::h67eac88e3f053d87
                               at libstd/panicking.rs:211
   3:     0x559d9710dfc0 - std::panicking::default_hook::hb9cbad724f559203
                               at libstd/panicking.rs:227
   4:     0x559d9710e8ec - std::panicking::rust_panic_with_hook::he4c3a67f6258a8f9
                               at libstd/panicking.rs:511
   5:     0x559d9710e699 - std::panicking::continue_panic_fmt::h156c04b2aea348c7
                               at libstd/panicking.rs:426
   6:     0x559d9710e5fd - std::panicking::begin_panic_fmt::h6c68b0cc82493124
                               at libstd/panicking.rs:413
   7:     0x559d97095f71 - rust_spdk::bindgen_test_layout_spdk_nvme_feat_async_event_configuration__bindgen_ty_1::h790a96593e87278e
                               at /home/zeyuanhu/rustfs/rust-spdk/target/debug/build/rust-spdk-3c1fe41f551c8d38/out/bindings.rs:13938
   8:     0x559d970cc389 - rust_spdk::__test::TESTS::{{closure}}::h43346ec73ce3a2a7
                               at /home/zeyuanhu/rustfs/rust-spdk/target/debug/build/rust-spdk-3c1fe41f551c8d38/out/bindings.rs:13937
   9:     0x559d96fbca4d - core::ops::function::FnOnce::call_once::h15018e8620f494d0
                               at /checkout/src/libcore/ops/function.rs:223
  10:     0x559d970cfebe - <F as alloc::boxed::FnBox<A>>::call_box::h35131d468a43c8d1
                               at libtest/lib.rs:1451
                               at /checkout/src/libcore/ops/function.rs:223
                               at /checkout/src/liballoc/boxed.rs:640
  11:     0x559d9712a9d9 - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:105
  12:     0x559d970ec61d - std::sys_common::backtrace::__rust_begin_short_backtrace::h02641c0f08c89101
                               at /checkout/src/libstd/panicking.rs:289
                               at /checkout/src/libstd/panic.rs:392
                               at libtest/lib.rs:1406
                               at /checkout/src/libstd/sys_common/backtrace.rs:136
  13:     0x559d970f1414 - std::panicking::try::do_call::h1d3083628cca3de7
                               at /checkout/src/libstd/thread/mod.rs:409
                               at /checkout/src/libstd/panic.rs:308
                               at /checkout/src/libstd/panicking.rs:310
  14:     0x559d9712a9d9 - __rust_maybe_catch_panic
                               at libpanic_unwind/lib.rs:105
  15:     0x559d970e2aa6 - <F as alloc::boxed::FnBox<A>>::call_box::h2f7e4058ba7bf228
                               at /checkout/src/libstd/panicking.rs:289
                               at /checkout/src/libstd/panic.rs:392
                               at /checkout/src/libstd/thread/mod.rs:408
                               at /checkout/src/liballoc/boxed.rs:640
  16:     0x559d9710c6ca - std::sys_common::thread::start_thread::h88a639c99862a9f5
                               at /checkout/src/liballoc/boxed.rs:650
                               at libstd/sys_common/thread.rs:24
  17:     0x559d9710f3f5 - std::sys::unix::thread::Thread::new::thread_start::h7d7a420a78cfa84d
                               at libstd/sys/unix/thread.rs:90
  18:     0x7f08b9ed06b9 - start_thread
  19:     0x7f08b99ef41c - clone
  20:                0x0 - <unknown>
test bindgen_test_layout_spdk_nvme_feat_async_event_configuration__bindgen_ty_1 ... FAILED

Here is the assertion failure:

thread 'bindgen_test_layout_spdk_nvme_feat_async_event_configuration' panicked at 'assertion failed: `(left == right)`
  left: `8`,
 right: `4`: Size of: spdk_nvme_feat_async_event_configuration', /home/zeyuanhu/rustfs/rust-spdk/target/debug/build/rust-spdk-3c1fe41f551c8d38/out/bindings.rs:14005:5
thread 'bindgen_test_layout_spdk_nvme_feat_async_event_configuration__bindgen_ty_1' panicked at 'assertion failed: `(left == right)`
  left: `8`,
 right: `4`: Size of: spdk_nvme_feat_async_event_configuration__bindgen_ty_1', /home/zeyuanhu/rustfs/rust-spdk/target/debug/build/rust-spdk-3c1fe41f551c8d38/out/bindings.rs:13938:5

The corresponding test is

#[test]
fn bindgen_test_layout_spdk_nvme_feat_async_event_configuration() {
    assert_eq!(::std::mem::size_of::<spdk_nvme_feat_async_event_configuration>(), 4usize, concat!( "Size of: " , stringify ! ( spdk_nvme_feat_async_event_configuration ) ));
    assert_eq!(::std::mem::align_of::<spdk_nvme_feat_async_event_configuration>(), 4usize, concat!( "Alignment of " , stringify ! ( spdk_nvme_feat_async_event_configuration ) ));
    assert_eq!(unsafe { &(*(::std::ptr::null::<spdk_nvme_feat_async_event_configuration>())).raw as *const _ as usize }, 0usize, concat!( "Offset of field: " , stringify ! ( spdk_nvme_feat_async_event_configuration ) , "::" , stringify ! ( raw ) ));
    assert_eq!(unsafe { &(*(::std::ptr::null::<spdk_nvme_feat_async_event_configuration>())).bits as *const _ as usize }, 0usize, concat!( "Offset of field: " , stringify ! ( spdk_nvme_feat_async_event_configuration ) , "::" , stringify ! ( bits ) ));
}

Is there anything special I should pay attention regarding bindgen when dealing with the structure I have in C? What are possible places I should look for to fix the error?

Thanks!

@emilio
Copy link
Contributor

emilio commented Aug 29, 2018

Hi @xxks-kkk, that makes sense. Those tests failing mean that the struct is unsafe to use from Rust. max_align_t is known (#605), and you should just blacklist_type("max_align_t") or use repr(align) via rust_target(Stable_1_25) for now, given otherwise we can't generate a sufficiently aligned type.

The other case looks a bit more problematic. You can mark them as opaque (via opaque_type) so bindgen generates the right layout, but that probably deserves a bit of look on its own, we're probably messing up the bitfield calculations. Chances are #1326 could fix it.

Mind filing a new issue about that, with the code snippet you posted plus the definition of spdk_nvme_critical_warning_state (and the definitions needed for that and such)? Thinks!

@xxks-kkk
Copy link

Hello @emilio , sorry for the delay. I created issue #1377 to track the problem we have discussed here. Please let me know any information you need from me. Also, I'm wondering if opaque_type will have any side effects in terms of using the structure inside Rust?

Thanks!

@emilio
Copy link
Contributor

emilio commented Aug 31, 2018

Yes, opaque_type will make it sort of unusable inside rust, it'll make it a blob of bytes.

@stillinbeta
Copy link

For future discoverers of this issue, I'm using this code:

#[derive(Debug)]
struct IgnoreMacros(HashSet<String>);

impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
    fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
        if self.0.contains(name) {
            bindgen::callbacks::MacroParsingBehavior::Ignore
        } else {
            bindgen::callbacks::MacroParsingBehavior::Default
        }
    }
}

Initialized as

let ignored_macros = IgnoreMacros(
            vec![
                "FP_INFINITE".into(),
                "FP_NAN".into(),
                "FP_NORMAL".into(),
                "FP_SUBNORMAL".into(),
                "FP_ZERO".into(),
                "IPPORT_RESERVED".into(),
            ]
            .into_iter()
            .collect(),
        );

and called as

    .header("wrapper.h")
            .parse_callbacks(Box::new(ignored_macros))
            .rustfmt_bindings(true)

@CommanderTvis
Copy link

Reproduced this issue. What's the workaround of it?
image

@db48x
Copy link
Contributor

db48x commented Jan 30, 2021

Check out @stillinbeta's comment #687 (comment).

@CommanderTvis
Copy link

Thank you!

@CommanderTvis
Copy link

@db48x How to apply that snippet?

@tgross35
Copy link
Contributor

Slightly tweaked version, and including cmath which defines things like FE_DIVBYZERO

const IGNORE_MACROS
: [&str; 20] = [
    "FE_DIVBYZERO",
    "FE_DOWNWARD",
    "FE_INEXACT",
    "FE_INVALID",
    "FE_OVERFLOW",
    "FE_TONEAREST",
    "FE_TOWARDZERO",
    "FE_UNDERFLOW",
    "FE_UPWARD",
    "FP_INFINITE",
    "FP_INT_DOWNWARD",
    "FP_INT_TONEAREST",
    "FP_INT_TONEARESTFROMZERO",
    "FP_INT_TOWARDZERO",
    "FP_INT_UPWARD",
    "FP_NAN",
    "FP_NORMAL",
    "FP_SUBNORMAL",
    "FP_ZERO",
    "IPPORT_RESERVED",
];

#[derive(Debug)]
struct IgnoreMacros(HashSet<String>);

impl ParseCallbacks for IgnoreMacros {
    fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior {
        if self.0.contains(name) {
            MacroParsingBehavior::Ignore
        } else {
            MacroParsingBehavior::Default
        }
    }
}

impl IgnoreMacros {
    fn new() -> Self {
        Self(IGNORE_MACROS
            .into_iter().map(|s| s.to_owned()).collect())
    }
}

And usage

.parse_callbacks(Box::new(IgnoreMacros::new()))
// Longdouble creates warnings about 16-bit numbers, good to ignore if relevant
.blocklist_function("strtold")

I wonder if bindgen could ignore these specific macros by default with the option to disable them, that would save some head scratching.

@wildwestrom
Copy link

wildwestrom commented Apr 30, 2023

I see this issue is labeled is closed and was "fixed" by another PR, but it must have regressed. I used the same header and bindgen 0.65.1, and it gave me almost the exact same error. I can post more details if necessary.

@pvdrz
Copy link
Contributor

pvdrz commented Aug 9, 2023

This issue has not regressed, what happens is that there is no magic solution for it. As mentioned https://github.com/rust-lang/rust-bindgen/issues/687#issuecomment-416537395, you need to either block the macro or the enumerator. A more in-depth explanation is given here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests