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
27 changes: 16 additions & 11 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,11 +508,11 @@ bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl) {
return true;
}
for (const auto *ctor : cxx->ctors()) {
if (ctor->isCopyConstructor()) {
return !ctor->isUserProvided() && !ctor->isDeleted();
if (ctor->isCopyConstructor() && ctor->isUserProvided()) {
return false;
}
}
return !cxx->defaultedCopyConstructorIsDeleted();
return HasCallableCopyConstructor(cxx);
}

bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl) {
Expand Down Expand Up @@ -542,16 +542,21 @@ bool HasCallableCopyConstructor(const clang::RecordDecl *decl) {
if (!cxx) {
return true;
}
if (!cxx->hasUserDeclaredCopyConstructor()) {
return !cxx->defaultedCopyConstructorIsDeleted();
if (cxx->hasUserDeclaredCopyConstructor()) {
return std::ranges::any_of(cxx->ctors(), [](const auto *ctor) {
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
ctor->getDefinition();
});
}
for (const auto *ctor : cxx->ctors()) {
if (ctor->isCopyConstructor() && !ctor->isDeleted() &&
ctor->getDefinition()) {
return true;
}
if (cxx->defaultedCopyConstructorIsDeleted()) {
return false;
}
return false;
auto &ctx = cxx->getASTContext();
return std::ranges::all_of(cxx->fields(), [&](const clang::FieldDecl *f) {
auto *record = ctx.getBaseElementType(f->getType())->getAsCXXRecordDecl();
return !record || !IsUserDefinedDecl(record) ||
HasCallableCopyConstructor(record);
});
}

bool IsRValueConvertingConstructor(const clang::CXXConstructorDecl *ctor) {
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/copy_ctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ struct Holder {
Counted arr[2];
};

template <class T> struct Box {
T val;
Box(T v) : val(std::move(v)) {}
Box(const Box &o) : val(o.val) {}
Box(Box &&) = default;
};

struct Owner {
Box<int> box;
};

static int by_value(Counted c) { return c.v; }

static Counted make(int v) {
Expand Down Expand Up @@ -74,6 +85,10 @@ int main() {
assert(i1.v == 1 && i2.v == -1);
assert(copies == 11);

Owner o{Box<int>(3)};
Owner o2 = std::move(o);
assert(o2.box.val == 3);

NonConst n;
NonConst n1(n);
const NonConst cn;
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/out/refcount/copy_ctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,37 @@ impl Default for Holder {
}
}
}
#[derive(Record, ByteRepr, Default)]
#[byte_size(4)]
pub struct Box_int_ {
#[offset(0)]
pub val: i32,
}
impl Box_int_ {
pub fn new(v: i32) -> Self {
let v: Value<i32> = Rc::new(RefCell::new(v));
Self { val: (*v.borrow()) }
}
pub fn move_from(_a0: Ptr<Box_int_>) -> Self {
Self {
val: { (*_a0.upgrade().deref()).val },
}
}
}
#[derive(Record, ByteRepr, Default)]
#[byte_size(4)]
pub struct Owner {
#[offset(0)]
#[byte_size(4)]
pub box_: Box_int_,
}
impl Owner {
pub fn move_from(_a0: Ptr<Owner>) -> Self {
Self {
box_: Box_int_::move_from({ field_ptr!(_a0, box_) }),
}
}
}
pub fn by_value_1(mut c: Counted) -> i32 {
return c.v;
}
Expand Down Expand Up @@ -176,6 +207,11 @@ fn main_0() -> i32 {
let mut i2: Ignored = Ignored::copy_from({ i1.as_pointer() });
assert!(({ (*i1.borrow()).v } == 1) && (i2.v == -1_i32));
assert!((copies_0.with(|rc| *rc.borrow()) == 11));
let o: Value<Owner> = Rc::new(RefCell::new(Owner {
box_: Box_int_::new({ 3 }),
}));
let mut o2: Owner = Owner::move_from({ o.as_pointer() });
assert!((o2.box_.val == 3));
let n: Value<NonConst> = Rc::new(RefCell::new(NonConst::new()));
let mut n1: NonConst = NonConst::new_1({ n.as_pointer() });
let cn: Value<NonConst> = Rc::new(RefCell::new(NonConst::new()));
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/out/unsafe/copy_ctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,34 @@ pub struct Holder {
pub c: Counted,
pub arr: [Counted; 2],
}
#[repr(C)]
#[derive(Default)]
pub struct Box_int_ {
pub val: i32,
}
impl Box_int_ {
pub unsafe fn new(mut v: i32) -> Self {
let mut this = Self { val: v };
this
}
pub unsafe fn move_from(_a0: *mut Box_int_) -> Self {
let mut this = Self { val: (*_a0).val };
this
}
}
#[repr(C)]
#[derive(Default)]
pub struct Owner {
pub box_: Box_int_,
}
impl Owner {
pub unsafe fn move_from(_a0: *mut Owner) -> Self {
let mut this = Self {
box_: Box_int_::move_from({ &mut (*_a0).box_ }),
};
this
}
}
pub unsafe fn by_value_1(mut c: Counted) -> i32 {
return c.v;
}
Expand Down Expand Up @@ -141,6 +169,11 @@ unsafe fn main_0() -> i32 {
let mut i2: Ignored = Ignored::copy_from({ &i1 });
assert!(((i1.v) == (1)) && ((i2.v) == (-1_i32)));
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (11)));
let mut o: Owner = Owner {
box_: Box_int_::new({ 3 }),
};
let mut o2: Owner = Owner::move_from({ &mut o });
assert!(((o2.box_.val) == (3)));
let mut n: NonConst = NonConst::new();
let mut n1: NonConst = NonConst::new_1({ &mut n });
let cn: NonConst = NonConst::new();
Expand Down
Loading