Rust-bindgen: Octave oct.h unresolved import `self::super::super::u32`'

Created on 24 Jul 2019  路  10Comments  路  Source: rust-lang/rust-bindgen

Looking at https://github.com/ctaggart/octh/issues/15 again, I'm running in one final error where this rust code:

pub use self::super::super::u32 as ios_base_openmode;

My workaround is to change it to:

pub type ios_base_openmode = u32;

Is there an option that would make that happen. I tried .opaque_type("ios_base::.*"), but it did not work.

Input C/C++ Header

When I manually try to run bingen tool, I'm getting a bunch of different errors. I'm not sure why.

ctaggart@rustasia:~/octh$ ~/rust-bindgen/target/release/bindgen \
>     --output "__bindgen.rs" \
>     --enable-cxx-namespaces \
>     --opaque-type "octave.refcount" \
>     --use-core \
>     --raw-line "extern crate core;" \
>     --opaque-type "std::.*" \
>     src/octhelp.h \
>     -- -v -x c++ -I/usr/local/include/octave-6.0.0 \
>     &> bindgen.txt
clang version 8.0.1-svn363027-1~exp1~20190611211629.77 (branches/release_80)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: 
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.4.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.4.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
ignoring nonexistent directory "lib/clang/8.0.1/include"
ignoring nonexistent directory "/include"
ignoring duplicate directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0"
ignoring duplicate directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/x86_64-linux-gnu/c++/7.4.0"
ignoring duplicate directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/x86_64-linux-gnu/c++/7.4.0"
ignoring duplicate directory "/usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/backward"
ignoring duplicate directory "/usr/include/clang/8.0.1/include"
ignoring duplicate directory "/usr/local/include"
ignoring duplicate directory "/usr/include/x86_64-linux-gnu"
ignoring duplicate directory "/usr/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include/octave-6.0.0
 /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0
 /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/x86_64-linux-gnu/c++/7.4.0
 /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/backward
 /usr/include/clang/8.0.1/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 400: Cursor( kind: UnexposedAttr, loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/x86_64-linux-gnu/c++/7.4.0/bits/c++config.h:253:43, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 400: Cursor( kind: UnexposedAttr, loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/x86_64-linux-gnu/c++/7.4.0/bits/c++config.h:257:43, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/stl_relops.h:67:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/move.h:36:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/type_traits:52:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/move.h:56:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/move.h:166:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/stl_pair.h:65:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/utility:78:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/functexcept.h:42:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/bits/cpp_type_traits.h:69:15, usr: None)
[2019-07-24T19:46:46Z ERROR bindgen::ir::item] Unhandled cursor kind 417: Cursor(default kind: attribute(visibility), loc: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0/../../../../include/c++/7.4.0/ext/type_traits.h:39:21, usr: None)

Bindgen Invocation

https://github.com/ctaggart/octh/blob/42bb0f00c5ff7043a48e9fdde136779031f0761c/build.rs#L6-L18

    let mut builder = bindgen::Builder::default()
        .header("src/octhelp.h")
        .clang_arg("-v")
        .clang_arg("-x")
        .clang_arg("c++")
        .enable_cxx_namespaces()
        .whitelist_type("octave.*")
        .whitelist_function("octave.*")
        .opaque_type("octave.refcount")
        .use_core()
        .raw_line("#![allow(warnings)]")
        .raw_line("extern crate core;")
        .opaque_type("ios_base::.*")
        .opaque_type("std::.*");

Actual Results

ctaggart@rustasia:~/octh$ export RUST_BACKTRACE=1
ctaggart@rustasia:~/octh$ cargo build
   Compiling octh v0.1.0 (/home/ctaggart/octh)
error[E0432]: unresolved import `self::super::super::u32`
   --> src/lib.rs:134:17
    |
134 |         pub use self::super::super::u32 as ios_base_openmode;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `u32` in the root

error: aborting due to previous error

For more information about this error, try `rustc --explain E0432`.
error: Could not compile `octh`.

To learn more, run the command again with --verbose.

Expected Results

I-bogus-codegen bug

All 10 comments

Hmm, that's a bit surprising, does octave somehow define their own u32 type or something? Could you point me to the definition of that enum?

Here are the header files that contain 矛os_base::openmode`:

ctaggart@rustasia:~/octh$ sudo rg --color never -l 'ios_base::openmode' -g '*.h' /usr 2> /dev/null
/usr/local/include/octave-6.0.0/octave/zfstream.h
/usr/include/c++/7/bits/ios_base.h
/usr/include/c++/7/ext/stdio_sync_filebuf.h
/usr/include/c++/7/ext/stdio_filebuf.h
/usr/include/x86_64-linux-gnu/c++/7/bits/basic_file.h

Here is the Octave header:
https://github.com/ctaggart/octave/blob/master/libinterp/corefcn/zfstream.h

I think these are the correct links to the gcc files:
https://github.com/gcc-mirror/gcc/blob/gcc-7_4_0-release/libstdc++-v3/include/bits/ios_base.h
https://github.com/gcc-mirror/gcc/blob/gcc-7_4_0-release/libstdc++-v3/include/ext/stdio_sync_filebuf.h
https://github.com/gcc-mirror/gcc/blob/gcc-7_4_0-release/libstdc++-v3/include/ext/stdio_filebuf.h
https://github.com/gcc-mirror/gcc/blob/gcc-7_4_0-release/libstdc++-v3/config/io/basic_file_stdio.h

Any idea why I'm getting the Unhandled cursor kind with bindgen command line? I'd like that to work, so I can narrow this down to a test case.

I think unhandled cursor kind is not a fatal error? I'd expect something to be generated regardless.

You are correct, bindgen works even with those errors. I was able to reduce the header to:

namespace std {
enum a {} typedef b;
}

bindgen produces:

/* automatically generated by rust-bindgen */

extern crate core;

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod std {
        #[allow(unused_imports)]
        use self::super::super::root;
        pub type a = u32;
        pub use self::super::super::u32 as b;
    }
}

Which rustc fails with:

error[E0432]: unresolved import `self::super::super::u32`
  --> __bindgen.rs:13:17
   |
13 |         pub use self::super::super::u32 as b;
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `u32` in the root

error[E0601]: `main` function not found in crate `__bindgen`
  |
  = note: consider adding a `main` function to `__bindgen.rs`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0432, E0601.
For more information about an error, try `rustc --explain E0432`.

For completeness, my script to reduce this was:

#!/bin/bash -eu

# https://github.com/rust-lang/rust-bindgen/blob/master/CONTRIBUTING.md#using-creduce-to-minimize-test-cases
# bash -c 'time creduce ./issue/octh15.sh __bindgen.ii' &> creduce.txt &

export RUST_BACKTRACE=1
clang-8 -c __bindgen.ii

~/rust-bindgen/target/release/bindgen \
    --output "__bindgen.rs" \
    --enable-cxx-namespaces \
    --opaque-type "octave.refcount" \
    --use-core \
    --raw-line "#![allow(warnings)]" \
    --raw-line "extern crate core;" \
    --opaque-type "std::.*" \
    __bindgen.ii \
    -- -v -x c++ \
    2>/dev/null

rustc __bindgen.rs \
    2>&1 \
    | grep 'error\[E0432\]: unresolved import `self::super::super::u32`'

Thanks!

enum a {} typedef b;

Wow, I had no idea you could write something like that, I guess C++ will never stop surprising me... what does that even mean? :)

Anyhow, that's a nice test-case :)

Ha! I don't know what it means. I was looking for examples, found one, but still don't get it.

https://github.com/gcc-mirror/gcc/blob/gcc-7_4_0-release/libstdc++-v3/include/bits/ios_base.h#L323

typedef _Ios_Fmtflags fmtflags;

Another thing I don't understand, however, is how to use the bindgen translated constructors. I am just trying to translate a very simple cc files to rs here: https://github.com/ctaggart/octave-add/tree/octh15/src

For example, the cc code is octave_value_list retval(nargout);. binden created this:

    extern "C" {
        #[link_name = "\u{1}_ZN17octave_value_listC1ERKNSt7__cxx114listIS_SaIS_EEE"]
        pub fn octave_value_list_octave_value_list(
            this: *mut root::octave_value_list,
            arg1: *const [u64; 3usize],
        );
    }

    #[inline]
    pub unsafe fn new(arg1: *const [u64; 3usize]) -> Self {
        let mut __bindgen_tmp = ::core::mem::uninitialized();
        octave_value_list_octave_value_list(&mut __bindgen_tmp, arg1);
        __bindgen_tmp
    }

What is a *const [u64; 3usize] type?

It seems that's an opaque type. I don't know what the octave_value_list constructor takes. Also note that the constructors are unsafe not only because they're calling into C++ but also because the structs shouldn't contain interior pointers (otherwise moving them with rust is bad).

I wouldn't be surprised if octave_value_list had interior pointers or relied otherwise on its stack location.

@emilio, any chance solving the test case:

enum a {} typedef b;

So that the rust code ends up being something like:

pub type ios_base_openmode = u32;

Instead of what it does currently:

pub use self::super::super::u32 as ios_base_openmode;

It should be feasible yes. Presumably it'd end up being something like:

pub type a = u32;
pub type b = a;

Or something. That seems to be the semantics of that construct.

I hadn't looked closely, but this requires opaque types to fail, otherwise bindgen behaves correctly.

So the issue is that we're treating opaque typedefs incorrectly. Trivial example is:

enum a { b, c } typedef d;

Ran with:

bindgen t.h --opaque-type d

But this is also an issue for:

enum a { b, c };                                                                                                                                                                                                                              

typedef enum a d;

So the good thing is:

  • This is not due to that weird construct.
  • This is not a libclang issue.
  • You can workaround it by not making typedefs opaque.
  • This should be relatively easy to track down.
Was this page helpful?
0 / 5 - 0 ratings