aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-08 21:18:48 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-08 21:18:48 +0000
commite2a7ad001fe1dc4a0d5fef312e7f7189e1f29369 (patch)
tree7d672c4818d335191785875f986f6ce4f2fa67cd /lib/Sema/SemaExprCXX.cpp
parent1e3767ac5449db6a1ede192d5e4217e34fa61f26 (diff)
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
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp330
1 files changed, 0 insertions, 330 deletions
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<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
-
-}
-
-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<LambdaExpr::Capture, 4> Captures;
- llvm::SmallVector<Expr *, 4> 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();
-}