From a2ce948f94bfda69a2068b06de810a5fee310730 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 6 Jul 2026 12:24:24 +0100 Subject: [PATCH] Add Ptr::from_int and Ptr::to_int --- .../converter/models/converter_refcount.cpp | 22 +++++++++++++++++ libcc2rs/src/rc.rs | 24 +++++++++++++++++++ tests/unit/out/refcount/unconst.rs | 24 +++++++++++++++++++ tests/unit/out/unsafe/unconst.rs | 21 ++++++++++++++++ tests/unit/unconst.cpp | 13 ++++++++++ 5 files changed, 104 insertions(+) create mode 100644 tests/unit/out/refcount/unconst.rs create mode 100644 tests/unit/out/unsafe/unconst.rs create mode 100644 tests/unit/unconst.cpp diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index c7a2be2b..639aef48 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1307,8 +1307,30 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { return false; case clang::Stmt::CStyleCastExprClass: case clang::Stmt::CXXStaticCastExprClass: + if (expr->getCastKind() == clang::CastKind::CK_PointerToIntegral || + expr->getCastKind() == clang::CastKind::CK_IntegralToPointer) { + std::string dst_type; + { + PushConversionKind push(*this, ConversionKind::Unboxed); + dst_type = ToString(expr->getType()); + } + if (expr->getCastKind() == clang::CastKind::CK_PointerToIntegral) { + StrCat(std::format("{}.to_int::<{}>()", ToString(expr->getSubExpr()), + dst_type)); + computed_expr_type_ = ComputedExprType::FreshValue; + } else { + StrCat(std::format("<{}>::from_int({})", dst_type, + ToString(expr->getSubExpr()))); + computed_expr_type_ = ComputedExprType::FreshPointer; + } + return false; + } + if (!VisitFunctionPointerCast(expr)) { return false; + } else if (expr->getSubExpr()->getType()->isVoidPointerType() && + expr->getType()->isVoidPointerType()) { + return Convert(expr->getSubExpr()); } else if (expr->getSubExpr()->getType()->isVoidPointerType() && expr->getType()->isPointerType()) { Convert(expr->getSubExpr()); diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index f13be101..7a714b50 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -1211,6 +1211,30 @@ impl AsPointerDyn for Rc> { impl ByteRepr for Ptr {} impl ByteRepr for AnyPtr {} +impl Ptr { + pub fn to_int(&self) -> U { + let mut buf = vec![0u8; Self::byte_size()]; + self.to_bytes(&mut buf); + U::from_bytes(&buf[..U::byte_size()]) + } + + pub fn from_int(value: U) -> Self { + let mut buf = vec![0u8; Self::byte_size()]; + value.to_bytes(&mut buf[..U::byte_size()]); + Self::from_bytes(&buf) + } +} + +impl AnyPtr { + pub fn to_int(&self) -> U { + self.reinterpret_cast::().to_int() + } + + pub fn from_int(value: U) -> Self { + Ptr::::from_int(value).to_any() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/unit/out/refcount/unconst.rs b/tests/unit/out/refcount/unconst.rs new file mode 100644 index 00000000..be6be423 --- /dev/null +++ b/tests/unit/out/refcount/unconst.rs @@ -0,0 +1,24 @@ +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 a: Value = Rc::new(RefCell::new(1)); + let p: Value> = Rc::new(RefCell::new((a.as_pointer()))); + let q: Value> = Rc::new(RefCell::new( + (::from_int(((*p.borrow()).clone() as Ptr).to_any().to_int::())) + .reinterpret_cast::(), + )); + assert!({ + let _lhs = (*p.borrow()).clone(); + _lhs == (*q.borrow()).clone() + }); + return 0; +} diff --git a/tests/unit/out/unsafe/unconst.rs b/tests/unit/out/unsafe/unconst.rs new file mode 100644 index 00000000..13041748 --- /dev/null +++ b/tests/unit/out/unsafe/unconst.rs @@ -0,0 +1,21 @@ +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 a: i32 = 1; + let mut p: *const i32 = (&a as *const i32); + let mut q: *mut i32 = (((((p) as *const i32 as *const ::libc::c_void) as u64) + as *mut ::libc::c_void) as *mut i32); + assert!(((p) == ((q).cast_const()))); + return 0; +} diff --git a/tests/unit/unconst.cpp b/tests/unit/unconst.cpp new file mode 100644 index 00000000..aeecc852 --- /dev/null +++ b/tests/unit/unconst.cpp @@ -0,0 +1,13 @@ +// panic: refcount +#include +#include + +#define UNCONST(p) ((void *)(uintptr_t)(const void *)(p)) + +int main() { + const int a = 1; + const int *p = &a; + auto q = static_cast(UNCONST(p)); + assert(p == q); + return 0; +}