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
This commit is contained in:
Douglas Gregor
2012-02-17 03:02:34 +00:00
parent d608bac682
commit 355efbb2e0
8 changed files with 122 additions and 69 deletions

View File

@@ -448,13 +448,15 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
FD->hasAttr<CUDAGlobalAttr>())
CGM.getCUDARuntime().EmitDeviceStubBody(*this, Args);
else if (isa<CXXConversionDecl>(FD) &&
cast<CXXConversionDecl>(FD)->getParent()->isLambda()) {
// The lambda conversion operators are special; the semantics can't be
// expressed in the AST, so IRGen needs to special-case them.
if (cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion())
EmitLambdaToBlockPointerBody(Args);
else
EmitLambdaToFunctionPointerBody(Args);
cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion()) {
// The lambda conversion to block pointer is special; the semantics can't be
// expressed in the AST, so IRGen needs to special-case it.
EmitLambdaToBlockPointerBody(Args);
} else if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
// The lambda "__invoke" function is special, because it forwards or
// clones the body of the function call operator (but is actually static).
EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
}
else
EmitFunctionBody(Args);