diff options
author | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-04-16 06:03:29 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-04-16 06:03:29 +0200 |
commit | 774c7dadba23bcc84cb906206cf6b34da2fd6337 (patch) | |
tree | 35fde45ed5752236686ba3529873b3a6dc77cd9e | |
parent | ca9f853fba5cace90febb52ea4a16d6a4ae394ca (diff) |
Refactor how template specialisations are tracked to prevent borrow panics
-rw-r--r-- | src/gen.rs | 2 | ||||
-rw-r--r-- | src/parser.rs | 28 | ||||
-rw-r--r-- | src/types.rs | 10 | ||||
-rw-r--r-- | tests/expectations/namespace.rs | 104 | ||||
-rw-r--r-- | tests/expectations/template.rs | 2 | ||||
-rw-r--r-- | tests/headers/namespace.hpp | 2 | ||||
-rw-r--r-- | tests/headers/template.hpp | 2 |
7 files changed, 84 insertions, 66 deletions
@@ -2014,7 +2014,7 @@ fn cty_to_rs(ctx: &mut GenCtx, ty: &Type, allow_bool: bool, use_full_path: bool) }).collect(); if use_full_path { - let mut path = ctx.full_path_for_module(c.module_id); + let mut path = ctx.full_path_for_module(c.module_id()); path.push(id); mk_ty_args(ctx, false, &path, args) } else { diff --git a/src/parser.rs b/src/parser.rs index da093f84..1a740bd6 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -97,7 +97,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { CompKind::Struct }; - let mut opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling); + let opaque = ctx.options.opaque_types.iter().any(|name| *name == spelling); let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling); let mut has_non_type_template_params = false; @@ -123,30 +123,19 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { _ => vec![], }; - let mut module_id = ctx.current_module_id; - let mut has_dtor = false; + let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout); // If it's an instantiation of another template, // find the canonical declaration to find the module // it belongs to and if it's opaque. let parent = cursor.specialized(); if let Some(parent) = ctx.name.get(&parent) { - match *parent { - GComp(ref ci) | - GCompDecl(ref ci) => { - opaque |= ci.borrow().opaque; - has_dtor |= ci.borrow().has_destructor; - module_id = ci.borrow().module_id; - } - _ => {} - } + ci.ref_template = Some(parent.clone().to_type()) } - let mut ci = CompInfo::new(spelling, module_id, filename, comment, kind, vec![], layout); ci.opaque = opaque; ci.hide = hide; ci.args = args; - ci.has_destructor = has_dtor; ci.has_non_type_template_params = has_non_type_template_params; let ci = Rc::new(RefCell::new(ci)); @@ -365,16 +354,12 @@ fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx, list } }; + let ci = decl.compinfo(); + // NB: Args might be filled from decl_name, + // it's important not to override if !args.is_empty() { ci.borrow_mut().args = args; - cursor.visit(|c, _: &Cursor| { - if c.kind() == CXCursor_TemplateRef { - let decl = decl_name(ctx, &c.referenced()); - ci.borrow_mut().ref_template = Some(decl.to_type()); - } - CXChildVisit_Continue - }); } TComp(ci) @@ -859,6 +844,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, } CXCursor_Destructor => { ci.has_destructor = true; + // Propagate the change to the parent if let Some(ref t) = ci.ref_template { match *t { TComp(ref parent_ci) => parent_ci.borrow_mut().has_destructor = true, diff --git a/src/types.rs b/src/types.rs index 6e62fb98..5bf8693d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -458,6 +458,15 @@ impl CompInfo { } } + // Return the module id or the class declaration module id. + pub fn module_id(&self) -> ModuleId { + self.ref_template.as_ref().and_then(|t| if let TComp(ref ci) = *t { + Some(ci.borrow().module_id) + } else { + None + }).unwrap_or(self.module_id) + } + pub fn can_derive_debug(&self) -> bool { if self.hide || self.is_opaque() { return false; @@ -511,6 +520,7 @@ impl CompInfo { // not having destructor. // // This is unfortunate, but... + self.ref_template.as_ref().map_or(false, |t| t.has_destructor()) || self.args.iter().any(|t| t.has_destructor()) || self.members.iter().enumerate().any(|(index, m)| match *m { CompMember::Field(ref f) | diff --git a/tests/expectations/namespace.rs b/tests/expectations/namespace.rs index 334542a9..59c6c349 100644 --- a/tests/expectations/namespace.rs +++ b/tests/expectations/namespace.rs @@ -5,45 +5,67 @@ #![allow(non_snake_case)] -pub type whatever_int_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Struct_A { - pub b: whatever_int_t, -} -impl ::std::clone::Clone for Struct_A { - fn clone(&self) -> Self { *self } -} -#[test] -fn bindgen_test_layout_Struct_A() { - assert_eq!(::std::mem::size_of::<Struct_A>() , 4usize); - assert_eq!(::std::mem::align_of::<Struct_A>() , 4usize); -} -#[repr(C)] -#[derive(Debug)] -pub struct Struct_C<T> { - pub _base: Struct_A, - pub m_c: T, - pub m_c_ptr: *mut T, - pub m_c_arr: [T; 10usize], -} -#[repr(C)] -#[derive(Debug)] -pub struct Struct_D<T> { - pub m_c: Struct_C<T>, - pub _phantom0: ::std::marker::PhantomData<T>, -} -extern "C" { - #[link_name = "_Z9top_levelv"] - pub fn top_level(); - #[link_name = "_ZN8whatever11in_whateverEv"] - pub fn in_whatever(); - #[link_name = "_ZN12_GLOBAL__N_13fooEv"] - pub fn foo(); - #[link_name = "_ZN1w3hehEv"] - pub fn heh() -> whatever_int_t; - #[link_name = "_ZN1w3fooEv"] - pub fn foo1() -> Struct_C<::std::os::raw::c_int>; - #[link_name = "_ZN1w4barrEv"] - pub fn barr() -> Struct_C<f32>; +pub use root::*; +pub mod root { + #[repr(C)] + #[derive(Debug)] + pub struct Struct_C<T> { + pub _base: __anonymous1::Struct_A, + pub m_c: T, + pub m_c_ptr: *mut T, + pub m_c_arr: [T; 10usize], + } + extern "C" { + #[link_name = "_Z9top_levelv"] + pub fn top_level(); + } + pub mod whatever { + use root; + pub type whatever_int_t = ::std::os::raw::c_int; + extern "C" { + #[link_name = "_ZN8whatever11in_whateverEv"] + pub fn in_whatever(); + } + } + pub mod __anonymous1 { + use root; + #[repr(C)] + #[derive(Debug, Copy)] + pub struct Struct_A { + pub b: root::whatever::whatever_int_t, + } + impl ::std::clone::Clone for Struct_A { + fn clone(&self) -> Self { *self } + } + #[test] + fn bindgen_test_layout_Struct_A() { + assert_eq!(::std::mem::size_of::<Struct_A>() , 4usize); + assert_eq!(::std::mem::align_of::<Struct_A>() , 4usize); + } + extern "C" { + #[link_name = "_ZN12_GLOBAL__N_13fooEv"] + pub fn foo(); + } + pub mod empty { + use root; + } + } + pub mod w { + use root; + pub type whatever_int_t = ::std::os::raw::c_uint; + #[repr(C)] + #[derive(Debug)] + pub struct Struct_D<T> { + pub m_c: root::Struct_C<T>, + pub _phantom0: ::std::marker::PhantomData<T>, + } + extern "C" { + #[link_name = "_ZN1w3hehEv"] + pub fn heh() -> root::w::whatever_int_t; + #[link_name = "_ZN1w3fooEv"] + pub fn foo() -> root::Struct_C<::std::os::raw::c_int>; + #[link_name = "_ZN1w4barrEv"] + pub fn barr() -> root::Struct_C<f32>; + } + } } diff --git a/tests/expectations/template.rs b/tests/expectations/template.rs index fb790d9b..d3200440 100644 --- a/tests/expectations/template.rs +++ b/tests/expectations/template.rs @@ -31,7 +31,7 @@ pub struct Struct_D_U<T, Z> { #[derive(Debug, Copy, Clone)] pub struct Struct_Rooted<T> { pub prev: *mut T, - pub next: *mut T, + pub next: *mut Struct_Rooted<*mut ::std::os::raw::c_void>, pub ptr: T, } #[repr(C)] diff --git a/tests/headers/namespace.hpp b/tests/headers/namespace.hpp index 90c95d39..e69158d7 100644 --- a/tests/headers/namespace.hpp +++ b/tests/headers/namespace.hpp @@ -1,4 +1,4 @@ - +// bindgen-flags: -enable-cxx-namespaces void top_level(); diff --git a/tests/headers/template.hpp b/tests/headers/template.hpp index 872d6e60..d70459ad 100644 --- a/tests/headers/template.hpp +++ b/tests/headers/template.hpp @@ -22,7 +22,7 @@ class D { template<typename T> class Rooted { T* prev; - T* next; + Rooted<void*>* next; T ptr; }; |