Skip to content

Commit 87cd939

Browse files
committed
Convert delegating constructors
1 parent b5dd144 commit 87cd939

5 files changed

Lines changed: 136 additions & 18 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,8 +1157,11 @@ bool Converter::VisitCXXConstructorDecl(clang::CXXConstructorDecl *decl) {
11571157

11581158
void Converter::ConvertCXXConstructorBody(clang::CXXConstructorDecl *decl) {
11591159
EmitFunctionPreamble(decl);
1160-
StrCat(keyword::kLet, "mut", "this", token::kAssign, "Self");
1161-
{
1160+
StrCat(keyword::kLet, "mut", "this", token::kAssign);
1161+
if (decl->isDelegatingConstructor()) {
1162+
Convert((*decl->init_begin())->getInit());
1163+
} else {
1164+
StrCat("Self");
11621165
PushBrace this_init(*this);
11631166
EmitConstructorFieldInits(decl);
11641167
}
@@ -1174,26 +1177,23 @@ void Converter::EmitConstructorFieldInits(clang::CXXConstructorDecl *decl) {
11741177
assert(definition_or_null);
11751178
auto *definition = clang::cast<clang::CXXConstructorDecl>(definition_or_null);
11761179

1177-
bool has_inits = !definition->inits().empty();
1178-
auto **ctor_initializer_list = definition->inits().begin();
1179-
int curr_init =
1180-
has_inits ? (ctor_initializer_list[0]->isBaseInitializer() ? 1 : 0) : 0;
1181-
11821180
for (const auto *field : record_decl->fields()) {
11831181
auto field_name = GetNamedDeclAsString(field);
11841182
auto field_type = field->getType();
1185-
auto *ctor_initializer =
1186-
has_inits ? ctor_initializer_list[curr_init] : nullptr;
1183+
const clang::CXXCtorInitializer *ctor_initializer = nullptr;
1184+
for (const auto *init : definition->inits()) {
1185+
if (init->isMemberInitializer() && init->getMember() == field) {
1186+
ctor_initializer = init;
1187+
break;
1188+
}
1189+
}
11871190

1188-
if (has_inits &&
1189-
GetNamedDeclAsString(ctor_initializer->getMember()) == field_name) {
1190-
auto *ctor_init_expr = ctor_initializer->getInit();
1191+
if (ctor_initializer) {
11911192
StrCat(field_name, token::kColon);
1192-
ConvertVarInit(field_type, ctor_init_expr);
1193-
curr_init = (curr_init + 1) % definition->getNumCtorInitializers();
1194-
} else if (field->hasInClassInitializer()) {
1193+
ConvertVarInit(field_type, ctor_initializer->getInit());
1194+
} else if (auto *init = field->getInClassInitializer()) {
11951195
StrCat(field_name, token::kColon);
1196-
ConvertVarInit(field_type, field->getInClassInitializer());
1196+
ConvertVarInit(field_type, init);
11971197
} else {
11981198
StrCat(field_name, token::kColon, GetDefaultAsString(field_type));
11991199
}

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,8 +2890,11 @@ void ConverterRefCount::ConvertCXXConstructorBody(
28902890
auto record_name = GetRecordName(decl->getParent());
28912891
StrCat(keyword::kLet, "__this", token::kColon,
28922892
std::format("Value<{}>", record_name), token::kAssign,
2893-
"Rc::new(RefCell::new(Self");
2894-
{
2893+
"Rc::new(RefCell::new(");
2894+
if (decl->isDelegatingConstructor()) {
2895+
Convert((*decl->init_begin())->getInit());
2896+
} else {
2897+
StrCat("Self");
28952898
PushBrace this_init(*this);
28962899
EmitConstructorFieldInits(decl);
28972900
}

‎tests/unit/constructor.cpp‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,26 @@ struct S {
1818
}
1919
};
2020

21+
struct Point {
22+
int x;
23+
int y;
24+
Point(int x, int y) : x(x), y(y) {}
25+
Point(int v) : Point(v, v + 1) { y *= 10; }
26+
Point() : Point(4) { x += 100; }
27+
};
28+
2129
int main() {
2230
{
2331
S s(3);
2432
assert(s.v == 4);
2533
assert(total == 8);
2634
}
2735
assert(total == 18);
36+
Point p;
37+
assert(p.x == 104);
38+
assert(p.y == 50);
39+
Point q(7);
40+
assert(q.x == 7);
41+
assert(q.y == 80);
2842
return 0;
2943
}

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,68 @@ impl ByteRepr for S {
4747
}
4848
}
4949
}
50+
#[derive()]
51+
pub struct Point {
52+
pub x: Value<i32>,
53+
pub y: Value<i32>,
54+
}
55+
impl Point {
56+
pub fn Point1(x: i32, y: i32) -> Self {
57+
let x: Value<i32> = Rc::new(RefCell::new(x));
58+
let y: Value<i32> = Rc::new(RefCell::new(y));
59+
let __this: Value<Point> = Rc::new(RefCell::new(Self {
60+
x: Rc::new(RefCell::new((*x.borrow()))),
61+
y: Rc::new(RefCell::new((*y.borrow()))),
62+
}));
63+
let this: Ptr<Point> = __this.as_pointer();
64+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
65+
}
66+
pub fn Point2(v: i32) -> Self {
67+
let v: Value<i32> = Rc::new(RefCell::new(v));
68+
let __this: Value<Point> = Rc::new(RefCell::new(Point::Point1({ (*v.borrow()) }, {
69+
((*v.borrow()) + 1)
70+
})));
71+
let this: Ptr<Point> = __this.as_pointer();
72+
(*(*this.upgrade().deref()).y.borrow_mut()) *= 10;
73+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
74+
}
75+
pub fn Point3() -> Self {
76+
let __this: Value<Point> = Rc::new(RefCell::new(Point::Point2({ 4 })));
77+
let this: Ptr<Point> = __this.as_pointer();
78+
(*(*this.upgrade().deref()).x.borrow_mut()) += 100;
79+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
80+
}
81+
}
82+
impl Clone for Point {
83+
fn clone(&self) -> Self {
84+
let __this: Value<Point> = Rc::new(RefCell::new(Self {
85+
x: Rc::new(RefCell::new((*self.x.borrow()))),
86+
y: Rc::new(RefCell::new((*self.y.borrow()))),
87+
}));
88+
let this: Ptr<Point> = __this.as_pointer();
89+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
90+
}
91+
}
92+
impl Default for Point {
93+
fn default() -> Self {
94+
{ Point::Point3() }
95+
}
96+
}
97+
impl ByteRepr for Point {
98+
fn byte_size() -> usize {
99+
8
100+
}
101+
fn to_bytes(&self, buf: &mut [u8]) {
102+
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
103+
(*self.y.borrow()).to_bytes(&mut buf[4..8]);
104+
}
105+
fn from_bytes(buf: &[u8]) -> Self {
106+
Self {
107+
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
108+
y: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
109+
}
110+
}
111+
}
50112
pub fn main() {
51113
__cpp2rust_init_globals();
52114
std::process::exit(main_0());
@@ -59,6 +121,12 @@ fn main_0() -> i32 {
59121
assert!((total_0.with(|rc| rc.borrow().clone()) == 8));
60122
}
61123
assert!((total_0.with(|rc| rc.borrow().clone()) == 18));
124+
let p: Value<Point> = Rc::new(RefCell::new(Point::Point3()));
125+
assert!(((*(*p.borrow()).x.borrow()) == 104));
126+
assert!(((*(*p.borrow()).y.borrow()) == 50));
127+
let q: Value<Point> = Rc::new(RefCell::new(Point::Point2({ 7 })));
128+
assert!(((*(*q.borrow()).x.borrow()) == 7));
129+
assert!(((*(*q.borrow()).y.borrow()) == 80));
62130
return 0;
63131
}
64132
pub trait SImpl {

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,33 @@ impl S {
3232
(unsafe { S::const_method(self) });
3333
}
3434
}
35+
#[repr(C)]
36+
#[derive(Copy, Clone)]
37+
pub struct Point {
38+
pub x: i32,
39+
pub y: i32,
40+
}
41+
impl Point {
42+
pub unsafe fn Point1(mut x: i32, mut y: i32) -> Self {
43+
let mut this = Self { x: x, y: y };
44+
this
45+
}
46+
pub unsafe fn Point2(mut v: i32) -> Self {
47+
let mut this = Point::Point1({ v }, { ((v) + (1)) });
48+
this.y *= 10;
49+
this
50+
}
51+
pub unsafe fn Point3() -> Self {
52+
let mut this = Point::Point2({ 4 });
53+
this.x += 100;
54+
this
55+
}
56+
}
57+
impl Default for Point {
58+
fn default() -> Self {
59+
unsafe { Point::Point3() }
60+
}
61+
}
3562
pub fn main() {
3663
unsafe {
3764
__cpp2rust_init_globals();
@@ -46,6 +73,12 @@ unsafe fn main_0() -> i32 {
4673
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut total_0)) == (8)));
4774
}
4875
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut total_0)) == (18)));
76+
let mut p: Point = Point::Point3();
77+
assert!(((p.x) == (104)));
78+
assert!(((p.y) == (50)));
79+
let mut q: Point = Point::Point2({ 7 });
80+
assert!(((q.x) == (7)));
81+
assert!(((q.y) == (80)));
4982
return 0;
5083
}
5184
pub unsafe fn __cpp2rust_init_globals() {

0 commit comments

Comments
 (0)