Skip to content

Commit abea5bf

Browse files
authored
Translate void casts (#47)
1 parent 75d3e8b commit abea5bf

22 files changed

Lines changed: 423 additions & 15 deletions

cpp2rust/converter/converter.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,8 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
18691869
auto type = expr->getTypeAsWritten();
18701870
auto *sub_expr = expr->getSubExpr();
18711871
if (type->isVoidType()) {
1872+
PushExprKind push(*this, ExprKind::Void);
1873+
Convert(expr->getSubExpr());
18721874
return false;
18731875
}
18741876
switch (expr->getStmtClass()) {
@@ -1950,7 +1952,10 @@ bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) {
19501952
ConvertCast(lhs_type);
19511953
}
19521954
} else if (expr->isCommaOp()) {
1953-
Convert(lhs);
1955+
{
1956+
PushExprKind push(*this, ExprKind::Void);
1957+
Convert(lhs);
1958+
}
19541959
StrCat(token::kSemiColon);
19551960
Convert(rhs);
19561961
} else if (IsUnsignedArithOp(expr)) {
@@ -2248,11 +2253,20 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
22482253
}
22492254

22502255
bool Converter::VisitParenExpr(clang::ParenExpr *expr) {
2256+
// Comma operator becomes (A, B, C) -> { A; B; C }
2257+
if (auto *bin = clang::dyn_cast<clang::BinaryOperator>(expr->getSubExpr())) {
2258+
if (bin->isCommaOp()) {
2259+
PushBrace push(*this);
2260+
Convert(expr->getSubExpr());
2261+
return false;
2262+
}
2263+
}
2264+
22512265
// Add cast to avoid ambigous integers. Don't add cast if sub expression is a
22522266
// pointer dereference because we might want to mutate the dereferenced value.
22532267
bool should_add_integral_cast =
22542268
expr->getType()->isIntegralOrEnumerationType() && !isAddrOf() &&
2255-
!clang::isa<clang::UnaryOperator>(expr->getSubExpr());
2269+
!isVoid() && !clang::isa<clang::UnaryOperator>(expr->getSubExpr());
22562270
PushParen outer(*this, should_add_integral_cast);
22572271

22582272
{
@@ -3399,7 +3413,7 @@ void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,
33993413

34003414
void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) {
34013415
assert(pointer_type->isPointerType());
3402-
if (IsReferenceType(expr)) {
3416+
if (IsReferenceType(expr) || pointer_type->isFunctionPointerType()) {
34033417
PushExprKind push(*this, ExprKind::AddrOf);
34043418
Convert(expr);
34053419
} else {

cpp2rust/converter/converter_lib.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,4 +814,9 @@ ConstCastType GetConstCastType(clang::QualType to, clang::QualType from) {
814814
}
815815
}
816816

817+
bool TypeIsCopyable(clang::QualType ty) {
818+
return ty->isIntegerType() || ty->isFunctionPointerType() ||
819+
ty->isFunctionType();
820+
}
821+
817822
} // namespace cpp2rust

cpp2rust/converter/converter_lib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,6 @@ enum class ConstCastType {
180180

181181
ConstCastType GetConstCastType(clang::QualType to, clang::QualType from);
182182

183+
bool TypeIsCopyable(clang::QualType ty);
184+
183185
} // namespace cpp2rust

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,11 @@ bool ConverterRefCount::VisitFunctionPointerCast(
11281128

11291129
bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
11301130
if (expr->getTypeAsWritten()->isVoidType()) {
1131+
PushExprKind push(*this, ExprKind::Void);
1132+
Convert(expr->getSubExpr());
1133+
if (!TypeIsCopyable(expr->getSubExpr()->getType())) {
1134+
StrCat(".clone()");
1135+
}
11311136
return false;
11321137
}
11331138
switch (expr->getStmtClass()) {

tests/unit/comma_operator.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <cassert>
2+
3+
int main() {
4+
int x = 1;
5+
int y = (x = 2, x + 1);
6+
assert(x == 2);
7+
assert(y == 3);
8+
9+
int z = (1, 2, 3);
10+
assert(z == 3);
11+
12+
int counter = 0;
13+
int w = (counter++, counter++, counter);
14+
assert(counter == 2);
15+
assert(w == 2);
16+
17+
int a = 0, b = 0;
18+
if ((a = 1, b = 2, a + b > 0)) {
19+
assert(a == 1);
20+
assert(b == 2);
21+
}
22+
23+
return 0;
24+
}

tests/unit/out/refcount/bool_printing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ fn main_0() -> i32 {
2323
write!(
2424
libcc2rs::cout(),
2525
"{:}\n",
26-
((((*i1.borrow()) != (*i2.borrow())) as bool) as u8),
26+
(((*i1.borrow()) != (*i2.borrow())) as u8),
2727
);
2828
write!(
2929
libcc2rs::cout(),
3030
"{:}\n",
31-
((((*i1.borrow()) == (*i2.borrow())) as bool) as u8),
31+
(((*i1.borrow()) == (*i2.borrow())) as u8),
3232
);
3333
write!(libcc2rs::cout(), "{:}\n", (({ foo_0() }) as u8),);
3434
write!(libcc2rs::cout(), "{:}\n", (({ bar_1() }) as u8),);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
let y: Value<i32> = Rc::new(RefCell::new({
15+
(*x.borrow_mut()) = 2;
16+
((*x.borrow()) + 1)
17+
}));
18+
assert!(((*x.borrow()) == 2));
19+
assert!(((*y.borrow()) == 3));
20+
let z: Value<i32> = Rc::new(RefCell::new({
21+
1;
22+
2;
23+
3
24+
}));
25+
assert!(((*z.borrow()) == 3));
26+
let counter: Value<i32> = Rc::new(RefCell::new(0));
27+
let w: Value<i32> = Rc::new(RefCell::new({
28+
(*counter.borrow_mut()).postfix_inc();
29+
(*counter.borrow_mut()).postfix_inc();
30+
(*counter.borrow())
31+
}));
32+
assert!(((*counter.borrow()) == 2));
33+
assert!(((*w.borrow()) == 2));
34+
let a: Value<i32> = Rc::new(RefCell::new(0));
35+
let b: Value<i32> = Rc::new(RefCell::new(0));
36+
if {
37+
(*a.borrow_mut()) = 1;
38+
(*b.borrow_mut()) = 2;
39+
(((*a.borrow()) + (*b.borrow())) > 0)
40+
} {
41+
assert!(((*a.borrow()) == 1));
42+
assert!(((*b.borrow()) == 2));
43+
}
44+
return 0;
45+
}

tests/unit/out/refcount/continue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ fn main_0() -> i32 {
3535
'loop_: while ((*k2.borrow()) < 5) {
3636
let k3: Value<i32> = Rc::new(RefCell::new(0));
3737
'loop_: while ((*k3.borrow()) < 5) {
38-
if ((((((*k1.borrow()) + (*k2.borrow())) + (*k3.borrow())) as i32) % 2) == 0) {
38+
if (((((*k1.borrow()) + (*k2.borrow())) + (*k3.borrow())) % 2) == 0) {
3939
(*k3.borrow_mut()).postfix_inc();
4040
continue 'loop_;
4141
}
4242
(*out.borrow_mut()).prefix_inc();
4343
(*k3.borrow_mut()).postfix_inc();
4444
}
45-
if (((((*k1.borrow()) + (*k2.borrow())) as i32) % 2) == 0) {
45+
if ((((*k1.borrow()) + (*k2.borrow())) % 2) == 0) {
4646
(*k2.borrow_mut()).postfix_inc();
4747
continue 'loop_;
4848
}

tests/unit/out/refcount/reinterpret_cast_oob_read.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ fn main_0() -> i32 {
1515
let x: Value<u8> = Rc::new(RefCell::new(
1616
((*bytes.borrow()).offset((4) as isize).read()),
1717
));
18+
(*x.borrow_mut());
1819
return 0;
1920
}

tests/unit/out/refcount/reinterpret_cast_undersize.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ fn main_0() -> i32 {
1313
let b: Value<u8> = Rc::new(RefCell::new(66_u8));
1414
let p: Value<Ptr<u32>> = Rc::new(RefCell::new((b.as_pointer()).reinterpret_cast::<u32>()));
1515
let val: Value<u32> = Rc::new(RefCell::new(((*p.borrow()).read())));
16+
(*val.borrow_mut());
1617
return 0;
1718
}

0 commit comments

Comments
 (0)