Skip to content

Commit d3e29bc

Browse files
committed
Translate StmtExpr
1 parent 2165500 commit d3e29bc

7 files changed

Lines changed: 178 additions & 2 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,9 @@ bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) {
20582058
return false;
20592059
}
20602060
switch (opcode) {
2061+
case clang::UO_Extension:
2062+
Convert(sub_expr);
2063+
break;
20612064
case clang::UO_AddrOf: {
20622065
PushParen paren(*this);
20632066
ConvertAddrOf(sub_expr, expr->getType());
@@ -2091,6 +2094,29 @@ bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) {
20912094
return false;
20922095
}
20932096

2097+
bool Converter::VisitStmtExpr(clang::StmtExpr *expr) {
2098+
auto *body = expr->getSubStmt();
2099+
PushBrace brace(*this);
2100+
auto stmts = body->body();
2101+
size_t n = static_cast<size_t>(stmts.end() - stmts.begin());
2102+
size_t i = 0;
2103+
for (auto *s : stmts) {
2104+
++i;
2105+
if (i == n) {
2106+
if (auto *tail = clang::dyn_cast<clang::Expr>(s)) {
2107+
EmitStmtExprTail(tail);
2108+
continue;
2109+
}
2110+
}
2111+
Convert(s);
2112+
}
2113+
return false;
2114+
}
2115+
2116+
void Converter::EmitStmtExprTail(clang::Expr *tail) {
2117+
Convert(tail);
2118+
}
2119+
20942120
bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) {
20952121
StrCat(keyword::kIf);
20962122
Convert(expr->getCond());

cpp2rust/converter/converter.h

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

249249
virtual bool VisitUnaryOperator(clang::UnaryOperator *expr);
250250

251+
virtual bool VisitStmtExpr(clang::StmtExpr *expr);
252+
253+
virtual void EmitStmtExprTail(clang::Expr *tail);
254+
251255
virtual bool VisitConditionalOperator(clang::ConditionalOperator *expr);
252256

253257
virtual bool VisitDeclRefExpr(clang::DeclRefExpr *expr);

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,18 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
11411141
}
11421142
}
11431143

1144+
bool ConverterRefCount::VisitStmtExpr(clang::StmtExpr *expr) {
1145+
PushConversionKind push(*this, ConversionKind::FullRefCount);
1146+
return Converter::VisitStmtExpr(expr);
1147+
}
1148+
1149+
void ConverterRefCount::EmitStmtExprTail(clang::Expr *tail) {
1150+
StrCat("let __result = ");
1151+
Convert(tail);
1152+
StrCat(token::kSemiColon);
1153+
StrCat("__result");
1154+
}
1155+
11441156
bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) {
11451157
auto *lhs = expr->getLHS();
11461158
auto *rhs = expr->getRHS();
@@ -1654,12 +1666,10 @@ void ConverterRefCount::ConvertVarInit(clang::QualType qual_type,
16541666
}
16551667

16561668
bool is_ref = qual_type->isReferenceType();
1657-
in_function_formals_ = true;
16581669
PushConversionKind push(*this, ConversionKind::Unboxed, is_ref);
16591670
StrCat(BoxValue((is_ref || qual_type->isFunctionPointerType())
16601671
? ConvertFreshPointer(expr)
16611672
: ConvertFreshRValue(expr)));
1662-
in_function_formals_ = false;
16631673
}
16641674

16651675
static std::unordered_set<const clang::ValueDecl *>

cpp2rust/converter/models/converter_refcount.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ class ConverterRefCount final : public Converter {
8484

8585
bool VisitBinaryOperator(clang::BinaryOperator *expr) override;
8686

87+
bool VisitStmtExpr(clang::StmtExpr *expr) override;
88+
89+
void EmitStmtExprTail(clang::Expr *tail) override;
90+
8791
bool VisitInitListExpr(clang::InitListExpr *expr) override;
8892

8993
bool VisitArraySubscriptExpr(clang::ArraySubscriptExpr *expr) override;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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({
14+
let a: Value<i32> = Rc::new(RefCell::new(1));
15+
let b: Value<i32> = Rc::new(RefCell::new(2));
16+
let __result = ((*a.borrow()) + (*b.borrow()));
17+
__result
18+
}));
19+
assert!(((*x.borrow()) == 3));
20+
let counter: Value<i32> = Rc::new(RefCell::new(0));
21+
let y: Value<i32> = Rc::new(RefCell::new({
22+
(*counter.borrow_mut()).postfix_inc();
23+
let __result = ((*counter.borrow()) * 10);
24+
__result
25+
}));
26+
assert!(((*y.borrow()) == 10));
27+
assert!(((*counter.borrow()) == 1));
28+
let z: Value<i32> = Rc::new(RefCell::new({
29+
let v: Value<i32> = Rc::new(RefCell::new(5));
30+
if ((*v.borrow()) > 0) {
31+
let __rhs = ((*v.borrow()) * 2);
32+
(*v.borrow_mut()) = __rhs;
33+
}
34+
let __result = (*v.borrow());
35+
__result
36+
}));
37+
assert!(((*z.borrow()) == 10));
38+
assert!(
39+
({
40+
let inner: Value<i32> = Rc::new(RefCell::new({
41+
let a: Value<i32> = Rc::new(RefCell::new(100));
42+
let __result = (*a.borrow());
43+
__result
44+
}));
45+
let __result = (*inner.borrow());
46+
__result
47+
} == 100)
48+
);
49+
return 0;
50+
}

tests/unit/out/unsafe/stmt_expr.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
pub fn main() {
10+
unsafe {
11+
std::process::exit(main_0() as i32);
12+
}
13+
}
14+
unsafe fn main_0() -> i32 {
15+
let mut x: i32 = {
16+
let mut a: i32 = 1;
17+
let mut b: i32 = 2;
18+
((a) + (b))
19+
};
20+
assert!(((x) == (3)));
21+
let mut counter: i32 = 0;
22+
let mut y: i32 = {
23+
counter.postfix_inc();
24+
((counter) * (10))
25+
};
26+
assert!(((y) == (10)));
27+
assert!(((counter) == (1)));
28+
let mut z: i32 = {
29+
let mut v: i32 = 5;
30+
if ((v) > (0)) {
31+
v = ((v) * (2));
32+
}
33+
v
34+
};
35+
assert!(((z) == (10)));
36+
assert!(
37+
(({
38+
let mut inner: i32 = {
39+
let mut a: i32 = 100;
40+
a
41+
};
42+
inner
43+
}) == (100))
44+
);
45+
return 0;
46+
}

tests/unit/stmt_expr.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <cassert>
2+
3+
int main() {
4+
int x = __extension__({
5+
int a = 1;
6+
int b = 2;
7+
a + b;
8+
});
9+
assert(x == 3);
10+
11+
int counter = 0;
12+
int y = ({
13+
counter++;
14+
counter * 10;
15+
});
16+
assert(y == 10);
17+
assert(counter == 1);
18+
19+
int z = ({
20+
int v = 5;
21+
if (v > 0) {
22+
v = v * 2;
23+
}
24+
v;
25+
});
26+
assert(z == 10);
27+
28+
assert(({
29+
int inner = ({
30+
int a = 100;
31+
a;
32+
});
33+
inner;
34+
}) == 100);
35+
return 0;
36+
}

0 commit comments

Comments
 (0)