From db419a6f7c13393c2f1b2ed4b6ed4148839263d1 Mon Sep 17 00:00:00 2001 From: Gor Nishanov Date: Tue, 5 Sep 2017 19:31:52 +0000 Subject: [PATCH] [coroutines] Make sure auto return type of await_resume is properly handled Reviewers: rsmith, EricWF Reviewed By: rsmith Subscribers: javed.absar, cfe-commits Differential Revision: https://reviews.llvm.org/D37454 llvm-svn: 312565 --- clang/lib/Sema/SemaCoroutine.cpp | 4 ++-- clang/test/SemaCXX/coroutines.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index ae8744c07ba1..e6b640f878c2 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -438,14 +438,14 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, // - await-suspend is the expression e.await_suspend(h), which shall be // a prvalue of type void or bool. QualType RetType = AwaitSuspend->getCallReturnType(S.Context); + // Experimental support for coroutine_handle returning await_suspend. if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc)) Calls.Results[ACT::ACT_Suspend] = TailCallSuspend; else { // non-class prvalues always have cv-unqualified types - QualType AdjRetType = RetType.getUnqualifiedType(); if (RetType->isReferenceType() || - (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) { + (!RetType->isBooleanType() && !RetType->isVoidType())) { S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(), diag::err_await_suspend_invalid_return_type) << RetType; diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index 6394829f356a..65e17abb11fe 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -66,6 +66,12 @@ struct suspend_never { 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 @@ void yield() { co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}} } +void check_auto_await_suspend() { + co_await auto_await_suspend{}; // Should compile successfully. +} + void coreturn(int n) { co_await a; if (n == 0)