Skip to content

ir: Ensure we check for typedefs of anonymous structs at the right time. #641

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

Merged
merged 1 commit into from
Apr 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,19 @@ impl CompInfo {
let mut maybe_anonymous_struct_field = None;
cursor.visit(|cur| {
if cur.kind() != CXCursor_FieldDecl {
if let Some((ty, _, offset)) =
if let Some((ty, clang_ty, offset)) =
maybe_anonymous_struct_field.take() {
let field =
Field::new(None, ty, None, None, None, false, offset);
ci.fields.push(field);
if cur.kind() == CXCursor_TypedefDecl &&
cur.typedef_type().unwrap().canonical_type() == clang_ty {
// Typedefs of anonymous structs appear later in the ast
// than the struct itself, that would otherwise be an
// anonymous field. Detect that case here, and do
// nothing.
} else {
let field =
Field::new(None, ty, None, None, None, false, offset);
ci.fields.push(field);
}
}
}

Expand Down Expand Up @@ -737,7 +745,8 @@ impl CompInfo {
});

if let Some((ty, _, offset)) = maybe_anonymous_struct_field {
let field = Field::new(None, ty, None, None, None, false, offset);
let field =
Field::new(None, ty, None, None, None, false, offset);
ci.fields.push(field);
}

Expand Down
81 changes: 81 additions & 0 deletions tests/expectations/tests/issue-639-typedef-anon-field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* automatically generated by rust-bindgen */


#![allow(non_snake_case)]


#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Foo {
pub bar: Foo_Bar,
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Foo_Bar {
pub abc: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_Foo_Bar() {
assert_eq!(::std::mem::size_of::<Foo_Bar>() , 4usize , concat ! (
"Size of: " , stringify ! ( Foo_Bar ) ));
assert_eq! (::std::mem::align_of::<Foo_Bar>() , 4usize , concat ! (
"Alignment of " , stringify ! ( Foo_Bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Foo_Bar ) ) . abc as * const _ as usize }
, 0usize , concat ! (
"Alignment of field: " , stringify ! ( Foo_Bar ) , "::" ,
stringify ! ( abc ) ));
}
impl Clone for Foo_Bar {
fn clone(&self) -> Self { *self }
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(::std::mem::size_of::<Foo>() , 4usize , concat ! (
"Size of: " , stringify ! ( Foo ) ));
assert_eq! (::std::mem::align_of::<Foo>() , 4usize , concat ! (
"Alignment of " , stringify ! ( Foo ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Foo ) ) . bar as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( Foo ) , "::" ,
stringify ! ( bar ) ));
}
impl Clone for Foo {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Baz {
pub _address: u8,
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Baz_Bar {
pub abc: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_Baz_Bar() {
assert_eq!(::std::mem::size_of::<Baz_Bar>() , 4usize , concat ! (
"Size of: " , stringify ! ( Baz_Bar ) ));
assert_eq! (::std::mem::align_of::<Baz_Bar>() , 4usize , concat ! (
"Alignment of " , stringify ! ( Baz_Bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Baz_Bar ) ) . abc as * const _ as usize }
, 0usize , concat ! (
"Alignment of field: " , stringify ! ( Baz_Bar ) , "::" ,
stringify ! ( abc ) ));
}
impl Clone for Baz_Bar {
fn clone(&self) -> Self { *self }
}
#[test]
fn bindgen_test_layout_Baz() {
assert_eq!(::std::mem::size_of::<Baz>() , 1usize , concat ! (
"Size of: " , stringify ! ( Baz ) ));
assert_eq! (::std::mem::align_of::<Baz>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Baz ) ));
}
impl Clone for Baz {
fn clone(&self) -> Self { *self }
}
15 changes: 15 additions & 0 deletions tests/headers/issue-639-typedef-anon-field.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo {
public:
typedef struct {
int abc;
} Bar;

Bar bar;
};

class Baz {
public:
typedef struct {
int abc;
} Bar;
};