Skip to content

Commit 02d26b8

Browse files
authored
Wrap BinaryOperator in integer cast in C mode (#58)
In C, comparison and logical binary operations always produce an int where a bool is expected. For this reason, wrap binary operators in `(... as i32)` if the type of BinaryOperator is int. ConvertIntegralToBooleanCast will later take care to convert the integer back to boolean.
1 parent fb1e8ea commit 02d26b8

110 files changed

Lines changed: 1581 additions & 771 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cpp2rust/converter/converter.cpp

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,24 +1742,12 @@ void Converter::ConvertIntegralToBooleanCast(clang::ImplicitCastExpr *expr) {
17421742
auto *stripped = sub_expr->IgnoreParenImpCasts();
17431743

17441744
if (auto binop = clang::dyn_cast<clang::BinaryOperator>(stripped)) {
1745-
// Comparison already produces bool, no wrap needed.
1746-
if (binop->isComparisonOp()) {
1745+
// Comparisons and logical ops already produces bool, no wrap needed.
1746+
if ((binop->isComparisonOp() || binop->isLogicalOp()) &&
1747+
binop->getType()->isBooleanType()) {
17471748
Convert(sub_expr);
17481749
return;
17491750
}
1750-
// Distribute bool conversion to each argument of the logical op.
1751-
if (binop->isLogicalOp()) {
1752-
{
1753-
PushParen paren(*this);
1754-
ConvertCondition(binop->getLHS());
1755-
}
1756-
StrCat(binop->getOpcodeStr());
1757-
{
1758-
PushParen paren(*this);
1759-
ConvertCondition(binop->getRHS());
1760-
}
1761-
return;
1762-
}
17631751
}
17641752

17651753
PushParen paren(*this);
@@ -1945,6 +1933,21 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
19451933
}
19461934

19471935
bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) {
1936+
bool needs_cast = (expr->isComparisonOp() || expr->isLogicalOp()) &&
1937+
expr->getType()->isIntegerType() &&
1938+
!expr->getType()->isBooleanType();
1939+
PushParen outer(*this, needs_cast);
1940+
{
1941+
PushParen inner(*this, needs_cast);
1942+
ConvertBinaryOperator(expr);
1943+
}
1944+
if (needs_cast) {
1945+
ConvertCast(expr->getType());
1946+
}
1947+
return false;
1948+
}
1949+
1950+
void Converter::ConvertBinaryOperator(clang::BinaryOperator *expr) {
19481951
auto type = expr->getType();
19491952
auto *lhs = expr->getLHS();
19501953
auto *rhs = expr->getRHS();
@@ -2048,10 +2051,19 @@ bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) {
20482051
}
20492052
ConvertCast(expr->getType());
20502053
computed_expr_type_ = ComputedExprType::FreshValue;
2054+
} else if (expr->isLogicalOp()) {
2055+
{
2056+
PushParen paren(*this);
2057+
ConvertCondition(expr->getLHS());
2058+
}
2059+
StrCat(expr->getOpcodeStr());
2060+
{
2061+
PushParen paren(*this);
2062+
ConvertCondition(expr->getRHS());
2063+
}
20512064
} else {
20522065
ConvertGenericBinaryOperator(expr);
20532066
}
2054-
return false;
20552067
}
20562068

20572069
void Converter::ConvertGenericBinaryOperator(clang::BinaryOperator *expr) {
@@ -2063,8 +2075,10 @@ void Converter::ConvertGenericBinaryOperator(clang::BinaryOperator *expr) {
20632075

20642076
StrCat(expr->getOpcodeStr());
20652077

2066-
PushParen rhs_paren(*this);
2067-
Convert(expr->getRHS());
2078+
{
2079+
PushParen rhs_paren(*this);
2080+
Convert(expr->getRHS());
2081+
}
20682082
}
20692083

20702084
bool Converter::IsReferenceType(const clang::Expr *expr) const {

cpp2rust/converter/converter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
252252

253253
virtual bool VisitBinaryOperator(clang::BinaryOperator *expr);
254254

255+
virtual void ConvertBinaryOperator(clang::BinaryOperator *expr);
256+
255257
virtual bool ConvertIncAndDec(clang::UnaryOperator *expr);
256258

257259
virtual bool VisitUnaryOperator(clang::UnaryOperator *expr);

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ void ConverterRefCount::EmitStmtExprTail(clang::Expr *tail) {
11911191
StrCat("__result");
11921192
}
11931193

1194-
bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) {
1194+
void ConverterRefCount::ConvertBinaryOperator(clang::BinaryOperator *expr) {
11951195
auto *lhs = expr->getLHS();
11961196
auto *rhs = expr->getRHS();
11971197
auto lhs_type = lhs->getType();
@@ -1229,7 +1229,7 @@ bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) {
12291229
}
12301230
StrCat(token::kSemiColon);
12311231
EmitSetOrAssign(lhs, "rhs_0");
1232-
return false;
1232+
return;
12331233
}
12341234

12351235
if (IsUnsignedArithOp(expr)) {
@@ -1249,7 +1249,7 @@ bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) {
12491249
StrCat(token::kSemiColon);
12501250
EmitSetOrAssign(lhs, "rhs_0");
12511251
}
1252-
return false;
1252+
return;
12531253
}
12541254

12551255
// pointer subtraction. The Sub trait gets elements by Value, so we need
@@ -1263,15 +1263,15 @@ bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) {
12631263
}
12641264
ConvertCast(expr->getType());
12651265
computed_expr_type_ = ComputedExprType::FreshValue;
1266-
return false;
1266+
return;
12671267
}
12681268

12691269
if (expr->isAssignmentOp()) {
12701270
ConvertAssignment(lhs, rhs, opcode_as_string);
1271-
return false;
1271+
return;
12721272
}
12731273

1274-
return Converter::VisitBinaryOperator(expr);
1274+
Converter::ConvertBinaryOperator(expr);
12751275
}
12761276

12771277
bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) {
@@ -1840,7 +1840,7 @@ void ConverterRefCount::ConvertGenericBinaryOperator(
18401840
return;
18411841
}
18421842

1843-
PushParen paren(*this);
1843+
PushParen outer(*this);
18441844
Convert(lhs);
18451845
StrCat(opcode);
18461846
Convert(rhs);

cpp2rust/converter/models/converter_refcount.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class ConverterRefCount final : public Converter {
8282

8383
bool VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) override;
8484

85-
bool VisitBinaryOperator(clang::BinaryOperator *expr) override;
85+
void ConvertBinaryOperator(clang::BinaryOperator *expr) override;
8686

8787
bool VisitStmtExpr(clang::StmtExpr *expr) override;
8888

tests/benchmarks/out/refcount/bst.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,21 @@ impl ByteRepr for node_t {}
2626
pub fn find_0(node: Ptr<node_t>, value: i32) -> Ptr<node_t> {
2727
let node: Value<Ptr<node_t>> = Rc::new(RefCell::new(node));
2828
let value: Value<i32> = Rc::new(RefCell::new(value));
29-
if {
30-
let _lhs = {
31-
let _lhs = (*value.borrow());
32-
_lhs < (*(*(*node.borrow()).upgrade().deref()).value.borrow())
33-
};
34-
_lhs && (!((*(*(*node.borrow()).upgrade().deref()).left.borrow()).is_null())).clone()
35-
} {
29+
if ({
30+
let _lhs = (*value.borrow());
31+
_lhs < (*(*(*node.borrow()).upgrade().deref()).value.borrow())
32+
}) && (!((*(*(*node.borrow()).upgrade().deref()).left.borrow()).is_null()))
33+
{
3634
return ({
3735
let _node: Ptr<node_t> = (*(*(*node.borrow()).upgrade().deref()).left.borrow()).clone();
3836
let _value: i32 = (*value.borrow());
3937
find_0(_node, _value)
4038
});
41-
} else if {
42-
let _lhs = {
43-
let _lhs = (*value.borrow());
44-
_lhs > (*(*(*node.borrow()).upgrade().deref()).value.borrow())
45-
};
46-
_lhs && (!((*(*(*node.borrow()).upgrade().deref()).right.borrow()).is_null())).clone()
47-
} {
39+
} else if ({
40+
let _lhs = (*value.borrow());
41+
_lhs > (*(*(*node.borrow()).upgrade().deref()).value.borrow())
42+
}) && (!((*(*(*node.borrow()).upgrade().deref()).right.borrow()).is_null()))
43+
{
4844
return ({
4945
let _node: Ptr<node_t> =
5046
(*(*(*node.borrow()).upgrade().deref()).right.borrow()).clone();

tests/benchmarks/out/refcount/fibonacci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn fib_0(n: u64) -> u64 {
1010
let n: Value<u64> = Rc::new(RefCell::new(n));
11-
return if (((*n.borrow()) == 0_u64) || ((*n.borrow()) == 1_u64)) {
11+
return if ((*n.borrow()) == 0_u64) || ((*n.borrow()) == 1_u64) {
1212
(*n.borrow())
1313
} else {
1414
({

tests/benchmarks/out/refcount/ptr_fibonacci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn fib_0(n: Ptr<u64>) {
1010
let n: Value<Ptr<u64>> = Rc::new(RefCell::new(n));
11-
if ((((*n.borrow()).read()) == 0_u64) || (((*n.borrow()).read()) == 1_u64)) {
11+
if (((*n.borrow()).read()) == 0_u64) || (((*n.borrow()).read()) == 1_u64) {
1212
return;
1313
}
1414
let n_1: Value<u64> = Rc::new(RefCell::new(((*n.borrow()).read()).wrapping_sub(1_u64)));

tests/benchmarks/out/refcount/ref_fibonacci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
pub fn fib_0(n: Ptr<u64>) {
10-
if (((n.read()) == 0_u64) || ((n.read()) == 1_u64)) {
10+
if ((n.read()) == 0_u64) || ((n.read()) == 1_u64) {
1111
return;
1212
}
1313
let n_1: Value<u64> = Rc::new(RefCell::new((n.read()).wrapping_sub(1_u64)));

tests/benchmarks/out/unsafe/bst.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ pub struct node_t {
1414
pub value: i32,
1515
}
1616
pub unsafe fn find_0(mut node: *mut node_t, mut value: i32) -> *mut node_t {
17-
if (((value) < ((*node).value)) && (!(((*node).left).is_null()))) {
17+
if ((value) < ((*node).value)) && (!(((*node).left).is_null())) {
1818
return (unsafe {
1919
let _node: *mut node_t = (*node).left;
2020
let _value: i32 = value;
2121
find_0(_node, _value)
2222
});
23-
} else if (((value) > ((*node).value)) && (!(((*node).right).is_null()))) {
23+
} else if ((value) > ((*node).value)) && (!(((*node).right).is_null())) {
2424
return (unsafe {
2525
let _node: *mut node_t = (*node).right;
2626
let _value: i32 = value;

tests/benchmarks/out/unsafe/fibonacci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn fib_0(mut n: u64) -> u64 {
10-
return if (((n) == (0_u64)) || ((n) == (1_u64))) {
10+
return if ((n) == (0_u64)) || ((n) == (1_u64)) {
1111
n
1212
} else {
1313
(unsafe {

0 commit comments

Comments
 (0)