Skip to content

Commit 6ae7d0c

Browse files
committed
Fix mismatched u64/usize in function pointer signature
1 parent b907253 commit 6ae7d0c

5 files changed

Lines changed: 117 additions & 3 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ Converter::MaterializeTemp(const std::string &binding_name,
236236
auto pointee = param_type.getNonReferenceType();
237237
auto value = ConvertRValue(expr, pointee);
238238
auto type_str = ToStringBase(pointee);
239+
auto src_type = expr->IgnoreImplicit()->getType().getNonReferenceType();
240+
if (src_type->isFunctionType()) {
241+
src_type = ctx_.getPointerType(src_type);
242+
}
243+
if (pointee->isFunctionPointerType() && src_type->isFunctionPointerType()) {
244+
auto src_str = ToStringBase(src_type);
245+
if (src_str != type_str) {
246+
value = std::format("std::mem::transmute::<{}, {}>({})", src_str,
247+
type_str, value);
248+
}
249+
}
239250
const auto *decl = in_const_initializer_ ? keyword::kStatic : keyword::kLet;
240251

241252
auto binding =

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,9 @@ ConverterRefCount::MaterializeTemp(const std::string &binding_name,
411411
clang::QualType param_type,
412412
clang::Expr *expr) {
413413
auto pointee = param_type.getNonReferenceType();
414-
auto value = ConvertRValue(expr, pointee);
414+
auto value = pointee->isFunctionPointerType()
415+
? ConvertFnPtrValue(pointee, expr)
416+
: ConvertRValue(expr, pointee);
415417
auto type_str = ToStringBase(pointee);
416418
const auto *decl = in_const_initializer_ ? keyword::kStatic : keyword::kLet;
417419

@@ -2357,11 +2359,15 @@ std::string ConverterRefCount::ConvertFnPtrValue(clang::QualType qual_type,
23572359
// automatically, so just insert it whenever the two differ.
23582360
auto target_proto =
23592361
qual_type->getPointeeType()->getAs<clang::FunctionProtoType>();
2360-
if (!target_proto || !expr->getType()->isFunctionPointerType()) {
2362+
auto src_type = expr->IgnoreImplicit()->getType().getNonReferenceType();
2363+
if (src_type->isFunctionType()) {
2364+
src_type = ctx_.getPointerType(src_type);
2365+
}
2366+
if (!target_proto || !src_type->isFunctionPointerType()) {
23612367
return base;
23622368
}
23632369
auto src_proto =
2364-
expr->getType()->getPointeeType()->getAs<clang::FunctionProtoType>();
2370+
src_type->getPointeeType()->getAs<clang::FunctionProtoType>();
23652371
if (!src_proto) {
23662372
return base;
23672373
}

‎tests/unit/fn_ptr.cpp‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
#include <assert.h>
2+
#include <cstddef>
23

34
typedef int (*foo_t)(void *);
45

56
int my_foo(void *p) { return *static_cast<int *>(p); }
67

78
int foo(foo_t fn, int *pi) { return fn(pi); }
89

10+
template <class T> static size_t ret_size(T v) { return v + 1; }
11+
12+
template <class T> static size_t call_fn(size_t (*f)(T), T v) {
13+
return f(v) * 2;
14+
}
15+
16+
template <class T> static std::size_t identity_hash(T v) { return v; }
17+
18+
template <class H> struct HashHolder {
19+
H h;
20+
HashHolder(const H &h) : h(h) {}
21+
};
22+
923
int main() {
1024
foo_t fn = nullptr;
1125
assert(fn == nullptr);
@@ -17,5 +31,10 @@ int main() {
1731

1832
int a = 10;
1933
assert(foo(fn, &a) == a);
34+
35+
assert(call_fn(ret_size<int>, 3) == 8);
36+
37+
HashHolder<std::size_t (*)(bool)> hh(identity_hash<bool>);
38+
assert(hh.h(true) == 1);
2039
return 0;
2140
}

‎tests/unit/out/refcount/fn_ptr.rs‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@ pub fn foo_1(fn_: FnPtr<fn(AnyPtr) -> i32>, pi: Ptr<i32>) -> i32 {
1515
let pi: Value<Ptr<i32>> = Rc::new(RefCell::new(pi));
1616
return ({ (*fn_.borrow()).call((*pi.borrow()).to_any()) });
1717
}
18+
pub fn ret_size_2(v: i32) -> usize {
19+
let v: Value<i32> = Rc::new(RefCell::new(v));
20+
return (((*v.borrow()) + 1) as usize);
21+
}
22+
pub fn call_fn_3(f: FnPtr<fn(i32) -> usize>, v: i32) -> usize {
23+
let f: Value<FnPtr<fn(i32) -> usize>> = Rc::new(RefCell::new(f));
24+
let v: Value<i32> = Rc::new(RefCell::new(v));
25+
return ({ (*f.borrow()).call((*v.borrow())) }).wrapping_mul(2_usize);
26+
}
27+
pub fn identity_hash_4(v: bool) -> usize {
28+
let v: Value<bool> = Rc::new(RefCell::new(v));
29+
return ((*v.borrow()) as usize);
30+
}
31+
#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg)]
32+
#[byte_size(8)]
33+
pub struct HashHolder_unsigned_long__ptr__bool__ {
34+
#[offset(0)]
35+
#[byte_size(8)]
36+
pub h: FnPtr<fn(bool) -> u64>,
37+
}
38+
impl HashHolder_unsigned_long__ptr__bool__ {
39+
pub fn new(h: Ptr<FnPtr<fn(bool) -> u64>>) -> Self {
40+
let __this: Value<HashHolder_unsigned_long__ptr__bool__> = Rc::new(RefCell::new(Self {
41+
h: (h.read()).clone(),
42+
}));
43+
let this: Ptr<HashHolder_unsigned_long__ptr__bool__> = __this.as_pointer();
44+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
45+
}
46+
}
47+
impl Default for HashHolder_unsigned_long__ptr__bool__ {
48+
fn default() -> Self {
49+
HashHolder_unsigned_long__ptr__bool__ {
50+
h: FnPtr::<fn(bool) -> u64>::null(),
51+
}
52+
}
53+
}
1854
pub fn main() {
1955
__cpp2rust_init_globals();
2056
std::process::exit(main_0());
@@ -29,6 +65,14 @@ fn main_0() -> i32 {
2965
assert!(({ (*fn_.borrow()).clone() } == { FnPtr::<fn(AnyPtr) -> i32>::new(my_foo_0) }));
3066
let a: Value<i32> = Rc::new(RefCell::new(10));
3167
assert!(({ ({ foo_1((*fn_.borrow()).clone(), (a.as_pointer()),) }) } == { (*a.borrow()) }));
68+
assert!((({ call_fn_3(FnPtr::<fn(i32) -> usize>::new(ret_size_2), 3,) }) == 8_usize));
69+
let hh: Value<HashHolder_unsigned_long__ptr__bool__> = Rc::new(RefCell::new({
70+
let __tmp_0: Value<FnPtr<fn(bool) -> u64>> = Rc::new(RefCell::new(
71+
FnPtr::<fn(bool) -> usize>::new(identity_hash_4).cast::<fn(bool) -> u64>(),
72+
));
73+
HashHolder_unsigned_long__ptr__bool__::new({ __tmp_0.as_pointer() })
74+
}));
75+
assert!((({ { (*hh.borrow()).h.clone() }.call(true,) }) == 1_u64));
3276
return 0;
3377
}
3478
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/fn_ptr.rs‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,31 @@ pub unsafe fn foo_1(
1515
) -> i32 {
1616
return (unsafe { (fn_).unwrap()((pi as *mut ::libc::c_void)) });
1717
}
18+
pub unsafe fn ret_size_2(mut v: i32) -> usize {
19+
return (((v) + (1)) as usize);
20+
}
21+
pub unsafe fn call_fn_3(mut f: Option<unsafe fn(i32) -> usize>, mut v: i32) -> usize {
22+
return (unsafe { (f).unwrap()(v) }).wrapping_mul(2_usize);
23+
}
24+
pub unsafe fn identity_hash_4(mut v: bool) -> usize {
25+
return (v as usize);
26+
}
27+
#[repr(C)]
28+
#[derive(Copy, Clone, VaArg)]
29+
pub struct HashHolder_unsigned_long__ptr__bool__ {
30+
pub h: Option<unsafe fn(bool) -> u64>,
31+
}
32+
impl HashHolder_unsigned_long__ptr__bool__ {
33+
pub unsafe fn new(h: *const Option<unsafe fn(bool) -> u64>) -> Self {
34+
let mut this = Self { h: (*h) };
35+
this
36+
}
37+
}
38+
impl Default for HashHolder_unsigned_long__ptr__bool__ {
39+
fn default() -> Self {
40+
HashHolder_unsigned_long__ptr__bool__ { h: None }
41+
}
42+
}
1843
pub fn main() {
1944
unsafe {
2045
__cpp2rust_init_globals();
@@ -30,6 +55,15 @@ unsafe fn main_0() -> i32 {
3055
assert!(((fn_) == (Some(my_foo_0))));
3156
let mut a: i32 = 10;
3257
assert!(((unsafe { foo_1(fn_, (&mut a as *mut i32),) }) == (a)));
58+
assert!(((unsafe { call_fn_3(Some(ret_size_2), 3,) }) == (8_usize)));
59+
let mut hh: HashHolder_unsigned_long__ptr__bool__ = {
60+
let mut __tmp_0: Option<unsafe fn(bool) -> u64> = std::mem::transmute::<
61+
Option<unsafe fn(bool) -> usize>,
62+
Option<unsafe fn(bool) -> u64>,
63+
>(Some(identity_hash_4));
64+
HashHolder_unsigned_long__ptr__bool__::new({ &mut __tmp_0 })
65+
};
66+
assert!(((unsafe { (hh.h).unwrap()(true,) }) == (1_u64)));
3367
return 0;
3468
}
3569
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)