Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -444,6 +444,9 @@ else { // non-class prvalues always have cv-unqualified types QualType AdjRetType = RetType.getUnqualifiedType(); + if (auto *AT = dyn_cast(AdjRetType)) + AdjRetType = AT->desugar(); + if (RetType->isReferenceType() || (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) { S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(), Index: test/SemaCXX/coroutines.cpp =================================================================== --- test/SemaCXX/coroutines.cpp +++ test/SemaCXX/coroutines.cpp @@ -66,6 +66,12 @@ void await_resume() {} }; +struct auto_await_suspend { + bool await_ready(); + template auto await_suspend(F) {} + void await_resume(); +}; + struct DummyVoidTag {}; DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits' has no member named 'promise_type'}} co_await a; @@ -159,6 +165,10 @@ co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}} } +void check_auto_await_suspend() { + co_await auto_await_suspend{}; // OK +} + void coreturn(int n) { co_await a; if (n == 0)