diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -3015,8 +3015,24 @@ CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); // Add the rest of the parameters. - for (auto *Param : MD->parameters()) - EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); + for (auto *Param : MD->parameters()) { + // If there's an inalloca param type, use a reference to the inalloca type + // in the forwarding call instead. + const CXXRecordDecl *RD = Param->getType()->getAsCXXRecordDecl(); + if (RD && CGM.getCXXABI().getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory) { + QualType ParamAsRefType = + getContext().getLValueReferenceType(Param->getType()); + ParmVarDecl *ParamAsRef = ParmVarDecl::Create( + Param->getASTContext(), Param->getDeclContext(), + Param->getBeginLoc(), Param->getEndLoc(), Param->getIdentifier(), + ParamAsRefType, Param->getTypeSourceInfo(), + Param->getStorageClass(), Param->getDefaultArg()); + setAddrOfLocalVar(ParamAsRef, GetAddrOfLocalVar(Param)); + EmitDelegateCallArg(CallArgs, ParamAsRef, Param->getBeginLoc()); + } else { + EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); + } + } const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); // For a generic lambda, find the corresponding call operator specialization diff --git a/clang/test/CodeGenCXX/inalloca-lambda.cpp b/clang/test/CodeGenCXX/inalloca-lambda.cpp --- a/clang/test/CodeGenCXX/inalloca-lambda.cpp +++ b/clang/test/CodeGenCXX/inalloca-lambda.cpp @@ -1,7 +1,4 @@ -// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s 2>&1 | FileCheck %s - -// PR28299 -// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet +// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s 2>&1 | FileCheck %s class A { A(const A &); @@ -9,3 +6,14 @@ typedef void (*fptr_t)(A); fptr_t fn1() { return [](A) {}; } +// CHECK-LABEL: define dso_local noundef ptr @"?fn1@@YAP6AXVA@@@ZXZ" +// CHECK-LABEL: define internal x86_thiscallcc noundef ptr @"??B@?0??fn1@@YAP6AXVA@@@ZXZ@QBEP6A?A?@@0@ZXZ" +// CHECK-LABEL: define internal void @"?__invoke@@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?@@0@Z" +// CHECK: %argmem = alloca inalloca <{ %class.A, [3 x i8] }>, align 4 +// CHECK: %[[V1:[0-9]+]] = getelementptr inbounds +// CHECK: %[[V2:[0-9]+]] = load %class.A, ptr %[[V1]], align 4 +// CHECK: %[[V3:[0-9]+]] = getelementptr inbounds +// CHECK: store %class.A %[[V2]], ptr %[[V3]], align 4 +// CHECK: call x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z" +// CHECK-SAME: ptr noundef %unused.capture, ptr inalloca(<{ %class.A, [3 x i8] }>) %argmem +// CHECK-LABEL: define internal x86_thiscallcc void @"??R@?0??fn1@@YAP6AXVA@@@ZXZ@QBE?A?@@0@Z"