Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -8562,6 +8562,8 @@ "'%1' cannot be used in a %select{constructor|destructor}0">; def err_coroutine_constexpr : Error< "'%0' cannot be used in a constexpr function">; +def err_coroutine_main : Error< + "'main' cannot be a coroutine">; def err_coroutine_varargs : Error< "'%0' cannot be used in a varargs function">; def ext_coroutine_without_co_await_co_yield : ExtWarn< Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -127,6 +127,11 @@ S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword; } else if (FD->isVariadic()) { S.Diag(Loc, diag::err_coroutine_varargs) << Keyword; + } else if (FD->isMain()) { + S.Diag(FD->getLocStart(), diag::err_coroutine_main); + S.Diag(Loc, diag::note_declared_coroutine_here) + << (Keyword == "co_await" ? 0 : + Keyword == "co_yield" ? 1 : 2); } else { auto *ScopeInfo = S.getCurFunction(); assert(ScopeInfo && "missing function scope for function"); Index: test/SemaCXX/coroutines.cpp =================================================================== --- test/SemaCXX/coroutines.cpp +++ test/SemaCXX/coroutines.cpp @@ -283,3 +283,11 @@ coro bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} co_await a; } + + +template<> struct std::coroutine_traits +{ using promise_type = promise; }; + +int main(int, const char**) { // expected-error {{'main' cannot be a coroutine}} + co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} +}