summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp89
1 files changed, 15 insertions, 74 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 73df1c9457..4f0e160950 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -8825,15 +8825,6 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
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();
ImplicitlyDefinedFunctionScope Scope(*this, Conv);
@@ -8842,79 +8833,29 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
// Copy-initialize the lambda object as needed to capture it.
Expr *This = ActOnCXXThis(CurrentLocation).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);
Conv->setInvalidDecl();
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
// function.
- StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock);
+ StmtResult Return = ActOnReturnStmt(Conv->getLocation(), BuildBlock.get());
if (Return.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
Conv->setInvalidDecl();