From 29f199c00317b8bf4021cf3efaf863fa21d5a81f Mon Sep 17 00:00:00 2001 From: Nikhil Shagrithaya Date: Mon, 27 Feb 2017 16:01:15 +0530 Subject: [PATCH 1/2] Added codegen for destructors --- src/codegen/mod.rs | 19 +++++++++++++++++++ src/ir/comp.rs | 21 +++++++++++++++++++-- src/ir/function.rs | 7 ++++--- src/lib.rs | 4 ++++ tests/expectations/tests/public-dtor.rs | 10 ++++++++++ tests/expectations/tests/union_dtor.rs | 10 ++++++++++ tests/expectations/tests/virtual_dtor.rs | 10 ++++++++++ 7 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 120acefad3..42e0a4f672 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1456,6 +1456,20 @@ impl CodeGenerator for CompInfo { self); } } + + if ctx.options().codegen_config.destructor { + if let Some(destructor) = *self.destructor() { + Method::new(MethodKind::Destructor, + destructor, + false) + .codegen_method(ctx, + &mut methods, + &mut method_names, + result, + whitelisted_items, + self); + } + } } // NB: We can't use to_rust_ty here since for opaque types this tries to @@ -1560,6 +1574,11 @@ impl MethodCodegen for Method { let signature_item = ctx.resolve_item(function.signature()); let mut name = match self.kind() { MethodKind::Constructor => "new".into(), + MethodKind::Destructor => { + let mut prefix = "_bindgen_destructor_".to_owned(); + prefix.push_str(function.name().trim_left_matches('~')); + prefix + }, _ => function.name().to_owned(), }; diff --git a/src/ir/comp.rs b/src/ir/comp.rs index b97879f710..0d3ffde58d 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -26,6 +26,8 @@ pub enum MethodKind { /// A constructor. We represent it as method for convenience, to avoid code /// duplication. Constructor, + /// A destructor method + Destructor, /// A static method. Static, /// A normal method. @@ -61,6 +63,11 @@ impl Method { self.kind } + /// Is this a destructor method? + pub fn is_destructor(&self) -> bool { + self.kind == MethodKind::Destructor + } + /// Is this a constructor? pub fn is_constructor(&self) -> bool { self.kind == MethodKind::Constructor @@ -249,6 +256,9 @@ pub struct CompInfo { /// The different constructors this struct or class contains. constructors: Vec, + /// The destructor of this type + destructor: Option, + /// Vector of classes this one inherits from. base_members: Vec, @@ -323,6 +333,7 @@ impl CompInfo { template_args: vec![], methods: vec![], constructors: vec![], + destructor: None, base_members: vec![], ref_template: None, inner_types: vec![], @@ -468,6 +479,11 @@ impl CompInfo { &self.constructors } + /// Get this type's destructor. + pub fn destructor(&self) -> &Option { + &self.destructor + } + /// What kind of compound type is this? pub fn kind(&self) -> CompKind { self.kind @@ -729,8 +745,9 @@ impl CompInfo { CXCursor_Constructor => { ci.constructors.push(signature); } - // TODO(emilio): Bind the destructor? - CXCursor_Destructor => {} + CXCursor_Destructor => { + ci.destructor = Some(signature); + } CXCursor_CXXMethod => { let is_const = cur.method_is_const(); let method_kind = if is_static { diff --git a/src/ir/function.rs b/src/ir/function.rs index ad336c4ba3..dd5981533a 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -217,13 +217,14 @@ impl FunctionSig { let is_method = cursor.kind() == CXCursor_CXXMethod; let is_constructor = cursor.kind() == CXCursor_Constructor; - if (is_constructor || is_method) && + let is_destructor = cursor.kind() == CXCursor_Destructor; + if (is_constructor || is_destructor || is_method) && cursor.lexical_parent() != cursor.semantic_parent() { // Only parse constructors once. return Err(ParseError::Continue); } - if is_method || is_constructor { + if is_method || is_constructor || is_destructor { let is_const = is_method && cursor.method_is_const(); let is_virtual = is_method && cursor.method_is_virtual(); let is_static = is_method && cursor.method_is_static(); @@ -288,9 +289,9 @@ impl ClangSubItemParser for Function { -> Result, ParseError> { use clang_sys::*; match cursor.kind() { - // FIXME(emilio): Generate destructors properly. CXCursor_FunctionDecl | CXCursor_Constructor | + CXCursor_Destructor | CXCursor_CXXMethod => {} _ => return Err(ParseError::Continue), }; diff --git a/src/lib.rs b/src/lib.rs index 5e14d81eed..277660f274 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,6 +109,8 @@ pub struct CodegenConfig { pub methods: bool, /// Whether to generate constructors. pub constructors: bool, + /// Whether to generate a destructor. + pub destructor: bool, } impl CodegenConfig { @@ -120,6 +122,7 @@ impl CodegenConfig { vars: true, methods: true, constructors: true, + destructor: true, } } @@ -131,6 +134,7 @@ impl CodegenConfig { vars: false, methods: false, constructors: false, + destructor: false, } } } diff --git a/tests/expectations/tests/public-dtor.rs b/tests/expectations/tests/public-dtor.rs index 1accf49cb5..88bed98b02 100644 --- a/tests/expectations/tests/public-dtor.rs +++ b/tests/expectations/tests/public-dtor.rs @@ -16,3 +16,13 @@ fn bindgen_test_layout_cv_String() { assert_eq! (::std::mem::align_of::() , 1usize , concat ! ( "Alignment of " , stringify ! ( cv_String ) )); } +extern "C" { + #[link_name = "_ZN2cv6StringD1Ev"] + pub fn cv_String_~String(this: *mut cv_String); +} +impl cv_String { + #[inline] + pub unsafe fn _bindgen_destructor_String(&mut self) { + cv_String_~String(&mut *self) + } +} diff --git a/tests/expectations/tests/union_dtor.rs b/tests/expectations/tests/union_dtor.rs index bfd573e021..5d1378d157 100644 --- a/tests/expectations/tests/union_dtor.rs +++ b/tests/expectations/tests/union_dtor.rs @@ -52,3 +52,13 @@ fn bindgen_test_layout_UnionWithDtor() { "Alignment of field: " , stringify ! ( UnionWithDtor ) , "::" , stringify ! ( mBar ) )); } +extern "C" { + #[link_name = "_ZN13UnionWithDtorD1Ev"] + pub fn UnionWithDtor_~UnionWithDtor(this: *mut UnionWithDtor); +} +impl UnionWithDtor { + #[inline] + pub unsafe fn _bindgen_destructor_UnionWithDtor(&mut self) { + UnionWithDtor_~UnionWithDtor(&mut *self) + } +} diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs index 0c4109776d..5e2b098542 100644 --- a/tests/expectations/tests/virtual_dtor.rs +++ b/tests/expectations/tests/virtual_dtor.rs @@ -20,6 +20,16 @@ fn bindgen_test_layout_nsSlots() { assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( nsSlots ) )); } +extern "C" { + #[link_name = "_ZN7nsSlotsD1Ev"] + pub fn nsSlots_~nsSlots(this: *mut nsSlots); +} impl Default for nsSlots { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } +impl nsSlots { + #[inline] + pub unsafe fn _bindgen_destructor_nsSlots(&mut self) { + nsSlots_~nsSlots(&mut *self) + } +} From dfb6a584bbfd0a1abea76b2c9627b01331414352 Mon Sep 17 00:00:00 2001 From: Nikhil Shagrithaya Date: Tue, 14 Mar 2017 00:40:15 +0530 Subject: [PATCH 2/2] Changes: part I --- src/codegen/mod.rs | 6 +----- src/ir/function.rs | 11 ++++++++++- tests/expectations/tests/public-dtor.rs | 6 +++--- tests/expectations/tests/union_dtor.rs | 6 +++--- tests/expectations/tests/virtual_dtor.rs | 6 +++--- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 42e0a4f672..b6161e4cb3 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1574,11 +1574,7 @@ impl MethodCodegen for Method { let signature_item = ctx.resolve_item(function.signature()); let mut name = match self.kind() { MethodKind::Constructor => "new".into(), - MethodKind::Destructor => { - let mut prefix = "_bindgen_destructor_".to_owned(); - prefix.push_str(function.name().trim_left_matches('~')); - prefix - }, + MethodKind::Destructor => "__bindgen_destructor__".into(), _ => function.name().to_owned(), }; diff --git a/src/ir/function.rs b/src/ir/function.rs index dd5981533a..ca6c0a7488 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -323,7 +323,16 @@ impl ClangSubItemParser for Function { None, context)); - let name = cursor.spelling(); + let name = match cursor.kind() { + CXCursor_Destructor => { + let mut name_ = cursor.spelling(); + // remove the `~` + name_.remove(0); + name_ + "_destructor" + }, + _ => cursor.spelling(), + }; + assert!(!name.is_empty(), "Empty function name?"); let mut mangled_name = cursor_mangling(context, &cursor); diff --git a/tests/expectations/tests/public-dtor.rs b/tests/expectations/tests/public-dtor.rs index 88bed98b02..0412b9f4b7 100644 --- a/tests/expectations/tests/public-dtor.rs +++ b/tests/expectations/tests/public-dtor.rs @@ -18,11 +18,11 @@ fn bindgen_test_layout_cv_String() { } extern "C" { #[link_name = "_ZN2cv6StringD1Ev"] - pub fn cv_String_~String(this: *mut cv_String); + pub fn cv_String_String_destructor(this: *mut cv_String); } impl cv_String { #[inline] - pub unsafe fn _bindgen_destructor_String(&mut self) { - cv_String_~String(&mut *self) + pub unsafe fn __bindgen_destructor__(&mut self) { + cv_String_String_destructor(&mut *self) } } diff --git a/tests/expectations/tests/union_dtor.rs b/tests/expectations/tests/union_dtor.rs index 5d1378d157..1bcb45b672 100644 --- a/tests/expectations/tests/union_dtor.rs +++ b/tests/expectations/tests/union_dtor.rs @@ -54,11 +54,11 @@ fn bindgen_test_layout_UnionWithDtor() { } extern "C" { #[link_name = "_ZN13UnionWithDtorD1Ev"] - pub fn UnionWithDtor_~UnionWithDtor(this: *mut UnionWithDtor); + pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor); } impl UnionWithDtor { #[inline] - pub unsafe fn _bindgen_destructor_UnionWithDtor(&mut self) { - UnionWithDtor_~UnionWithDtor(&mut *self) + pub unsafe fn __bindgen_destructor__(&mut self) { + UnionWithDtor_UnionWithDtor_destructor(&mut *self) } } diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs index 5e2b098542..2a594ab5a3 100644 --- a/tests/expectations/tests/virtual_dtor.rs +++ b/tests/expectations/tests/virtual_dtor.rs @@ -22,14 +22,14 @@ fn bindgen_test_layout_nsSlots() { } extern "C" { #[link_name = "_ZN7nsSlotsD1Ev"] - pub fn nsSlots_~nsSlots(this: *mut nsSlots); + pub fn nsSlots_nsSlots_destructor(this: *mut nsSlots); } impl Default for nsSlots { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } impl nsSlots { #[inline] - pub unsafe fn _bindgen_destructor_nsSlots(&mut self) { - nsSlots_~nsSlots(&mut *self) + pub unsafe fn __bindgen_destructor__(&mut self) { + nsSlots_nsSlots_destructor(&mut *self) } }