2012-02-09 05:18:48 +08:00
|
|
|
//===--- 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(),
|
2012-02-09 10:20:38 +08:00
|
|
|
/*IdLoc=*/Intro.Range.getBegin(),
|
2012-02-09 05:18:48 +08:00
|
|
|
/*Id=*/0);
|
|
|
|
Class->startDefinition();
|
2012-02-10 15:45:31 +08:00
|
|
|
Class->makeLambda();
|
2012-02-09 05:18:48 +08:00
|
|
|
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;
|
2012-02-10 17:58:53 +08:00
|
|
|
EPI.HasTrailingReturn = true;
|
2012-02-09 05:18:48 +08:00
|
|
|
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);
|
2012-02-10 16:36:38 +08:00
|
|
|
|
|
|
|
// Temporarily set the lexical declaration context to the current
|
|
|
|
// context, so that the Scope stack matches the lexical nesting.
|
|
|
|
Method->setLexicalDeclContext(DC);
|
2012-02-09 08:47:04 +08:00
|
|
|
|
|
|
|
// Attributes on the lambda apply to the method.
|
2012-02-09 05:18:48 +08:00
|
|
|
ProcessDeclAttributes(CurScope, Method, ParamInfo);
|
|
|
|
|
2012-02-09 08:47:04 +08:00
|
|
|
// Introduce the function call operator as the current declaration context.
|
2012-02-09 05:18:48 +08:00
|
|
|
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<LambdaCapture, 4>::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<VarDecl> 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<VarDecl>();
|
|
|
|
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<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
|
|
|
|
FunctionProtoTypeLoc Proto =
|
|
|
|
cast<FunctionProtoTypeLoc>(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<FunctionType>();
|
|
|
|
QualType RetTy = Fn->getResultType();
|
|
|
|
if (RetTy != Context.DependentTy) {
|
|
|
|
LSI->ReturnType = RetTy;
|
|
|
|
} else {
|
|
|
|
LSI->HasImplicitReturnType = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Check return type is complete, !isObjCObjectType
|
|
|
|
|
2012-02-09 08:47:04 +08:00
|
|
|
// Enter a new evaluation context to insulate the block from any
|
|
|
|
// cleanups from the enclosing full-expression.
|
|
|
|
PushExpressionEvaluationContext(PotentiallyEvaluated);
|
2012-02-09 05:18:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
|
|
|
|
// Leave the expression-evaluation context.
|
|
|
|
DiscardCleanupsInEvaluationContext();
|
|
|
|
PopExpressionEvaluationContext();
|
|
|
|
|
|
|
|
// Leave the context of the lambda.
|
|
|
|
PopDeclContext();
|
2012-02-09 09:28:42 +08:00
|
|
|
|
|
|
|
// Finalize the lambda.
|
|
|
|
LambdaScopeInfo *LSI = getCurLambda();
|
|
|
|
CXXRecordDecl *Class = LSI->Lambda;
|
|
|
|
Class->setInvalidDecl();
|
|
|
|
SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
|
|
|
|
ActOnFields(0, Class->getLocation(), Class, Fields,
|
|
|
|
SourceLocation(), SourceLocation(), 0);
|
|
|
|
CheckCompletedCXXClass(Class);
|
|
|
|
|
2012-02-09 05:18:48 +08:00
|
|
|
PopFunctionScopeInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
|
|
|
Stmt *Body, Scope *CurScope) {
|
|
|
|
// Leave the expression-evaluation context.
|
|
|
|
DiscardCleanupsInEvaluationContext();
|
|
|
|
PopExpressionEvaluationContext();
|
|
|
|
|
|
|
|
// Collect information from the lambda scope.
|
|
|
|
llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
|
|
|
|
llvm::SmallVector<Expr *, 4> CaptureInits;
|
|
|
|
LambdaCaptureDefault CaptureDefault;
|
|
|
|
CXXRecordDecl *Class;
|
2012-02-10 16:36:38 +08:00
|
|
|
CXXMethodDecl *CallOperator;
|
2012-02-09 05:18:48 +08:00
|
|
|
SourceRange IntroducerRange;
|
|
|
|
bool ExplicitParams;
|
2012-02-09 08:47:04 +08:00
|
|
|
bool LambdaExprNeedsCleanups;
|
2012-02-09 05:18:48 +08:00
|
|
|
{
|
|
|
|
LambdaScopeInfo *LSI = getCurLambda();
|
2012-02-10 16:36:38 +08:00
|
|
|
CallOperator = LSI->CallOperator;
|
2012-02-09 05:18:48 +08:00
|
|
|
Class = LSI->Lambda;
|
|
|
|
IntroducerRange = LSI->IntroducerRange;
|
|
|
|
ExplicitParams = LSI->ExplicitParams;
|
2012-02-09 08:47:04 +08:00
|
|
|
LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
|
2012-02-09 05:18:48 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2012-02-09 18:18:50 +08:00
|
|
|
// C++11 [expr.prim.lambda]p4:
|
|
|
|
// If a lambda-expression does not include a
|
|
|
|
// trailing-return-type, it is as if the trailing-return-type
|
|
|
|
// denotes the following type:
|
|
|
|
// FIXME: Assumes current resolution to core issue 975.
|
|
|
|
if (LSI->HasImplicitReturnType) {
|
|
|
|
// - if there are no return statements in the
|
|
|
|
// compound-statement, or all return statements return
|
|
|
|
// either an expression of type void or no expression or
|
|
|
|
// braced-init-list, the type void;
|
|
|
|
if (LSI->ReturnType.isNull()) {
|
|
|
|
LSI->ReturnType = Context.VoidTy;
|
|
|
|
} else {
|
|
|
|
// C++11 [expr.prim.lambda]p4:
|
|
|
|
// - if the compound-statement is of the form
|
|
|
|
//
|
|
|
|
// { attribute-specifier-seq[opt] return expression ; }
|
|
|
|
//
|
|
|
|
// the type of the returned expression after
|
|
|
|
// lvalue-to-rvalue conversion (4.1), array-to-pointer
|
|
|
|
// conver- sion (4.2), and function-to-pointer conversion
|
|
|
|
// (4.3);
|
|
|
|
//
|
|
|
|
// Since we're accepting the resolution to a post-C++11 core
|
|
|
|
// issue with a non-trivial extension, provide a warning (by
|
|
|
|
// default).
|
|
|
|
CompoundStmt *CompoundBody = cast<CompoundStmt>(Body);
|
|
|
|
if (!(CompoundBody->size() == 1 &&
|
|
|
|
isa<ReturnStmt>(*CompoundBody->body_begin())) &&
|
|
|
|
!Context.hasSameType(LSI->ReturnType, Context.VoidTy))
|
|
|
|
Diag(IntroducerRange.getBegin(),
|
|
|
|
diag::ext_lambda_implies_void_return);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a function type with the inferred return type.
|
|
|
|
const FunctionProtoType *Proto
|
|
|
|
= CallOperator->getType()->getAs<FunctionProtoType>();
|
|
|
|
QualType FunctionTy
|
|
|
|
= Context.getFunctionType(LSI->ReturnType,
|
|
|
|
Proto->arg_type_begin(),
|
|
|
|
Proto->getNumArgs(),
|
|
|
|
Proto->getExtProtoInfo());
|
|
|
|
CallOperator->setType(FunctionTy);
|
|
|
|
}
|
|
|
|
|
2012-02-09 08:47:04 +08:00
|
|
|
// Finalize the lambda class.
|
|
|
|
SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end());
|
|
|
|
ActOnFields(0, Class->getLocation(), Class, Fields,
|
|
|
|
SourceLocation(), SourceLocation(), 0);
|
|
|
|
CheckCompletedCXXClass(Class);
|
|
|
|
|
2012-02-09 05:18:48 +08:00
|
|
|
// C++ [expr.prim.lambda]p7:
|
|
|
|
// The lambda-expression's compound-statement yields the
|
|
|
|
// function-body (8.4) of the function call operator [...].
|
2012-02-09 16:52:43 +08:00
|
|
|
ActOnFinishFunctionBody(CallOperator, Body, /*IsInstantation=*/false);
|
|
|
|
CallOperator->setLexicalDeclContext(Class);
|
2012-02-09 05:18:48 +08:00
|
|
|
}
|
|
|
|
|
2012-02-09 08:47:04 +08:00
|
|
|
if (LambdaExprNeedsCleanups)
|
|
|
|
ExprNeedsCleanups = true;
|
|
|
|
|
2012-02-09 16:14:43 +08:00
|
|
|
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
|
|
|
|
CaptureDefault, Captures,
|
|
|
|
ExplicitParams, CaptureInits,
|
|
|
|
Body->getLocEnd());
|
2012-02-10 15:45:31 +08:00
|
|
|
Class->setLambda(Lambda);
|
2012-02-09 16:14:43 +08:00
|
|
|
|
|
|
|
// C++11 [expr.prim.lambda]p2:
|
|
|
|
// A lambda-expression shall not appear in an unevaluated operand
|
|
|
|
// (Clause 5).
|
|
|
|
switch (ExprEvalContexts.back().Context) {
|
|
|
|
case Unevaluated:
|
|
|
|
// We don't actually diagnose this case immediately, because we
|
|
|
|
// could be within a context where we might find out later that
|
|
|
|
// the expression is potentially evaluated (e.g., for typeid).
|
|
|
|
ExprEvalContexts.back().Lambdas.push_back(Lambda);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ConstantEvaluated:
|
|
|
|
case PotentiallyEvaluated:
|
|
|
|
case PotentiallyEvaluatedIfUsed:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-02-10 16:36:38 +08:00
|
|
|
// C++11 [expr.prim.lambda]p6:
|
|
|
|
// The closure type for a lambda-expression with no lambda-capture
|
|
|
|
// has a public non-virtual non-explicit const conversion function
|
|
|
|
// to pointer to function having the same parameter and return
|
|
|
|
// types as the closure type's function call operator.
|
|
|
|
if (Captures.empty() && CaptureDefault == LCD_None) {
|
|
|
|
const FunctionProtoType *Proto
|
|
|
|
= CallOperator->getType()->getAs<FunctionProtoType>();
|
|
|
|
QualType FunctionPtrTy;
|
|
|
|
{
|
|
|
|
FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
|
|
|
|
ExtInfo.TypeQuals = 0;
|
|
|
|
QualType FunctionTy
|
|
|
|
= Context.getFunctionType(Proto->getResultType(),
|
|
|
|
Proto->arg_type_begin(),
|
|
|
|
Proto->getNumArgs(),
|
|
|
|
ExtInfo);
|
|
|
|
FunctionPtrTy = Context.getPointerType(FunctionTy);
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionProtoType::ExtProtoInfo ExtInfo;
|
|
|
|
ExtInfo.TypeQuals = Qualifiers::Const;
|
|
|
|
QualType ConvTy = Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo);
|
|
|
|
|
|
|
|
SourceLocation Loc = IntroducerRange.getBegin();
|
|
|
|
DeclarationName Name
|
|
|
|
= Context.DeclarationNames.getCXXConversionFunctionName(
|
|
|
|
Context.getCanonicalType(FunctionPtrTy));
|
|
|
|
DeclarationNameLoc NameLoc;
|
|
|
|
NameLoc.NamedType.TInfo = Context.getTrivialTypeSourceInfo(FunctionPtrTy,
|
|
|
|
Loc);
|
|
|
|
CXXConversionDecl *Conversion
|
|
|
|
= CXXConversionDecl::Create(Context, Class, Loc,
|
|
|
|
DeclarationNameInfo(Name, Loc, NameLoc),
|
|
|
|
ConvTy,
|
|
|
|
Context.getTrivialTypeSourceInfo(ConvTy, Loc),
|
|
|
|
/*isInline=*/false, /*isExplicit=*/false,
|
|
|
|
/*isConstexpr=*/false, Body->getLocEnd());
|
|
|
|
Conversion->setAccess(AS_public);
|
|
|
|
Conversion->setImplicit(true);
|
|
|
|
Class->addDecl(Conversion);
|
|
|
|
}
|
|
|
|
|
2012-02-09 08:47:04 +08:00
|
|
|
return MaybeBindToTemporary(Lambda);
|
2012-02-09 05:18:48 +08:00
|
|
|
}
|