summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-17 03:02:34 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-17 03:02:34 +0000
commit355efbb2e044126adecdcadca87c8cdfb5c33a85 (patch)
tree1414f54d5ff0cc4f6b5b09b8b806178a0ae2d9e2 /clang/lib/Sema/SemaDeclCXX.cpp
parentd608bac682fc88eb8ab7dc1ef65245c0f5c75712 (diff)
downloadbcm5719-llvm-355efbb2e044126adecdcadca87c8cdfb5c33a85.tar.gz
bcm5719-llvm-355efbb2e044126adecdcadca87c8cdfb5c33a85.zip
Rework the Sema/AST/IRgen dance for the lambda closure type's
conversion to function pointer. Rather than having IRgen synthesize the body of this function, we instead introduce a static member function "__invoke" with the same signature as the lambda's operator() in the AST. Sema then generates a body for the conversion to function pointer which simply returns the address of __invoke. This approach makes it easier to evaluate a call to the conversion function as a constant, makes the linkage of the __invoke function follow the normal rules for member functions, and may make life easier down the road if we ever want to constexpr'ify some of lambdas. Note that IR generation is responsible for filling in the body of __invoke (Sema just adds a dummy body), because the body can't generally be expressed in C++. Eli, please review! llvm-svn: 150783
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp37
1 files changed, 35 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 66ec800c726..82e59ddafee 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9051,21 +9051,52 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
isa<CXXMethodDecl>(FD);
}
+/// \brief Mark the call operator of the given lambda closure type as "used".
+static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) {
+ CXXMethodDecl *CallOperator
+ = cast<CXXMethodDecl>(
+ *Lambda->lookup(
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first);
+ CallOperator->setReferenced();
+ CallOperator->setUsed();
+}
+
void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
+ CXXRecordDecl *Lambda = Conv->getParent();
+
+ // Make sure that the lambda call operator is marked used.
+ markLambdaCallOperatorUsed(*this, Lambda);
+
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(),
+ // Return the address of the __invoke function.
+ DeclarationName InvokeName = &Context.Idents.get("__invoke");
+ CXXMethodDecl *Invoke
+ = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first);
+ Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
+ VK_LValue, Conv->getLocation()).take();
+ assert(FunctionRef && "Can't refer to __invoke function?");
+ Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
+ Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1,
+ Conv->getLocation(),
Conv->getLocation()));
+
+ // Fill in the __invoke function with a dummy implementation. IR generation
+ // will fill in the actual details.
+ Invoke->setUsed();
+ Invoke->setReferenced();
+ Invoke->setBody(new (Context) CompoundStmt(Context, 0, 0, Conv->getLocation(),
+ Conv->getLocation()));
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
+ L->CompletedImplicitDefinition(Invoke);
}
}
@@ -9073,6 +9104,8 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
+ // Make sure that the lambda call operator is marked used.
+ markLambdaCallOperatorUsed(*this, Conv->getParent());
Conv->setUsed();
ImplicitlyDefinedFunctionScope Scope(*this, Conv);
OpenPOWER on IntegriCloud