Skip to content

Commit 27ea512

Browse files
committed
Add Clone impl for C structs
1 parent 22edd84 commit 27ea512

31 files changed

Lines changed: 510 additions & 2 deletions

cpp2rust/converter/converter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,9 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
819819
// Traits
820820
if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
821821
AddOrdTrait(cxx);
822-
AddCloneTrait(cxx);
823822
AddDropTrait(cxx);
824823
}
824+
AddCloneTrait(decl);
825825
AddDefaultTrait(decl);
826826
AddByteReprTrait(decl);
827827
}

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,22 @@ void ConverterRefCount::AddCloneTrait(const clang::RecordDecl *decl) {
465465
}
466466

467467
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
468-
if (!cxx || cxx->defaultedCopyConstructorIsDeleted()) {
468+
if (!cxx) {
469+
StrCat(keyword::kImpl, "Clone for", record_name);
470+
PushBrace impl_brace(*this);
471+
StrCat("fn clone(&self) -> Self");
472+
PushBrace fn_brace(*this);
473+
StrCat("Self");
474+
PushBrace init_brace(*this);
475+
for (auto *field : decl->fields()) {
476+
auto name = GetNamedDeclAsString(field);
477+
StrCat(std::format(
478+
"{0}: Rc::new(RefCell::new((*self.{0}.borrow()).clone())),", name));
479+
}
480+
return;
481+
}
482+
483+
if (cxx->defaultedCopyConstructorIsDeleted()) {
469484
return;
470485
}
471486

tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ use std::rc::{Rc, Weak};
1010
pub struct widget {
1111
pub id: Value<i32>,
1212
}
13+
impl Clone for widget {
14+
fn clone(&self) -> Self {
15+
Self {
16+
id: Rc::new(RefCell::new((*self.id.borrow()).clone())),
17+
}
18+
}
19+
}
1320
impl ByteRepr for widget {
1421
fn byte_size() -> usize {
1522
4

tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub struct container {
1111
pub p: Value<Ptr<opaque>>,
1212
pub x: Value<i32>,
1313
}
14+
impl Clone for container {
15+
fn clone(&self) -> Self {
16+
Self {
17+
p: Rc::new(RefCell::new((*self.p.borrow()).clone())),
18+
x: Rc::new(RefCell::new((*self.x.borrow()).clone())),
19+
}
20+
}
21+
}
1422
impl ByteRepr for container {
1523
fn byte_size() -> usize {
1624
16

tests/unit/c_struct.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ int main() {
2929
assert(p.x == 10);
3030
assert(p.y == 20);
3131

32+
struct Point q = p;
33+
q.x = 99;
34+
assert(p.x == 10);
35+
assert(q.x == 99);
36+
assert(q.y == 20);
37+
3238
struct Line l = {{1, 2}, {3, 4}};
3339
assert(l.start.x == 1);
3440
assert(l.end.y == 4);

tests/unit/out/refcount/anonymous-struct_c.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub struct Named {
1111
pub a: Value<i32>,
1212
pub b: Value<i32>,
1313
}
14+
impl Clone for Named {
15+
fn clone(&self) -> Self {
16+
Self {
17+
a: Rc::new(RefCell::new((*self.a.borrow()).clone())),
18+
b: Rc::new(RefCell::new((*self.b.borrow()).clone())),
19+
}
20+
}
21+
}
1422
impl ByteRepr for Named {
1523
fn byte_size() -> usize {
1624
8
@@ -31,6 +39,14 @@ pub struct anon_0 {
3139
pub c: Value<i32>,
3240
pub d: Value<i32>,
3341
}
42+
impl Clone for anon_0 {
43+
fn clone(&self) -> Self {
44+
Self {
45+
c: Rc::new(RefCell::new((*self.c.borrow()).clone())),
46+
d: Rc::new(RefCell::new((*self.d.borrow()).clone())),
47+
}
48+
}
49+
}
3450
impl ByteRepr for anon_0 {
3551
fn byte_size() -> usize {
3652
8
@@ -51,6 +67,14 @@ pub struct anon_1 {
5167
pub g: Value<i32>,
5268
pub h: Value<i32>,
5369
}
70+
impl Clone for anon_1 {
71+
fn clone(&self) -> Self {
72+
Self {
73+
g: Rc::new(RefCell::new((*self.g.borrow()).clone())),
74+
h: Rc::new(RefCell::new((*self.h.borrow()).clone())),
75+
}
76+
}
77+
}
5478
impl ByteRepr for anon_1 {
5579
fn byte_size() -> usize {
5680
8
@@ -71,6 +95,14 @@ pub struct anon_2 {
7195
pub e: Value<i32>,
7296
pub f: Value<i32>,
7397
}
98+
impl Clone for anon_2 {
99+
fn clone(&self) -> Self {
100+
Self {
101+
e: Rc::new(RefCell::new((*self.e.borrow()).clone())),
102+
f: Rc::new(RefCell::new((*self.f.borrow()).clone())),
103+
}
104+
}
105+
}
74106
impl ByteRepr for anon_2 {
75107
fn byte_size() -> usize {
76108
8
@@ -90,6 +122,13 @@ impl ByteRepr for anon_2 {
90122
pub struct anon_4 {
91123
pub j: Value<i32>,
92124
}
125+
impl Clone for anon_4 {
126+
fn clone(&self) -> Self {
127+
Self {
128+
j: Rc::new(RefCell::new((*self.j.borrow()).clone())),
129+
}
130+
}
131+
}
93132
impl ByteRepr for anon_4 {
94133
fn byte_size() -> usize {
95134
4
@@ -107,6 +146,13 @@ impl ByteRepr for anon_4 {
107146
pub struct anon_5 {
108147
pub k: Value<i32>,
109148
}
149+
impl Clone for anon_5 {
150+
fn clone(&self) -> Self {
151+
Self {
152+
k: Rc::new(RefCell::new((*self.k.borrow()).clone())),
153+
}
154+
}
155+
}
110156
impl ByteRepr for anon_5 {
111157
fn byte_size() -> usize {
112158
4
@@ -126,6 +172,15 @@ pub struct anon_3 {
126172
pub inner_named: Value<anon_4>,
127173
pub anon_5: Value<anon_5>,
128174
}
175+
impl Clone for anon_3 {
176+
fn clone(&self) -> Self {
177+
Self {
178+
i: Rc::new(RefCell::new((*self.i.borrow()).clone())),
179+
inner_named: Rc::new(RefCell::new((*self.inner_named.borrow()).clone())),
180+
anon_5: Rc::new(RefCell::new((*self.anon_5.borrow()).clone())),
181+
}
182+
}
183+
}
129184
impl ByteRepr for anon_3 {
130185
fn byte_size() -> usize {
131186
12
@@ -151,6 +206,17 @@ pub struct Outer {
151206
pub anon_2: Value<anon_2>,
152207
pub anon_3: Value<anon_3>,
153208
}
209+
impl Clone for Outer {
210+
fn clone(&self) -> Self {
211+
Self {
212+
named: Rc::new(RefCell::new((*self.named.borrow()).clone())),
213+
anon0: Rc::new(RefCell::new((*self.anon0.borrow()).clone())),
214+
anon1: Rc::new(RefCell::new((*self.anon1.borrow()).clone())),
215+
anon_2: Rc::new(RefCell::new((*self.anon_2.borrow()).clone())),
216+
anon_3: Rc::new(RefCell::new((*self.anon_3.borrow()).clone())),
217+
}
218+
}
219+
}
154220
impl ByteRepr for Outer {
155221
fn byte_size() -> usize {
156222
44
@@ -229,6 +295,14 @@ fn main_0() -> i32 {
229295
pub x: Value<i32>,
230296
pub z: Value<i32>,
231297
}
298+
impl Clone for anon_6 {
299+
fn clone(&self) -> Self {
300+
Self {
301+
x: Rc::new(RefCell::new((*self.x.borrow()).clone())),
302+
z: Rc::new(RefCell::new((*self.z.borrow()).clone())),
303+
}
304+
}
305+
}
232306
impl ByteRepr for anon_6 {
233307
fn byte_size() -> usize {
234308
8

tests/unit/out/refcount/anonymous_enum_c.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ impl ByteRepr for anon_1 {
5858
pub struct S {
5959
pub a: Value<i32>,
6060
}
61+
impl Clone for S {
62+
fn clone(&self) -> Self {
63+
Self {
64+
a: Rc::new(RefCell::new((*self.a.borrow()).clone())),
65+
}
66+
}
67+
}
6168
impl ByteRepr for S {
6269
fn byte_size() -> usize {
6370
4
@@ -124,6 +131,14 @@ pub struct WithAnonField {
124131
pub a: Value<i32>,
125132
pub field: Value<anon_2>,
126133
}
134+
impl Clone for WithAnonField {
135+
fn clone(&self) -> Self {
136+
Self {
137+
a: Rc::new(RefCell::new((*self.a.borrow()).clone())),
138+
field: Rc::new(RefCell::new((*self.field.borrow()).clone())),
139+
}
140+
}
141+
}
127142
impl ByteRepr for WithAnonField {
128143
fn byte_size() -> usize {
129144
8

tests/unit/out/refcount/array_const_init.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ pub struct S {
1212
pub tail: Value<Box<[i32]>>,
1313
pub buf: Value<Box<[u8]>>,
1414
}
15+
impl Clone for S {
16+
fn clone(&self) -> Self {
17+
Self {
18+
head: Rc::new(RefCell::new((*self.head.borrow()).clone())),
19+
tail: Rc::new(RefCell::new((*self.tail.borrow()).clone())),
20+
buf: Rc::new(RefCell::new((*self.buf.borrow()).clone())),
21+
}
22+
}
23+
}
1524
impl Default for S {
1625
fn default() -> Self {
1726
S {

tests/unit/out/refcount/c_struct.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub struct Point {
1111
pub x: Value<i32>,
1212
pub y: Value<i32>,
1313
}
14+
impl Clone for Point {
15+
fn clone(&self) -> Self {
16+
Self {
17+
x: Rc::new(RefCell::new((*self.x.borrow()).clone())),
18+
y: Rc::new(RefCell::new((*self.y.borrow()).clone())),
19+
}
20+
}
21+
}
1422
impl ByteRepr for Point {
1523
fn byte_size() -> usize {
1624
8
@@ -31,6 +39,14 @@ pub struct Line {
3139
pub start: Value<Point>,
3240
pub end: Value<Point>,
3341
}
42+
impl Clone for Line {
43+
fn clone(&self) -> Self {
44+
Self {
45+
start: Rc::new(RefCell::new((*self.start.borrow()).clone())),
46+
end: Rc::new(RefCell::new((*self.end.borrow()).clone())),
47+
}
48+
}
49+
}
3450
impl ByteRepr for Line {
3551
fn byte_size() -> usize {
3652
16
@@ -51,6 +67,14 @@ pub struct Node {
5167
pub value: Value<i32>,
5268
pub next: Value<Ptr<Node>>,
5369
}
70+
impl Clone for Node {
71+
fn clone(&self) -> Self {
72+
Self {
73+
value: Rc::new(RefCell::new((*self.value.borrow()).clone())),
74+
next: Rc::new(RefCell::new((*self.next.borrow()).clone())),
75+
}
76+
}
77+
}
5478
impl ByteRepr for Node {
5579
fn byte_size() -> usize {
5680
16
@@ -97,6 +121,14 @@ pub struct Inner {
97121
pub a: Value<i32>,
98122
pub b: Value<i32>,
99123
}
124+
impl Clone for Inner {
125+
fn clone(&self) -> Self {
126+
Self {
127+
a: Rc::new(RefCell::new((*self.a.borrow()).clone())),
128+
b: Rc::new(RefCell::new((*self.b.borrow()).clone())),
129+
}
130+
}
131+
}
100132
impl ByteRepr for Inner {
101133
fn byte_size() -> usize {
102134
8
@@ -118,6 +150,15 @@ pub struct Container {
118150
pub color: Value<Color>,
119151
pub count: Value<i32>,
120152
}
153+
impl Clone for Container {
154+
fn clone(&self) -> Self {
155+
Self {
156+
inner: Rc::new(RefCell::new((*self.inner.borrow()).clone())),
157+
color: Rc::new(RefCell::new((*self.color.borrow()).clone())),
158+
count: Rc::new(RefCell::new((*self.count.borrow()).clone())),
159+
}
160+
}
161+
}
121162
impl ByteRepr for Container {
122163
fn byte_size() -> usize {
123164
16
@@ -145,6 +186,11 @@ fn main_0() -> i32 {
145186
}));
146187
assert!(((((*(*p.borrow()).x.borrow()) == 10) as i32) != 0));
147188
assert!(((((*(*p.borrow()).y.borrow()) == 20) as i32) != 0));
189+
let q: Value<Point> = Rc::new(RefCell::new((*p.borrow()).clone()));
190+
(*(*q.borrow()).x.borrow_mut()) = 99;
191+
assert!(((((*(*p.borrow()).x.borrow()) == 10) as i32) != 0));
192+
assert!(((((*(*q.borrow()).x.borrow()) == 99) as i32) != 0));
193+
assert!(((((*(*q.borrow()).y.borrow()) == 20) as i32) != 0));
148194
let l: Value<Line> = Rc::new(RefCell::new(Line {
149195
start: Rc::new(RefCell::new(Point {
150196
x: Rc::new(RefCell::new(1)),

tests/unit/out/refcount/enum_default_in_static.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ pub struct Config {
3737
pub count: Value<i32>,
3838
pub mode: Value<Mode>,
3939
}
40+
impl Clone for Config {
41+
fn clone(&self) -> Self {
42+
Self {
43+
count: Rc::new(RefCell::new((*self.count.borrow()).clone())),
44+
mode: Rc::new(RefCell::new((*self.mode.borrow()).clone())),
45+
}
46+
}
47+
}
4048
impl ByteRepr for Config {
4149
fn byte_size() -> usize {
4250
8

0 commit comments

Comments
 (0)