summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-04-16 06:03:29 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-04-16 06:03:29 +0200
commit774c7dadba23bcc84cb906206cf6b34da2fd6337 (patch)
tree35fde45ed5752236686ba3529873b3a6dc77cd9e
parentca9f853fba5cace90febb52ea4a16d6a4ae394ca (diff)
Refactor how template specialisations are tracked to prevent borrow panics
-rw-r--r--src/gen.rs2
-rw-r--r--src/parser.rs28
-rw-r--r--src/types.rs10
-rw-r--r--tests/expectations/namespace.rs104
-rw-r--r--tests/expectations/template.rs2
-rw-r--r--tests/headers/namespace.hpp2
-rw-r--r--tests/headers/template.hpp2
7 files changed, 84 insertions, 66 deletions
diff --git a/src/gen.rs b/src/gen.rs
index c8144c00..b819c516 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -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;
};