Skip to content

Commit

Permalink
Auto merge of #926 - emilio:issue-888, r=fitzgen
Browse files Browse the repository at this point in the history
ir: When something has a definition, return unresolved type references until we parse it.

This fixes #888
  • Loading branch information
bors-servo authored Sep 5, 2017
2 parents 28de37e + 8ecb50a commit d23db77
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 149 deletions.
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

0 comments on commit d23db77

Please sign in to comment.