Skip to content

Commit ba10c52

Browse files
authored
Translate scopes (#326)
Each C++ scope: ```cpp int foo() { int a; { int a; } } ``` Becomes a proper Rust scope: ```rust fn foo() { let a: i32; { let a: i32; } } ```
1 parent f1e7c53 commit ba10c52

12 files changed

Lines changed: 289 additions & 116 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -435,25 +435,17 @@ void Converter::ConvertGotoBlock(clang::CompoundStmt *body) {
435435
}
436436

437437
void Converter::ConvertFunctionBody(clang::FunctionDecl *decl) {
438-
if (auto compound = clang::dyn_cast<clang::CompoundStmt>(decl->getBody())) {
439-
if (CompoundHasTopLevelLabel(compound)) {
440-
ConvertGotoBlock(compound);
441-
if (!decl->getReturnType()->isVoidType()) {
442-
StrCat(R"(panic!("ub: non-void function does not return a value"))");
443-
}
444-
return;
445-
}
438+
ConvertBodyStmts(decl->getBody());
439+
if (decl->getReturnType()->isVoidType()) {
440+
return;
446441
}
447-
448-
Convert(decl->getBody());
449-
if (!decl->getReturnType()->isVoidType()) {
450-
if (auto compound = clang::dyn_cast<clang::CompoundStmt>(decl->getBody())) {
451-
if (!compound->body_empty()) {
452-
if (!clang::isa<clang::ReturnStmt>(compound->body_back())) {
453-
StrCat(R"(panic!("ub: non-void function does not return a value"))");
454-
}
455-
}
456-
}
442+
auto compound = clang::dyn_cast<clang::CompoundStmt>(decl->getBody());
443+
if (!compound || compound->body_empty()) {
444+
return;
445+
}
446+
if (CompoundHasTopLevelLabel(compound) ||
447+
!clang::isa<clang::ReturnStmt>(compound->body_back())) {
448+
StrCat(R"(panic!("ub: non-void function does not return a value"))");
457449
}
458450
}
459451

@@ -1057,7 +1049,7 @@ void Converter::ConvertCXXConstructorBody(clang::CXXConstructorDecl *decl) {
10571049
}
10581050

10591051
StrCat(token::kSemiColon);
1060-
Convert(decl->getBody());
1052+
ConvertBodyStmts(decl->getBody());
10611053
StrCat("this");
10621054
}
10631055

@@ -1127,14 +1119,28 @@ bool Converter::Convert(clang::Stmt *stmt) {
11271119
return exited_visit;
11281120
}
11291121

1130-
bool Converter::VisitCompoundStmt(clang::CompoundStmt *stmt) {
1131-
if (CompoundHasTopLevelLabel(stmt)) {
1132-
ConvertGotoBlock(stmt);
1133-
return false;
1122+
void Converter::ConvertBody(clang::Stmt *body) {
1123+
PushBrace brace(*this);
1124+
ConvertBodyStmts(body);
1125+
}
1126+
1127+
void Converter::ConvertBodyStmts(clang::Stmt *body) {
1128+
auto *compound = clang::dyn_cast_or_null<clang::CompoundStmt>(body);
1129+
if (!compound) {
1130+
Convert(body);
1131+
return;
11341132
}
1135-
for (auto *child : stmt->body()) {
1133+
if (CompoundHasTopLevelLabel(compound)) {
1134+
ConvertGotoBlock(compound);
1135+
return;
1136+
}
1137+
for (auto *child : compound->body()) {
11361138
Convert(child);
11371139
}
1140+
}
1141+
1142+
bool Converter::VisitCompoundStmt(clang::CompoundStmt *stmt) {
1143+
ConvertBody(stmt);
11381144
return false;
11391145
}
11401146

@@ -1172,17 +1178,13 @@ void Converter::ConvertCondition(clang::Expr *cond) {
11721178
bool Converter::VisitIfStmt(clang::IfStmt *stmt) {
11731179
StrCat(keyword::kIf);
11741180
ConvertCondition(stmt->getCond());
1175-
{
1176-
PushBrace brace(*this);
1177-
Convert(stmt->getThen());
1178-
}
1181+
ConvertBody(stmt->getThen());
11791182
if (stmt->hasElseStorage()) {
11801183
StrCat(keyword::kElse);
11811184
if (clang::isa<clang::IfStmt>(stmt->getElse())) {
11821185
Convert(stmt->getElse());
11831186
} else {
1184-
PushBrace brace(*this);
1185-
Convert(stmt->getElse());
1187+
ConvertBody(stmt->getElse());
11861188
}
11871189
}
11881190
return false;
@@ -1193,12 +1195,9 @@ bool Converter::VisitWhileStmt(clang::WhileStmt *stmt) {
11931195
StrCat("'loop_:");
11941196
StrCat(keyword::kWhile);
11951197
ConvertCondition(stmt->getCond());
1196-
{
1197-
PushBrace brace(*this);
1198-
curr_for_inc_.emplace_back(nullptr);
1199-
Convert(stmt->getBody());
1200-
curr_for_inc_.pop_back();
1201-
}
1198+
curr_for_inc_.emplace_back(nullptr);
1199+
ConvertBody(stmt->getBody());
1200+
curr_for_inc_.pop_back();
12021201
return false;
12031202
}
12041203

@@ -1216,7 +1215,7 @@ bool Converter::VisitDoStmt(clang::DoStmt *stmt) {
12161215
PushBrace loop_brace(*this);
12171216
StrCat(control_var, token::kAssign, keyword::kFalse, token::kSemiColon);
12181217
curr_for_inc_.emplace_back(nullptr);
1219-
Convert(stmt->getBody());
1218+
ConvertBodyStmts(stmt->getBody());
12201219
curr_for_inc_.pop_back();
12211220
}
12221221
return false;
@@ -1235,7 +1234,7 @@ bool Converter::VisitForStmt(clang::ForStmt *stmt) {
12351234
{
12361235
PushBrace brace(*this);
12371236
curr_for_inc_.emplace_back(stmt->getInc());
1238-
Convert(stmt->getBody());
1237+
ConvertBodyStmts(stmt->getBody());
12391238
curr_for_inc_.pop_back();
12401239
Convert(stmt->getInc());
12411240
StrCat(token::kSemiColon);
@@ -1273,7 +1272,7 @@ void Converter::ConvertForRangeBody(clang::CXXForRangeStmt *stmt,
12731272
if (map_iter_decl)
12741273
skip.emplace(*this, map_iter_decl);
12751274
curr_for_inc_.emplace_back(nullptr);
1276-
Convert(stmt->getBody());
1275+
ConvertBodyStmts(stmt->getBody());
12771276
curr_for_inc_.pop_back();
12781277
}
12791278

‎cpp2rust/converter/converter.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
8686

8787
void ConvertGotoBlock(clang::CompoundStmt *body);
8888

89+
void ConvertBody(clang::Stmt *body);
90+
91+
void ConvertBodyStmts(clang::Stmt *body);
92+
8993
void EmitHoistedDecls(clang::CompoundStmt *body);
9094

9195
virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *decl);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,9 +585,8 @@ void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) {
585585
auto record_name = GetRecordName(decl);
586586

587587
StrCat(keyword::kImpl, "Drop for", record_name, '{');
588-
StrCat("fn drop(&mut self) {");
589-
Convert(body);
590-
StrCat('}');
588+
StrCat("fn drop(&mut self)");
589+
ConvertBody(body);
591590
StrCat('}');
592591
}
593592

‎tests/unit/nested_block_scope.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <assert.h>
2+
3+
int main() {
4+
int x = 1;
5+
{
6+
int x = 2;
7+
assert(x == 2);
8+
{
9+
int x = 3;
10+
assert(x == 3);
11+
}
12+
assert(x == 2);
13+
}
14+
assert(x == 1);
15+
16+
int sum = 0;
17+
for (int i = 0; i < 3; i++) {
18+
int y = i;
19+
{
20+
int y = 10;
21+
sum += y;
22+
}
23+
sum += y;
24+
}
25+
assert(sum == 33);
26+
27+
if (x == 1) {
28+
int x = 5;
29+
{
30+
int x = 6;
31+
assert(x == 6);
32+
}
33+
assert(x == 5);
34+
}
35+
assert(x == 1);
36+
return 0;
37+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
pub fn main() {
10+
std::process::exit(main_0());
11+
}
12+
fn main_0() -> i32 {
13+
let x: Value<i32> = Rc::new(RefCell::new(1));
14+
{
15+
let x: Value<i32> = Rc::new(RefCell::new(2));
16+
assert!(((*x.borrow()) == 2));
17+
{
18+
let x: Value<i32> = Rc::new(RefCell::new(3));
19+
assert!(((*x.borrow()) == 3));
20+
}
21+
assert!(((*x.borrow()) == 2));
22+
}
23+
assert!(((*x.borrow()) == 1));
24+
let sum: Value<i32> = Rc::new(RefCell::new(0));
25+
let i: Value<i32> = Rc::new(RefCell::new(0));
26+
'loop_: while ((*i.borrow()) < 3) {
27+
let y: Value<i32> = Rc::new(RefCell::new((*i.borrow())));
28+
{
29+
let y: Value<i32> = Rc::new(RefCell::new(10));
30+
(*sum.borrow_mut()) += (*y.borrow());
31+
}
32+
(*sum.borrow_mut()) += (*y.borrow());
33+
(*i.borrow_mut()).postfix_inc();
34+
}
35+
assert!(((*sum.borrow()) == 33));
36+
if ((*x.borrow()) == 1) {
37+
let x: Value<i32> = Rc::new(RefCell::new(5));
38+
{
39+
let x: Value<i32> = Rc::new(RefCell::new(6));
40+
assert!(((*x.borrow()) == 6));
41+
}
42+
assert!(((*x.borrow()) == 5));
43+
}
44+
assert!(((*x.borrow()) == 1));
45+
return 0;
46+
}

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

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,45 @@ pub fn main() {
1111
}
1212
fn main_0() -> i32 {
1313
let arr: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::new([1_u8, 2_u8, 3_u8])));
14-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
15-
(*p.borrow_mut()) += (1_u8 as i32);
16-
assert!(((((*p.borrow()).read()) as i32) == 2));
17-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
18-
(*p.borrow_mut()) += (1_i8 as i32);
19-
assert!(((((*p.borrow()).read()) as i32) == 2));
20-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
21-
(*p.borrow_mut()) += (1_u16 as i32);
22-
assert!(((((*p.borrow()).read()) as i32) == 2));
23-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
24-
(*p.borrow_mut()) += (1_i16 as i32);
25-
assert!(((((*p.borrow()).read()) as i32) == 2));
26-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
27-
(*p.borrow_mut()) += 1_u32;
28-
assert!(((((*p.borrow()).read()) as i32) == 2));
29-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
30-
(*p.borrow_mut()) += (1 as i32);
31-
assert!(((((*p.borrow()).read()) as i32) == 2));
32-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
33-
(*p.borrow_mut()) += 1_u64;
34-
assert!(((((*p.borrow()).read()) as i32) == 2));
35-
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
36-
(*p.borrow_mut()) += 1_i64;
37-
assert!(((((*p.borrow()).read()) as i32) == 2));
14+
{
15+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
16+
(*p.borrow_mut()) += (1_u8 as i32);
17+
assert!(((((*p.borrow()).read()) as i32) == 2));
18+
}
19+
{
20+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
21+
(*p.borrow_mut()) += (1_i8 as i32);
22+
assert!(((((*p.borrow()).read()) as i32) == 2));
23+
}
24+
{
25+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
26+
(*p.borrow_mut()) += (1_u16 as i32);
27+
assert!(((((*p.borrow()).read()) as i32) == 2));
28+
}
29+
{
30+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
31+
(*p.borrow_mut()) += (1_i16 as i32);
32+
assert!(((((*p.borrow()).read()) as i32) == 2));
33+
}
34+
{
35+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
36+
(*p.borrow_mut()) += 1_u32;
37+
assert!(((((*p.borrow()).read()) as i32) == 2));
38+
}
39+
{
40+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
41+
(*p.borrow_mut()) += (1 as i32);
42+
assert!(((((*p.borrow()).read()) as i32) == 2));
43+
}
44+
{
45+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
46+
(*p.borrow_mut()) += 1_u64;
47+
assert!(((((*p.borrow()).read()) as i32) == 2));
48+
}
49+
{
50+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new(((arr.as_pointer() as Ptr<u8>).offset(0))));
51+
(*p.borrow_mut()) += 1_i64;
52+
assert!(((((*p.borrow()).read()) as i32) == 2));
53+
}
3854
return 0;
3955
}

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,20 @@ fn main_0() -> i32 {
1717
.collect::<Vec<u8>>(),
1818
));
1919
let file: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::from(*b"test_stdcopy_ostream.txt\0")));
20-
let ofs: Value<::std::fs::File> = Rc::new(RefCell::new(
21-
::std::fs::File::create((file.as_pointer() as Ptr<u8>).to_string())
22-
.expect("Failed to open file"),
23-
));
2420
{
25-
(*ofs.borrow_mut()).write_all(
26-
(str.as_pointer() as Ptr<u8>)
27-
.slice_until(&(str.as_pointer() as Ptr<u8>).to_last())
28-
.as_slice(),
29-
);
30-
(*ofs.borrow_mut()).try_clone().unwrap()
31-
};
21+
let ofs: Value<::std::fs::File> = Rc::new(RefCell::new(
22+
::std::fs::File::create((file.as_pointer() as Ptr<u8>).to_string())
23+
.expect("Failed to open file"),
24+
));
25+
{
26+
(*ofs.borrow_mut()).write_all(
27+
(str.as_pointer() as Ptr<u8>)
28+
.slice_until(&(str.as_pointer() as Ptr<u8>).to_last())
29+
.as_slice(),
30+
);
31+
(*ofs.borrow_mut()).try_clone().unwrap()
32+
};
33+
}
3234
match nix::unistd::unlink((file.as_pointer() as Ptr<u8>).to_rust_string().as_str()) {
3335
Ok(()) => 0,
3436
Err(__e) => {

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ pub fn fallthrough_into_block_0(x: i32) -> i32 {
1414
(*r.borrow_mut()) += 1;
1515
}
1616
__v if __v == 2 => {
17-
let tmp: Value<i32> = Rc::new(RefCell::new(((*r.borrow()) * 10)));
18-
(*r.borrow_mut()) = ((*tmp.borrow()) + 5);
19-
break;
17+
{
18+
let tmp: Value<i32> = Rc::new(RefCell::new(((*r.borrow()) * 10)));
19+
(*r.borrow_mut()) = ((*tmp.borrow()) + 5);
20+
break;
21+
}
2022
}
2123
_ => {
2224
(*r.borrow_mut()) = -1_i32;

0 commit comments

Comments
 (0)