Skip to content

Commit 3b52da7

Browse files
committed
Translate fn ptr cast using mem::transmute
1 parent e5aa768 commit 3b52da7

2 files changed

Lines changed: 23 additions & 5 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,17 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
17371737
if (expr->getType() == sub_expr->getType()) {
17381738
return Convert(sub_expr);
17391739
}
1740+
if (type->isFunctionPointerType() ||
1741+
sub_expr->getType()->isFunctionPointerType()) {
1742+
StrCat("std::mem::transmute::<");
1743+
Convert(sub_expr->getType());
1744+
StrCat(",");
1745+
Convert(type);
1746+
StrCat(">(");
1747+
Convert(sub_expr);
1748+
StrCat(")");
1749+
return false;
1750+
}
17401751
StrCat(token::kOpenParen);
17411752
Convert(sub_expr);
17421753
if (auto *unary_oper = clang::dyn_cast<clang::UnaryOperator>(sub_expr);

tests/unit/out/unsafe/fn_ptr_cast.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ pub unsafe fn test_roundtrip_1() {
1818
(fn_).unwrap()(_arg0)
1919
}) == (10))
2020
);
21-
let mut gfn: Option<unsafe fn()> = (fn_ as Option<unsafe fn()>);
21+
let mut gfn: Option<unsafe fn()> =
22+
std::mem::transmute::<Option<unsafe fn(i32) -> i32>, Option<unsafe fn()>>(fn_);
2223
assert!(!((gfn).is_none()));
23-
let mut fn2: Option<unsafe fn(i32) -> i32> = (gfn as Option<unsafe fn(i32) -> i32>);
24+
let mut fn2: Option<unsafe fn(i32) -> i32> =
25+
std::mem::transmute::<Option<unsafe fn()>, Option<unsafe fn(i32) -> i32>>(gfn);
2426
assert!(
2527
((unsafe {
2628
let _arg0: i32 = 5;
@@ -32,7 +34,9 @@ pub unsafe fn test_roundtrip_1() {
3234
pub unsafe fn test_double_cast_2() {
3335
let mut fn_: Option<unsafe fn(i32) -> i32> = Some(double_it_0 as _);
3436
let mut fn2: Option<unsafe fn(i32) -> i32> =
35-
((fn_ as Option<unsafe fn()>) as Option<unsafe fn(i32) -> i32>);
37+
std::mem::transmute::<Option<unsafe fn()>, Option<unsafe fn(i32) -> i32>>(
38+
std::mem::transmute::<Option<unsafe fn(i32) -> i32>, Option<unsafe fn()>>(fn_),
39+
);
3640
assert!(
3741
((unsafe {
3842
let _arg0: i32 = 5;
@@ -47,8 +51,11 @@ pub struct Command {
4751
}
4852
pub unsafe fn test_void_ptr_to_fn_3() {
4953
let mut cmd: Command = <Command>::default();
50-
cmd.data = (Some(double_it_0 as _) as *mut ::libc::c_void);
51-
let mut fn_: Option<unsafe fn(i32) -> i32> = (cmd.data as Option<unsafe fn(i32) -> i32>);
54+
cmd.data = std::mem::transmute::<Option<unsafe fn(i32) -> i32>, *mut ::libc::c_void>(Some(
55+
double_it_0 as _,
56+
));
57+
let mut fn_: Option<unsafe fn(i32) -> i32> =
58+
std::mem::transmute::<*mut ::libc::c_void, Option<unsafe fn(i32) -> i32>>(cmd.data);
5259
assert!(
5360
((unsafe {
5461
let _arg0: i32 = 5;

0 commit comments

Comments
 (0)