@@ -215,62 +215,6 @@ bool ConverterRefCount::VisitReferenceType(clang::ReferenceType *type) {
215215 return false ;
216216}
217217
218- std::string ConverterRefCount::BuildFnAdapter (
219- const clang::FunctionDecl *src_fn,
220- const clang::FunctionProtoType *src_proto,
221- const clang::FunctionProtoType *target_proto) {
222-
223- // UB: Incompatible arity
224- if (src_proto->getNumParams () != target_proto->getNumParams ()) {
225- return " None" ;
226- }
227-
228- PushConversionKind push (*this , ConversionKind::Unboxed);
229-
230- // Build adapter signature: |a0: T0, a1: T1, ...| -> Tr
231- std::string closure = " (|" ;
232- for (unsigned i = 0 ; i < target_proto->getNumParams (); ++i) {
233- closure +=
234- std::format (" a{}: {}," , i, ToString (target_proto->getParamType (i)));
235- }
236- closure += ' |' ;
237- if (!target_proto->getReturnType ()->isVoidType ()) {
238- closure += std::format (" -> {} " , ToString (target_proto->getReturnType ()));
239- }
240- closure += " { " ;
241-
242- // Build adapter body: src_fn(convert(a0), convert(a1), ...)
243- closure += Mapper::MapFunctionName (src_fn) + ' (' ;
244- for (unsigned i = 0 ; i < src_proto->getNumParams (); ++i) {
245- auto src_pty = src_proto->getParamType (i);
246- auto tgt_pty = target_proto->getParamType (i);
247- if (ToString (src_pty) == ToString (tgt_pty)) {
248- closure += std::format (" a{}" , i);
249- } else if (src_pty->isPointerType () && tgt_pty->isPointerType ()) {
250- if (tgt_pty->isVoidPointerType ()) {
251- closure += std::format (" a{}.reinterpret_cast::<{}>()" , i,
252- ConvertPointeeType (src_pty));
253- } else if (src_pty->isVoidPointerType ()) {
254- closure += std::format (" a{}.to_any()" , i);
255- } else if (tgt_pty->getPointeeType ()->isCharType ()) {
256- closure += std::format (" a{}.reinterpret_cast::<{}>()" , i,
257- ConvertPointeeType (src_pty));
258- } else if (src_pty->getPointeeType ()->isCharType ()) {
259- closure += std::format (" a{}.reinterpret_cast::<{}>()" , i,
260- ConvertPointeeType (src_pty));
261- }
262- } else {
263- // UB: Incompatible types
264- return " None" ;
265- }
266- closure += " , " ;
267- }
268- closure += " ) })" ;
269-
270- return std::format (" Some({} as {})" , closure,
271- ConvertFunctionPointerType (target_proto));
272- }
273-
274218std::string ConverterRefCount::ConvertFunctionPointerType (
275219 const clang::FunctionProtoType *proto, FnProtoType kind) {
276220 PushConversionKind push (*this , ConversionKind::Unboxed);
@@ -1390,9 +1334,8 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
13901334}
13911335
13921336void ConverterRefCount::EmitFnPtrCall (clang::Expr *callee) {
1393- StrCat (" (*" );
13941337 Convert (callee);
1395- StrCat (' ) ' );
1338+ StrCat (" .call " );
13961339}
13971340
13981341void ConverterRefCount::ConvertFunctionToFunctionPointer (
@@ -1423,25 +1366,8 @@ bool ConverterRefCount::VisitFunctionPointerCast(
14231366 expr->getType ()->isFunctionPointerType ()) {
14241367 auto target_proto =
14251368 expr->getType ()->getPointeeType ()->getAs <clang::FunctionProtoType>();
1426- auto src_proto = expr->getSubExpr ()
1427- ->getType ()
1428- ->getPointeeType ()
1429- ->getAs <clang::FunctionProtoType>();
1430- auto fn_type = ConvertFunctionPointerType (target_proto);
1431-
1432- std::string adapter = " None" ;
1433- // Only accept direct references to the casted function. Otherwise the
1434- // closure would be capturing and would not coerce into a fn pointer.
1435- if (auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(
1436- expr->getSubExpr ()->IgnoreImplicit ())) {
1437- if (auto *fn_decl =
1438- clang::dyn_cast<clang::FunctionDecl>(decl_ref->getDecl ())) {
1439- adapter = BuildFnAdapter (fn_decl, src_proto, target_proto);
1440- }
1441- }
1442-
1443- StrCat (std::format (" {}.cast::<{}>({})" , ToString (expr->getSubExpr ()),
1444- fn_type, adapter));
1369+ StrCat (std::format (" {}.cast::<{}>()" , ToString (expr->getSubExpr ()),
1370+ ConvertFunctionPointerType (target_proto)));
14451371 } else if (expr->getSubExpr ()->getType ()->isFunctionPointerType () ||
14461372 expr->getType ()->isVoidPointerType ()) {
14471373 Convert (expr->getSubExpr ());
@@ -1456,6 +1382,7 @@ bool ConverterRefCount::VisitFunctionPointerCast(
14561382 } else {
14571383 assert (0 && " Unhandled function pointer cast" );
14581384 }
1385+ computed_expr_type_ = ComputedExprType::FreshPointer;
14591386 return false ;
14601387 }
14611388
@@ -2251,11 +2178,40 @@ std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
22512178 return std::format (" ({} as {})" , ConvertFreshPointer (expr),
22522179 ToString (qual_type));
22532180 }
2181+ if (qual_type->isFunctionPointerType ()) {
2182+ return ConvertFnPtrValue (qual_type, expr);
2183+ }
22542184 return ConvertFreshPointer (expr);
22552185 }
22562186 return ConvertFreshRValue (expr, qual_type);
22572187}
22582188
2189+ std::string ConverterRefCount::ConvertFnPtrValue (clang::QualType qual_type,
2190+ clang::Expr *expr) {
2191+ auto base = ConvertFreshPointer (expr);
2192+
2193+ // `qual_type` (the expected fn pointer type) and `expr`'s own fn pointer
2194+ // type may differ in spelling only because the translation maps two
2195+ // typedefs of the same C type to distinct Rust types (e.g. size_t vs
2196+ // unsigned long) -- FnPtr::cast handles this (and any other cast)
2197+ // automatically, so just insert it whenever the two differ.
2198+ auto target_proto =
2199+ qual_type->getPointeeType ()->getAs <clang::FunctionProtoType>();
2200+ if (!target_proto || !expr->getType ()->isFunctionPointerType ()) {
2201+ return base;
2202+ }
2203+ auto src_proto =
2204+ expr->getType ()->getPointeeType ()->getAs <clang::FunctionProtoType>();
2205+ if (!src_proto) {
2206+ return base;
2207+ }
2208+ auto fn_type = ConvertFunctionPointerType (target_proto);
2209+ if (ConvertFunctionPointerType (src_proto) == fn_type) {
2210+ return base;
2211+ }
2212+ return std::format (" {}.cast::<{}>()" , base, fn_type);
2213+ }
2214+
22592215void ConverterRefCount::ConvertVarInit (clang::QualType qual_type,
22602216 clang::Expr *expr) {
22612217 bool is_ref = qual_type->isReferenceType ();
0 commit comments