Skip to content

Commit

Permalink
Fix recursive aliases to const module enum
Browse files Browse the repository at this point in the history
Item::is_constified_enum_module() only returns true for the base type, not for
"layers" of aliases.

Added a "simple alias" test and added content to the types test.
  • Loading branch information
tmfink committed Jun 19, 2017
1 parent 5f4b730 commit 4b10529
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 24 deletions.
60 changes: 47 additions & 13 deletions src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,37 @@ impl Item {
/// Returns whether the item is a constified module enum
fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
if let ItemKind::Type(ref type_) = self.kind {
// Do not count an "alias of an alias" as a constified module enum;
// otherwise, we will get:
// pub mod foo {
// pub type Type = ::std::os::raw::c_uint;
// ...
// }
// pub use foo::Type as foo_alias1;
// pub use foo_alias1::Type as foo_alias2;
// pub use foo_alias2::Type as foo_alias3;
// ...
//
// (We do not want the '::Type' appended to the alias types; only the base type)
if let TypeKind::Alias(inner_id) = *type_.kind() {
let inner_item = ctx.resolve_item(inner_id);
if let ItemKind::Type(ref inner_type) = *inner_item.kind() {
match *inner_type.kind() {
TypeKind::Alias(..) => { return false; }
TypeKind::ResolvedTypeRef(resolved_id) => {
// We need to handle:
// Alias -> ResolvedTypeRef -> Alias
let resolved_item = ctx.resolve_item(resolved_id);
if let ItemKind::Type(ref resolved_type) = *resolved_item.kind() {
if let TypeKind::Alias(..) = *resolved_type.kind() {
return false;
}
}
}
_ => (),
}
}
}
if let Some(ref type_) = type_.safe_canonical_type(ctx) {
if let TypeKind::Enum(ref enum_) = *type_.kind() {
return enum_.is_constified_enum_module(ctx, self);
Expand Down Expand Up @@ -1458,21 +1489,24 @@ impl ItemCanonicalPath for Item {
ctx: &BindgenContext)
-> Vec<String> {
let mut path = self.canonical_path(ctx);
let is_constified_module_enum = self.is_constified_enum_module(ctx);
if ctx.options().enable_cxx_namespaces {
if is_constified_module_enum {
path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
}
return path;
}
if is_constified_module_enum {
return vec![path.last().unwrap().clone(),
CONSTIFIED_ENUM_MODULE_REPR_NAME.into()];
}

// ASSUMPTION: (disable_name_namespacing && cxx_namespaces)
// is equivalent to
// disable_name_namespacing
if ctx.options().disable_name_namespacing {
return vec![path.last().unwrap().clone()];
// Only keep the last item in path
let split_idx = path.len() - 1;
path = path.split_off(split_idx);
} else if !ctx.options().enable_cxx_namespaces {
// Ignore first item "root"
path = vec![path[1..].join("_")];
}
return vec![path[1..].join("_")];

if self.is_constified_enum_module(ctx) {
path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
}

return path;
}

fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
Expand Down
80 changes: 80 additions & 0 deletions tests/expectations/tests/constify-module-enums-simple-alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* automatically generated by rust-bindgen */


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


pub mod Foo {
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
pub const Variant3: Type = 2;
}
pub use self::Foo::Type as Foo_alias1;
pub use self::Foo_alias1 as Foo_alias2;
pub use self::Foo_alias2 as Foo_alias3;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Bar {
pub baz1: Foo::Type,
pub baz2: Foo_alias1,
pub baz3: Foo_alias2,
pub baz4: Foo_alias3,
pub baz_ptr1: *mut Foo::Type,
pub baz_ptr2: *mut Foo_alias1,
pub baz_ptr3: *mut Foo_alias2,
pub baz_ptr4: *mut Foo_alias3,
}
#[test]
fn bindgen_test_layout_Bar() {
assert_eq!(::std::mem::size_of::<Bar>() , 48usize , concat ! (
"Size of: " , stringify ! ( Bar ) ));
assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz1 as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz1 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz2 as * const _ as usize } ,
4usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz2 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz3 as * const _ as usize } ,
8usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz3 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz4 as * const _ as usize } ,
12usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz4 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz_ptr1 as * const _ as usize
} , 16usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz_ptr1 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz_ptr2 as * const _ as usize
} , 24usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz_ptr2 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz_ptr3 as * const _ as usize
} , 32usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz_ptr3 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz_ptr4 as * const _ as usize
} , 40usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz_ptr4 ) ));
}
impl Clone for Bar {
fn clone(&self) -> Self { *self }
}
impl Default for Bar {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* automatically generated by rust-bindgen */


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


pub mod one_Foo {
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Bar {
pub baz1: one_Foo::Type,
pub baz2: *mut one_Foo::Type,
}
#[test]
fn bindgen_test_layout_Bar() {
assert_eq!(::std::mem::size_of::<Bar>() , 16usize , concat ! (
"Size of: " , stringify ! ( Bar ) ));
assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz1 as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz1 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz2 as * const _ as usize } ,
8usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz2 ) ));
}
impl Clone for Bar {
fn clone(&self) -> Self { *self }
}
impl Default for Bar {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
90 changes: 83 additions & 7 deletions tests/expectations/tests/constify-module-enums-types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,36 @@ pub mod foo {
pub const ALSO_THIS: Type = 42;
pub const AND_ALSO_THIS: Type = 42;
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ns1_foo2 { THIS = 0, SHOULD_BE = 1, A_CONSTANT = 2, ALSO_THIS = 42, }
pub use self::ns1_foo2 as ns1_foo;
pub mod ns1_foo {
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
pub const ALSO_THIS: Type = 42;
}
pub mod ns2_Foo {
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
pub use self::foo::Type as foo_alias1;
pub use self::foo_alias1 as foo_alias2;
pub use self::foo_alias2 as foo_alias3;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct bar {
pub member1: foo::Type,
pub member2: foo_alias1,
pub member3: foo_alias2,
pub member4: ns1_foo,
pub member4: foo_alias3,
pub member5: ns1_foo::Type,
pub member6: *mut ns2_Foo::Type,
}
#[test]
fn bindgen_test_layout_bar() {
assert_eq!(::std::mem::size_of::<bar>() , 16usize , concat ! (
assert_eq!(::std::mem::size_of::<bar>() , 32usize , concat ! (
"Size of: " , stringify ! ( bar ) ));
assert_eq! (::std::mem::align_of::<bar>() , 4usize , concat ! (
assert_eq! (::std::mem::align_of::<bar>() , 8usize , concat ! (
"Alignment of " , stringify ! ( bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const bar ) ) . member1 as * const _ as usize }
Expand All @@ -52,13 +63,74 @@ fn bindgen_test_layout_bar() {
, 12usize , concat ! (
"Alignment of field: " , stringify ! ( bar ) , "::" ,
stringify ! ( member4 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const bar ) ) . member5 as * const _ as usize }
, 16usize , concat ! (
"Alignment of field: " , stringify ! ( bar ) , "::" ,
stringify ! ( member5 ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const bar ) ) . member6 as * const _ as usize }
, 24usize , concat ! (
"Alignment of field: " , stringify ! ( bar ) , "::" ,
stringify ! ( member6 ) ));
}
impl Clone for bar {
fn clone(&self) -> Self { *self }
}
impl Default for bar {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Baz {
pub member1: ns2_Foo::Type,
}
#[test]
fn bindgen_test_layout_Baz() {
assert_eq!(::std::mem::size_of::<Baz>() , 4usize , concat ! (
"Size of: " , stringify ! ( Baz ) ));
assert_eq! (::std::mem::align_of::<Baz>() , 4usize , concat ! (
"Alignment of " , stringify ! ( Baz ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Baz ) ) . member1 as * const _ as usize }
, 0usize , concat ! (
"Alignment of field: " , stringify ! ( Baz ) , "::" ,
stringify ! ( member1 ) ));
}
impl Clone for Baz {
fn clone(&self) -> Self { *self }
}
impl Default for Baz {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
pub mod one_Foo {
pub type Type = ::std::os::raw::c_int;
pub const Variant1: Type = 0;
pub const Variant2: Type = 1;
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Bar {
pub baz: *mut one_Foo::Type,
}
#[test]
fn bindgen_test_layout_Bar() {
assert_eq!(::std::mem::size_of::<Bar>() , 8usize , concat ! (
"Size of: " , stringify ! ( Bar ) ));
assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Bar ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const Bar ) ) . baz as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( Bar ) , "::" ,
stringify ! ( baz ) ));
}
impl Clone for Bar {
fn clone(&self) -> Self { *self }
}
impl Default for Bar {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
extern "C" {
#[link_name = "_Z5func13fooPS_PS0_"]
pub fn func1(arg1: foo::Type, arg2: *mut foo::Type,
Expand All @@ -82,3 +154,7 @@ extern "C" {
#[link_name = "_Z5func35ThingI3fooE"]
pub fn func3(arg1: Thing<foo::Type>) -> foo::Type;
}
extern "C" {
#[link_name = "_Z5func45ThingIS_I3fooEE"]
pub fn func4(arg1: Thing<Thing<foo::Type>>) -> foo::Type;
}
21 changes: 21 additions & 0 deletions tests/headers/constify-module-enums-simple-alias.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// bindgen-flags: --constified-enum-module Foo

enum class Foo {
Variant1, Variant2, Variant3,
};

typedef Foo Foo_alias1;
typedef Foo_alias1 Foo_alias2;
typedef Foo_alias2 Foo_alias3;

class Bar {
Foo baz1;
Foo_alias1 baz2;
Foo_alias2 baz3;
Foo_alias3 baz4;

Foo *baz_ptr1;
Foo_alias1 *baz_ptr2;
Foo_alias2 *baz_ptr3;
Foo_alias3 *baz_ptr4;
};
12 changes: 12 additions & 0 deletions tests/headers/constify-module-enums-simple-nonamespace.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// bindgen-flags: --constified-enum-module one_Foo

namespace one {
enum class Foo {
Variant1, Variant2,
};
}

class Bar {
one::Foo baz1;
one::Foo* baz2;
};
Loading

0 comments on commit 4b10529

Please sign in to comment.