Skip to content

Commit 67cf0c7

Browse files
authored
Fix address of static method (#409)
1 parent 9ba5a08 commit 67cf0c7

6 files changed

Lines changed: 81 additions & 4 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,9 +1896,18 @@ void Converter::EmitFnPtrCall(clang::Expr *callee) {
18961896
StrCat(".unwrap()");
18971897
}
18981898

1899+
std::string Converter::GetFunctionRefName(const clang::FunctionDecl *fn_decl) {
1900+
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(fn_decl);
1901+
method && method->isStatic()) {
1902+
return std::format("{}::{}", GetRecordName(method->getParent()),
1903+
GetMethodName(method));
1904+
}
1905+
return Mapper::MapFunctionName(fn_decl);
1906+
}
1907+
18991908
void Converter::ConvertFunctionToFunctionPointer(
19001909
const clang::FunctionDecl *fn_decl) {
1901-
StrCat(std::format("Some({})", Mapper::MapFunctionName(fn_decl)));
1910+
StrCat(std::format("Some({})", GetFunctionRefName(fn_decl)));
19021911
computed_expr_type_ = ComputedExprType::FreshPointer;
19031912
}
19041913

@@ -3015,8 +3024,7 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
30153024
if (auto *function = decl->getAsFunction()) {
30163025
if (auto method = clang::dyn_cast<clang::CXXMethodDecl>(function)) {
30173026
if (method->isStatic()) {
3018-
return std::format("{}::{}", GetRecordName(method->getParent()),
3019-
GetNamedDeclAsString(method));
3027+
return GetFunctionRefName(method);
30203028
}
30213029
}
30223030
return GetNamedDeclAsString(function->getCanonicalDecl());

‎cpp2rust/converter/converter.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
314314
virtual void
315315
ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl);
316316

317+
std::string GetFunctionRefName(const clang::FunctionDecl *fn_decl);
318+
317319
std::string ConvertFnPtrCallee(clang::Expr *arg);
318320
virtual std::string ConvertFnPtrPlaceholder(clang::Expr *arg);
319321

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ void ConverterRefCount::ConvertFunctionToFunctionPointer(
13521352
StrCat(std::format("FnPtr::<{}>::new({})",
13531353
ConvertFunctionPointerType(
13541354
fn_decl->getType()->getAs<clang::FunctionProtoType>()),
1355-
Mapper::MapFunctionName(fn_decl)));
1355+
GetFunctionRefName(fn_decl)));
13561356
computed_expr_type_ = ComputedExprType::FreshPointer;
13571357
}
13581358

‎tests/unit/fn_ptr_struct.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,22 @@ struct Handler {
1010
int double_it(int x) { return x * 2; }
1111
int negate(int x) { return -x; }
1212

13+
struct S {
14+
static int pick(int x) { return x + 1; }
15+
static int pick(long x) { return (int)x + 2; }
16+
static int solo(int x) { return x + 3; }
17+
};
18+
1319
int main() {
20+
handler_t p1 = &S::pick;
21+
handler_t p2 = S::solo;
22+
assert(p1(5) == 6);
23+
assert(p2(5) == 8);
24+
assert(S::pick(5L) == 7);
25+
26+
Handler h3 = {3, &S::pick};
27+
assert(h3.cb(1) == 2);
28+
1429
Handler h1 = {1, double_it};
1530
Handler h2 = {2, negate};
1631

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,39 @@ pub fn negate_1(x: i32) -> i32 {
5454
let x: Value<i32> = Rc::new(RefCell::new(x));
5555
return -(*x.borrow());
5656
}
57+
#[derive(Clone, ByteRepr, Default)]
58+
pub struct S {}
59+
impl S {
60+
pub fn pick_i32(x: i32) -> i32 {
61+
let x: Value<i32> = Rc::new(RefCell::new(x));
62+
return ((*x.borrow()) + 1);
63+
}
64+
pub fn pick_i64(x: i64) -> i32 {
65+
let x: Value<i64> = Rc::new(RefCell::new(x));
66+
return (((*x.borrow()) as i32) + 2);
67+
}
68+
pub fn solo(x: i32) -> i32 {
69+
let x: Value<i32> = Rc::new(RefCell::new(x));
70+
return ((*x.borrow()) + 3);
71+
}
72+
}
5773
pub fn main() {
5874
__cpp2rust_init_globals();
5975
std::process::exit(main_0());
6076
}
6177
fn main_0() -> i32 {
78+
let p1: Value<FnPtr<fn(i32) -> i32>> =
79+
Rc::new(RefCell::new((FnPtr::<fn(i32) -> i32>::new(S::pick_i32))));
80+
let p2: Value<FnPtr<fn(i32) -> i32>> =
81+
Rc::new(RefCell::new(FnPtr::<fn(i32) -> i32>::new(S::solo)));
82+
assert!((({ (*(*p1.borrow()))(5,) }) == 6));
83+
assert!((({ (*(*p2.borrow()))(5,) }) == 8));
84+
assert!((({ S::pick_i64(5_i64,) }) == 7));
85+
let h3: Value<Handler> = Rc::new(RefCell::new(Handler {
86+
tag: Rc::new(RefCell::new(3)),
87+
cb: Rc::new(RefCell::new((FnPtr::<fn(i32) -> i32>::new(S::pick_i32)))),
88+
}));
89+
assert!((({ (*(*(*h3.borrow()).cb.borrow()))(1,) }) == 2));
6290
let h1: Value<Handler> = Rc::new(RefCell::new(Handler {
6391
tag: Rc::new(RefCell::new(1)),
6492
cb: Rc::new(RefCell::new(FnPtr::<fn(i32) -> i32>::new(double_it_0))),

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,37 @@ pub unsafe fn double_it_0(mut x: i32) -> i32 {
2626
pub unsafe fn negate_1(mut x: i32) -> i32 {
2727
return -x;
2828
}
29+
#[repr(C)]
30+
#[derive(Copy, Clone, Default)]
31+
pub struct S {}
32+
impl S {
33+
pub unsafe fn pick_i32(mut x: i32) -> i32 {
34+
return ((x) + (1));
35+
}
36+
pub unsafe fn pick_i64(mut x: i64) -> i32 {
37+
return ((x as i32) + (2));
38+
}
39+
pub unsafe fn solo(mut x: i32) -> i32 {
40+
return ((x) + (3));
41+
}
42+
}
2943
pub fn main() {
3044
unsafe {
3145
__cpp2rust_init_globals();
3246
std::process::exit(main_0() as i32);
3347
}
3448
}
3549
unsafe fn main_0() -> i32 {
50+
let mut p1: Option<unsafe fn(i32) -> i32> = (Some(S::pick_i32));
51+
let mut p2: Option<unsafe fn(i32) -> i32> = Some(S::solo);
52+
assert!(((unsafe { (p1).unwrap()(5,) }) == (6)));
53+
assert!(((unsafe { (p2).unwrap()(5,) }) == (8)));
54+
assert!(((unsafe { S::pick_i64(5_i64,) }) == (7)));
55+
let mut h3: Handler = Handler {
56+
tag: 3,
57+
cb: (Some(S::pick_i32)),
58+
};
59+
assert!(((unsafe { (h3.cb).unwrap()(1,) }) == (2)));
3660
let mut h1: Handler = Handler {
3761
tag: 1,
3862
cb: Some(double_it_0),

0 commit comments

Comments
 (0)