diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 55 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 9 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 2 |
5 files changed, 81 insertions, 2 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5b9ab4ff5c..b5b3f12f5e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1759,6 +1759,21 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, EndLocation); } +bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { + return isImplicit() && getParent()->isLambda() && + getConversionType()->isBlockPointerType(); +} + +Expr *CXXConversionDecl::getLambdaToBlockPointerCopyInit() const { + assert(isLambdaToBlockPointerConversion()); + return getASTContext().LambdaBlockPointerInits[this]; +} + +void CXXConversionDecl::setLambdaToBlockPointerCopyInit(Expr *Init) { + assert(isLambdaToBlockPointerConversion()); + getASTContext().LambdaBlockPointerInits[this] = Init; +} + void LinkageSpecDecl::anchor() { } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 447a4b4257..66ec800c72 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9050,7 +9050,60 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { (FD->isDefaulted() || FD->isImplicit()) && isa<CXXMethodDecl>(FD); } - + +void Sema::DefineImplicitLambdaToFunctionPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Introduce a bogus body, which IR generation will override anyway. + Conv->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + Conv->getLocation())); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + } +} + +void Sema::DefineImplicitLambdaToBlockPointerConversion( + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) +{ + Conv->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, Conv); + DiagnosticErrorTrap Trap(Diags); + + // Copy-initialize the lambda object as needed to capture + 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()) + Conv->setLambdaToBlockPointerCopyInit(Init.take()); + else { + Diag(CurrentLocation, diag::note_lambda_to_block_conv); + } + + // Introduce a bogus body, which IR generation will override anyway. + Conv->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(), + Conv->getLocation())); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Conv); + } +} + ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b05f4d5623..7fee518d2c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9447,6 +9447,13 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { else DefineImplicitMoveAssignment(Loc, MethodDecl); } + } else if (isa<CXXConversionDecl>(MethodDecl) && + MethodDecl->getParent()->isLambda()) { + CXXConversionDecl *Conversion = cast<CXXConversionDecl>(MethodDecl); + if (Conversion->isLambdaToBlockPointerConversion()) + DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion); + else + DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion); } else if (MethodDecl->isVirtual()) MarkVTableUsed(Loc, MethodDecl->getParent()); } @@ -10041,7 +10048,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, } SemaRef.MarkAnyDeclReferenced(Loc, D); -} +} /// \brief Perform reference-marking and odr-use handling for a /// BlockDeclRefExpr. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 547dc568e7..6e044fd0db 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1206,6 +1206,8 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); D->IsExplicitSpecified = Record[Idx++]; + if (D->isLambdaToBlockPointerConversion()) + D->setLambdaToBlockPointerCopyInit(Reader.ReadExpr(F)); } void ASTDeclReader::VisitImportDecl(ImportDecl *D) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 7cd2f4ebed..584ff1c144 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -961,6 +961,8 @@ void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); Record.push_back(D->IsExplicitSpecified); + if (D->isLambdaToBlockPointerConversion()) + Writer.AddStmt(D->getLambdaToBlockPointerCopyInit()); Code = serialization::DECL_CXX_CONVERSION; } |