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}; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits