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

Making type template opaque has undesired behavior #869

Open
upsuper opened this issue Jul 30, 2017 · 3 comments
Open

Making type template opaque has undesired behavior #869

upsuper opened this issue Jul 30, 2017 · 3 comments

Comments

@upsuper
Copy link
Contributor

upsuper commented Jul 30, 2017

Input C/C++ Header

template<typename T>
struct Foo {
  void* a;
};

template<typename T>
class Bar {
  Foo<T> m;
};

class Baz {
  Bar<int> m;
};

Bindgen Invocation

$ bindgen input.hpp --opaque-type Foo

Actual Results

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Foo {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Bar {
    pub m: u8,
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Baz {
    pub m: Bar,
}
#[test]
fn bindgen_test_layout_Baz() {
    assert_eq!(::std::mem::size_of::<Baz>() , 8usize , concat ! (
               "Size of: " , stringify ! ( Baz ) ));
    assert_eq! (::std::mem::align_of::<Baz>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( Baz ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const Baz ) ) . m as * const _ as usize } ,
                0usize , concat ! (
                "Alignment of field: " , stringify ! ( Baz ) , "::" ,
                stringify ! ( m ) ));
}
impl Clone for Baz {
    fn clone(&self) -> Self { *self }
}
#[test]
fn __bindgen_test_layout_Bar_open0_int_close0_instantiation() {
    assert_eq!(::std::mem::size_of::<Bar>() , 8usize , concat ! (
               "Size of template specialization: " , stringify ! ( Bar ) ));
    assert_eq!(::std::mem::align_of::<Bar>() , 8usize , concat ! (
               "Alignment of template specialization: " , stringify ! ( Bar )
               ));
}

Expected Results

As can be seen from the C++ code, Foo should have a pointer size, and Bar and Baz as well. However, Bar and Baz in this case only have 1 byte, while the layout test asserts they have 8 bytes.

Bar probably should have something like [u8; 8usize] or [usize; 2usize] instead.

@fitzgen
Copy link
Member

fitzgen commented Jul 31, 2017

Oh wow. Yeah, we should be doing much better with generating opaque blobs here.

@bsilver8192
Copy link

I think the same thing happens when bindgen decides a type is opaque by itself (as opposed to forcing it with --opaque-type) ( due to #362 for example):

template <int> struct has_int_template { int y; };

has_int_template<0> function();

produces this:

extern "C" {
    #[link_name = "\u{1}_Z8functionv"]
    pub fn function() -> u8;
}

which is returning an object of the wrong size.

@bsilver8192
Copy link

Looks like u8 is coming from ToOpaque::get_layout's fallback to Layout::for_size(ctx, 1). That seems unlikely to result in valid bindings. I'm not sure how to gracefully refuse to generate bindings for types which trigger that codepath though, and panicing while generating code is less friendly because then you can't even use other bindings which might be correct.

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

3 participants