diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-10-22 04:46:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-10-22 04:46:14 +0000 |
commit | 0e304ea8a1a49f3c4443c335de448f667c43af1b (patch) | |
tree | e7d3e8654ce52c22e32c56236f4d6529be3af635 /clang/lib/Parse | |
parent | 629aaaf143743c183babcd2c03227cbbd8b6104b (diff) | |
download | bcm5719-llvm-0e304ea8a1a49f3c4443c335de448f667c43af1b.tar.gz bcm5719-llvm-0e304ea8a1a49f3c4443c335de448f667c43af1b.zip |
[coroutines] Add parsing support for co_await expression, co_yield expression,
co_await modifier on range-based for loop, co_return statement.
llvm-svn: 250985
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 32 |
3 files changed, 54 insertions, 3 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 52690470f24..ec1edbcde2f 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -163,6 +163,8 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); + if (Tok.is(tok::kw_co_yield)) + return ParseCoyieldExpression(); ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, @@ -522,6 +524,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// postfix-expression /// '++' unary-expression /// '--' unary-expression +/// [Coro] 'co_await' cast-expression /// unary-operator cast-expression /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' @@ -1041,6 +1044,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Res; } + case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression + SourceLocation SavedLoc = ConsumeToken(); + Res = ParseCastExpression(false); + (void)SavedLoc; + // FIXME: Pass to Sema. + return Res; + } + case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 2bf4cba7984..c3df77300ca 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1558,6 +1558,20 @@ ExprResult Parser::ParseThrowExpression() { } } +/// \brief Parse the C++ Coroutines co_yield expression. +/// +/// co_yield-expression: +/// 'co_yield' assignment-expression[opt] +ExprResult Parser::ParseCoyieldExpression() { + assert(Tok.is(tok::kw_co_yield) && "Not co_yield!"); + + SourceLocation Loc = ConsumeToken(); + ExprResult Expr = ParseAssignmentExpression(); + (void)Loc; + // FIXME: Pass to Sema. + return Expr; +} + /// ParseCXXThis - This handles the C++ 'this' pointer. /// /// C++ 9.3.2: In the body of a non-static member function, the keyword this is diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 312c5e6f511..6ea8f4ec891 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -259,6 +259,10 @@ Retry: Res = ParseReturnStatement(); SemiError = "return"; break; + case tok::kw_co_return: // C++ Coroutines: co_return statement + Res = ParseReturnStatement(); + SemiError = "co_return"; + break; case tok::kw_asm: { ProhibitAttributes(Attrs); @@ -1443,7 +1447,10 @@ bool Parser::isForRangeIdentifier() { /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')' /// [C++] statement -/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement +/// [C++0x] 'for' +/// 'co_await'[opt] [Coroutines] +/// '(' for-range-declaration ':' for-range-initializer ')' +/// statement /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement /// [OBJC2] 'for' '(' expr 'in' expr ')' statement /// @@ -1460,6 +1467,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { assert(Tok.is(tok::kw_for) && "Not a for stmt!"); SourceLocation ForLoc = ConsumeToken(); // eat the 'for'. + SourceLocation CoawaitLoc; + if (Tok.is(tok::kw_co_await)) + CoawaitLoc = ConsumeToken(); + if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "for"; SkipUntil(tok::semi); @@ -1666,6 +1677,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Match the ')'. T.consumeClose(); + // C++ Coroutines [stmt.iter]: + // 'co_await' can only be used for a range-based for statement. + if (CoawaitLoc.isValid() && !ForRange) { + Diag(CoawaitLoc, diag::err_for_co_await_not_range_for); + CoawaitLoc = SourceLocation(); + } + // We need to perform most of the semantic analysis for a C++0x for-range // statememt before parsing the body, in order to be able to deduce the type // of an auto-typed loop variable. @@ -1673,6 +1691,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForEachStmt; if (ForRange) { + // FIXME: Pass CoawaitLoc to Sema. ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), @@ -1800,13 +1819,19 @@ StmtResult Parser::ParseBreakStatement() { /// ParseReturnStatement /// jump-statement: /// 'return' expression[opt] ';' +/// 'return' braced-init-list ';' +/// 'co_return' expression[opt] ';' +/// 'co_return' braced-init-list ';' StmtResult Parser::ParseReturnStatement() { - assert(Tok.is(tok::kw_return) && "Not a return stmt!"); + assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) && + "Not a return stmt!"); + bool IsCoreturn = Tok.is(tok::kw_co_return); SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'. ExprResult R; if (Tok.isNot(tok::semi)) { - if (Tok.is(tok::code_completion)) { + // FIXME: Code completion for co_return. + if (Tok.is(tok::code_completion) && !IsCoreturn) { Actions.CodeCompleteReturn(getCurScope()); cutOffParsing(); return StmtError(); @@ -1826,6 +1851,7 @@ StmtResult Parser::ParseReturnStatement() { return StmtError(); } } + // FIXME: Pass IsCoreturn to Sema. return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } |