@@ -170,6 +170,10 @@ bool Converter::VisitBuiltinType(clang::BuiltinType *type) {
170170bool Converter::VisitRecordType (clang::RecordType *type) {
171171 auto *decl = type->getDecl ();
172172 if (auto lambda = AsLambdaClass (clang::QualType (type, 0 ))) {
173+ if (lambda->isGenericLambda ()) {
174+ StrCat (" FnPtr<Generic>" );
175+ return false ;
176+ }
173177 auto proto = lambda->getLambdaCallOperator ()
174178 ->getType ()
175179 ->castAs <clang::FunctionProtoType>();
@@ -1877,7 +1881,8 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
18771881 expr->getCalleeDecl ());
18781882 conversion && conversion->getParent ()->isLambda ()) {
18791883 ConvertLambdaToFunctionPointer (clang::cast<clang::CXXMemberCallExpr>(expr)
1880- ->getImplicitObjectArgument ());
1884+ ->getImplicitObjectArgument (),
1885+ conversion);
18811886 return false ;
18821887 }
18831888
@@ -1958,16 +1963,31 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
19581963 return false ;
19591964}
19601965
1961- void Converter::ConvertLambdaToFunctionPointer (clang::Expr *lambda) {
1966+ void Converter::ConvertLambdaToFunctionPointer (
1967+ clang::Expr *lambda, const clang::CXXConversionDecl *conversion) {
19621968 StrCat (" Some" );
19631969 PushParen paren (*this );
1964- ConvertLambdaClosure (AsLambdaClass (lambda->getType ()));
1970+ ConvertLambdaClosure (AsLambdaClass (lambda->getType ()),
1971+ AsLambdaCallOperator (conversion));
19651972 computed_expr_type_ = ComputedExprType::FreshPointer;
19661973}
19671974
1968- void Converter::EmitFnPtrCall (clang::Expr *callee) {
1969- if (AsLambdaClass (callee->getType ())) {
1970- StrCat (ConvertRValue (callee), " .call" );
1975+ void Converter::ConvertLambdaCall (clang::CallExpr *expr,
1976+ const clang::CXXRecordDecl *lambda) {
1977+ StrCat (ConvertRValue (GetCallee (expr)));
1978+ if (lambda->isGenericLambda ()) {
1979+ auto call_operator = expr->getDirectCallee ();
1980+ auto proto = call_operator->getType ()->castAs <clang::FunctionProtoType>();
1981+ StrCat (std::format (" .spec::<{}>({})" , ConvertFunctionPointerType (proto),
1982+ GetLambdaSpecializationIndex (call_operator)));
1983+ }
1984+ StrCat (" .call" );
1985+ }
1986+
1987+ void Converter::EmitFnPtrCall (clang::CallExpr *expr) {
1988+ auto callee = GetCallee (expr);
1989+ if (auto lambda = AsLambdaClass (callee->getType ())) {
1990+ ConvertLambdaCall (expr, lambda);
19711991 return ;
19721992 }
19731993 {
@@ -2014,8 +2034,9 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
20142034 auto callee = GetCallee (expr);
20152035 unsigned arg_begin = 0 ;
20162036 if (auto op_call = llvm::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
2017- if (clang::isa_and_nonnull<clang::CXXMethodDecl>(
2018- op_call->getDirectCallee ())) {
2037+ if (auto method = clang::dyn_cast_or_null<clang::CXXMethodDecl>(
2038+ op_call->getDirectCallee ());
2039+ method && !method->isExplicitObjectMemberFunction ()) {
20192040 arg_begin = 1 ;
20202041 }
20212042 }
@@ -2221,7 +2242,7 @@ void Converter::EmitCall(CallInfo &&info) {
22212242 EmitHoistedArgs (info);
22222243
22232244 if (info.is_fn_ptr_call ) {
2224- EmitFnPtrCall (GetCallee ( info.expr ) );
2245+ EmitFnPtrCall (info.expr );
22252246 } else if (info.is_libc_passthrough ) {
22262247 auto *direct_callee = info.expr ->getDirectCallee ();
22272248 assert (direct_callee);
@@ -3926,32 +3947,37 @@ bool Converter::VisitConstantExpr(clang::ConstantExpr *expr) {
39263947
39273948bool Converter::VisitLambdaExpr (clang::LambdaExpr *expr) {
39283949 auto decl = expr->getLambdaClass ();
3929- if (decl->captures ().empty ()) {
3950+ if (decl->captures ().empty () && !decl-> isGenericLambda () ) {
39303951 ConvertCapturelessLambda (decl);
39313952 return false ;
39323953 }
39333954 StrCat (LambdaMacro ());
39343955 PushParen paren (*this );
3956+ if (decl->isGenericLambda ()) {
3957+ StrCat (" Generic" , token::kComma );
3958+ }
39353959 {
39363960 PushBrace captures (*this );
39373961 auto init = expr->capture_init_begin ();
39383962 for (auto field : decl->fields ()) {
39393963 ConvertLambdaCapture (field, *init++);
39403964 }
39413965 }
3942- StrCat (token::kComma );
3943- ConvertLambdaClosure (decl);
3966+ ForEachLambdaCallOperator (decl, [&](clang::CXXMethodDecl *call_operator) {
3967+ StrCat (token::kComma );
3968+ ConvertLambdaClosure (decl, call_operator);
3969+ });
39443970 computed_expr_type_ = ComputedExprType::FreshValue;
39453971 return false ;
39463972}
39473973
39483974void Converter::ConvertCapturelessLambda (const clang::CXXRecordDecl *decl) {
3949- auto proto = decl->getLambdaCallOperator ()
3950- -> getType ()
3951- ->castAs <clang::FunctionProtoType>();
3975+ assert (! decl->isGenericLambda ());
3976+ auto call_operator = decl-> getLambdaCallOperator ();
3977+ auto proto = call_operator-> getType () ->castAs <clang::FunctionProtoType>();
39523978 StrCat (std::format (" FnPtr::<{}>::new" , ConvertFunctionPointerType (proto)));
39533979 PushParen paren (*this );
3954- ConvertLambdaClosure (decl);
3980+ ConvertLambdaClosure (decl, call_operator );
39553981 computed_expr_type_ = ComputedExprType::FreshValue;
39563982}
39573983
@@ -3964,8 +3990,8 @@ void Converter::ConvertLambdaCapture(const clang::FieldDecl *field,
39643990 StrCat (token::kSemiColon );
39653991}
39663992
3967- void Converter::ConvertLambdaClosure (const clang::CXXRecordDecl *decl) {
3968- auto call_operator = decl-> getLambdaCallOperator ();
3993+ void Converter::ConvertLambdaClosure (const clang::CXXRecordDecl *decl,
3994+ clang::CXXMethodDecl *call_operator) {
39693995 StrCat (' |' );
39703996 for (auto p : call_operator->parameters ()) {
39713997 StrCat (GetNamedDeclAsString (p), token::kColon , ToString (p->getType ()),
@@ -3975,7 +4001,7 @@ void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl) {
39754001 ConvertFunctionReturnType (call_operator);
39764002 PushBrace body (*this );
39774003 std::optional<PushBrace> unsafe_brace;
3978- if (decl->captures ().empty ()) {
4004+ if (decl->captures ().empty () && !decl-> isGenericLambda () ) {
39794005 StrCat (keyword_unsafe_);
39804006 unsafe_brace.emplace (*this );
39814007 }
0 commit comments