From 20681dafa35ba01ffb49d25ae305da8450c04ddd Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 12:56:05 +0100 Subject: [PATCH 1/2] Fix const_cast for references --- cpp2rust/converter/converter.cpp | 23 ++++++++++++++++++++++- tests/unit/unconst.cpp | 12 ++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index b63c7fcb3..0b28ff6be 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2767,7 +2767,28 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { } // A cast to a reference type only rebinds the operand, it converts nothing if (type->isReferenceType()) { - Convert(sub_expr); + const char *suffix = nullptr; + if (isAddrOf()) { + switch ( + GetConstCastType(type.getNonReferenceType(), sub_expr->getType())) { + case ConstCastType::MutableToConst: + suffix = ".cast_const()"; + break; + case ConstCastType::ConstToMutable: + suffix = ".cast_mut()"; + break; + default: + break; + } + } + { + PushParen paren(*this, suffix); + Convert(sub_expr); + } + if (suffix) { + StrCat(suffix); + computed_expr_type_ = ComputedExprType::FreshPointer; + } return false; } switch (expr->getStmtClass()) { diff --git a/tests/unit/unconst.cpp b/tests/unit/unconst.cpp index aeecc852b..88928c369 100644 --- a/tests/unit/unconst.cpp +++ b/tests/unit/unconst.cpp @@ -4,10 +4,22 @@ #define UNCONST(p) ((void *)(uintptr_t)(const void *)(p)) +void set(int &r) { r = 7; } + +template void set_through(const T &v) { set(const_cast(v)); } + int main() { const int a = 1; const int *p = &a; auto q = static_cast(UNCONST(p)); assert(p == q); + + int v = 1; + const int &cr = v; + set(const_cast(cr)); + assert(v == 7); + v = 0; + set_through(v); + assert(v == 7); return 0; } From c727d3cff79e4cb444f5accf1296043efe55a7c3 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 18:34:19 +0100 Subject: [PATCH 2/2] Update tests --- tests/unit/out/refcount/unconst.rs | 13 +++++++++++++ tests/unit/out/unsafe/unconst.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tests/unit/out/refcount/unconst.rs b/tests/unit/out/refcount/unconst.rs index 7b29ff537..1fcc9ba65 100644 --- a/tests/unit/out/refcount/unconst.rs +++ b/tests/unit/out/refcount/unconst.rs @@ -6,6 +6,12 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; +pub fn set_0(r: Ptr) { + r.write(7); +} +pub fn set_through_1(v: Ptr) { + ({ set_0((v).clone()) }); +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -15,6 +21,13 @@ fn main_0() -> i32 { let mut p: Ptr = (a.as_pointer()); let mut q: Ptr = (::from_int((p).to_any().to_int())).reinterpret_cast::(); assert!(({ (p).clone() } == { (q).clone() })); + let v: Value = Rc::new(RefCell::new(1)); + let cr: Ptr = v.as_pointer(); + ({ set_0((cr).clone()) }); + assert!(((*v.borrow()) == 7)); + (*v.borrow_mut()) = 0; + ({ set_through_1(v.as_pointer()) }); + assert!(((*v.borrow()) == 7)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/unconst.rs b/tests/unit/out/unsafe/unconst.rs index a4511edcb..db5e98286 100644 --- a/tests/unit/out/unsafe/unconst.rs +++ b/tests/unit/out/unsafe/unconst.rs @@ -6,6 +6,12 @@ use std::collections::BTreeMap; use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; +pub unsafe fn set_0(r: *mut i32) { + (*r) = 7; +} +pub unsafe fn set_through_1(v: *const i32) { + (unsafe { set_0((v).cast_mut()) }); +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -18,6 +24,13 @@ unsafe fn main_0() -> i32 { let mut q: *mut i32 = (((((p) as *const ::libc::c_void) as u64) as *mut ::libc::c_void) as *mut i32); assert!(((p) == ((q).cast_const()))); + let mut v: i32 = 1; + let cr: *const i32 = &v; + (unsafe { set_0((cr).cast_mut()) }); + assert!(((v) == (7))); + v = 0; + (unsafe { set_through_1(&v) }); + assert!(((v) == (7))); return 0; } pub unsafe fn __cpp2rust_init_globals() {}