Skip to content

Commit 3d04fd0

Browse files
committed
Translat move ctors for records that have custom move ctors fields
1 parent 62b87af commit 3d04fd0

5 files changed

Lines changed: 70 additions & 18 deletions

File tree

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -528,12 +528,21 @@ IsConvertibleImplicitMemberParent(const clang::CXXRecordDecl *decl) {
528528
decl->getNumBases() == 0;
529529
}
530530

531+
static bool HasFieldWithMoveFrom(const clang::RecordDecl *decl) {
532+
return llvm::any_of(decl->fields(), [](const clang::FieldDecl *field) {
533+
auto *record = field->getType()->getAsRecordDecl();
534+
return record && HasMoveFromConstructor(record);
535+
});
536+
}
537+
531538
bool IsConvertibleMoveConstructor(const clang::CXXConstructorDecl *ctor) {
532-
return ctor->isMoveConstructor() && !ctor->isDeleted() &&
533-
IsConvertibleImplicitMemberParent(ctor->getParent()) &&
534-
(ctor->isUserProvided() ||
535-
!HasDefaultedCopyConstructor(ctor->getParent())) &&
536-
ctor->hasBody();
539+
auto *parent = ctor->getParent();
540+
if (!ctor->isMoveConstructor() || ctor->isDeleted() || !ctor->hasBody() ||
541+
!IsConvertibleImplicitMemberParent(parent)) {
542+
return false;
543+
}
544+
return ctor->isUserProvided() || !HasDefaultedCopyConstructor(parent) ||
545+
HasFieldWithMoveFrom(parent);
537546
}
538547

539548
bool HasMoveFromConstructor(const clang::RecordDecl *decl) {
@@ -544,12 +553,23 @@ bool HasMoveFromConstructor(const clang::RecordDecl *decl) {
544553
});
545554
}
546555

556+
static bool HasFieldWithMoveAssign(const clang::RecordDecl *decl) {
557+
return llvm::any_of(decl->fields(), [](const clang::FieldDecl *field) {
558+
auto *record = field->getType()->getAsCXXRecordDecl();
559+
return record && llvm::any_of(record->methods(), [](auto *method) {
560+
return IsConvertibleMoveAssignment(method);
561+
});
562+
});
563+
}
564+
547565
bool IsConvertibleMoveAssignment(const clang::CXXMethodDecl *method) {
548-
return method->isMoveAssignmentOperator() && !method->isDeleted() &&
549-
IsConvertibleImplicitMemberParent(method->getParent()) &&
550-
(method->isUserProvided() ||
551-
!HasDefaultedCopyAssignment(method->getParent())) &&
552-
method->hasBody();
566+
auto *parent = method->getParent();
567+
if (!method->isMoveAssignmentOperator() || method->isDeleted() ||
568+
!method->hasBody() || !IsConvertibleImplicitMemberParent(parent)) {
569+
return false;
570+
}
571+
return method->isUserProvided() || !HasDefaultedCopyAssignment(parent) ||
572+
HasFieldWithMoveAssign(parent);
553573
}
554574

555575
bool IsConvertibleImplicitMember(const clang::CXXMethodDecl *method) {

‎tests/unit/out/refcount/copy_ctor.rs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,20 @@ impl Clone for Box_int_ {
143143
Box_int_::copy_from(__src.as_pointer())
144144
}
145145
}
146-
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)]
146+
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)]
147147
#[byte_size(4)]
148148
pub struct Owner {
149149
#[offset(0)]
150150
#[byte_size(4)]
151151
pub box_: Box_int_,
152152
}
153+
impl Owner {
154+
pub fn move_from(_a0: Ptr<Owner>) -> Self {
155+
Self {
156+
box_: Box_int_::move_from({ field_ptr!(_a0, box_) }),
157+
}
158+
}
159+
}
153160
#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)]
154161
#[byte_size(4)]
155162
pub struct OutOfLine {
@@ -272,7 +279,7 @@ fn main_0() -> i32 {
272279
let o: Value<Owner> = Rc::new(RefCell::new(Owner {
273280
box_: Box_int_::new({ 3 }),
274281
}));
275-
let mut o2: Owner = (*o.borrow()).clone();
282+
let mut o2: Owner = Owner::move_from({ o.as_pointer() });
276283
assert!((o2.box_.val == 3));
277284
let ol1: Value<OutOfLine> = Rc::new(RefCell::new(OutOfLine::new({ 5 })));
278285
let mut ol2: OutOfLine = OutOfLine::copy_from({ ol1.as_pointer() });

‎tests/unit/out/refcount/structured_binding_element_ctor.rs‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Clone for Elem {
4444
Elem::copy_from(__src.as_pointer())
4545
}
4646
}
47-
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)]
47+
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)]
4848
#[byte_size(8)]
4949
pub struct Two {
5050
#[offset(0)]
@@ -54,6 +54,14 @@ pub struct Two {
5454
#[byte_size(4)]
5555
pub b: Elem,
5656
}
57+
impl Two {
58+
pub fn move_from(_a0: Ptr<Two>) -> Self {
59+
Self {
60+
a: Elem::move_from({ field_ptr!(_a0, a) }),
61+
b: Elem::move_from({ field_ptr!(_a0, b) }),
62+
}
63+
}
64+
}
5765
pub fn make_two_2() -> Two {
5866
return Two {
5967
a: Elem::new({ 1 }),
@@ -81,7 +89,7 @@ fn main_0() -> i32 {
8189
assert!(({ (*__decomp_4.upgrade().deref()).a.v } == 1));
8290
field!(field!(__decomp_4, a), v).write(50);
8391
assert!(({ (*t.borrow()).a.v } == 50));
84-
let __decomp_5: Value<Two> = Rc::new(RefCell::new((*t.borrow()).clone()));
92+
let __decomp_5: Value<Two> = Rc::new(RefCell::new(Two::move_from({ t.as_pointer() })));
8593
assert!((moves_1.with(|rc| *rc.borrow()) == (base_moves + 2)));
8694
assert!(({ (*__decomp_5.borrow()).a.v } == 1050));
8795
assert!(({ (*__decomp_5.borrow()).b.v } == 1002));

‎tests/unit/out/unsafe/copy_ctor.rs‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,18 @@ impl Clone for Box_int_ {
113113
}
114114
}
115115
#[repr(C)]
116-
#[derive(Clone, VaArg, FnPtrArg, Default)]
116+
#[derive(Clone, VaArg, FnPtrArg, MoveCtorUnsafe, Default)]
117117
pub struct Owner {
118118
pub box_: Box_int_,
119119
}
120+
impl Owner {
121+
pub unsafe fn move_from(_a0: *mut Owner) -> Self {
122+
let mut this = Self {
123+
box_: Box_int_::move_from({ &mut (*_a0).box_ }),
124+
};
125+
this
126+
}
127+
}
120128
#[repr(C)]
121129
#[derive(VaArg, FnPtrArg, Default)]
122130
pub struct OutOfLine {
@@ -226,7 +234,7 @@ unsafe fn main_0() -> i32 {
226234
let mut o: Owner = Owner {
227235
box_: Box_int_::new({ 3 }),
228236
};
229-
let mut o2: Owner = o.clone();
237+
let mut o2: Owner = Owner::move_from({ &mut o });
230238
assert!(((o2.box_.val) == (3)));
231239
let mut ol1: OutOfLine = OutOfLine::new({ 5 });
232240
let mut ol2: OutOfLine = OutOfLine::copy_from({ &ol1 });

‎tests/unit/out/unsafe/structured_binding_element_ctor.rs‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,20 @@ impl Clone for Elem {
4040
}
4141
}
4242
#[repr(C)]
43-
#[derive(Clone, VaArg, FnPtrArg, Default)]
43+
#[derive(Clone, VaArg, FnPtrArg, MoveCtorUnsafe, Default)]
4444
pub struct Two {
4545
pub a: Elem,
4646
pub b: Elem,
4747
}
48+
impl Two {
49+
pub unsafe fn move_from(_a0: *mut Two) -> Self {
50+
let mut this = Self {
51+
a: Elem::move_from({ &mut (*_a0).a }),
52+
b: Elem::move_from({ &mut (*_a0).b }),
53+
};
54+
this
55+
}
56+
}
4857
pub unsafe fn make_two_2() -> Two {
4958
return Two {
5059
a: Elem::new({ 1 }),
@@ -74,7 +83,7 @@ unsafe fn main_0() -> i32 {
7483
assert!((((*__decomp_4).a.v) == (1)));
7584
(*__decomp_4).a.v = 50;
7685
assert!(((t.a.v) == (50)));
77-
let mut __decomp_5: Two = t.clone();
86+
let mut __decomp_5: Two = Two::move_from({ &mut t });
7887
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == ((base_moves) + (2))));
7988
assert!(((__decomp_5.a.v) == (1050)));
8089
assert!(((__decomp_5.b.v) == (1002)));

0 commit comments

Comments
 (0)