Skip to content

Commit f469942

Browse files
authored
Fix assignments that produce values (#158)
1 parent 9a6306d commit f469942

6 files changed

Lines changed: 119 additions & 4 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2108,13 +2108,17 @@ void Converter::ConvertBinaryOperator(clang::BinaryOperator *expr) {
21082108
if (expr->isCompoundAssignmentOp() &&
21092109
expr->getLHS()->getType()->isPointerType() &&
21102110
expr->getRHS()->getType()->isIntegralOrEnumerationType()) {
2111+
PushBrace brace(*this, !isVoid());
21112112
Convert(lhs);
21122113
StrCat(token::kAssign);
21132114
{
21142115
PushParen paren(*this);
21152116
ConvertUnsignedArithOperand(lhs, type);
21162117
}
21172118
ConvertUnsignedArithBinaryOperator(expr, rhs);
2119+
if (!isVoid()) {
2120+
StrCat(token::kSemiColon, ConvertRValue(lhs));
2121+
}
21182122
} else {
21192123
ConvertAssignment(lhs, rhs, opcode_as_string);
21202124
}
@@ -3030,7 +3034,8 @@ bool Converter::VisitSwitchStmt(clang::SwitchStmt *stmt) {
30303034
if (has_fallthrough) {
30313035
StrCat("match", ToString(stmt->getCond()));
30323036
} else {
3033-
StrCat(std::format("let __match_cond = {};", ToString(stmt->getCond())));
3037+
StrCat(
3038+
std::format("let __match_cond = {};", ConvertRValue(stmt->getCond())));
30343039
StrCat("match __match_cond");
30353040
}
30363041

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1879,7 +1879,7 @@ void ConverterRefCount::ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
18791879
}
18801880

18811881
if (isRValue()) {
1882-
StrCat(token::kSemiColon, ConvertRValue(lhs));
1882+
StrCat(token::kSemiColon, ConvertFreshRValue(lhs));
18831883
}
18841884
}
18851885

tests/unit/assign_as_value.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
3+
int main(void) {
4+
char buf[2];
5+
char *p = buf, *q;
6+
q = p += 1;
7+
assert(q == buf + 1);
8+
9+
char out;
10+
switch (out = 'x') {
11+
case 'x':
12+
assert(1);
13+
break;
14+
default:
15+
assert(0);
16+
break;
17+
}
18+
assert(out == 'x');
19+
return 0;
20+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 buf: Value<Box<[u8]>> = Rc::new(RefCell::new(
14+
(0..2).map(|_| <u8>::default()).collect::<Box<[u8]>>(),
15+
));
16+
let p: Value<Ptr<u8>> = Rc::new(RefCell::new((buf.as_pointer() as Ptr<u8>)));
17+
let q: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::<u8>::null()));
18+
(*q.borrow_mut()) = {
19+
(*p.borrow_mut()) += 1;
20+
(*p.borrow()).clone()
21+
};
22+
assert!(
23+
((({
24+
let _lhs = (*q.borrow()).clone();
25+
_lhs == (buf.as_pointer() as Ptr<u8>).offset((1) as isize)
26+
}) as i32)
27+
!= 0)
28+
);
29+
let out: Value<u8> = <Value<u8>>::default();
30+
'switch: {
31+
let __match_cond = (({
32+
(*out.borrow_mut()) = (('x' as i32) as u8);
33+
(*out.borrow())
34+
}) as i32);
35+
match __match_cond {
36+
v if v == ('x' as i32) => {
37+
assert!((1 != 0));
38+
break 'switch;
39+
}
40+
_ => {
41+
assert!((0 != 0));
42+
break 'switch;
43+
}
44+
}
45+
};
46+
assert!((((((*out.borrow()) as i32) == ('x' as i32)) as i32) != 0));
47+
return 0;
48+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 buf: [u8; 2] = [0_u8; 2];
16+
let mut p: *mut u8 = buf.as_mut_ptr();
17+
let mut q: *mut u8 = std::ptr::null_mut();
18+
q = {
19+
p = (p).wrapping_add(1 as i32 as usize);
20+
p
21+
};
22+
assert!(((((q) == (buf.as_mut_ptr().offset((1) as isize))) as i32) != 0));
23+
let mut out: u8 = 0_u8;
24+
'switch: {
25+
let __match_cond = (({
26+
out = (('x' as i32) as u8);
27+
out
28+
}) as i32);
29+
match __match_cond {
30+
v if v == ('x' as i32) => {
31+
assert!((1 != 0));
32+
break 'switch;
33+
}
34+
_ => {
35+
assert!((0 != 0));
36+
break 'switch;
37+
}
38+
}
39+
};
40+
assert!(((((out as i32) == ('x' as i32)) as i32) != 0));
41+
return 0;
42+
}

tests/unit/out/unsafe/union_tagged_struct_arms.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn main() {
7373
}
7474
}
7575
unsafe fn main_0() -> i32 {
76-
static mut items_0: [*mut u8; 3] = unsafe {
76+
static mut items_4: [*mut u8; 3] = unsafe {
7777
[
7878
b"a\0".as_ptr().cast_mut(),
7979
b"b\0".as_ptr().cast_mut(),
@@ -83,7 +83,7 @@ unsafe fn main_0() -> i32 {
8383
let mut p_list: Branch = <Branch>::default();
8484
p_list.choice = Choice::C_LIST;
8585
p_list.index = 0;
86-
p_list.v.list.items = items_0.as_mut_ptr();
86+
p_list.v.list.items = items_4.as_mut_ptr();
8787
p_list.v.list.count = 3_i64;
8888
p_list.v.list.cursor = 1_i64;
8989
assert!(((((p_list.v.list.count) == (3_i64)) as i32) != 0));

0 commit comments

Comments
 (0)