From feaaa9f9df47397a8e498c19c4a7f670e82c523f Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 2 May 2026 19:38:07 +0100 Subject: [PATCH 1/3] Translate pointer diff --- cpp2rust/converter/converter.cpp | 2 +- .../converter/models/converter_refcount.cpp | 8 ++- libcc2rs/src/rc.rs | 60 +++++++------------ 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 7da20748..6d56236a 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2028,7 +2028,7 @@ bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) { std::format("::std::mem::size_of::<{}>()", pointee_type_as_string); StrCat(size_of_as_string); } - StrCat(keyword::kAs, "u64"); + ConvertCast(expr->getType()); computed_expr_type_ = ComputedExprType::FreshValue; } else { ConvertGenericBinaryOperator(expr); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index e906bd0f..645cf63b 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1247,8 +1247,12 @@ bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) { // fresh pointers if (expr->isAdditiveOp() && lhs_type->isPointerType() && rhs_type->isPointerType()) { - StrCat(ConvertFreshPointer(lhs), expr->getOpcodeStr(), - ConvertFreshPointer(rhs)); + { + PushParen paren(*this); + StrCat(ConvertFreshPointer(lhs), expr->getOpcodeStr(), + ConvertFreshPointer(rhs)); + } + ConvertCast(expr->getType()); computed_expr_type_ = ComputedExprType::FreshValue; return false; } diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index 4c16e5a5..63f1942b 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -675,45 +675,29 @@ impl Sub for Ptr { } } -impl std::ops::AddAssign for Ptr { - #[inline] - fn add_assign(&mut self, other: u64) { - let step = self.elem_step(); - self.offset = self - .offset - .wrapping_add((other as usize).wrapping_mul(step)); - } -} - -impl std::ops::AddAssign for Ptr { - #[inline] - fn add_assign(&mut self, other: i32) { - let step = self.elem_step(); - self.offset = self - .offset - .wrapping_add(((other as isize).wrapping_mul(step as isize)) as usize); - } -} - -impl std::ops::AddAssign for Ptr { - #[inline] - fn add_assign(&mut self, other: u32) { - let step = self.elem_step(); - self.offset = self - .offset - .wrapping_add((other as usize).wrapping_mul(step)); - } -} - -impl std::ops::AddAssign for Ptr { - #[inline] - fn add_assign(&mut self, other: isize) { - let step = self.elem_step(); - self.offset = self - .offset - .wrapping_add((other.wrapping_mul(step as isize)) as usize); - } +macro_rules! impl_ptr_add_sub_assign { + ($($rhs:ty),+) => { $( + impl std::ops::AddAssign<$rhs> for Ptr { + #[inline] + fn add_assign(&mut self, other: $rhs) { + let step = self.elem_step(); + self.offset = self.offset.wrapping_add( + ((other as isize).wrapping_mul(step as isize)) as usize, + ); + } + } + impl std::ops::SubAssign<$rhs> for Ptr { + #[inline] + fn sub_assign(&mut self, other: $rhs) { + let step = self.elem_step(); + self.offset = self.offset.wrapping_sub( + ((other as isize).wrapping_mul(step as isize)) as usize, + ); + } + } + )+ } } +impl_ptr_add_sub_assign!(i32, u32, u64, isize); macro_rules! impl_ptr_add_sub { ($($rhs:ty),+) => { $( From d4668b83a88860a9cc7c63a706a0bdec2121ce03 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 2 May 2026 19:38:27 +0100 Subject: [PATCH 2/3] Update tests --- .../unit/out/refcount/pointer_usize_arith.rs | 116 ++++++++++++++++++ tests/unit/out/unsafe/pointer_usize_arith.rs | 83 +++++++++++++ tests/unit/pointer_usize_arith.cpp | 93 ++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 tests/unit/out/refcount/pointer_usize_arith.rs create mode 100644 tests/unit/out/unsafe/pointer_usize_arith.rs create mode 100644 tests/unit/pointer_usize_arith.cpp diff --git a/tests/unit/out/refcount/pointer_usize_arith.rs b/tests/unit/out/refcount/pointer_usize_arith.rs new file mode 100644 index 00000000..6d5edec0 --- /dev/null +++ b/tests/unit/out/refcount/pointer_usize_arith.rs @@ -0,0 +1,116 @@ +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 arr: Value> = Rc::new(RefCell::new(Box::new([10, 11, 12, 13, 14, 15, 16, 17]))); + let p: Value> = Rc::new(RefCell::new((arr.as_pointer() as Ptr))); + let q: Value> = Rc::new(RefCell::new((*p.borrow()).offset((1) as isize))); + assert!((((*q.borrow()).read()) == 11)); + let r: Value> = Rc::new(RefCell::new((*p.borrow()).offset((3) as isize))); + assert!((((*r.borrow()).read()) == 13)); + let s: Value> = Rc::new(RefCell::new((*r.borrow()).offset(-((2) as isize)))); + assert!((((*s.borrow()).read()) == 11)); + let diff: Value = Rc::new(RefCell::new( + ((*r.borrow()).clone() - (*p.borrow()).clone()) as i64, + )); + assert!(((*diff.borrow()) == 3_i64)); + let idx: Value = Rc::new(RefCell::new( + (((((*r.borrow()).clone() - (*p.borrow()).clone()) as i64) as i64) as u64), + )); + assert!(((*idx.borrow()) == 3_u64)); + let q2: Value> = Rc::new(RefCell::new((*p.borrow()).clone())); + (*q2.borrow_mut()).prefix_inc(); + assert!((((*q2.borrow()).read()) == 11)); + (*q2.borrow_mut()).postfix_inc(); + assert!((((*q2.borrow()).read()) == 12)); + (*q2.borrow_mut()).prefix_dec(); + assert!((((*q2.borrow()).read()) == 11)); + (*q2.borrow_mut()).postfix_dec(); + assert!((((*q2.borrow()).read()) == 10)); + assert!({ + let _lhs = (*q2.borrow()).clone(); + _lhs == (*p.borrow()).clone() + }); + let q3: Value> = Rc::new(RefCell::new((*p.borrow()).clone())); + (*q3.borrow_mut()) += 4; + assert!((((*q3.borrow()).read()) == 14)); + (*q3.borrow_mut()) -= 2; + assert!((((*q3.borrow()).read()) == 12)); + let step: Value = Rc::new(RefCell::new(2_u64)); + let q4: Value> = Rc::new(RefCell::new( + (*p.borrow()).offset((*step.borrow()) as isize), + )); + assert!((((*q4.borrow()).read()) == 12)); + let v: Value = Rc::new(RefCell::new(((*p.borrow()).offset((3) as isize).read()))); + assert!(((*v.borrow()) == 13)); + let v2: Value = Rc::new(RefCell::new((((*p.borrow()).offset((4) as isize)).read()))); + assert!(((*v2.borrow()) == 14)); + ((*p.borrow()).offset((5) as isize)).write(99); + assert!((((*p.borrow()).offset((5) as isize).read()) == 99)); + assert!(((*arr.borrow())[(5) as usize] == 99)); + let end: Value> = Rc::new(RefCell::new((*p.borrow()).offset((8) as isize))); + let sum: Value = Rc::new(RefCell::new(0)); + let it: Value> = Rc::new(RefCell::new((*p.borrow()).clone())); + 'loop_: while { + let _lhs = (*it.borrow()).clone(); + _lhs != (*end.borrow()).clone() + } { + let __rhs = ((*it.borrow()).read()); + (*sum.borrow_mut()) += __rhs; + (*it.borrow_mut()).prefix_inc(); + } + assert!(((*sum.borrow()) == (((((((10 + 11) + 12) + 13) + 14) + 99) + 16) + 17))); + let bytes: Value> = Rc::new(RefCell::new(Box::new([ + 0_u8, 1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8, + ]))); + let bp: Value> = Rc::new(RefCell::new((bytes.as_pointer() as Ptr))); + let bq: Value> = Rc::new(RefCell::new((*bp.borrow()).offset((4) as isize))); + assert!(((((*bq.borrow()).read()) as i32) == 4)); + let bdiff: Value = Rc::new(RefCell::new( + ((*bq.borrow()).clone() - (*bp.borrow()).clone()) as i64, + )); + assert!(((*bdiff.borrow()) == 4_i64)); + let cp: Value> = Rc::new(RefCell::new((arr.as_pointer() as Ptr))); + let cq: Value> = Rc::new(RefCell::new((*cp.borrow()).offset((2) as isize))); + assert!((((*cq.borrow()).read()) == 12)); + let cdiff: Value = Rc::new(RefCell::new( + ((*cq.borrow()).clone() - (*cp.borrow()).clone()) as i64, + )); + assert!(((*cdiff.borrow()) == 2_i64)); + let n: Value = Rc::new(RefCell::new(3_u64)); + let q5: Value> = Rc::new(RefCell::new( + (arr.as_pointer() as Ptr).offset((*n.borrow()) as isize), + )); + assert!((((*q5.borrow()).read()) == 13)); + let q6: Value> = Rc::new(RefCell::new( + ((arr.as_pointer() as Ptr).offset((*n.borrow()) as isize)), + )); + assert!({ + let _lhs = (*q6.borrow()).clone(); + _lhs == (*q5.borrow()).clone() + }); + let matrix: Value>]>> = Rc::new(RefCell::new(Box::new([ + Rc::new(RefCell::new(Box::new([0, 1, 2, 3]))), + Rc::new(RefCell::new(Box::new([4, 5, 6, 7]))), + Rc::new(RefCell::new(Box::new([8, 9, 10, 11]))), + ]))); + let row1: Value> = Rc::new(RefCell::new( + ((((matrix.as_pointer() as Ptr>>) + .offset(1 as isize) + .read() + .as_pointer()) as Ptr) + .offset(0 as isize)), + )); + assert!((((*row1.borrow()).offset((2) as isize).read()) == 6)); + let back: Value> = Rc::new(RefCell::new((*end.borrow()).offset(-((1) as isize)))); + assert!((((*back.borrow()).read()) == 17)); + return 0; +} diff --git a/tests/unit/out/unsafe/pointer_usize_arith.rs b/tests/unit/out/unsafe/pointer_usize_arith.rs new file mode 100644 index 00000000..693f1b46 --- /dev/null +++ b/tests/unit/out/unsafe/pointer_usize_arith.rs @@ -0,0 +1,83 @@ +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 arr: [i32; 8] = [10, 11, 12, 13, 14, 15, 16, 17]; + let mut p: *mut i32 = arr.as_mut_ptr(); + let mut q: *mut i32 = p.offset((1) as isize); + assert!(((*q) == (11))); + let mut r: *mut i32 = p.offset((3) as isize); + assert!(((*r) == (13))); + let mut s: *mut i32 = r.offset(-((2) as isize)); + assert!(((*s) == (11))); + let mut diff: i64 = ((r as usize - p as usize) / ::std::mem::size_of::()) as i64; + assert!(((diff) == (3_i64))); + let mut idx: u64 = + (((((r as usize - p as usize) / ::std::mem::size_of::()) as i64) as i64) as u64); + assert!(((idx) == (3_u64))); + let mut q2: *mut i32 = p; + q2.prefix_inc(); + assert!(((*q2) == (11))); + q2.postfix_inc(); + assert!(((*q2) == (12))); + q2.prefix_dec(); + assert!(((*q2) == (11))); + q2.postfix_dec(); + assert!(((*q2) == (10))); + assert!(((q2) == (p))); + let mut q3: *mut i32 = p; + q3 = (q3).wrapping_add(4 as i32 as usize); + assert!(((*q3) == (14))); + q3 = (q3).wrapping_sub(2 as i32 as usize); + assert!(((*q3) == (12))); + let mut step: u64 = 2_u64; + let mut q4: *mut i32 = p.offset((step) as isize); + assert!(((*q4) == (12))); + let mut v: i32 = (*p.offset((3) as isize)); + assert!(((v) == (13))); + let mut v2: i32 = (*(p.offset((4) as isize))); + assert!(((v2) == (14))); + (*(p.offset((5) as isize))) = 99; + assert!(((*p.offset((5) as isize)) == (99))); + assert!(((arr[(5) as usize]) == (99))); + let mut end: *mut i32 = p.offset((8) as isize); + let mut sum: i32 = 0; + let mut it: *mut i32 = p; + 'loop_: while ((it) != (end)) { + sum += (*it); + it.prefix_inc(); + } + assert!(((sum) == ((((((((10) + (11)) + (12)) + (13)) + (14)) + (99)) + (16)) + (17)))); + let mut bytes: [u8; 8] = [0_u8, 1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8]; + let mut bp: *mut u8 = bytes.as_mut_ptr(); + let mut bq: *mut u8 = bp.offset((4) as isize); + assert!((((*bq) as i32) == (4))); + let mut bdiff: i64 = ((bq as usize - bp as usize) / ::std::mem::size_of::()) as i64; + assert!(((bdiff) == (4_i64))); + let mut cp: *const i32 = arr.as_mut_ptr().cast_const(); + let mut cq: *const i32 = cp.offset((2) as isize); + assert!(((*cq) == (12))); + let mut cdiff: i64 = ((cq as usize - cp as usize) / ::std::mem::size_of::()) as i64; + assert!(((cdiff) == (2_i64))); + let mut n: u64 = 3_u64; + let mut q5: *mut i32 = arr.as_mut_ptr().offset((n) as isize); + assert!(((*q5) == (13))); + let mut q6: *mut i32 = (&mut arr[(n) as usize] as *mut i32); + assert!(((q6) == (q5))); + let mut matrix: [[i32; 4]; 3] = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]; + let mut row1: *mut i32 = (&mut matrix[(1) as usize][(0) as usize] as *mut i32); + assert!(((*row1.offset((2) as isize)) == (6))); + let mut back: *mut i32 = end.offset(-((1) as isize)); + assert!(((*back) == (17))); + return 0; +} diff --git a/tests/unit/pointer_usize_arith.cpp b/tests/unit/pointer_usize_arith.cpp new file mode 100644 index 00000000..d1c48652 --- /dev/null +++ b/tests/unit/pointer_usize_arith.cpp @@ -0,0 +1,93 @@ +#include +#include + +int main() { + int arr[8] = {10, 11, 12, 13, 14, 15, 16, 17}; + int *p = arr; + + int *q = p + 1; + assert(*q == 11); + + int *r = p + 3; + assert(*r == 13); + + int *s = r - 2; + assert(*s == 11); + + ptrdiff_t diff = r - p; + assert(diff == 3); + + size_t idx = (size_t)(r - p); + assert(idx == 3); + + int *q2 = p; + ++q2; + assert(*q2 == 11); + + q2++; + assert(*q2 == 12); + + --q2; + assert(*q2 == 11); + + q2--; + assert(*q2 == 10); + assert(q2 == p); + + int *q3 = p; + q3 += 4; + assert(*q3 == 14); + q3 -= 2; + assert(*q3 == 12); + + size_t step = 2; + int *q4 = p + step; + assert(*q4 == 12); + + int v = p[3]; + assert(v == 13); + + int v2 = *(p + 4); + assert(v2 == 14); + + *(p + 5) = 99; + assert(p[5] == 99); + assert(arr[5] == 99); + + int *end = p + 8; + int sum = 0; + for (int *it = p; it != end; ++it) { + sum += *it; + } + assert(sum == 10 + 11 + 12 + 13 + 14 + 99 + 16 + 17); + + unsigned char bytes[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + unsigned char *bp = bytes; + unsigned char *bq = bp + 4; + assert(*bq == 4); + + ptrdiff_t bdiff = bq - bp; + assert(bdiff == 4); + + const int *cp = arr; + const int *cq = cp + 2; + assert(*cq == 12); + ptrdiff_t cdiff = cq - cp; + assert(cdiff == 2); + + size_t n = 3; + int *q5 = arr + n; + assert(*q5 == 13); + + int *q6 = &arr[n]; + assert(q6 == q5); + + int matrix[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}; + int *row1 = &matrix[1][0]; + assert(row1[2] == 6); + + int *back = end - 1; + assert(*back == 17); + + return 0; +} From 36f17503948cde7e4473445ed027cde8fce42a33 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 2 May 2026 19:45:46 +0100 Subject: [PATCH 3/3] Update tests --- tests/ub/out/refcount/ub7.rs | 2 +- tests/ub/out/unsafe/ub7.rs | 2 +- tests/unit/out/refcount/02_address_taken.rs | 2 +- tests/unit/out/refcount/pointer_diff.rs | 2 +- tests/unit/out/refcount/strlen_diff.rs | 2 +- tests/unit/out/unsafe/02_address_taken.rs | 2 +- tests/unit/out/unsafe/pointer_diff.rs | 2 +- tests/unit/out/unsafe/strlen_diff.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ub/out/refcount/ub7.rs b/tests/ub/out/refcount/ub7.rs index d073d77a..c4be4783 100644 --- a/tests/ub/out/refcount/ub7.rs +++ b/tests/ub/out/refcount/ub7.rs @@ -12,7 +12,7 @@ pub fn strlen_0(s: Ptr) -> u64 { 'loop_: while (((*s.borrow()).read()) != 0) { (*s.borrow_mut()).prefix_inc(); } - return (((*s.borrow()).clone() - (*begin.borrow()).clone()) as u64); + return ((((*s.borrow()).clone() - (*begin.borrow()).clone()) as i64) as u64); } pub fn main() { std::process::exit(main_0()); diff --git a/tests/ub/out/unsafe/ub7.rs b/tests/ub/out/unsafe/ub7.rs index 9f19b8ae..266ccb76 100644 --- a/tests/ub/out/unsafe/ub7.rs +++ b/tests/ub/out/unsafe/ub7.rs @@ -11,7 +11,7 @@ pub unsafe fn strlen_0(mut s: *const u8) -> u64 { 'loop_: while ((*s) != 0) { s.prefix_inc(); } - return ((((s as usize - begin as usize) / ::std::mem::size_of::()) as u64) as u64); + return ((((s as usize - begin as usize) / ::std::mem::size_of::()) as i64) as u64); } pub fn main() { unsafe { diff --git a/tests/unit/out/refcount/02_address_taken.rs b/tests/unit/out/refcount/02_address_taken.rs index 9f9728f2..bb9f33c0 100644 --- a/tests/unit/out/refcount/02_address_taken.rs +++ b/tests/unit/out/refcount/02_address_taken.rs @@ -18,7 +18,7 @@ fn main_0() -> i32 { let __rhs = (((*b_ptr_ptr.borrow()).read()).read()); (*b_ptr.borrow()).write(__rhs); let offset: Value = Rc::new(RefCell::new( - (((*b_ptr.borrow()).clone() - (*b_ptr.borrow()).clone()) as u64), + ((((*b_ptr.borrow()).clone() - (*b_ptr.borrow()).clone()) as i64) as u64), )); return (*b.borrow()); } diff --git a/tests/unit/out/refcount/pointer_diff.rs b/tests/unit/out/refcount/pointer_diff.rs index e8e926f8..c305cf56 100644 --- a/tests/unit/out/refcount/pointer_diff.rs +++ b/tests/unit/out/refcount/pointer_diff.rs @@ -17,5 +17,5 @@ fn main_0() -> i32 { let p1: Value> = Rc::new(RefCell::new( ((a.as_pointer() as Ptr).offset(4 as isize)), )); - return (((*p1.borrow()).clone() - (*p0.borrow()).clone()) as i32); + return ((((*p1.borrow()).clone() - (*p0.borrow()).clone()) as i64) as i32); } diff --git a/tests/unit/out/refcount/strlen_diff.rs b/tests/unit/out/refcount/strlen_diff.rs index a9667d34..75ac13f3 100644 --- a/tests/unit/out/refcount/strlen_diff.rs +++ b/tests/unit/out/refcount/strlen_diff.rs @@ -12,7 +12,7 @@ pub fn strlen_0(s: Ptr) -> u64 { 'loop_: while (((*s.borrow()).read()) != 0) { (*s.borrow_mut()).prefix_inc(); } - return (((*s.borrow()).clone() - (*begin.borrow()).clone()) as u64); + return ((((*s.borrow()).clone() - (*begin.borrow()).clone()) as i64) as u64); } pub fn main() { std::process::exit(main_0()); diff --git a/tests/unit/out/unsafe/02_address_taken.rs b/tests/unit/out/unsafe/02_address_taken.rs index be020eba..719c0bc1 100644 --- a/tests/unit/out/unsafe/02_address_taken.rs +++ b/tests/unit/out/unsafe/02_address_taken.rs @@ -19,6 +19,6 @@ unsafe fn main_0() -> i32 { (*(*b_ptr_ptr)) = 4; (*b_ptr) = (*(*b_ptr_ptr)); let mut offset: u64 = - ((((b_ptr as usize - b_ptr as usize) / ::std::mem::size_of::()) as u64) as u64); + ((((b_ptr as usize - b_ptr as usize) / ::std::mem::size_of::()) as i64) as u64); return b; } diff --git a/tests/unit/out/unsafe/pointer_diff.rs b/tests/unit/out/unsafe/pointer_diff.rs index 794fdc58..77c617fa 100644 --- a/tests/unit/out/unsafe/pointer_diff.rs +++ b/tests/unit/out/unsafe/pointer_diff.rs @@ -15,5 +15,5 @@ unsafe fn main_0() -> i32 { let mut a: [i32; 5] = [1, 2, 3, 4, 5]; let mut p0: *const i32 = (&mut a[(0) as usize] as *mut i32).cast_const(); let mut p1: *const i32 = (&mut a[(4) as usize] as *mut i32).cast_const(); - return ((((p1 as usize - p0 as usize) / ::std::mem::size_of::()) as u64) as i32); + return ((((p1 as usize - p0 as usize) / ::std::mem::size_of::()) as i64) as i32); } diff --git a/tests/unit/out/unsafe/strlen_diff.rs b/tests/unit/out/unsafe/strlen_diff.rs index 10a8349b..3fa7d592 100644 --- a/tests/unit/out/unsafe/strlen_diff.rs +++ b/tests/unit/out/unsafe/strlen_diff.rs @@ -11,7 +11,7 @@ pub unsafe fn strlen_0(mut s: *const u8) -> u64 { 'loop_: while ((*s) != 0) { s.prefix_inc(); } - return ((((s as usize - begin as usize) / ::std::mem::size_of::()) as u64) as u64); + return ((((s as usize - begin as usize) / ::std::mem::size_of::()) as i64) as u64); } pub fn main() { unsafe {