diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 0dbb2fd11..026e28cec 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -352,6 +352,15 @@ bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl) { return !cxx->defaultedCopyConstructorIsDeleted(); } +bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl) { + for (auto *field : decl->fields()) { + if (!field->getType()->isReferenceType()) { + return false; + } + } + return true; +} + bool HasDefaultedCopyAssignment(const clang::RecordDecl *decl) { auto *cxx = clang::dyn_cast(decl); if (!cxx) { diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index 709940a70..9de6114f9 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -87,6 +87,8 @@ bool HasCallableCopyConstructor(const clang::RecordDecl *decl); bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl); +bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl); + bool HasDefaultedCopyAssignment(const clang::RecordDecl *decl); bool IsRValueConvertingConstructor(const clang::CXXConstructorDecl *ctor); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index e139bf48b..31c1e77e9 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -480,6 +480,9 @@ void ConverterRefCount::AddCloneTrait(const clang::RecordDecl *decl) { return; } + if (HasDefaultedCopyConstructor(decl) && RecordHasOnlyReferenceFields(decl)) { + return; + } auto *cxx = clang::dyn_cast(decl); if (!cxx) { StrCat(keyword::kImpl, "Clone for", record_name); @@ -2115,6 +2118,10 @@ ConverterRefCount::GetStructAttributes(const clang::RecordDecl *decl) { return attrs; } + if (HasDefaultedCopyConstructor(decl) && RecordHasOnlyReferenceFields(decl)) { + attrs.emplace_back("Clone"); + } + if (RecordDerivesDefault(decl)) { attrs.emplace_back("Default"); } diff --git a/tests/ub/out/refcount/ctor_ref_member.rs b/tests/ub/out/refcount/ctor_ref_member.rs index 485688a0f..7cde83873 100644 --- a/tests/ub/out/refcount/ctor_ref_member.rs +++ b/tests/ub/out/refcount/ctor_ref_member.rs @@ -6,7 +6,7 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(Default)] +#[derive(Clone, Default)] pub struct S { pub r: Ptr, } @@ -17,15 +17,6 @@ impl S { Rc::try_unwrap(__this).ok().unwrap().into_inner() } } -impl Clone for S { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - r: (self.r).clone(), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for S {} pub fn main() { __cpp2rust_init_globals(); diff --git a/tests/ub/out/refcount/ub6.rs b/tests/ub/out/refcount/ub6.rs index ad4b8c8fd..aa8222876 100644 --- a/tests/ub/out/refcount/ub6.rs +++ b/tests/ub/out/refcount/ub6.rs @@ -6,21 +6,11 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(Default)] +#[derive(Clone, Default)] pub struct Pair { pub x1: Ptr, pub x2: Ptr, } -impl Clone for Pair { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - x1: (self.x1).clone(), - x2: (self.x2).clone(), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Pair {} pub fn mkPair_0(x1: Ptr, x2: Ptr) -> Pair { return Pair { diff --git a/tests/unit/clone_vs_move.cpp b/tests/unit/clone_vs_move.cpp index 915f55e21..5d4cd0757 100644 --- a/tests/unit/clone_vs_move.cpp +++ b/tests/unit/clone_vs_move.cpp @@ -16,6 +16,11 @@ struct Foo { Bar bar; }; +struct Refs { + int &a; + int &b; +}; + int main() { int x1 = 1; int x2 = x1; @@ -182,5 +187,15 @@ int main() { assert(v2[i] == i + 1); } + int ra = 1, rb = 2; + Refs r1{ra, rb}; + Refs r2 = r1; + r2.a = 10; + ++r2.b; + assert(ra == 10); + assert(rb == 3); + assert(r1.a == 10); + assert(r1.b == 3); + return 0; } diff --git a/tests/unit/out/refcount/clone_vs_move.rs b/tests/unit/out/refcount/clone_vs_move.rs index d23c00968..e4b3e3cd3 100644 --- a/tests/unit/out/refcount/clone_vs_move.rs +++ b/tests/unit/out/refcount/clone_vs_move.rs @@ -69,6 +69,12 @@ impl Default for Foo { } } impl ByteRepr for Foo {} +#[derive(Clone, Default)] +pub struct Refs { + pub a: Ptr, + pub b: Ptr, +} +impl ByteRepr for Refs {} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -507,6 +513,19 @@ fn main_0() -> i32 { ); (*i.borrow_mut()).prefix_inc(); } + let ra: Value = Rc::new(RefCell::new(1)); + let rb: Value = Rc::new(RefCell::new(2)); + let r1: Value = Rc::new(RefCell::new(Refs { + a: ra.as_pointer(), + b: rb.as_pointer(), + })); + let r2: Value = Rc::new(RefCell::new((*r1.borrow()).clone())); + (*r2.borrow()).a.write(10); + (*r2.borrow()).b.with_mut(|__v| __v.prefix_inc()); + assert!(((*ra.borrow()) == 10)); + assert!(((*rb.borrow()) == 3)); + assert!((((*r1.borrow()).a.read()) == 10)); + assert!((((*r1.borrow()).b.read()) == 3)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/complex_function.rs b/tests/unit/out/refcount/complex_function.rs index 76ba6b783..7ecac949a 100644 --- a/tests/unit/out/refcount/complex_function.rs +++ b/tests/unit/out/refcount/complex_function.rs @@ -43,19 +43,10 @@ impl ByteRepr for X1 { } } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct X2 { pub v: Ptr, } -impl Clone for X2 { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - v: (self.v).clone(), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for X2 {} #[derive(Default)] pub struct X3 { diff --git a/tests/unit/out/refcount/destructor.rs b/tests/unit/out/refcount/destructor.rs index 5050cd7c4..92e25ceed 100644 --- a/tests/unit/out/refcount/destructor.rs +++ b/tests/unit/out/refcount/destructor.rs @@ -9,15 +9,8 @@ use std::rc::{Rc, Weak}; thread_local!( pub static global_0: Value = Rc::new(RefCell::new(0)); ); -#[derive(Default)] +#[derive(Clone, Default)] pub struct S {} -impl Clone for S { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for S { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/function_overloading.rs b/tests/unit/out/refcount/function_overloading.rs index e720b72b7..954075010 100644 --- a/tests/unit/out/refcount/function_overloading.rs +++ b/tests/unit/out/refcount/function_overloading.rs @@ -36,15 +36,8 @@ pub fn foo_3(x: Ptr, y: Ptr, z: Ptr) -> i32 { pub fn bar_4(x: Ptr) -> i32 { return (x.read()); } -#[derive(Default)] +#[derive(Clone, Default)] pub struct Foo {} -impl Clone for Foo { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Foo { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/global_init_side_effect.rs b/tests/unit/out/refcount/global_init_side_effect.rs index 847bf9cf8..3cd7aac03 100644 --- a/tests/unit/out/refcount/global_init_side_effect.rs +++ b/tests/unit/out/refcount/global_init_side_effect.rs @@ -9,7 +9,7 @@ use std::rc::{Rc, Weak}; thread_local!( pub static total_0: Value = Rc::new(RefCell::new(0)); ); -#[derive(Default)] +#[derive(Clone, Default)] pub struct S {} impl S { pub fn S(x: i32) -> Self { @@ -20,13 +20,6 @@ impl S { Rc::try_unwrap(__this).ok().unwrap().into_inner() } } -impl Clone for S { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for S { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/global_non_const_init.rs b/tests/unit/out/refcount/global_non_const_init.rs index a60421a35..760b566e3 100644 --- a/tests/unit/out/refcount/global_non_const_init.rs +++ b/tests/unit/out/refcount/global_non_const_init.rs @@ -99,15 +99,8 @@ thread_local!( thread_local!( pub static inline_member_11: Value = Rc::new(RefCell::new(Ctor::Ctor2({ 5 }))); ); -#[derive(Default)] +#[derive(Clone, Default)] pub struct Holder {} -impl Clone for Holder { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Holder { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/nested_structs.rs b/tests/unit/out/refcount/nested_structs.rs index 31ba4c3eb..1bd02d720 100644 --- a/tests/unit/out/refcount/nested_structs.rs +++ b/tests/unit/out/refcount/nested_structs.rs @@ -144,15 +144,8 @@ impl ByteRepr for Level0_Level1_2 { } } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct Level0 {} -impl Clone for Level0 { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Level0 { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/operator_member_pointer_member.rs b/tests/unit/out/refcount/operator_member_pointer_member.rs index ef79b5c54..90e82e56b 100644 --- a/tests/unit/out/refcount/operator_member_pointer_member.rs +++ b/tests/unit/out/refcount/operator_member_pointer_member.rs @@ -32,7 +32,7 @@ impl ByteRepr for Inner { } } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct Table {} impl Table { pub fn operator_index(i: i32) -> Ptr { @@ -40,13 +40,6 @@ impl Table { return (table_0.with(|v| v.as_pointer()) as Ptr).offset((*i.borrow())); } } -impl Clone for Table { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr
= __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Table { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/operator_other_member.rs b/tests/unit/out/refcount/operator_other_member.rs index fbd3e5c22..930b78f63 100644 --- a/tests/unit/out/refcount/operator_other_member.rs +++ b/tests/unit/out/refcount/operator_other_member.rs @@ -6,7 +6,7 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(Default)] +#[derive(Clone, Default)] pub struct Static {} impl Static { pub fn operator_call(a: i32, b: i32) -> i32 { @@ -15,13 +15,6 @@ impl Static { return ((*a.borrow()) * (*b.borrow())); } } -impl Clone for Static { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Static { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/polymorphism.rs b/tests/unit/out/refcount/polymorphism.rs index ecceb0753..8a78db664 100644 --- a/tests/unit/out/refcount/polymorphism.rs +++ b/tests/unit/out/refcount/polymorphism.rs @@ -9,20 +9,13 @@ use std::rc::{Rc, Weak}; pub trait Animal { fn bark(&self) -> bool; } -#[derive(Default)] +#[derive(Clone, Default)] pub struct Dog {} impl Animal for Dog { fn bark(&self) -> bool { return true; } } -impl Clone for Dog { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Dog { fn byte_size() -> usize { 8 @@ -32,20 +25,13 @@ impl ByteRepr for Dog { Self {} } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct Cat {} impl Animal for Cat { fn bark(&self) -> bool { return false; } } -impl Clone for Cat { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for Cat { fn byte_size() -> usize { 8 diff --git a/tests/unit/out/refcount/random.rs b/tests/unit/out/refcount/random.rs index e81f828cd..ba8f0cdf0 100644 --- a/tests/unit/out/refcount/random.rs +++ b/tests/unit/out/refcount/random.rs @@ -58,15 +58,8 @@ impl ByteRepr for Pair {} pub fn zero_0() -> i32 { return 0; } -#[derive(Default)] +#[derive(Clone, Default)] pub struct X1 {} -impl Clone for X1 { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for X1 { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/static_var_in_class.rs b/tests/unit/out/refcount/static_var_in_class.rs index 25170f912..0996ec9ff 100644 --- a/tests/unit/out/refcount/static_var_in_class.rs +++ b/tests/unit/out/refcount/static_var_in_class.rs @@ -9,15 +9,8 @@ use std::rc::{Rc, Weak}; thread_local!( static inner_const_0: Value = Rc::new(RefCell::new(1)); ); -#[derive(Default)] +#[derive(Clone, Default)] pub struct C {} -impl Clone for C { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for C { fn byte_size() -> usize { 1 @@ -30,15 +23,8 @@ impl ByteRepr for C { thread_local!( pub static inner_const_1: Value = Rc::new(RefCell::new(2)); ); -#[derive(Default)] +#[derive(Clone, Default)] pub struct S {} -impl Clone for S { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for S { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/refcount/vector_with_allocator.rs b/tests/unit/out/refcount/vector_with_allocator.rs index 9787e6eab..401a0f8c2 100644 --- a/tests/unit/out/refcount/vector_with_allocator.rs +++ b/tests/unit/out/refcount/vector_with_allocator.rs @@ -6,15 +6,8 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(Default)] +#[derive(Clone, Default)] pub struct TestAllocator_int_ {} -impl Clone for TestAllocator_int_ { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for TestAllocator_int_ { fn byte_size() -> usize { 1 @@ -24,15 +17,8 @@ impl ByteRepr for TestAllocator_int_ { Self {} } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct TestAllocator_double_ {} -impl Clone for TestAllocator_double_ { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self {})); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} impl ByteRepr for TestAllocator_double_ { fn byte_size() -> usize { 1 diff --git a/tests/unit/out/unsafe/clone_vs_move.rs b/tests/unit/out/unsafe/clone_vs_move.rs index b764f6f73..dc31af089 100644 --- a/tests/unit/out/unsafe/clone_vs_move.rs +++ b/tests/unit/out/unsafe/clone_vs_move.rs @@ -31,6 +31,12 @@ impl Default for Foo { } } } +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct Refs { + pub a: *mut i32, + pub b: *mut i32, +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -246,6 +252,19 @@ unsafe fn main_0() -> i32 { assert!(((v2[(i as usize)]) == ((i) + (1)))); i.prefix_inc(); } + let mut ra: i32 = 1; + let mut rb: i32 = 2; + let mut r1: Refs = Refs { + a: &mut ra, + b: &mut rb, + }; + let mut r2: Refs = r1; + (*r2.a) = 10; + (*r2.b).prefix_inc(); + assert!(((ra) == (10))); + assert!(((rb) == (3))); + assert!(((*r1.a) == (10))); + assert!(((*r1.b) == (3))); return 0; } pub unsafe fn __cpp2rust_init_globals() {}