diff options
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 89 |
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(); |