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.35k stars 687 forks source link

error[E0428]: the name `sentry` is defined multiple times #1048

Closed ctaggart closed 6 years ago

ctaggart commented 6 years ago

For Octave bindings, I need to interop with C++ std::string https://github.com/ctaggart/octh/issues/28. Any recommendations of how to do this are appreciated. This is the first issue I'm up against that I'm not sure how to solve. https://github.com/ctaggart/octh/issues/29

Input C/C++ Header

namespace a {
template <typename, typename> class b;
template <typename, typename = int> class c;
class B {
  typedef b<int, int> d;
};
class e {
  B g;
};
template <typename, typename> class c : e { class sentry; };
template <typename f, typename h> class c<f, h>::sentry {};
template <typename, typename> class b { class sentry; };
template <typename f, typename h> class b<f, h>::sentry {};
}
class octave_diary_stream : a::c<char> {};

Bindgen Invocation

#!/usr/bin/env bash
set -eu
clang-3.9 --std=c++11 -c __bindgen.ii

~/rust-bindgen/target/release/bindgen \
    --output __bindgen.rs \
    --enable-cxx-namespaces \
    --whitelist-type octave.* \
    --whitelist-function octave.* \
    --use-core \
    --raw-line "extern crate core;" \
    __bindgen.ii \
    -- -v -x c++ -std=c++11 \
    2>/dev/null

rustc __bindgen.rs \
    2>&1 \
    | grep 'error\[E0428\]: the name `sentry` is defined multiple times'

# time creduce ./bindgen-bug.sh __bindgen.ii

Actual Results

error[E0428]: the name `sentry` is defined multiple times

Expected Results

It compiles.

fitzgen commented 6 years ago

Thanks for the bug report @ctaggart !

Here is a slightly cleaned up / annotated test case:

// bindgen-flags: --enable-cxx-namespaces -- -std=c++11

// First::sentry and Second::sentry should be emitted as `First_sentry` and
// `Second_sentry`, but instead are both being named just `sentry` which leads
// to compilation errors.
//
// Note: if there is no namespace, then we don't run into problems. Similarly,
// making the `sentry` definitions inline in `First` and `Second`, rather than
// declared inline with out of line definitions, makes the problem go away as
// well.

namespace whatever {
    template <typename, typename>
    class First {
        // Declaration of First::sentry
        class sentry;
    };

    // Definition of First::sentry
    template <typename f, typename h>
    class First<f, h>::sentry {};

    template <typename, typename>
    class Second {
        // Declaration of Second::sentry
        class sentry;
    };

    // Definition of Second::sentry
    template <typename f, typename h>
    class Second<f, h>::sentry {};
}

And here are the bindings that get generated:

/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod whatever {
        #[allow(unused_imports)]
        use self::super::super::root;
        #[repr(C)]
        #[derive(Debug, Default, Copy, Clone)]
        pub struct First {
            pub _address: u8,
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy)]
        pub struct sentry {
            pub _address: u8,
        }
        impl Clone for sentry {
            fn clone(&self) -> Self {
                *self
            }
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy, Clone)]
        pub struct Second {
            pub _address: u8,
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy)]
        pub struct sentry {
            pub _address: u8,
        }
        impl Clone for sentry {
            fn clone(&self) -> Self {
                *self
            }
        }
    }
}

It seems like we're parsing the inner sentry classes incorrectly, and they don't end up with First or Second as their parents.

Here's the IR:

ir

fitzgen commented 6 years ago

I have a fix over in https://github.com/rust-lang-nursery/rust-bindgen/pull/1049

ctaggart commented 6 years ago

I tried the fix out and it worked for https://github.com/ctaggart/octh/issues/29.