From: Douglas Gregor Date: Wed, 8 Feb 2012 21:18:48 +0000 (+0000) Subject: Factor C++11 lambda expressions implementation into a separate X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2a7ad001fe1dc4a0d5fef312e7f7189e1f29369;p=clang Factor C++11 lambda expressions implementation into a separate file. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150089 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index ae878b0649..dece5bd998 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -29,6 +29,7 @@ add_clang_library(clangSema SemaExprObjC.cpp SemaFixItUtils.cpp SemaInit.cpp + SemaLambda.cpp SemaLookup.cpp SemaObjCProperty.cpp SemaOverload.cpp diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 98ab97808c..63fd869e7b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4870,333 +4870,3 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); } - -//===----------------------------------------------------------------------===// -// Lambdas. -//===----------------------------------------------------------------------===// - -void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, - Scope *CurScope) { - DeclContext *DC = CurContext; - while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) - DC = DC->getParent(); - - // Start constructing the lambda class. - CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC, - Intro.Range.getBegin(), - /*IdLoc=*/SourceLocation(), - /*Id=*/0); - Class->startDefinition(); - Class->setLambda(true); - CurContext->addDecl(Class); - - // Build the call operator; we don't really have all the relevant information - // at this point, but we need something to attach child declarations to. - QualType MethodTy; - TypeSourceInfo *MethodTyInfo; - bool ExplicitParams = true; - SourceLocation EndLoc; - if (ParamInfo.getNumTypeObjects() == 0) { - // C++11 [expr.prim.lambda]p4: - // If a lambda-expression does not include a lambda-declarator, it is as - // if the lambda-declarator were (). - FunctionProtoType::ExtProtoInfo EPI; - EPI.TypeQuals |= DeclSpec::TQ_const; - MethodTy = Context.getFunctionType(Context.DependentTy, - /*Args=*/0, /*NumArgs=*/0, EPI); - MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); - ExplicitParams = false; - EndLoc = Intro.Range.getEnd(); - } else { - assert(ParamInfo.isFunctionDeclarator() && - "lambda-declarator is a function"); - DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); - - // C++11 [expr.prim.lambda]p5: - // This function call operator is declared const (9.3.1) if and only if - // the lambda-expression’s parameter-declaration-clause is not followed - // by mutable. It is neither virtual nor declared volatile. [...] - if (!FTI.hasMutableQualifier()) - FTI.TypeQuals |= DeclSpec::TQ_const; - - // C++11 [expr.prim.lambda]p5: - // [...] Default arguments (8.3.6) shall not be specified in the - // parameter-declaration-clause of a lambda-declarator. - CheckExtraCXXDefaultArguments(ParamInfo); - - MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); - // FIXME: Can these asserts actually fail? - assert(MethodTyInfo && "no type from lambda-declarator"); - MethodTy = MethodTyInfo->getType(); - assert(!MethodTy.isNull() && "no type from lambda declarator"); - EndLoc = ParamInfo.getSourceRange().getEnd(); - } - - // C++11 [expr.prim.lambda]p5: - // The closure type for a lambda-expression has a public inline function - // call operator (13.5.4) whose parameters and return type are described by - // the lambda-expression’s parameter-declaration-clause and - // trailing-return-type respectively. - DeclarationName MethodName - = Context.DeclarationNames.getCXXOperatorName(OO_Call); - DeclarationNameLoc MethodNameLoc; - MethodNameLoc.CXXOperatorName.BeginOpNameLoc - = Intro.Range.getBegin().getRawEncoding(); - MethodNameLoc.CXXOperatorName.EndOpNameLoc - = Intro.Range.getEnd().getRawEncoding(); - CXXMethodDecl *Method - = CXXMethodDecl::Create(Context, Class, EndLoc, - DeclarationNameInfo(MethodName, - Intro.Range.getBegin(), - MethodNameLoc), - MethodTy, MethodTyInfo, - /*isStatic=*/false, - SC_None, - /*isInline=*/true, - /*isConstExpr=*/false, - EndLoc); - Method->setAccess(AS_public); - Class->addDecl(Method); - Method->setLexicalDeclContext(DC); // FIXME: Minor hack. - - ProcessDeclAttributes(CurScope, Method, ParamInfo); - - // Enter a new evaluation context to insulate the block from any - // cleanups from the enclosing full-expression. - PushExpressionEvaluationContext(PotentiallyEvaluated); - - PushDeclContext(CurScope, Method); - - // Introduce the lambda scope. - PushLambdaScope(Class, Method); - LambdaScopeInfo *LSI = getCurLambda(); - if (Intro.Default == LCD_ByCopy) - LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; - else if (Intro.Default == LCD_ByRef) - LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; - LSI->IntroducerRange = Intro.Range; - LSI->ExplicitParams = ExplicitParams; - LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0; - - // Handle explicit captures. - for (llvm::SmallVector::const_iterator - C = Intro.Captures.begin(), - E = Intro.Captures.end(); - C != E; ++C) { - if (C->Kind == LCK_This) { - // C++11 [expr.prim.lambda]p8: - // An identifier or this shall not appear more than once in a - // lambda-capture. - if (LSI->isCXXThisCaptured()) { - Diag(C->Loc, diag::err_capture_more_than_once) - << "'this'" - << SourceRange(LSI->getCXXThisCapture().getLocation()); - continue; - } - - // C++11 [expr.prim.lambda]p8: - // If a lambda-capture includes a capture-default that is =, the - // lambda-capture shall not contain this [...]. - if (Intro.Default == LCD_ByCopy) { - Diag(C->Loc, diag::err_this_capture_with_copy_default); - continue; - } - - // C++11 [expr.prim.lambda]p12: - // If this is captured by a local lambda expression, its nearest - // enclosing function shall be a non-static member function. - QualType ThisCaptureType = getCurrentThisType(); - if (ThisCaptureType.isNull()) { - Diag(C->Loc, diag::err_this_capture) << true; - continue; - } - - CheckCXXThisCapture(C->Loc, /*Explicit=*/true); - continue; - } - - assert(C->Id && "missing identifier for capture"); - - // C++11 [expr.prim.lambda]p8: - // If a lambda-capture includes a capture-default that is &, the - // identifiers in the lambda-capture shall not be preceded by &. - // If a lambda-capture includes a capture-default that is =, [...] - // each identifier it contains shall be preceded by &. - if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { - Diag(C->Loc, diag::err_reference_capture_with_reference_default); - continue; - } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { - Diag(C->Loc, diag::err_copy_capture_with_copy_default); - continue; - } - - DeclarationNameInfo Name(C->Id, C->Loc); - LookupResult R(*this, Name, LookupOrdinaryName); - LookupName(R, CurScope); - if (R.isAmbiguous()) - continue; - if (R.empty()) { - // FIXME: Disable corrections that would add qualification? - CXXScopeSpec ScopeSpec; - DeclFilterCCC Validator; - if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) - continue; - } - - // C++11 [expr.prim.lambda]p10: - // The identifiers in a capture-list are looked up using the usual rules - // for unqualified name lookup (3.4.1); each such lookup shall find a - // variable with automatic storage duration declared in the reaching - // scope of the local lambda expression. - // FIXME: Check reaching scope. - VarDecl *Var = R.getAsSingle(); - if (!Var) { - Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; - continue; - } - - if (!Var->hasLocalStorage()) { - Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; - Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; - continue; - } - - // C++11 [expr.prim.lambda]p8: - // An identifier or this shall not appear more than once in a - // lambda-capture. - if (LSI->isCaptured(Var)) { - Diag(C->Loc, diag::err_capture_more_than_once) - << C->Id - << SourceRange(LSI->getCapture(Var).getLocation()); - continue; - } - - TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : - TryCapture_ExplicitByVal; - TryCaptureVar(Var, C->Loc, Kind); - } - LSI->finishedExplicitCaptures(); - - // Set the parameters on the decl, if specified. - if (isa(MethodTyInfo->getTypeLoc())) { - FunctionProtoTypeLoc Proto = - cast(MethodTyInfo->getTypeLoc()); - Method->setParams(Proto.getParams()); - CheckParmsForFunctionDef(Method->param_begin(), - Method->param_end(), - /*CheckParameterNames=*/false); - - // Introduce our parameters into the function scope - for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) { - ParmVarDecl *Param = Method->getParamDecl(p); - Param->setOwningFunction(Method); - - // If this has an identifier, add it to the scope stack. - if (Param->getIdentifier()) { - CheckShadow(CurScope, Param); - - PushOnScopeChains(Param, CurScope); - } - } - } - - const FunctionType *Fn = MethodTy->getAs(); - QualType RetTy = Fn->getResultType(); - if (RetTy != Context.DependentTy) { - LSI->ReturnType = RetTy; - } else { - LSI->HasImplicitReturnType = true; - } - - // FIXME: Check return type is complete, !isObjCObjectType - -} - -void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { - // Leave the expression-evaluation context. - DiscardCleanupsInEvaluationContext(); - PopExpressionEvaluationContext(); - - // Leave the context of the lambda. - PopDeclContext(); - PopFunctionScopeInfo(); -} - -ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, - Stmt *Body, Scope *CurScope) { - // Leave the expression-evaluation context. - DiscardCleanupsInEvaluationContext(); - PopExpressionEvaluationContext(); - - // FIXME: End-of-lambda checking - - // Collect information from the lambda scope. - llvm::SmallVector Captures; - llvm::SmallVector CaptureInits; - LambdaCaptureDefault CaptureDefault; - CXXRecordDecl *Class; - SourceRange IntroducerRange; - bool ExplicitParams; - { - LambdaScopeInfo *LSI = getCurLambda(); - Class = LSI->Lambda; - IntroducerRange = LSI->IntroducerRange; - ExplicitParams = LSI->ExplicitParams; - - // Translate captures. - for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { - LambdaScopeInfo::Capture From = LSI->Captures[I]; - assert(!From.isBlockCapture() && "Cannot capture __block variables"); - bool IsImplicit = I >= LSI->NumExplicitCaptures; - - // Handle 'this' capture. - if (From.isThisCapture()) { - Captures.push_back(LambdaExpr::Capture(From.getLocation(), - IsImplicit, - LCK_This)); - CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), - getCurrentThisType(), - /*isImplicit=*/true)); - continue; - } - - VarDecl *Var = From.getVariable(); - // FIXME: Handle pack expansions. - LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; - Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, - Kind, Var)); - CaptureInits.push_back(From.getCopyExpr()); - } - - switch (LSI->ImpCaptureStyle) { - case CapturingScopeInfo::ImpCap_None: - CaptureDefault = LCD_None; - break; - - case CapturingScopeInfo::ImpCap_LambdaByval: - CaptureDefault = LCD_ByCopy; - break; - - case CapturingScopeInfo::ImpCap_LambdaByref: - CaptureDefault = LCD_ByRef; - break; - - case CapturingScopeInfo::ImpCap_Block: - llvm_unreachable("block capture in lambda"); - break; - } - - // C++ [expr.prim.lambda]p7: - // The lambda-expression’s compound-statement yields the - // function-body (8.4) of the function call operator [...]. - ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false); - } - - Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, - CaptureDefault, Captures, ExplicitParams, - CaptureInits, Body->getLocEnd()); - (void)Lambda; - Diag(StartLoc, diag::err_lambda_unsupported); - return ExprError(); -} diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp new file mode 100644 index 0000000000..3e9e210244 --- /dev/null +++ b/lib/Sema/SemaLambda.cpp @@ -0,0 +1,346 @@ +//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/ExprCXX.h" +using namespace clang; +using namespace sema; + +void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, + Scope *CurScope) { + DeclContext *DC = CurContext; + while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) + DC = DC->getParent(); + + // Start constructing the lambda class. + CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC, + Intro.Range.getBegin(), + /*IdLoc=*/SourceLocation(), + /*Id=*/0); + Class->startDefinition(); + Class->setLambda(true); + CurContext->addDecl(Class); + + // Build the call operator; we don't really have all the relevant information + // at this point, but we need something to attach child declarations to. + QualType MethodTy; + TypeSourceInfo *MethodTyInfo; + bool ExplicitParams = true; + SourceLocation EndLoc; + if (ParamInfo.getNumTypeObjects() == 0) { + // C++11 [expr.prim.lambda]p4: + // If a lambda-expression does not include a lambda-declarator, it is as + // if the lambda-declarator were (). + FunctionProtoType::ExtProtoInfo EPI; + EPI.TypeQuals |= DeclSpec::TQ_const; + MethodTy = Context.getFunctionType(Context.DependentTy, + /*Args=*/0, /*NumArgs=*/0, EPI); + MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); + ExplicitParams = false; + EndLoc = Intro.Range.getEnd(); + } else { + assert(ParamInfo.isFunctionDeclarator() && + "lambda-declarator is a function"); + DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); + + // C++11 [expr.prim.lambda]p5: + // This function call operator is declared const (9.3.1) if and only if + // the lambda-expression's parameter-declaration-clause is not followed + // by mutable. It is neither virtual nor declared volatile. [...] + if (!FTI.hasMutableQualifier()) + FTI.TypeQuals |= DeclSpec::TQ_const; + + // C++11 [expr.prim.lambda]p5: + // [...] Default arguments (8.3.6) shall not be specified in the + // parameter-declaration-clause of a lambda-declarator. + CheckExtraCXXDefaultArguments(ParamInfo); + + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + // FIXME: Can these asserts actually fail? + assert(MethodTyInfo && "no type from lambda-declarator"); + MethodTy = MethodTyInfo->getType(); + assert(!MethodTy.isNull() && "no type from lambda declarator"); + EndLoc = ParamInfo.getSourceRange().getEnd(); + } + + // C++11 [expr.prim.lambda]p5: + // The closure type for a lambda-expression has a public inline function + // call operator (13.5.4) whose parameters and return type are described by + // the lambda-expression's parameter-declaration-clause and + // trailing-return-type respectively. + DeclarationName MethodName + = Context.DeclarationNames.getCXXOperatorName(OO_Call); + DeclarationNameLoc MethodNameLoc; + MethodNameLoc.CXXOperatorName.BeginOpNameLoc + = Intro.Range.getBegin().getRawEncoding(); + MethodNameLoc.CXXOperatorName.EndOpNameLoc + = Intro.Range.getEnd().getRawEncoding(); + CXXMethodDecl *Method + = CXXMethodDecl::Create(Context, Class, EndLoc, + DeclarationNameInfo(MethodName, + Intro.Range.getBegin(), + MethodNameLoc), + MethodTy, MethodTyInfo, + /*isStatic=*/false, + SC_None, + /*isInline=*/true, + /*isConstExpr=*/false, + EndLoc); + Method->setAccess(AS_public); + Class->addDecl(Method); + Method->setLexicalDeclContext(DC); // FIXME: Minor hack. + + ProcessDeclAttributes(CurScope, Method, ParamInfo); + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); + + PushDeclContext(CurScope, Method); + + // Introduce the lambda scope. + PushLambdaScope(Class, Method); + LambdaScopeInfo *LSI = getCurLambda(); + if (Intro.Default == LCD_ByCopy) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; + else if (Intro.Default == LCD_ByRef) + LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; + LSI->IntroducerRange = Intro.Range; + LSI->ExplicitParams = ExplicitParams; + LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0; + + // Handle explicit captures. + for (llvm::SmallVector::const_iterator + C = Intro.Captures.begin(), + E = Intro.Captures.end(); + C != E; ++C) { + if (C->Kind == LCK_This) { + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (LSI->isCXXThisCaptured()) { + Diag(C->Loc, diag::err_capture_more_than_once) + << "'this'" + << SourceRange(LSI->getCXXThisCapture().getLocation()); + continue; + } + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is =, the + // lambda-capture shall not contain this [...]. + if (Intro.Default == LCD_ByCopy) { + Diag(C->Loc, diag::err_this_capture_with_copy_default); + continue; + } + + // C++11 [expr.prim.lambda]p12: + // If this is captured by a local lambda expression, its nearest + // enclosing function shall be a non-static member function. + QualType ThisCaptureType = getCurrentThisType(); + if (ThisCaptureType.isNull()) { + Diag(C->Loc, diag::err_this_capture) << true; + continue; + } + + CheckCXXThisCapture(C->Loc, /*Explicit=*/true); + continue; + } + + assert(C->Id && "missing identifier for capture"); + + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is &, the + // identifiers in the lambda-capture shall not be preceded by &. + // If a lambda-capture includes a capture-default that is =, [...] + // each identifier it contains shall be preceded by &. + if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { + Diag(C->Loc, diag::err_reference_capture_with_reference_default); + continue; + } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { + Diag(C->Loc, diag::err_copy_capture_with_copy_default); + continue; + } + + DeclarationNameInfo Name(C->Id, C->Loc); + LookupResult R(*this, Name, LookupOrdinaryName); + LookupName(R, CurScope); + if (R.isAmbiguous()) + continue; + if (R.empty()) { + // FIXME: Disable corrections that would add qualification? + CXXScopeSpec ScopeSpec; + DeclFilterCCC Validator; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) + continue; + } + + // C++11 [expr.prim.lambda]p10: + // The identifiers in a capture-list are looked up using the usual rules + // for unqualified name lookup (3.4.1); each such lookup shall find a + // variable with automatic storage duration declared in the reaching + // scope of the local lambda expression. + // FIXME: Check reaching scope. + VarDecl *Var = R.getAsSingle(); + if (!Var) { + Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; + continue; + } + + if (!Var->hasLocalStorage()) { + Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; + Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; + continue; + } + + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (LSI->isCaptured(Var)) { + Diag(C->Loc, diag::err_capture_more_than_once) + << C->Id + << SourceRange(LSI->getCapture(Var).getLocation()); + continue; + } + + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + TryCaptureVar(Var, C->Loc, Kind); + } + LSI->finishedExplicitCaptures(); + + // Set the parameters on the decl, if specified. + if (isa(MethodTyInfo->getTypeLoc())) { + FunctionProtoTypeLoc Proto = + cast(MethodTyInfo->getTypeLoc()); + Method->setParams(Proto.getParams()); + CheckParmsForFunctionDef(Method->param_begin(), + Method->param_end(), + /*CheckParameterNames=*/false); + + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *Param = Method->getParamDecl(p); + Param->setOwningFunction(Method); + + // If this has an identifier, add it to the scope stack. + if (Param->getIdentifier()) { + CheckShadow(CurScope, Param); + + PushOnScopeChains(Param, CurScope); + } + } + } + + const FunctionType *Fn = MethodTy->getAs(); + QualType RetTy = Fn->getResultType(); + if (RetTy != Context.DependentTy) { + LSI->ReturnType = RetTy; + } else { + LSI->HasImplicitReturnType = true; + } + + // FIXME: Check return type is complete, !isObjCObjectType + +} + +void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Leave the context of the lambda. + PopDeclContext(); + PopFunctionScopeInfo(); +} + +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, + Stmt *Body, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // FIXME: End-of-lambda checking + + // Collect information from the lambda scope. + llvm::SmallVector Captures; + llvm::SmallVector CaptureInits; + LambdaCaptureDefault CaptureDefault; + CXXRecordDecl *Class; + SourceRange IntroducerRange; + bool ExplicitParams; + { + LambdaScopeInfo *LSI = getCurLambda(); + Class = LSI->Lambda; + IntroducerRange = LSI->IntroducerRange; + ExplicitParams = LSI->ExplicitParams; + + // Translate captures. + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { + LambdaScopeInfo::Capture From = LSI->Captures[I]; + assert(!From.isBlockCapture() && "Cannot capture __block variables"); + bool IsImplicit = I >= LSI->NumExplicitCaptures; + + // Handle 'this' capture. + if (From.isThisCapture()) { + Captures.push_back(LambdaExpr::Capture(From.getLocation(), + IsImplicit, + LCK_This)); + CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), + getCurrentThisType(), + /*isImplicit=*/true)); + continue; + } + + VarDecl *Var = From.getVariable(); + // FIXME: Handle pack expansions. + LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; + Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, + Kind, Var)); + CaptureInits.push_back(From.getCopyExpr()); + } + + switch (LSI->ImpCaptureStyle) { + case CapturingScopeInfo::ImpCap_None: + CaptureDefault = LCD_None; + break; + + case CapturingScopeInfo::ImpCap_LambdaByval: + CaptureDefault = LCD_ByCopy; + break; + + case CapturingScopeInfo::ImpCap_LambdaByref: + CaptureDefault = LCD_ByRef; + break; + + case CapturingScopeInfo::ImpCap_Block: + llvm_unreachable("block capture in lambda"); + break; + } + + // C++ [expr.prim.lambda]p7: + // The lambda-expression's compound-statement yields the + // function-body (8.4) of the function call operator [...]. + ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false); + } + + Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, + CaptureDefault, Captures, ExplicitParams, + CaptureInits, Body->getLocEnd()); + (void)Lambda; + Diag(StartLoc, diag::err_lambda_unsupported); + return ExprError(); +}