@@ -1263,30 +1263,61 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
12631263 PopFunctionScopeInfo ();
12641264}
12651265
1266+ template <typename Func>
1267+ static void repeatForLambdaConversionFunctionCallingConvs (
1268+ Sema &S, const FunctionProtoType &CallOpProto, Func F) {
1269+ CallingConv DefaultFree = S.Context .getDefaultCallingConvention (
1270+ CallOpProto.isVariadic (), /* IsCXXMethod=*/ false );
1271+ CallingConv DefaultMember = S.Context .getDefaultCallingConvention (
1272+ CallOpProto.isVariadic (), /* IsCXXMethod=*/ true );
1273+ CallingConv CallOpCC = CallOpProto.getCallConv ();
1274+
1275+ if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) {
1276+ F (DefaultFree);
1277+ F (DefaultMember);
1278+ } else {
1279+ F (CallOpCC);
1280+ }
1281+ }
1282+
1283+ // Returns the 'standard' calling convention to be used for the lambda
1284+ // conversion function, that is, the 'free' function calling convention unless
1285+ // it is overridden by a non-default calling convention attribute.
1286+ static CallingConv
1287+ getLambdaConversionFunctionCallConv (Sema &S,
1288+ const FunctionProtoType *CallOpProto) {
1289+ CallingConv DefaultFree = S.Context .getDefaultCallingConvention (
1290+ CallOpProto->isVariadic (), /* IsCXXMethod=*/ false );
1291+ CallingConv DefaultMember = S.Context .getDefaultCallingConvention (
1292+ CallOpProto->isVariadic (), /* IsCXXMethod=*/ true );
1293+ CallingConv CallOpCC = CallOpProto->getCallConv ();
1294+
1295+ // If the call-operator hasn't been changed, return both the 'free' and
1296+ // 'member' function calling convention.
1297+ if (CallOpCC == DefaultMember && DefaultMember != DefaultFree)
1298+ return DefaultFree;
1299+ return CallOpCC;
1300+ }
1301+
12661302QualType Sema::getLambdaConversionFunctionResultType (
1267- const FunctionProtoType *CallOpProto) {
1268- // The function type inside the pointer type is the same as the call
1269- // operator with some tweaks. The calling convention is the default free
1270- // function convention, and the type qualifications are lost.
1303+ const FunctionProtoType *CallOpProto, CallingConv CC) {
12711304 const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
12721305 CallOpProto->getExtProtoInfo ();
12731306 FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
1274- CallingConv CC = Context.getDefaultCallingConvention (
1275- CallOpProto->isVariadic (), /* IsCXXMethod=*/ false );
12761307 InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo .withCallingConv (CC);
12771308 InvokerExtInfo.TypeQuals = Qualifiers ();
12781309 assert (InvokerExtInfo.RefQualifier == RQ_None &&
1279- " Lambda's call operator should not have a reference qualifier" );
1310+ " Lambda's call operator should not have a reference qualifier" );
12801311 return Context.getFunctionType (CallOpProto->getReturnType (),
12811312 CallOpProto->getParamTypes (), InvokerExtInfo);
12821313}
12831314
12841315// / Add a lambda's conversion to function pointer, as described in
12851316// / C++11 [expr.prim.lambda]p6.
1286- static void addFunctionPointerConversion (Sema &S,
1287- SourceRange IntroducerRange,
1317+ static void addFunctionPointerConversion (Sema &S, SourceRange IntroducerRange,
12881318 CXXRecordDecl *Class,
1289- CXXMethodDecl *CallOperator) {
1319+ CXXMethodDecl *CallOperator,
1320+ QualType InvokerFunctionTy) {
12901321 // This conversion is explicitly disabled if the lambda's function has
12911322 // pass_object_size attributes on any of its parameters.
12921323 auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) {
@@ -1296,8 +1327,6 @@ static void addFunctionPointerConversion(Sema &S,
12961327 return ;
12971328
12981329 // Add the conversion to function pointer.
1299- QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType (
1300- CallOperator->getType ()->castAs <FunctionProtoType>());
13011330 QualType PtrToFunctionTy = S.Context .getPointerType (InvokerFunctionTy);
13021331
13031332 // Create the type of the conversion function.
@@ -1442,13 +1471,37 @@ static void addFunctionPointerConversion(Sema &S,
14421471 Class->addDecl (Invoke);
14431472}
14441473
1474+ // / Add a lambda's conversion to function pointers, as described in
1475+ // / C++11 [expr.prim.lambda]p6. Note that in most cases, this should emit only a
1476+ // / single pointer conversion. In the event that the default calling convention
1477+ // / for free and member functions is different, it will emit both conventions.
1478+ // / FIXME: Implement emitting a version of the operator for EVERY calling
1479+ // / convention for MSVC, as described here:
1480+ // / https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623.
1481+ static void addFunctionPointerConversions (Sema &S, SourceRange IntroducerRange,
1482+ CXXRecordDecl *Class,
1483+ CXXMethodDecl *CallOperator) {
1484+ const FunctionProtoType *CallOpProto =
1485+ CallOperator->getType ()->castAs <FunctionProtoType>();
1486+
1487+ repeatForLambdaConversionFunctionCallingConvs (
1488+ S, *CallOpProto, [&](CallingConv CC) {
1489+ QualType InvokerFunctionTy =
1490+ S.getLambdaConversionFunctionResultType (CallOpProto, CC);
1491+ addFunctionPointerConversion (S, IntroducerRange, Class, CallOperator,
1492+ InvokerFunctionTy);
1493+ });
1494+ }
1495+
14451496// / Add a lambda's conversion to block pointer.
14461497static void addBlockPointerConversion (Sema &S,
14471498 SourceRange IntroducerRange,
14481499 CXXRecordDecl *Class,
14491500 CXXMethodDecl *CallOperator) {
1501+ const FunctionProtoType *CallOpProto =
1502+ CallOperator->getType ()->castAs <FunctionProtoType>();
14501503 QualType FunctionTy = S.getLambdaConversionFunctionResultType (
1451- CallOperator-> getType ()-> castAs <FunctionProtoType>( ));
1504+ CallOpProto, getLambdaConversionFunctionCallConv (S, CallOpProto ));
14521505 QualType BlockPtrTy = S.Context .getBlockPointerType (FunctionTy);
14531506
14541507 FunctionProtoType::ExtProtoInfo ConversionEPI (
@@ -1795,8 +1848,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
17951848 // to pointer to function having the same parameter and return
17961849 // types as the closure type's function call operator.
17971850 if (Captures.empty () && CaptureDefault == LCD_None)
1798- addFunctionPointerConversion (*this , IntroducerRange, Class,
1799- CallOperator);
1851+ addFunctionPointerConversions (*this , IntroducerRange, Class,
1852+ CallOperator);
18001853
18011854 // Objective-C++:
18021855 // The closure type for a lambda-expression has a public non-virtual
0 commit comments