Skip to content

Added codegen for destructors #542

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

Closed
Closed
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
15 changes: 15 additions & 0 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1560,6 +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 => "__bindgen_destructor__".into(),
_ => function.name().to_owned(),
};

Expand Down
21 changes: 19 additions & 2 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -249,6 +256,9 @@ pub struct CompInfo {
/// The different constructors this struct or class contains.
constructors: Vec<ItemId>,

/// The destructor of this type
destructor: Option<ItemId>,

/// Vector of classes this one inherits from.
base_members: Vec<Base>,

Expand Down Expand Up @@ -323,6 +333,7 @@ impl CompInfo {
template_args: vec![],
methods: vec![],
constructors: vec![],
destructor: None,
base_members: vec![],
ref_template: None,
inner_types: vec![],
Expand Down Expand Up @@ -468,6 +479,11 @@ impl CompInfo {
&self.constructors
}

/// Get this type's destructor.
pub fn destructor(&self) -> &Option<ItemId> {
&self.destructor
}

/// What kind of compound type is this?
pub fn kind(&self) -> CompKind {
self.kind
Expand Down Expand Up @@ -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 {
Expand Down
18 changes: 14 additions & 4 deletions src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -288,9 +289,9 @@ impl ClangSubItemParser for Function {
-> Result<ParseResult<Self>, ParseError> {
use clang_sys::*;
match cursor.kind() {
// FIXME(emilio): Generate destructors properly.
CXCursor_FunctionDecl |
CXCursor_Constructor |
CXCursor_Destructor |
CXCursor_CXXMethod => {}
_ => return Err(ParseError::Continue),
};
Expand Down Expand Up @@ -322,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);
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -120,6 +122,7 @@ impl CodegenConfig {
vars: true,
methods: true,
constructors: true,
destructor: true,
}
}

Expand All @@ -131,6 +134,7 @@ impl CodegenConfig {
vars: false,
methods: false,
constructors: false,
destructor: false,
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions tests/expectations/tests/public-dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,13 @@ fn bindgen_test_layout_cv_String() {
assert_eq! (::std::mem::align_of::<cv_String>() , 1usize , concat ! (
"Alignment of " , stringify ! ( cv_String ) ));
}
extern "C" {
#[link_name = "_ZN2cv6StringD1Ev"]
pub fn cv_String_String_destructor(this: *mut cv_String);
}
impl cv_String {
#[inline]
pub unsafe fn __bindgen_destructor__(&mut self) {
cv_String_String_destructor(&mut *self)
}
}
10 changes: 10 additions & 0 deletions tests/expectations/tests/union_dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_destructor(this: *mut UnionWithDtor);
}
impl UnionWithDtor {
#[inline]
pub unsafe fn __bindgen_destructor__(&mut self) {
UnionWithDtor_UnionWithDtor_destructor(&mut *self)
}
}
10 changes: 10 additions & 0 deletions tests/expectations/tests/virtual_dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ fn bindgen_test_layout_nsSlots() {
assert_eq! (::std::mem::align_of::<nsSlots>() , 8usize , concat ! (
"Alignment of " , stringify ! ( nsSlots ) ));
}
extern "C" {
#[link_name = "_ZN7nsSlotsD1Ev"]
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__(&mut self) {
nsSlots_nsSlots_destructor(&mut *self)
}
}