r250985 - [coroutines] Add parsing support for co_await expression, co_yield expression,

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 21 21:46:15 PDT 2015


Author: rsmith
Date: Wed Oct 21 23:46:14 2015
New Revision: 250985

URL: http://llvm.org/viewvc/llvm-project?rev=250985&view=rev
Log:
[coroutines] Add parsing support for co_await expression, co_yield expression,
co_await modifier on range-based for loop, co_return statement.

Added:
    cfe/trunk/test/Parser/cxx1z-coroutines.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=250985&r1=250984&r2=250985&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Oct 21 23:46:14 2015
@@ -1028,4 +1028,9 @@ def err_objc_type_args_after_protocols :
   "protocol qualifiers must precede type arguments">;
 }
 
+let CategoryName = "Coroutines Issue" in {
+def err_for_co_await_not_range_for : Error<
+  "'co_await' modifier can only be applied to range-based for loop">;
+}
+
 } // end of Parser diagnostics

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=250985&r1=250984&r2=250985&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Oct 21 23:46:14 2015
@@ -1580,7 +1580,9 @@ private:
                          SourceLocation Loc, bool ConvertToBoolean);
 
   //===--------------------------------------------------------------------===//
-  // C++ types
+  // C++ Coroutines
+
+  ExprResult ParseCoyieldExpression();
 
   //===--------------------------------------------------------------------===//
   // C99 6.7.8: Initialization.

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=250985&r1=250984&r2=250985&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Oct 21 23:46:14 2015
@@ -163,6 +163,8 @@ ExprResult Parser::ParseAssignmentExpres
 
   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
 ///         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(b
     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.

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=250985&r1=250984&r2=250985&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Oct 21 23:46:14 2015
@@ -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

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=250985&r1=250984&r2=250985&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Wed Oct 21 23:46:14 2015
@@ -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(Sou
   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(Sou
   // 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(Sou
   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());
 }
 

Added: cfe/trunk/test/Parser/cxx1z-coroutines.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx1z-coroutines.cpp?rev=250985&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx1z-coroutines.cpp (added)
+++ cfe/trunk/test/Parser/cxx1z-coroutines.cpp Wed Oct 21 23:46:14 2015
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++11 -fcoroutines %s -verify
+
+template<typename T, typename U>
+U f(T t) {
+  co_await t;
+  co_yield t;
+
+  1 + co_await t;
+  1 + co_yield t; // expected-error {{expected expression}}
+
+  auto x = co_await t;
+  auto y = co_yield t;
+
+  for co_await (int x : t) {}
+  for co_await (int x = 0; x != 10; ++x) {} // expected-error {{'co_await' modifier can only be applied to range-based for loop}}
+
+  if (t)
+    co_return t;
+  else
+    co_return {t};
+}




More information about the cfe-commits mailing list