aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclCXX.cpp15
-rw-r--r--lib/Sema/SemaDeclCXX.cpp55
-rw-r--r--lib/Sema/SemaExpr.cpp9
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp2
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp2
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;
}