Skip to content

Commit 658b9ed

Browse files
committed
Use reinterpret_cast to round-trip through void
1 parent 3436b46 commit 658b9ed

7 files changed

Lines changed: 64 additions & 27 deletions

File tree

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ std::string ConverterRefCount::BuildFnAdapter(
203203
closure += std::format("a{}", i);
204204
} else if (src_pty->isPointerType() && tgt_pty->isPointerType()) {
205205
if (tgt_pty->isVoidPointerType()) {
206-
closure += std::format("a{}.cast::<{}>().unwrap()", i,
206+
closure += std::format("a{}.reinterpret_cast::<{}>()", i,
207207
ConvertPointeeType(src_pty));
208208
} else if (src_pty->isVoidPointerType()) {
209209
closure += std::format("a{}.to_any()", i);
@@ -1298,7 +1298,7 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
12981298
expr->getType()->isPointerType()) {
12991299
Convert(expr->getSubExpr());
13001300
PushConversionKind push(*this, ConversionKind::Unboxed);
1301-
StrCat(std::format(".cast::<{}>().expect(\"ub:wrong type\")",
1301+
StrCat(std::format(".reinterpret_cast::<{}>()",
13021302
ConvertPointeeType(expr->getType())));
13031303
return false;
13041304
} else if (expr->getType()->isVoidPointerType() &&

libcc2rs/src/io.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ pub unsafe fn cerr_unsafe() -> *mut std::fs::File {
8686

8787
pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
8888
let total = a1.saturating_mul(a2);
89-
let mut dst = a0
90-
.cast::<u8>()
91-
.expect("fread: only supporting u8 pointers")
92-
.clone();
89+
let mut dst = a0.reinterpret_cast::<u8>();
9390

9491
let f = (*a3.upgrade().deref())
9592
.try_clone()
@@ -123,10 +120,7 @@ pub fn fread_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>
123120

124121
pub fn fwrite_refcount(a0: AnyPtr, a1: usize, a2: usize, a3: Ptr<::std::fs::File>) -> usize {
125122
let total = a1.saturating_mul(a2);
126-
let mut src = a0
127-
.cast::<u8>()
128-
.expect("fwrite: only supporting u8 pointers")
129-
.clone();
123+
let mut src = a0.reinterpret_cast::<u8>();
130124

131125
let f = (*a3.upgrade().deref())
132126
.try_clone()

libcc2rs/src/rc.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,11 +1096,14 @@ impl Default for AnyPtr {
10961096
}
10971097

10981098
impl AnyPtr {
1099-
pub fn cast<T: 'static>(&self) -> Option<Ptr<T>> {
1099+
pub fn reinterpret_cast<T: ByteRepr>(&self) -> Ptr<T> {
11001100
if self.ptr.is_null() {
1101-
return Some(Ptr::<T>::null());
1101+
return Ptr::<T>::null();
11021102
}
1103-
self.ptr.as_any().downcast_ref::<Ptr<T>>().cloned()
1103+
if let Some(p) = self.ptr.as_any().downcast_ref::<Ptr<T>>() {
1104+
return p.clone();
1105+
}
1106+
self.ptr.as_bytes().reinterpret_cast::<T>()
11041107
}
11051108
}
11061109

@@ -1260,27 +1263,23 @@ mod tests {
12601263
fn anyptr_null_cast() {
12611264
// void* nullptr
12621265
let any = Ptr::<()>::null().to_any();
1263-
let p: Option<Ptr<u32>> = any.cast::<u32>();
1264-
assert!(p.is_some());
1265-
assert!(p.unwrap().is_null());
1266+
let p = any.reinterpret_cast::<u32>();
1267+
assert!(p.is_null());
12661268

1267-
let p2: Option<Ptr<u8>> = any.cast::<u8>();
1268-
assert!(p2.is_some());
1269-
assert!(p2.unwrap().is_null());
1269+
let p2 = any.reinterpret_cast::<u8>();
1270+
assert!(p2.is_null());
12701271

12711272
// int* nullptr
12721273
let any2 = Ptr::<i32>::null().to_any();
1273-
let p3: Option<Ptr<f32>> = any2.cast::<f32>();
1274-
assert!(p3.is_some());
1275-
assert!(p3.unwrap().is_null());
1274+
let p3 = any2.reinterpret_cast::<f32>();
1275+
assert!(p3.is_null());
12761276
}
12771277

12781278
#[test]
12791279
fn to_any_without_clone() {
12801280
let p: Ptr<std::fs::File> = Ptr::null(); // std::fs::File is not Clone
12811281
let any = p.to_any();
1282-
let recovered = any.cast::<std::fs::File>();
1283-
assert!(recovered.is_some());
1284-
assert!(recovered.unwrap().is_null());
1282+
let recovered = any.reinterpret_cast::<std::fs::File>();
1283+
assert!(recovered.is_null());
12851284
}
12861285
}

libcc2rs/src/va_args.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ impl<T> VaArgGet for *const T {
119119
}
120120
}
121121

122-
impl<T: 'static> VaArgGet for crate::rc::Ptr<T> {
122+
impl<T: 'static + crate::ByteRepr> VaArgGet for crate::rc::Ptr<T> {
123123
fn get(v: &VaArg) -> Self {
124124
match v {
125-
VaArg::Ptr(any) => any.cast::<T>().expect("VaArgGet: Ptr type mismatch"),
125+
VaArg::Ptr(any) => any.reinterpret_cast::<T>(),
126126
_ => panic!("VaArgGet: expected Ptr"),
127127
}
128128
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 a: Value<u32> = Rc::new(RefCell::new(42_u32));
14+
assert!((((((a.as_pointer()).to_any().reinterpret_cast::<i32>().read()) == 42) as i32) != 0));
15+
return 0;
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 a: u32 = 42_u32;
16+
assert!(
17+
((((*(((&mut a as *mut u32) as *mut ::libc::c_void) as *mut i32)) == (42)) as i32) != 0)
18+
);
19+
return 0;
20+
}

tests/unit/void_round_trip.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdint.h>
2+
#include <assert.h>
3+
4+
int main() {
5+
uint32_t a = 42;
6+
assert(*(int32_t*)(void*)&a == 42);
7+
return 0;
8+
}

0 commit comments

Comments
 (0)