Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1869,6 +1869,8 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
auto type = expr->getTypeAsWritten();
auto *sub_expr = expr->getSubExpr();
if (type->isVoidType()) {
PushExprKind push(*this, ExprKind::Void);
Convert(expr->getSubExpr());
return false;
}
switch (expr->getStmtClass()) {
Expand Down Expand Up @@ -1950,7 +1952,10 @@ bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) {
ConvertCast(lhs_type);
}
} else if (expr->isCommaOp()) {
Convert(lhs);
{
PushExprKind push(*this, ExprKind::Void);
Convert(lhs);
}
StrCat(token::kSemiColon);
Convert(rhs);
} else if (IsUnsignedArithOp(expr)) {
Expand Down Expand Up @@ -2248,11 +2253,20 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
}

bool Converter::VisitParenExpr(clang::ParenExpr *expr) {
// Comma operator becomes (A, B, C) -> { A; B; C }
if (auto *bin = clang::dyn_cast<clang::BinaryOperator>(expr->getSubExpr())) {
if (bin->isCommaOp()) {
PushBrace push(*this);
Convert(expr->getSubExpr());
return false;
}
}

// Add cast to avoid ambigous integers. Don't add cast if sub expression is a
// pointer dereference because we might want to mutate the dereferenced value.
bool should_add_integral_cast =
expr->getType()->isIntegralOrEnumerationType() && !isAddrOf() &&
!clang::isa<clang::UnaryOperator>(expr->getSubExpr());
!isVoid() && !clang::isa<clang::UnaryOperator>(expr->getSubExpr());
PushParen outer(*this, should_add_integral_cast);

{
Expand Down Expand Up @@ -3399,7 +3413,7 @@ void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,

void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) {
assert(pointer_type->isPointerType());
if (IsReferenceType(expr)) {
if (IsReferenceType(expr) || pointer_type->isFunctionPointerType()) {
PushExprKind push(*this, ExprKind::AddrOf);
Convert(expr);
} else {
Expand Down
5 changes: 5 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,4 +814,9 @@ ConstCastType GetConstCastType(clang::QualType to, clang::QualType from) {
}
}

bool TypeIsCopyable(clang::QualType ty) {
return ty->isIntegerType() || ty->isFunctionPointerType() ||
ty->isFunctionType();
}

} // namespace cpp2rust
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,6 @@ enum class ConstCastType {

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

bool TypeIsCopyable(clang::QualType ty);

} // namespace cpp2rust
5 changes: 5 additions & 0 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,11 @@ bool ConverterRefCount::VisitFunctionPointerCast(

bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
if (expr->getTypeAsWritten()->isVoidType()) {
PushExprKind push(*this, ExprKind::Void);
Convert(expr->getSubExpr());
if (!TypeIsCopyable(expr->getSubExpr()->getType())) {
StrCat(".clone()");
}
return false;
}
switch (expr->getStmtClass()) {
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/comma_operator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <cassert>

int main() {
int x = 1;
int y = (x = 2, x + 1);
assert(x == 2);
assert(y == 3);

int z = (1, 2, 3);
assert(z == 3);

int counter = 0;
int w = (counter++, counter++, counter);
assert(counter == 2);
assert(w == 2);

int a = 0, b = 0;
if ((a = 1, b = 2, a + b > 0)) {
assert(a == 1);
assert(b == 2);
}

return 0;
}
4 changes: 2 additions & 2 deletions tests/unit/out/refcount/bool_printing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ fn main_0() -> i32 {
write!(
libcc2rs::cout(),
"{:}\n",
((((*i1.borrow()) != (*i2.borrow())) as bool) as u8),
(((*i1.borrow()) != (*i2.borrow())) as u8),
);
write!(
libcc2rs::cout(),
"{:}\n",
((((*i1.borrow()) == (*i2.borrow())) as bool) as u8),
(((*i1.borrow()) == (*i2.borrow())) as u8),
);
write!(libcc2rs::cout(), "{:}\n", (({ foo_0() }) as u8),);
write!(libcc2rs::cout(), "{:}\n", (({ bar_1() }) as u8),);
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/out/refcount/comma_operator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let x: Value<i32> = Rc::new(RefCell::new(1));
let y: Value<i32> = Rc::new(RefCell::new({
(*x.borrow_mut()) = 2;
((*x.borrow()) + 1)
}));
assert!(((*x.borrow()) == 2));
assert!(((*y.borrow()) == 3));
let z: Value<i32> = Rc::new(RefCell::new({
1;
2;
3
}));
assert!(((*z.borrow()) == 3));
let counter: Value<i32> = Rc::new(RefCell::new(0));
let w: Value<i32> = Rc::new(RefCell::new({
(*counter.borrow_mut()).postfix_inc();
(*counter.borrow_mut()).postfix_inc();
(*counter.borrow())
}));
assert!(((*counter.borrow()) == 2));
assert!(((*w.borrow()) == 2));
let a: Value<i32> = Rc::new(RefCell::new(0));
let b: Value<i32> = Rc::new(RefCell::new(0));
if {
(*a.borrow_mut()) = 1;
(*b.borrow_mut()) = 2;
(((*a.borrow()) + (*b.borrow())) > 0)
} {
assert!(((*a.borrow()) == 1));
assert!(((*b.borrow()) == 2));
}
return 0;
}
4 changes: 2 additions & 2 deletions tests/unit/out/refcount/continue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ fn main_0() -> i32 {
'loop_: while ((*k2.borrow()) < 5) {
let k3: Value<i32> = Rc::new(RefCell::new(0));
'loop_: while ((*k3.borrow()) < 5) {
if ((((((*k1.borrow()) + (*k2.borrow())) + (*k3.borrow())) as i32) % 2) == 0) {
if (((((*k1.borrow()) + (*k2.borrow())) + (*k3.borrow())) % 2) == 0) {
(*k3.borrow_mut()).postfix_inc();
continue 'loop_;
}
(*out.borrow_mut()).prefix_inc();
(*k3.borrow_mut()).postfix_inc();
}
if (((((*k1.borrow()) + (*k2.borrow())) as i32) % 2) == 0) {
if ((((*k1.borrow()) + (*k2.borrow())) % 2) == 0) {
(*k2.borrow_mut()).postfix_inc();
continue 'loop_;
}
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/reinterpret_cast_oob_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ fn main_0() -> i32 {
let x: Value<u8> = Rc::new(RefCell::new(
((*bytes.borrow()).offset((4) as isize).read()),
));
(*x.borrow_mut());
return 0;
}
1 change: 1 addition & 0 deletions tests/unit/out/refcount/reinterpret_cast_undersize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ fn main_0() -> i32 {
let b: Value<u8> = Rc::new(RefCell::new(66_u8));
let p: Value<Ptr<u32>> = Rc::new(RefCell::new((b.as_pointer()).reinterpret_cast::<u32>()));
let val: Value<u32> = Rc::new(RefCell::new(((*p.borrow()).read())));
(*val.borrow_mut());
return 0;
}
4 changes: 2 additions & 2 deletions tests/unit/out/refcount/string_escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ fn main_0() -> i32 {
);
let i: Value<i32> = Rc::new(RefCell::new(0));
'loop_: while ((*i.borrow())
< ((((::std::mem::size_of::<[u8; 40]>() as u64 as u64)
.wrapping_div(::std::mem::size_of::<u8>() as u64 as u64)) as u64) as i32))
< (((::std::mem::size_of::<[u8; 40]>() as u64 as u64)
.wrapping_div(::std::mem::size_of::<u8>() as u64 as u64)) as i32))
{
assert!({
let _lhs = (((*special.borrow()).offset((*i.borrow()) as isize).read()) as i32);
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/va_arg_printf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::rc::{Rc, Weak};
pub fn logf_impl_0(fmt: Ptr<u8>, ap: VaList) -> i32 {
let fmt: Value<Ptr<u8>> = Rc::new(RefCell::new(fmt));
let ap: Value<VaList> = Rc::new(RefCell::new(ap));
(*fmt.borrow()).clone();
return {
let _lhs = ((*ap.borrow_mut()).arg::<i32>()).clone();
_lhs + ((*ap.borrow_mut()).arg::<i32>()).clone()
Expand Down
97 changes: 97 additions & 0 deletions tests/unit/out/refcount/void_cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn unused_param_0(x: i32) {
let x: Value<i32> = Rc::new(RefCell::new(x));
(*x.borrow_mut());
}
thread_local!(
pub static side_effect_counter: Value<i32> = Rc::new(RefCell::new(0));
);
pub fn bump_and_return_1() -> i32 {
(*side_effect_counter.with(Value::clone).borrow_mut()).prefix_inc();
return (*side_effect_counter.with(Value::clone).borrow());
}
#[derive(Default)]
pub struct Holder {
pub field: Value<i32>,
}
impl Clone for Holder {
fn clone(&self) -> Self {
let mut this = Self {
field: Rc::new(RefCell::new((*self.field.borrow()))),
};
this
}
}
impl ByteRepr for Holder {}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
({
let _x: i32 = 42;
unused_param_0(_x)
});
let y: Value<i32> = Rc::new(RefCell::new(5));
(*y.borrow_mut());
let z: Value<i32> = Rc::new(RefCell::new({
(*y.borrow_mut());
7
}));
assert!(((*z.borrow()) == 7));
let counter: Value<i32> = Rc::new(RefCell::new(0));
let w: Value<i32> = Rc::new(RefCell::new({
(*counter.borrow_mut());
(*counter.borrow_mut()) = 3;
(*counter.borrow())
}));
assert!(((*w.borrow()) == 3));
assert!(((*counter.borrow()) == 3));
({ bump_and_return_1() });
assert!(((*side_effect_counter.with(Value::clone).borrow()) == 1));
let v: Value<i32> = Rc::new(RefCell::new({
({ bump_and_return_1() });
99
}));
assert!(((*side_effect_counter.with(Value::clone).borrow()) == 2));
assert!(((*v.borrow()) == 99));
0;
(0);
(*y.borrow_mut());
(0);
(*y.borrow_mut());
let err: Value<i32> = Rc::new(RefCell::new(0));
((*err.borrow_mut()) = 42);
assert!(((*err.borrow()) == 42));
let chosen: Value<i32> = Rc::new(RefCell::new({
((*err.borrow_mut()) = 7);
123
}));
assert!(((*err.borrow()) == 7));
assert!(((*chosen.borrow()) == 123));
bump_and_return_1;
assert!(((*side_effect_counter.with(Value::clone).borrow()) == 2));
(FnPtr::<fn() -> i32>::new(bump_and_return_1));
assert!(((*side_effect_counter.with(Value::clone).borrow()) == 2));
((FnPtr::<fn() -> i32>::new(bump_and_return_1)).cast::<fn() -> i32>(None));
assert!(((*side_effect_counter.with(Value::clone).borrow()) == 2));
let storage: Value<i32> = Rc::new(RefCell::new(11));
let p: Value<Ptr<i32>> = Rc::new(RefCell::new((storage.as_pointer())));
((*p.borrow()).read());
(*p.borrow_mut()).clone();
let arr: Value<Box<[i32]>> = Rc::new(RefCell::new(Box::new([1, 2, 3])));
((*arr.borrow_mut())[(1) as usize]);
let h: Value<Holder> = Rc::new(RefCell::new(Holder {
field: Rc::new(RefCell::new(17)),
}));
(*(*h.borrow()).field.borrow_mut());
let hp: Value<Ptr<Holder>> = Rc::new(RefCell::new((h.as_pointer())));
(*(*(*hp.borrow()).upgrade().deref()).field.borrow_mut());
return 0;
}
4 changes: 2 additions & 2 deletions tests/unit/out/unsafe/bool_printing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ unsafe fn main_0() -> i32 {
.into_raw_fd(),
),
"{:}\n",
((((i1) != (i2)) as bool) as u8),
(((i1) != (i2)) as u8),
);
write!(
std::fs::File::from_raw_fd(
Expand All @@ -62,7 +62,7 @@ unsafe fn main_0() -> i32 {
.into_raw_fd(),
),
"{:}\n",
((((i1) == (i2)) as bool) as u8),
(((i1) == (i2)) as u8),
);
write!(
std::fs::File::from_raw_fd(
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/out/unsafe/comma_operator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
extern crate libc;
use libc::*;
extern crate libcc2rs;
use libcc2rs::*;
use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut x: i32 = 1;
let mut y: i32 = {
x = 2;
((x) + (1))
};
assert!(((x) == (2)));
assert!(((y) == (3)));
let mut z: i32 = {
1;
2;
3
};
assert!(((z) == (3)));
let mut counter: i32 = 0;
let mut w: i32 = {
counter.postfix_inc();
counter.postfix_inc();
counter
};
assert!(((counter) == (2)));
assert!(((w) == (2)));
let mut a: i32 = 0;
let mut b: i32 = 0;
if {
a = 1;
b = 2;
(((a) + (b)) > (0))
} {
assert!(((a) == (1)));
assert!(((b) == (2)));
}
return 0;
}
4 changes: 2 additions & 2 deletions tests/unit/out/unsafe/continue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ unsafe fn main_0() -> i32 {
'loop_: while ((k2) < (5)) {
let mut k3: i32 = 0;
'loop_: while ((k3) < (5)) {
if ((((((k1) + (k2)) + (k3)) as i32) % (2)) == (0)) {
if (((((k1) + (k2)) + (k3)) % (2)) == (0)) {
k3.postfix_inc();
continue 'loop_;
}
out.prefix_inc();
k3.postfix_inc();
}
if (((((k1) + (k2)) as i32) % (2)) == (0)) {
if ((((k1) + (k2)) % (2)) == (0)) {
k2.postfix_inc();
continue 'loop_;
}
Expand Down
Loading
Loading