diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-04 02:40:39 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-04 02:40:39 +0000 |
commit | dc3b723d35067e5d13474247b94a10c869cc7e58 (patch) | |
tree | ff854188e2a842098addbad74dd52dde0987ac30 /lib | |
parent | 4cd55b04e37d2c2c078be8d55c767213af8cc4ef (diff) |
Stub out the Sema interface for lambda expressions, and change the parser to use it. Unconditionally error on lambda expressions because they don't work in any meaningful way yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147515 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 59 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 35 |
3 files changed, 83 insertions, 18 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 0dd48a2946..7eac984172 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1132,8 +1132,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::l_square: if (getLang().CPlusPlus0x) { if (getLang().ObjC1) { + // C++11 lambda expressions and Objective-C message sends both start with a + // square bracket. There are three possibilities here: + // we have a valid lambda expression, we have an invalid lambda + // expression, or we have something that doesn't appear to be a lambda. + // If we're in the last case, we fall back to ParseObjCMessageExpression. Res = TryParseLambdaExpression(); - if (Res.isInvalid()) + if (!Res.isInvalid() && !Res.get()) Res = ParseObjCMessageExpression(); break; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index bd97fcee7c..901a537f5e 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/Basic/PrettyStackTrace.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" @@ -563,6 +564,9 @@ ExprResult Parser::ParseLambdaExpression() { if (DiagID) { Diag(Tok, DiagID.getValue()); SkipUntil(tok::r_square); + SkipUntil(tok::l_brace); + SkipUntil(tok::r_brace); + return ExprError(); } return ParseLambdaExpressionAfterIntroducer(Intro); @@ -591,14 +595,21 @@ ExprResult Parser::TryParseLambdaExpression() { return ParseLambdaExpression(); } - // If lookahead indicates this is an Objective-C message... + // If lookahead indicates an ObjC message send... + // [identifier identifier if (Next.is(tok::identifier) && After.is(tok::identifier)) { - return ExprError(); + return ExprEmpty(); } + // Here, we're stuck: lambda introducers and Objective-C message sends are + // unambiguous, but it requires arbitrary lookhead. [a,b,c,d,e,f,g] is a + // lambda, and [a,b,c,d,e,f,g h] is a Objective-C message send. Instead of + // writing two routines to parse a lambda introducer, just try to parse + // a lambda introducer first, and fall back if that fails. + // (TryParseLambdaIntroducer never produces any diagnostic output.) LambdaIntroducer Intro; if (TryParseLambdaIntroducer(Intro)) - return ExprError(); + return ExprEmpty(); return ParseLambdaExpressionAfterIntroducer(Intro); } @@ -694,11 +705,17 @@ bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) { /// expression. ExprResult Parser::ParseLambdaExpressionAfterIntroducer( LambdaIntroducer &Intro) { - Diag(Intro.Range.getBegin(), diag::warn_cxx98_compat_lambda); + SourceLocation LambdaBeginLoc = Intro.Range.getBegin(); + Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda); + + PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, + "lambda expression parsing"); + + Actions.ActOnLambdaStart(LambdaBeginLoc, getCurScope()); // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, Declarator::PrototypeContext); + Declarator D(DS, Declarator::BlockLiteralContext); if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, @@ -775,24 +792,32 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); + + // Inform sema that we are starting a block. + Actions.ActOnLambdaArguments(D, getCurScope()); } // Parse compound-statement. - if (Tok.is(tok::l_brace)) { - // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using - // it. - ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | - Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope); - - ParseCompoundStatementBody(); - - BodyScope.Exit(); - } else { + if (!Tok.is(tok::l_brace)) { Diag(Tok, diag::err_expected_lambda_body); + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); + return ExprError(); } - return ExprEmpty(); + // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using + // it. + ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | + Scope::BreakScope | Scope::ContinueScope | + Scope::DeclScope); + StmtResult Stmt(ParseCompoundStatementBody()); + BodyScope.Exit(); + + if (!Stmt.isInvalid()) + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), + getCurScope()); + + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); + return ExprError(); } /// ParseCXXCasts - This handles the various ways to cast expressions to another diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index eaa330b183..67e1c2fb09 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4774,3 +4774,38 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); } +//===----------------------------------------------------------------------===// +// Lambdas. +//===----------------------------------------------------------------------===// + +void Sema::ActOnLambdaStart(SourceLocation StartLoc, Scope *CurScope) { + // FIXME: Add lambda-scope + // FIXME: Build lambda-decl + // FIXME: PushDeclContext + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); +} + +void Sema::ActOnLambdaArguments(Declarator &ParamInfo, Scope *CurScope) { + // FIXME: Implement +} + +void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Leave the context of the lambda. + // FIXME: PopDeclContext + // FIXME: Pop lambda-scope +} + +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, + Stmt *Body, Scope *CurScope) { + // FIXME: Implement + Diag(StartLoc, diag::err_lambda_unsupported); + ActOnLambdaError(StartLoc, CurScope); + return ExprError(); +} |