@@ -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,30 @@ 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+ }
1983+ StrCat (" .call" );
1984+ }
1985+
1986+ void Converter::EmitFnPtrCall (clang::CallExpr *expr) {
1987+ auto callee = GetCallee (expr);
1988+ if (auto lambda = AsLambdaClass (callee->getType ())) {
1989+ ConvertLambdaCall (expr, lambda);
19711990 return ;
19721991 }
19731992 {
@@ -2014,8 +2033,9 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
20142033 auto callee = GetCallee (expr);
20152034 unsigned arg_begin = 0 ;
20162035 if (auto op_call = llvm::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
2017- if (clang::isa_and_nonnull<clang::CXXMethodDecl>(
2018- op_call->getDirectCallee ())) {
2036+ if (auto method = clang::dyn_cast_or_null<clang::CXXMethodDecl>(
2037+ op_call->getDirectCallee ());
2038+ method && !method->isExplicitObjectMemberFunction ()) {
20192039 arg_begin = 1 ;
20202040 }
20212041 }
@@ -2221,7 +2241,7 @@ void Converter::EmitCall(CallInfo &&info) {
22212241 EmitHoistedArgs (info);
22222242
22232243 if (info.is_fn_ptr_call ) {
2224- EmitFnPtrCall (GetCallee ( info.expr ) );
2244+ EmitFnPtrCall (info.expr );
22252245 } else if (info.is_libc_passthrough ) {
22262246 auto *direct_callee = info.expr ->getDirectCallee ();
22272247 assert (direct_callee);
@@ -3926,12 +3946,15 @@ bool Converter::VisitConstantExpr(clang::ConstantExpr *expr) {
39263946
39273947bool Converter::VisitLambdaExpr (clang::LambdaExpr *expr) {
39283948 auto decl = expr->getLambdaClass ();
3929- if (decl->captures ().empty ()) {
3949+ if (decl->captures ().empty () && !decl-> isGenericLambda () ) {
39303950 ConvertCapturelessLambda (decl);
39313951 return false ;
39323952 }
39333953 StrCat (LambdaMacro ());
39343954 PushParen paren (*this );
3955+ if (decl->isGenericLambda ()) {
3956+ StrCat (" Generic" , token::kComma );
3957+ }
39353958 {
39363959 PushBrace captures (*this );
39373960 auto init = expr->capture_init_begin ();
@@ -3940,18 +3963,27 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) {
39403963 }
39413964 }
39423965 StrCat (token::kComma );
3943- ConvertLambdaClosure (decl);
3966+ std::unordered_set<std::string> signatures;
3967+ ForEachLambdaCallOperator (decl, [&](clang::CXXMethodDecl *call_operator) {
3968+ auto proto = call_operator->getType ()->castAs <clang::FunctionProtoType>();
3969+ if (!signatures.insert (ConvertFunctionPointerType (proto)).second ) {
3970+ llvm::report_fatal_error (" generic lambda with two specializations of "
3971+ " the same signature is not supported" );
3972+ }
3973+ ConvertLambdaClosure (decl, call_operator);
3974+ StrCat (token::kComma );
3975+ });
39443976 computed_expr_type_ = ComputedExprType::FreshValue;
39453977 return false ;
39463978}
39473979
39483980void Converter::ConvertCapturelessLambda (const clang::CXXRecordDecl *decl) {
3949- auto proto = decl->getLambdaCallOperator ()
3950- -> getType ()
3951- ->castAs <clang::FunctionProtoType>();
3981+ assert (! decl->isGenericLambda ());
3982+ auto call_operator = decl-> getLambdaCallOperator ();
3983+ auto proto = call_operator-> getType () ->castAs <clang::FunctionProtoType>();
39523984 StrCat (std::format (" FnPtr::<{}>::new" , ConvertFunctionPointerType (proto)));
39533985 PushParen paren (*this );
3954- ConvertLambdaClosure (decl);
3986+ ConvertLambdaClosure (decl, call_operator );
39553987 computed_expr_type_ = ComputedExprType::FreshValue;
39563988}
39573989
@@ -3964,8 +3996,8 @@ void Converter::ConvertLambdaCapture(const clang::FieldDecl *field,
39643996 StrCat (token::kSemiColon );
39653997}
39663998
3967- void Converter::ConvertLambdaClosure (const clang::CXXRecordDecl *decl) {
3968- auto call_operator = decl-> getLambdaCallOperator ();
3999+ void Converter::ConvertLambdaClosure (const clang::CXXRecordDecl *decl,
4000+ clang::CXXMethodDecl *call_operator) {
39694001 StrCat (' |' );
39704002 for (auto p : call_operator->parameters ()) {
39714003 StrCat (GetNamedDeclAsString (p), token::kColon , ToString (p->getType ()),
@@ -3975,7 +4007,7 @@ void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl) {
39754007 ConvertFunctionReturnType (call_operator);
39764008 PushBrace body (*this );
39774009 std::optional<PushBrace> unsafe_brace;
3978- if (decl->captures ().empty ()) {
4010+ if (decl->captures ().empty () && !decl-> isGenericLambda () ) {
39794011 StrCat (keyword_unsafe_);
39804012 unsafe_brace.emplace (*this );
39814013 }
0 commit comments