Skip to content

Commit

Permalink
enum: Add an option to generate copy-assignments.
Browse files Browse the repository at this point in the history
And recommend its usage if copy-constructors are being generated, as otherwise
C++ in its whole glory would do a bitwise copy, which is not really what you
want if you have constructors / destructors around.
  • Loading branch information
emilio committed Dec 16, 2019
1 parent 2b2ab90 commit 8cdf940
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 0 deletions.
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
22 changes: 22 additions & 0 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,28 @@ 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

0 comments on commit 8cdf940

Please sign in to comment.