Skip to content

Commit a6d0d48

Browse files
committed
Fix do while continue stmt (#160)
A continue statement inside a `do while` breakes the iteration and re-evaluates the condition. Our previous translation, i.e. ```rs loop { ... if !cond { break } } ``` never re-evaluated the condition after a continue, resulting in an infinite loop. To fix this, use while instead of loop. This ensures that the condition is re-evaluated right after the continue: ```rs let mut __do_while = true; while __do_while || cond { __do_while = false; ... } ``` __do_while makes sure that the first iteration of the loop is always executed.
1 parent a2c71b8 commit a6d0d48

4 files changed

Lines changed: 25 additions & 27 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,22 +1125,20 @@ bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
11251125

11261126
bool Converter::VisitDoStmt(clang::DoStmt *stmt) {
11271127
PushBreakTarget push(break_target_, BreakTarget::Loop);
1128-
StrCat("'loop_:");
1129-
StrCat(keyword::kLoop);
1128+
const char *control_var = "__do_while";
1129+
StrCat(keyword::kLet, "mut", control_var, token::kAssign, keyword::kTrue,
1130+
token::kSemiColon);
1131+
StrCat("'loop_:", keyword::kWhile, control_var, "||");
1132+
{
1133+
PushParen paren(*this);
1134+
ConvertCondition(stmt->getCond());
1135+
}
11301136
{
11311137
PushBrace loop_brace(*this);
1138+
StrCat(control_var, token::kAssign, keyword::kFalse, token::kSemiColon);
11321139
curr_for_inc_.emplace_back(nullptr);
11331140
Convert(stmt->getBody());
11341141
curr_for_inc_.pop_back();
1135-
StrCat(keyword::kIf, token::kNot);
1136-
{
1137-
PushParen paren(*this);
1138-
ConvertCondition(stmt->getCond());
1139-
}
1140-
{
1141-
PushBrace if_brace(*this);
1142-
StrCat(keyword::kBreak, token::kSemiColon);
1143-
}
11441142
}
11451143
return false;
11461144
}

tests/unit/out/refcount/fn_ptr_stdlib_compare.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,17 @@ fn main_0() -> i32 {
7777
'loop_: while __do_while || (0 != 0) {
7878
__do_while = false;
7979
let stream: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new(
80-
match Ptr::from_string_literal(b"rb").to_rust_string() {
80+
match Ptr::from_string_literal("rb").to_rust_string() {
8181
v if v == "rb" => std::fs::OpenOptions::new()
8282
.read(true)
83-
.open(Ptr::from_string_literal(b"/dev/zero").to_rust_string())
83+
.open(Ptr::from_string_literal("/dev/zero").to_rust_string())
8484
.ok()
8585
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
8686
v if v == "wb" => std::fs::OpenOptions::new()
8787
.write(true)
8888
.create(true)
8989
.truncate(true)
90-
.open(Ptr::from_string_literal(b"/dev/zero").to_rust_string())
90+
.open(Ptr::from_string_literal("/dev/zero").to_rust_string())
9191
.ok()
9292
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
9393
_ => panic!("unsupported mode"),
@@ -131,17 +131,17 @@ fn main_0() -> i32 {
131131
'loop_: while __do_while || (0 != 0) {
132132
__do_while = false;
133133
let stream: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new(
134-
match Ptr::from_string_literal(b"rb").to_rust_string() {
134+
match Ptr::from_string_literal("rb").to_rust_string() {
135135
v if v == "rb" => std::fs::OpenOptions::new()
136136
.read(true)
137-
.open(Ptr::from_string_literal(b"/dev/zero").to_rust_string())
137+
.open(Ptr::from_string_literal("/dev/zero").to_rust_string())
138138
.ok()
139139
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
140140
v if v == "wb" => std::fs::OpenOptions::new()
141141
.write(true)
142142
.create(true)
143143
.truncate(true)
144-
.open(Ptr::from_string_literal(b"/dev/zero").to_rust_string())
144+
.open(Ptr::from_string_literal("/dev/zero").to_rust_string())
145145
.ok()
146146
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
147147
_ => panic!("unsupported mode"),
@@ -241,17 +241,17 @@ fn main_0() -> i32 {
241241
'loop_: while __do_while || (0 != 0) {
242242
__do_while = false;
243243
let stream: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new(
244-
match Ptr::from_string_literal(b"wb").to_rust_string() {
244+
match Ptr::from_string_literal("wb").to_rust_string() {
245245
v if v == "rb" => std::fs::OpenOptions::new()
246246
.read(true)
247-
.open(Ptr::from_string_literal(b"/dev/null").to_rust_string())
247+
.open(Ptr::from_string_literal("/dev/null").to_rust_string())
248248
.ok()
249249
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
250250
v if v == "wb" => std::fs::OpenOptions::new()
251251
.write(true)
252252
.create(true)
253253
.truncate(true)
254-
.open(Ptr::from_string_literal(b"/dev/null").to_rust_string())
254+
.open(Ptr::from_string_literal("/dev/null").to_rust_string())
255255
.ok()
256256
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
257257
_ => panic!("unsupported mode"),
@@ -285,17 +285,17 @@ fn main_0() -> i32 {
285285
'loop_: while __do_while || (0 != 0) {
286286
__do_while = false;
287287
let stream: Value<Ptr<::std::fs::File>> = Rc::new(RefCell::new(
288-
match Ptr::from_string_literal(b"wb").to_rust_string() {
288+
match Ptr::from_string_literal("wb").to_rust_string() {
289289
v if v == "rb" => std::fs::OpenOptions::new()
290290
.read(true)
291-
.open(Ptr::from_string_literal(b"/dev/null").to_rust_string())
291+
.open(Ptr::from_string_literal("/dev/null").to_rust_string())
292292
.ok()
293293
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
294294
v if v == "wb" => std::fs::OpenOptions::new()
295295
.write(true)
296296
.create(true)
297297
.truncate(true)
298-
.open(Ptr::from_string_literal(b"/dev/null").to_rust_string())
298+
.open(Ptr::from_string_literal("/dev/null").to_rust_string())
299299
.ok()
300300
.map_or(Ptr::null(), |f| Ptr::alloc(f)),
301301
_ => panic!("unsupported mode"),

tests/unit/out/refcount/switch_in_dowhile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ pub fn switch_in_dowhile_0(n: i32) -> i32 {
1616
'switch: {
1717
let __match_cond = (*i.borrow());
1818
match __match_cond {
19-
__v if __v == 0 => {
19+
v if v == 0 => {
2020
(*r.borrow_mut()) += 1;
2121
break 'switch;
2222
}
23-
__v if __v == 1 => {
23+
v if v == 1 => {
2424
(*r.borrow_mut()) += 10;
2525
break 'switch;
2626
}

tests/unit/out/unsafe/switch_in_dowhile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ pub unsafe fn switch_in_dowhile_0(mut n: i32) -> i32 {
1515
'switch: {
1616
let __match_cond = i;
1717
match __match_cond {
18-
__v if __v == 0 => {
18+
v if v == 0 => {
1919
r += 1;
2020
break 'switch;
2121
}
22-
__v if __v == 1 => {
22+
v if v == 1 => {
2323
r += 10;
2424
break 'switch;
2525
}

0 commit comments

Comments
 (0)