|
@@ -8825,15 +8825,6 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
|
|
SourceLocation CurrentLocation,
|
|
SourceLocation CurrentLocation,
|
|
CXXConversionDecl *Conv)
|
|
CXXConversionDecl *Conv)
|
|
{
|
|
{
|
|
- CXXRecordDecl *Lambda = Conv->getParent();
|
|
|
|
-
|
|
|
|
- // Make sure that the lambda call operator is marked used.
|
|
|
|
- CXXMethodDecl *CallOperator
|
|
|
|
- = cast<CXXMethodDecl>(
|
|
|
|
- *Lambda->lookup(
|
|
|
|
- Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
|
|
|
|
- CallOperator->setReferenced();
|
|
|
|
- CallOperator->setUsed();
|
|
|
|
Conv->setUsed();
|
|
Conv->setUsed();
|
|
|
|
|
|
ImplicitlyDefinedFunctionScope Scope(*this, Conv);
|
|
ImplicitlyDefinedFunctionScope Scope(*this, Conv);
|
|
@@ -8842,79 +8833,29 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
|
|
// Copy-initialize the lambda object as needed to capture it.
|
|
// Copy-initialize the lambda object as needed to capture it.
|
|
Expr *This = ActOnCXXThis(CurrentLocation).take();
|
|
Expr *This = ActOnCXXThis(CurrentLocation).take();
|
|
Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take();
|
|
Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).take();
|
|
- ExprResult Init = PerformCopyInitialization(
|
|
|
|
- InitializedEntity::InitializeBlock(CurrentLocation,
|
|
|
|
- DerefThis->getType(),
|
|
|
|
- /*NRVO=*/false),
|
|
|
|
- CurrentLocation, DerefThis);
|
|
|
|
- if (!Init.isInvalid())
|
|
|
|
- Init = ActOnFinishFullExpr(Init.take());
|
|
|
|
|
|
|
|
- if (Init.isInvalid()) {
|
|
|
|
|
|
+ ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
|
|
|
|
+ Conv->getLocation(),
|
|
|
|
+ Conv, DerefThis);
|
|
|
|
+
|
|
|
|
+ // If we're not under ARC, make sure we still get the _Block_copy/autorelease
|
|
|
|
+ // behavior. Note that only the general conversion function does this
|
|
|
|
+ // (since it's unusable otherwise); in the case where we inline the
|
|
|
|
+ // block literal, it has block literal lifetime semantics.
|
|
|
|
+ if (!BuildBlock.isInvalid() && !getLangOptions().ObjCAutoRefCount)
|
|
|
|
+ BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
|
|
|
|
+ CK_CopyAndAutoreleaseBlockObject,
|
|
|
|
+ BuildBlock.get(), 0, VK_RValue);
|
|
|
|
+
|
|
|
|
+ if (BuildBlock.isInvalid()) {
|
|
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
|
|
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
|
|
Conv->setInvalidDecl();
|
|
Conv->setInvalidDecl();
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Create the new block to be returned.
|
|
|
|
- BlockDecl *Block = BlockDecl::Create(Context, Conv, Conv->getLocation());
|
|
|
|
-
|
|
|
|
- // Set the type information.
|
|
|
|
- Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo());
|
|
|
|
- Block->setIsVariadic(CallOperator->isVariadic());
|
|
|
|
- Block->setBlockMissingReturnType(false);
|
|
|
|
-
|
|
|
|
- // Add parameters.
|
|
|
|
- SmallVector<ParmVarDecl *, 4> BlockParams;
|
|
|
|
- for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) {
|
|
|
|
- ParmVarDecl *From = CallOperator->getParamDecl(I);
|
|
|
|
- BlockParams.push_back(ParmVarDecl::Create(Context, Block,
|
|
|
|
- From->getLocStart(),
|
|
|
|
- From->getLocation(),
|
|
|
|
- From->getIdentifier(),
|
|
|
|
- From->getType(),
|
|
|
|
- From->getTypeSourceInfo(),
|
|
|
|
- From->getStorageClass(),
|
|
|
|
- From->getStorageClassAsWritten(),
|
|
|
|
- /*DefaultArg=*/0));
|
|
|
|
- }
|
|
|
|
- Block->setParams(BlockParams);
|
|
|
|
-
|
|
|
|
- // Add capture. The capture uses a fake variable, which doesn't correspond
|
|
|
|
- // to any actual memory location. However, the initializer copy-initializes
|
|
|
|
- // the lambda object.
|
|
|
|
- TypeSourceInfo *CapVarTSI =
|
|
|
|
- Context.getTrivialTypeSourceInfo(DerefThis->getType());
|
|
|
|
- VarDecl *CapVar = VarDecl::Create(Context, Block, Conv->getLocation(),
|
|
|
|
- Conv->getLocation(), 0,
|
|
|
|
- DerefThis->getType(), CapVarTSI,
|
|
|
|
- SC_None, SC_None);
|
|
|
|
- BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
|
|
|
|
- /*Nested=*/false, /*Copy=*/Init.take());
|
|
|
|
- Block->setCaptures(Context, &Capture, &Capture + 1,
|
|
|
|
- /*CapturesCXXThis=*/false);
|
|
|
|
-
|
|
|
|
- // Add a fake function body to the block. IR generation is responsible
|
|
|
|
- // for filling in the actual body, which cannot be expressed as an AST.
|
|
|
|
- Block->setBody(new (Context) CompoundStmt(Context, 0, 0,
|
|
|
|
- Conv->getLocation(),
|
|
|
|
- Conv->getLocation()));
|
|
|
|
-
|
|
|
|
- // Create the block literal expression.
|
|
|
|
- Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType());
|
|
|
|
- ExprCleanupObjects.push_back(Block);
|
|
|
|
- ExprNeedsCleanups = true;
|
|
|
|
|
|
|
|
- // If we're not under ARC, make sure we still get the _Block_copy/autorelease
|
|
|
|
- // behavior.
|
|
|
|
- if (!getLangOptions().ObjCAutoRefCount)
|
|
|
|
- BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock->getType(),
|
|
|
|
- CK_CopyAndAutoreleaseBlockObject,
|
|
|
|
- BuildBlock, 0, VK_RValue);
|
|
|
|
-
|
|
|
|
// Create the return statement that returns the block from the conversion
|
|
// Create the return statement that returns the block from the conversion
|
|
// function.
|
|
// function.
|
|
- StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock);
|
|
|
|
|
|
+ StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get());
|
|
if (Return.isInvalid()) {
|
|
if (Return.isInvalid()) {
|
|
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
|
|
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
|
|
Conv->setInvalidDecl();
|
|
Conv->setInvalidDecl();
|