@@ -1495,125 +1495,157 @@ void Converter::ConvertFunctionToFunctionPointer(
14951495 StrCat (std::format (" Some({})" , Mapper::MapFunctionName (fn_decl)));
14961496}
14971497
1498- void Converter::ConvertGenericCallExpr (clang::CallExpr *expr) {
1499- clang::Expr *callee = expr->getCallee ();
1500- auto convert_param_ty = [&](clang::QualType param_type, clang::Expr *expr) {
1501- if (param_type->isLValueReferenceType ()) {
1502- PushExprKind push (*this , ExprKind::AddrOf);
1503- ConvertVarInit (param_type, expr);
1504- } else {
1505- ConvertVarInit (param_type, expr);
1506- }
1507- };
1498+ Converter::CallInfo Converter::CollectCallInfo (clang::CallExpr *expr) {
1499+ using Kind = CallArg::Kind;
15081500
1509- unsigned arg_begin = 0 ; // skip count for operator()'s implicit object arg
1501+ CallInfo info{};
1502+ info.callee = expr->getCallee ();
1503+ unsigned arg_begin = 0 ;
15101504 if (auto op_call = llvm::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
15111505 if (op_call->getOperator () == clang::OO_Call) {
1512- callee = op_call->getArg (0 );
1506+ info. callee = op_call->getArg (0 );
15131507 arg_begin = 1 ;
15141508 }
15151509 }
15161510
1517- PushParen outer (*this );
1518- StrCat (keyword_unsafe_);
1519- PushBrace unsafe_brace (*this );
15201511 const auto *function =
15211512 expr->getCalleeDecl () ? expr->getCalleeDecl ()->getAsFunction () : nullptr ;
15221513 const clang::FunctionProtoType *proto = nullptr ;
1523-
15241514 if (!function) {
1525- auto callee_ty = callee->getType ().getDesugaredType (ctx_);
1515+ auto callee_ty = info. callee ->getType ().getDesugaredType (ctx_);
15261516 if (auto ptr_ty = callee_ty->getAs <clang::PointerType>()) {
15271517 proto = ptr_ty->getPointeeType ()->getAs <clang::FunctionProtoType>();
15281518 }
15291519 }
1530-
15311520 assert ((function || proto) &&
15321521 " Either function decl or function prototype should be known" );
15331522
1534- auto num_args = expr->getNumArgs () - arg_begin;
1535- bool is_variadic =
1536- function ? function->isVariadic () : (proto && proto->isVariadic ());
1537- unsigned num_named_params = function
1538- ? function->getNumParams ()
1539- : (proto ? proto->getNumParams () : num_args);
1540-
1541- // Track which args are materialized temps bound to reference params
1542- std::vector<std::string> temp_refs (num_args);
1523+ unsigned num_args = expr->getNumArgs () - arg_begin;
1524+ unsigned num_named_params =
1525+ function ? function->getNumParams () : proto->getNumParams ();
1526+ info.is_variadic = function ? function->isVariadic () : proto->isVariadic ();
1527+ info.is_fn_ptr_call = !function;
15431528
15441529 for (unsigned i = 0 ; i < num_named_params && i < num_args; ++i) {
15451530 auto *arg = expr->getArg (i + arg_begin);
1546- std::string param_name = function
1547- ? function->getParamDecl (i)->getNameAsString ()
1548- : (" arg" + std::to_string (i));
1549- clang::QualType param_type = function ? function->getParamDecl (i)->getType ()
1550- : proto->getParamType (i);
1551-
1552- bool is_materialize_to_ref =
1553- clang::isa<clang::MaterializeTemporaryExpr>(arg) &&
1554- param_type->isLValueReferenceType ();
1555-
1556- if (is_materialize_to_ref) {
1557- auto [binding, ref] =
1558- MaterializeTemp (std::format (" _{}" , param_name), param_type, arg);
1559- StrCat (binding);
1560- temp_refs[i] = std::move (ref);
1561- } else if (!clang::isa<clang::MaterializeTemporaryExpr>(arg)) {
1562- StrCat (" let" , std::format (" _{}: {}" , param_name, ToString (param_type)),
1563- " =" );
1564- convert_param_ty (param_type, arg);
1565- StrCat (" ;" );
1531+ CallArg ca{
1532+ .expr = arg,
1533+ .kind = Kind::Hoisted,
1534+ .param_name = function ? function->getParamDecl (i)->getNameAsString ()
1535+ : (" arg" + std::to_string (i)),
1536+ .param_type = function ? function->getParamDecl (i)->getType ()
1537+ : proto->getParamType (i),
1538+ .has_default = function && function->getParamDecl (i)->hasDefaultArg (),
1539+ };
1540+ bool is_materialize = clang::isa<clang::MaterializeTemporaryExpr>(arg);
1541+ if (is_materialize && ca.param_type ->isLValueReferenceType ()) {
1542+ ca.kind = Kind::RefTemp;
1543+ } else if (is_materialize) {
1544+ ca.kind = Kind::InlineTemp;
1545+ }
1546+ info.args .push_back (std::move (ca));
1547+ }
1548+
1549+ if (info.is_variadic ) {
1550+ info.variadic_args .reserve (num_args - num_named_params);
1551+ for (unsigned i = num_named_params; i < num_args; ++i) {
1552+ info.variadic_args .push_back (expr->getArg (i + arg_begin));
15661553 }
15671554 }
15681555
1569- if (proto && !function) {
1570- EmitFnPtrCall (callee);
1556+ return info;
1557+ }
1558+
1559+ void Converter::ConvertParamTy (clang::QualType param_type, clang::Expr *expr) {
1560+ if (param_type->isLValueReferenceType ()) {
1561+ PushExprKind push (*this , ExprKind::AddrOf);
1562+ ConvertVarInit (param_type, expr);
15711563 } else {
1572- PushExprKind push (*this , ExprKind::Callee);
1573- Convert (callee);
1564+ ConvertVarInit (param_type, expr);
15741565 }
1575- {
1576- PushParen call_args (*this );
1577- for (unsigned i = 0 ; i < num_named_params && i < num_args; ++i) {
1578- auto *arg = expr->getArg (i + arg_begin);
1579- std::string param_name =
1580- function ? function->getParamDecl (i)->getNameAsString ()
1581- : (" arg" + std::to_string (i));
1582- clang::QualType param_type = function
1583- ? function->getParamDecl (i)->getType ()
1584- : proto->getParamType (i);
1585- bool is_parm_with_default_value =
1586- function && function->getParamDecl (i)->hasDefaultArg ();
1587-
1588- if (is_parm_with_default_value) {
1589- StrCat (" Some(" );
1590- }
1591- if (!temp_refs[i].empty ()) {
1592- StrCat (temp_refs[i]);
1593- } else if (clang::isa<clang::MaterializeTemporaryExpr>(arg)) {
1594- convert_param_ty (param_type, arg);
1595- } else {
1596- StrCat (std::format (" _{}" , param_name));
1597- }
1598- if (is_parm_with_default_value) {
1599- StrCat (' )' );
1600- }
1601- StrCat (token::kComma );
1566+ }
1567+
1568+ void Converter::EmitArgBindings (CallInfo &info) {
1569+ using Kind = CallArg::Kind;
1570+ for (auto &ca : info.args ) {
1571+ switch (ca.kind ) {
1572+ case Kind::Hoisted:
1573+ StrCat (" let" ,
1574+ std::format (" _{}: {}" , ca.param_name , ToString (ca.param_type )),
1575+ " =" );
1576+ ConvertParamTy (ca.param_type , ca.expr );
1577+ StrCat (" ;" );
1578+ break ;
1579+ case Kind::RefTemp: {
1580+ auto [binding, ref] = MaterializeTemp (std::format (" _{}" , ca.param_name ),
1581+ ca.param_type , ca.expr );
1582+ StrCat (binding);
1583+ ca.ref_temp_name = std::move (ref);
1584+ break ;
16021585 }
1586+ case Kind::InlineTemp:
1587+ break ;
1588+ }
1589+ }
1590+ }
1591+
1592+ void Converter::EmitArgList (const CallInfo &info) {
1593+ using Kind = CallArg::Kind;
1594+ PushParen call_args (*this );
16031595
1604- // Variadic args: wrap in &[arg.into(), ...]
1605- if (is_variadic) {
1606- StrCat (" & [" );
1607- for (unsigned i = num_named_params; i < num_args; ++i) {
1608- auto *arg = expr->getArg (i + arg_begin);
1609- ConvertVariadicArg (arg);
1610- StrCat (" .into()" , token::kComma );
1596+ for (const auto &ca : info.args ) {
1597+ if (ca.has_default ) {
1598+ StrCat (" Some" );
1599+ }
1600+
1601+ {
1602+ PushParen push (*this , ca.has_default );
1603+ switch (ca.kind ) {
1604+ case Kind::Hoisted:
1605+ StrCat (std::format (" _{}" , ca.param_name ));
1606+ break ;
1607+ case Kind::RefTemp:
1608+ StrCat (ca.ref_temp_name );
1609+ break ;
1610+ case Kind::InlineTemp:
1611+ ConvertParamTy (ca.param_type , ca.expr );
1612+ break ;
16111613 }
1612- StrCat (' ]' );
1614+ }
1615+
1616+ StrCat (token::kComma );
1617+ }
1618+
1619+ if (info.is_variadic ) {
1620+ StrCat (token::kRef );
1621+ PushBracket push (*this );
1622+ for (auto *arg : info.variadic_args ) {
1623+ ConvertVariadicArg (arg);
1624+ StrCat (" .into()" , token::kComma );
16131625 }
16141626 }
16151627}
16161628
1629+ void Converter::EmitCall (CallInfo info) {
1630+ EmitArgBindings (info);
1631+
1632+ if (info.is_fn_ptr_call ) {
1633+ EmitFnPtrCall (info.callee );
1634+ } else {
1635+ PushExprKind push (*this , ExprKind::Callee);
1636+ Convert (info.callee );
1637+ }
1638+
1639+ EmitArgList (info);
1640+ }
1641+
1642+ void Converter::ConvertGenericCallExpr (clang::CallExpr *expr) {
1643+ PushParen outer (*this );
1644+ StrCat (keyword_unsafe_);
1645+ PushBrace unsafe_brace (*this );
1646+ EmitCall (CollectCallInfo (expr));
1647+ }
1648+
16171649std::optional<Converter::TempMaterializationCtx>
16181650Converter::ConvertCallExpr (clang::CallExpr *expr) {
16191651 auto *callee = expr->getCallee ();
0 commit comments