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
9 changes: 9 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<clang::CXXRecordDecl>(decl);
if (!cxx) {
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,9 @@ void ConverterRefCount::AddCloneTrait(const clang::RecordDecl *decl) {
return;
}

if (HasDefaultedCopyConstructor(decl) && RecordHasOnlyReferenceFields(decl)) {
return;
}
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
if (!cxx) {
StrCat(keyword::kImpl, "Clone for", record_name);
Expand Down Expand Up @@ -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");
}
Expand Down
11 changes: 1 addition & 10 deletions tests/ub/out/refcount/ctor_ref_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<i32>,
}
Expand All @@ -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<S> = Rc::new(RefCell::new(Self {
r: (self.r).clone(),
}));
let this: Ptr<S> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for S {}
pub fn main() {
__cpp2rust_init_globals();
Expand Down
12 changes: 1 addition & 11 deletions tests/ub/out/refcount/ub6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<i32>,
pub x2: Ptr<i32>,
}
impl Clone for Pair {
fn clone(&self) -> Self {
let __this: Value<Pair> = Rc::new(RefCell::new(Self {
x1: (self.x1).clone(),
x2: (self.x2).clone(),
}));
let this: Ptr<Pair> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Pair {}
pub fn mkPair_0(x1: Ptr<i32>, x2: Ptr<i32>) -> Pair {
return Pair {
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/clone_vs_move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ struct Foo {
Bar bar;
};

struct Refs {
int &a;
int &b;
};

int main() {
int x1 = 1;
int x2 = x1;
Expand Down Expand Up @@ -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;
}
19 changes: 19 additions & 0 deletions tests/unit/out/refcount/clone_vs_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ impl Default for Foo {
}
}
impl ByteRepr for Foo {}
#[derive(Clone, Default)]
pub struct Refs {
pub a: Ptr<i32>,
pub b: Ptr<i32>,
}
impl ByteRepr for Refs {}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
Expand Down Expand Up @@ -507,6 +513,19 @@ fn main_0() -> i32 {
);
(*i.borrow_mut()).prefix_inc();
}
let ra: Value<i32> = Rc::new(RefCell::new(1));
let rb: Value<i32> = Rc::new(RefCell::new(2));
let r1: Value<Refs> = Rc::new(RefCell::new(Refs {
a: ra.as_pointer(),
b: rb.as_pointer(),
}));
let r2: Value<Refs> = 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() {}
11 changes: 1 addition & 10 deletions tests/unit/out/refcount/complex_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,10 @@ impl ByteRepr for X1 {
}
}
}
#[derive(Default)]
#[derive(Clone, Default)]
pub struct X2 {
pub v: Ptr<X1>,
}
impl Clone for X2 {
fn clone(&self) -> Self {
let __this: Value<X2> = Rc::new(RefCell::new(Self {
v: (self.v).clone(),
}));
let this: Ptr<X2> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for X2 {}
#[derive(Default)]
pub struct X3 {
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/destructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,8 @@ use std::rc::{Rc, Weak};
thread_local!(
pub static global_0: Value<i32> = Rc::new(RefCell::new(0));
);
#[derive(Default)]
#[derive(Clone, Default)]
pub struct S {}
impl Clone for S {
fn clone(&self) -> Self {
let __this: Value<S> = Rc::new(RefCell::new(Self {}));
let this: Ptr<S> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for S {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/function_overloading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,8 @@ pub fn foo_3(x: Ptr<i32>, y: Ptr<i32>, z: Ptr<i32>) -> i32 {
pub fn bar_4(x: Ptr<i32>) -> i32 {
return (x.read());
}
#[derive(Default)]
#[derive(Clone, Default)]
pub struct Foo {}
impl Clone for Foo {
fn clone(&self) -> Self {
let __this: Value<Foo> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Foo> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Foo {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/global_init_side_effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::rc::{Rc, Weak};
thread_local!(
pub static total_0: Value<i32> = Rc::new(RefCell::new(0));
);
#[derive(Default)]
#[derive(Clone, Default)]
pub struct S {}
impl S {
pub fn S(x: i32) -> Self {
Expand All @@ -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<S> = Rc::new(RefCell::new(Self {}));
let this: Ptr<S> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for S {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/global_non_const_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,8 @@ thread_local!(
thread_local!(
pub static inline_member_11: Value<Ctor> = 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<Holder> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Holder> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Holder {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/nested_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Level0> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Level0> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Level0 {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/operator_member_pointer_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,14 @@ impl ByteRepr for Inner {
}
}
}
#[derive(Default)]
#[derive(Clone, Default)]
pub struct Table {}
impl Table {
pub fn operator_index(i: i32) -> Ptr<i32> {
let i: Value<i32> = Rc::new(RefCell::new(i));
return (table_0.with(|v| v.as_pointer()) as Ptr<i32>).offset((*i.borrow()));
}
}
impl Clone for Table {
fn clone(&self) -> Self {
let __this: Value<Table> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Table> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Table {
fn byte_size() -> usize {
1
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/operator_other_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -15,13 +15,6 @@ impl Static {
return ((*a.borrow()) * (*b.borrow()));
}
}
impl Clone for Static {
fn clone(&self) -> Self {
let __this: Value<Static> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Static> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Static {
fn byte_size() -> usize {
1
Expand Down
18 changes: 2 additions & 16 deletions tests/unit/out/refcount/polymorphism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Dog> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Dog> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Dog {
fn byte_size() -> usize {
8
Expand All @@ -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<Cat> = Rc::new(RefCell::new(Self {}));
let this: Ptr<Cat> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Cat {
fn byte_size() -> usize {
8
Expand Down
9 changes: 1 addition & 8 deletions tests/unit/out/refcount/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<X1> = Rc::new(RefCell::new(Self {}));
let this: Ptr<X1> = __this.as_pointer();
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for X1 {
fn byte_size() -> usize {
1
Expand Down
Loading
Loading