Skip to content

Commit 4786462

Browse files
authored
Fix fn-ptr void-cast clone: skip only for fresh expressions, not variable refs
1 parent 9c227b6 commit 4786462

2 files changed

Lines changed: 10 additions & 2 deletions

File tree

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,8 +1322,16 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
13221322
if (expr->getTypeAsWritten()->isVoidType()) {
13231323
PushExprKind push(*this, ExprKind::Void);
13241324
Convert(expr->getSubExpr());
1325+
// Skip .clone() for fresh fn-ptr values (cast/constructor results).
1326+
// Variable references to fn-ptrs still need .clone() because FnPtr is
1327+
// non-Copy and (*var.borrow()) would otherwise attempt a move.
1328+
auto *inner = expr->getSubExpr()->IgnoreParenImpCasts();
1329+
bool is_fn_ptr_var_ref =
1330+
clang::isa<clang::DeclRefExpr>(inner) &&
1331+
inner->getType()->isFunctionPointerType();
13251332
if (!TypeIsCopyable(expr->getSubExpr()->getType()) &&
1326-
!expr->getSubExpr()->getType()->isFunctionPointerType()) {
1333+
(!expr->getSubExpr()->getType()->isFunctionPointerType() ||
1334+
is_fn_ptr_var_ref)) {
13271335
StrCat(".clone()");
13281336
}
13291337
return false;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn not_supported_5(ctx: AnyPtr, fn_: FnPtr<fn(i32) -> i32>, extra: AnyPtr) -
4747
let fn_: Value<FnPtr<fn(i32) -> i32>> = Rc::new(RefCell::new(fn_));
4848
let extra: Value<AnyPtr> = Rc::new(RefCell::new(extra));
4949
(*ctx.borrow()).clone();
50-
(*fn_.borrow());
50+
(*fn_.borrow()).clone();
5151
(*extra.borrow()).clone();
5252
return -3_i32;
5353
}

0 commit comments

Comments
 (0)