Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -267,6 +267,8 @@ - Improved Cpp20 Modules support. +- Improved Coroutinues support. + libclang -------- Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1004,6 +1004,8 @@ if (CurrentToken && CurrentToken->is(Keywords.kw_await)) next(); } + if (Style.isCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await)) + next(); Contexts.back().ColonIsForRangeExpr = true; next(); if (!parseParens()) @@ -2952,6 +2954,13 @@ if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace)) return false; + // Coroutines + if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous && + Left.Previous->is(tok::kw_operator)) + return false; + if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) && + Right.isNot(tok::semi)) + return true; // requires clause Concept1 && Concept2 if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier)) return true; Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2399,6 +2399,8 @@ if (Style.Language == FormatStyle::LK_JavaScript && FormatTok->is(Keywords.kw_await)) nextToken(); + if (Style.isCpp() && FormatTok->is(tok::kw_co_await)) + nextToken(); if (FormatTok->Tok.is(tok::l_paren)) parseParens(); if (FormatTok->Tok.is(tok::l_brace)) { Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -22710,6 +22710,61 @@ verifyFormat("export", Style); } +TEST_F(FormatTest, CoRoutineawaitForRangeCpp11) { + FormatStyle Style = getLLVMStyle(); + verifyFormat("for co_await (auto x : range())\n ;"); + verifyFormat("for (auto i : arr) {\n" + "}", + Style); + verifyFormat("for co_await (auto i : arr) {\n" + "}", + Style); + verifyFormat("for co_await (auto i : foo(T{})) {\n" + "}", + Style); +} + +TEST_F(FormatTest, CoRoutineawait) { + verifyFormat("int x = co_await foo();"); + verifyFormat("int x = (co_await foo());"); + verifyFormat("co_await (42);"); + verifyFormat("void operator co_await(int);"); + verifyFormat("co_await a;"); + verifyFormat("co_await missing_await_resume{};"); + verifyFormat("co_await a; // comment"); + verifyFormat("void test0() { co_await a; }"); + verifyFormat("co_await co_await co_await foo();"); + verifyFormat("co_await foo().bar();"); + verifyFormat("co_await [this]() -> Task { co_return x; }"); + verifyFormat("co_await [this](int a, int b) -> Task { co_return co_await " + "foo(); }(x, y);"); + + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 40; + verifyFormat("co_await [this](int a, int b) -> Task {\n" + " co_return co_await foo();\n" + "}(x, y);", + Style); +} + +TEST_F(FormatTest, CoRoutineyield) { + verifyFormat("int x = co_yield foo();"); + verifyFormat("int x = (co_yield foo());"); + verifyFormat("co_yield (42);"); + verifyFormat("co_yield {42};"); + verifyFormat("co_yield 42;"); + verifyFormat("co_yield n++;"); +} + +TEST_F(FormatTest, CoRoutinereturn) { + verifyFormat("co_return (42);"); + verifyFormat("co_return;"); + verifyFormat("co_return {};"); + verifyFormat("co_return x;"); + verifyFormat("co_return co_await foo();"); + verifyFormat("co_return co_yield foo();"); +} + } // namespace } // namespace format } // namespace clang