Skip to content

ir: When something has a definition, return unresolved type references until we parse it. #926

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 4 commits into from
Sep 5, 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
34 changes: 34 additions & 0 deletions src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ pub struct BindgenContext<'ctx> {
/// Current module being traversed.
current_module: ItemId,

/// A HashMap keyed on a type definition, and whose value is the parent id
/// of the declaration.
///
/// This is used to handle the cases where the semantic and the lexical
/// parents of the cursor differ, like when a nested class is defined
/// outside of the parent class.
semantic_parents: HashMap<clang::Cursor, ItemId>,

/// A stack with the current type declarations and types we're parsing. This
/// is needed to avoid infinite recursion when parsing a type like:
///
Expand Down Expand Up @@ -375,6 +383,7 @@ impl<'ctx> BindgenContext<'ctx> {
next_item_id: ItemId(1),
root_module: root_module.id(),
current_module: root_module.id(),
semantic_parents: Default::default(),
currently_parsed_types: vec![],
parsed_macros: Default::default(),
replacements: Default::default(),
Expand Down Expand Up @@ -1187,6 +1196,31 @@ impl<'ctx> BindgenContext<'ctx> {
self.current_module
}

/// Add a semantic parent for a given type definition.
///
/// We do this from the type declaration, in order to be able to find the
/// correct type definition afterwards.
///
/// TODO(emilio): We could consider doing this only when
/// declaration.lexical_parent() != definition.lexical_parent(), but it's
/// not sure it's worth it.
pub fn add_semantic_parent(
&mut self,
definition: clang::Cursor,
parent_id: ItemId,
) {
self.semantic_parents.insert(definition, parent_id);
}

/// Returns a known semantic parent for a given definition.
pub fn known_semantic_parent(
&self,
definition: clang::Cursor
) -> Option<ItemId> {
self.semantic_parents.get(&definition).cloned()
}


/// Given a cursor pointing to the location of a template instantiation,
/// return a tuple of the form `(declaration_cursor, declaration_id,
/// num_expected_template_args)`.
Expand Down
24 changes: 22 additions & 2 deletions src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,11 +1194,31 @@ impl ClangItemParser for Item {
// Types are sort of special, so to avoid parsing template classes
// twice, handle them separately.
{
let applicable_cursor = cursor.definition().unwrap_or(cursor);
let definition = cursor.definition();
let applicable_cursor = definition.unwrap_or(cursor);


let relevant_parent_id = match definition {
Some(definition) => {
if definition != cursor {
ctx.add_semantic_parent(definition, relevant_parent_id);
return Ok(Item::from_ty_or_ref(
applicable_cursor.cur_type(),
cursor,
parent_id,
ctx,
));
}
parent_id.or_else(|| ctx.known_semantic_parent(definition))
.unwrap_or(ctx.current_module())
}
None => relevant_parent_id,
};

match Item::from_ty(
&applicable_cursor.cur_type(),
applicable_cursor,
parent_id,
Some(relevant_parent_id),
ctx,
) {
Ok(ty) => return Ok(ty),
Expand Down
40 changes: 20 additions & 20 deletions tests/expectations/tests/class_nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,6 @@ impl Clone for A_B {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
pub struct A_C {
pub baz: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_A_C() {
assert_eq!(::std::mem::size_of::<A_C>() , 4usize , concat ! (
"Size of: " , stringify ! ( A_C ) ));
assert_eq! (::std::mem::align_of::<A_C>() , 4usize , concat ! (
"Alignment of " , stringify ! ( A_C ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const A_C ) ) . baz as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( A_C ) , "::" ,
stringify ! ( baz ) ));
}
impl Clone for A_C {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct A_D<T> {
pub foo: T,
Expand All @@ -73,6 +53,26 @@ fn bindgen_test_layout_A() {
impl Clone for A {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
pub struct A_C {
pub baz: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_A_C() {
assert_eq!(::std::mem::size_of::<A_C>() , 4usize , concat ! (
"Size of: " , stringify ! ( A_C ) ));
assert_eq! (::std::mem::align_of::<A_C>() , 4usize , concat ! (
"Alignment of " , stringify ! ( A_C ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const A_C ) ) . baz as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( A_C ) , "::" ,
stringify ! ( baz ) ));
}
impl Clone for A_C {
fn clone(&self) -> Self { *self }
}
extern "C" {
#[link_name = "var"]
pub static mut var: A_B;
Expand Down
14 changes: 7 additions & 7 deletions tests/expectations/tests/forward-inherit-struct-with-fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Rooted<T> {
pub _base: js_RootedBase<T>,
pub struct js_RootedBase<T> {
pub foo: *mut T,
pub next: *mut Rooted<T>,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl <T> Default for Rooted<T> {
impl <T> Default for js_RootedBase<T> {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct js_RootedBase<T> {
pub foo: *mut T,
pub next: *mut Rooted<T>,
pub struct Rooted<T> {
pub _base: js_RootedBase<T>,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl <T> Default for js_RootedBase<T> {
impl <T> Default for Rooted<T> {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
10 changes: 5 additions & 5 deletions tests/expectations/tests/forward-inherit-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct js_RootedBase {
pub _address: u8,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Rooted {
Expand All @@ -12,8 +17,3 @@ pub struct Rooted {
impl Default for Rooted {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct js_RootedBase {
pub _address: u8,
}
46 changes: 23 additions & 23 deletions tests/expectations/tests/issue-372.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,6 @@ pub mod root {
use self::super::root;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct d {
pub m: root::i,
}
#[test]
fn bindgen_test_layout_d() {
assert_eq!(::std::mem::size_of::<d>() , 24usize , concat ! (
"Size of: " , stringify ! ( d ) ));
assert_eq! (::std::mem::align_of::<d>() , 8usize , concat ! (
"Alignment of " , stringify ! ( d ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const d ) ) . m as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( d ) , "::" ,
stringify ! ( m ) ));
}
impl Clone for d {
fn clone(&self) -> Self { *self }
}
impl Default for d {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct i {
pub j: *mut root::i,
pub k: *mut root::i,
Expand Down Expand Up @@ -66,6 +43,29 @@ pub mod root {
impl Default for i {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct d {
pub m: root::i,
}
#[test]
fn bindgen_test_layout_d() {
assert_eq!(::std::mem::size_of::<d>() , 24usize , concat ! (
"Size of: " , stringify ! ( d ) ));
assert_eq! (::std::mem::align_of::<d>() , 8usize , concat ! (
"Alignment of " , stringify ! ( d ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const d ) ) . m as * const _ as usize } ,
0usize , concat ! (
"Alignment of field: " , stringify ! ( d ) , "::" ,
stringify ! ( m ) ));
}
impl Clone for d {
fn clone(&self) -> Self { *self }
}
impl Default for d {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum n {
Expand Down
36 changes: 18 additions & 18 deletions tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,6 @@

pub type RefPtr<T> = T;

#[repr(C)]
#[derive(Debug, Copy)]
pub struct b {
pub _base: g,
}
#[test]
fn bindgen_test_layout_b() {
assert_eq!(::std::mem::size_of::<b>() , 1usize , concat ! (
"Size of: " , stringify ! ( b ) ));
assert_eq! (::std::mem::align_of::<b>() , 1usize , concat ! (
"Alignment of " , stringify ! ( b ) ));
}
impl Clone for b {
fn clone(&self) -> Self { *self }
}
impl Default for b {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct A {
Expand Down Expand Up @@ -75,6 +57,24 @@ impl Clone for g {
impl Default for g {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct b {
pub _base: g,
}
#[test]
fn bindgen_test_layout_b() {
assert_eq!(::std::mem::size_of::<b>() , 1usize , concat ! (
"Size of: " , stringify ! ( b ) ));
assert_eq! (::std::mem::align_of::<b>() , 1usize , concat ! (
"Alignment of " , stringify ! ( b ) ));
}
impl Clone for b {
fn clone(&self) -> Self { *self }
}
impl Default for b {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
extern "C" {
#[link_name = "_Z25Servo_Element_GetSnapshotv"]
pub fn Servo_Element_GetSnapshot() -> A;
Expand Down
36 changes: 36 additions & 0 deletions tests/expectations/tests/issue-888-enum-var-decl-jump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* 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 Halide {
#[allow(unused_imports)]
use self::super::super::root;
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Type {
pub _address: u8,
}
extern "C" {
#[link_name = "_ZN6Halide4Type1bE"]
pub static mut Type_b: root::a;
}
#[test]
fn bindgen_test_layout_Type() {
assert_eq!(::std::mem::size_of::<Type>() , 1usize , concat ! (
"Size of: " , stringify ! ( Type ) ));
assert_eq! (::std::mem::align_of::<Type>() , 1usize , concat ! (
"Alignment of " , stringify ! ( Type ) ));
}
impl Clone for Type {
fn clone(&self) -> Self { *self }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum a { }
}
8 changes: 4 additions & 4 deletions tests/expectations/tests/objc_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
extern crate objc;
#[allow(non_camel_case_types)]
pub type id = *mut objc::runtime::Object;
extern "C" {
#[link_name = "fooVar"]
pub static mut fooVar: *mut id;
}
pub trait Foo {
unsafe fn method(self);
}
impl Foo for id {
unsafe fn method(self) { msg_send!(self , method) }
}
extern "C" {
#[link_name = "fooVar"]
pub static mut fooVar: *mut id;
}
8 changes: 4 additions & 4 deletions tests/expectations/tests/opaque-tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


extern "C" {
#[link_name = "_Z3fooP9Container"]
pub fn foo(c: *mut Container);
}
#[repr(C)]
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
pub struct Container {
Expand All @@ -19,7 +23,3 @@ fn bindgen_test_layout_Container() {
impl Clone for Container {
fn clone(&self) -> Self { *self }
}
extern "C" {
#[link_name = "_Z3fooP9Container"]
pub fn foo(c: *mut Container);
}
Loading