diff options
author | Steve Naroff <snaroff@apple.com> | 2008-08-28 19:20:44 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2008-08-28 19:20:44 +0000 |
commit | 296e8d5fdcf9946f51e866adc8d281379e51efe9 (patch) | |
tree | daaa761eb0b9625ff204cc4c950692074f2a729f /lib/Parse/ParseExpr.cpp | |
parent | 982e674e39b8022ff7dc020f9ed371f3904549c3 (diff) |
Add parser/action support for block literal expressions.
Parser support for blocks is almost complete...just need to add support for the __block() storage class qualifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55495 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d4b46982ac..b532078d40 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -21,6 +21,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Scope.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallString.h" @@ -380,6 +381,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) { /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'this' [C++ 9.3.2] +/// [clang] '^' block-literal /// /// constant: [C99 6.4.4] /// integer-constant @@ -595,6 +597,11 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { if (getLang().ObjC1) return ParsePostfixExpressionSuffix(ParseObjCMessageExpression()); // FALL THROUGH. + case tok::caret: + if (getLang().Blocks) + return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression()); + Diag(Tok, diag::err_expected_expression); + return ExprResult(true); default: UnhandledToken: Diag(Tok, diag::err_expected_expression); @@ -1068,3 +1075,74 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs) { CommaLocs.push_back(ConsumeToken()); } } + +/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks +/// like ^(int x){ return x+1; } or ^(int y)foo(4, y, z) +/// +/// block-literal: +/// [clang] '^' block-args[opt] compound-statement +/// [clang] '^' block-args cast-expression +/// [clang] block-args: +/// [clang] '(' parameter-list ')' +/// +Parser::ExprResult Parser::ParseBlockLiteralExpression() { + assert(Tok.is(tok::caret) && "block literal starts with ^"); + SourceLocation CaretLoc = ConsumeToken(); + + // Enter a scope to hold everything within the block. This includes the + // argument decls, decls within the compound expression, etc. This also + // allows determining whether a variable reference inside the block is + // within or outside of the block. + EnterScope(Scope::BlockScope|Scope::FnScope|Scope::BreakScope| + Scope::ContinueScope|Scope::DeclScope); + + // Parse the return type if present. + DeclSpec DS; + Declarator ParamInfo(DS, Declarator::PrototypeContext); + + // If this block has arguments, parse them. There is no ambiguity here with + // the expression case, because the expression case requires a parameter list. + if (Tok.is(tok::l_paren)) { + ParseParenDeclarator(ParamInfo); + // Parse the pieces after the identifier as if we had "int(...)". + ParamInfo.SetIdentifier(0, CaretLoc); + if (ParamInfo.getInvalidType()) { + // If there was an error parsing the arguments, they may have tried to use + // ^(x+y) which requires an argument list. Just skip the whole block + // literal. + ExitScope(); + return true; + } + } else { + // Otherwise, pretend we saw (void). + ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, + 0, 0, CaretLoc)); + } + + // Inform sema that we are starting a block. + Actions.ActOnBlockStart(CaretLoc, CurScope, ParamInfo); + + ExprResult Result; + if (Tok.is(tok::l_brace)) { + StmtResult Stmt = ParseCompoundStatementBody(); + if (!Stmt.isInvalid) { + Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.Val, CurScope); + } else { + Actions.ActOnBlockError(CaretLoc, CurScope); + Result = true; + } + } else { + ExprResult Expr = ParseCastExpression(false); + if (!Expr.isInvalid) { + Result = Actions.ActOnBlockExprExpr(CaretLoc, Expr.Val, CurScope); + } else { + Actions.ActOnBlockError(CaretLoc, CurScope); + Diag(Tok, diag::err_expected_block_lbrace); + Result = true; + } + } + + ExitScope(); + return Result; +} + |