Skip to content
Merged
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
7 changes: 7 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,13 @@ derive_tagged_enum_destructor = false
#
# default: false
derive_tagged_enum_copy_constructor = false
# Whether enums with fields should generate copy-assignment operators.
#
# This depends on also deriving copy-constructors, and it is highly encouraged
# for this to be set to true.
#
# default: false
derive_tagged_enum_copy_assignment = false

# Whether enums with fields should generate an empty, private destructor.
# This allows the auto-generated constructor functions to compile, if there are
Expand Down
11 changes: 11 additions & 0 deletions src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,11 @@ pub struct EnumConfig {
pub derive_tagged_enum_destructor: bool,
/// Whether to generate copy-constructors of tagged enums.
pub derive_tagged_enum_copy_constructor: bool,
/// Whether to generate copy-assignment operators of tagged enums.
///
/// This is only generated if a copy constructor for the same tagged enum is
/// generated as well.
pub derive_tagged_enum_copy_assignment: bool,
/// Whether to generate empty, private default-constructors for tagged
/// enums.
pub private_default_tagged_enum_constructor: bool,
Expand Down Expand Up @@ -462,6 +467,12 @@ impl EnumConfig {
}
self.derive_tagged_enum_copy_constructor
}
pub(crate) fn derive_tagged_enum_copy_assignment(&self, annotations: &AnnotationSet) -> bool {
if let Some(x) = annotations.bool("derive-tagged-enum-copy-assignment") {
return x;
}
self.derive_tagged_enum_copy_assignment
}
pub(crate) fn private_default_tagged_enum_constructor(
&self,
annotations: &AnnotationSet,
Expand Down
23 changes: 23 additions & 0 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,29 @@ impl Source for Enum {
write!(out, "default: break;");
out.close_brace(false);
out.close_brace(false);

if config.language == Language::Cxx
&& config
.enumeration
.derive_tagged_enum_copy_assignment(&self.annotations)
{
out.new_line();
write!(
out,
"{}& operator=(const {}& {})",
self.export_name, self.export_name, other
);
out.open_brace();
write!(out, "if (this != &{})", other);
out.open_brace();
write!(out, "this->~{}();", self.export_name);
out.new_line();
write!(out, "new (this) {}({});", self.export_name, other);
out.close_brace(false);
out.new_line();
write!(out, "return *this;");
out.close_brace(false);
}
}

if let Some(body) = config.export.extra_body(&self.path) {
Expand Down
21 changes: 21 additions & 0 deletions tests/expectations/destructor-and-copy-ctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ struct Foo {
default: break;
}
}
Foo& operator=(const Foo& other) {
if (this != &other) {
this->~Foo();
new (this) Foo(other);
}
return *this;
}
};

template<typename T>
Expand Down Expand Up @@ -310,6 +317,13 @@ union Baz {
default: break;
}
}
Baz& operator=(const Baz& other) {
if (this != &other) {
this->~Baz();
new (this) Baz(other);
}
return *this;
}
};

union Taz {
Expand Down Expand Up @@ -390,6 +404,13 @@ union Taz {
default: break;
}
}
Taz& operator=(const Taz& other) {
if (this != &other) {
this->~Taz();
new (this) Taz(other);
}
return *this;
}
};

union Tazz {
Expand Down
7 changes: 7 additions & 0 deletions tests/rust/destructor-and-copy-ctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,12 @@ pub enum Tazz {
Taz2(i32),
}

/// cbindgen:derive-tagged-enum-copy-assignment=false
#[repr(u8)]
pub enum Tazz {
Bar4,
Taz2(i32),
}

#[no_mangle]
pub extern "C" fn root(a: &Foo<u32>, b: &Baz<i32>, c: &Taz, d: Tazz) {}
1 change: 1 addition & 0 deletions tests/rust/destructor-and-copy-ctor.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[enum]
derive_tagged_enum_destructor = true
derive_tagged_enum_copy_constructor = true
derive_tagged_enum_copy_assignment = true
derive_helper_methods = true
private_default_tagged_enum_constructor = true

Expand Down