Index: clang/lib/Sema/SemaCoroutine.cpp =================================================================== --- clang/lib/Sema/SemaCoroutine.cpp +++ clang/lib/Sema/SemaCoroutine.cpp @@ -978,6 +978,11 @@ } VarDecl *Promise = FSI->CoroutinePromise; + if ((E && E->getType()->isDependentType()) || + Promise->getType()->isDependentType()) + // It is dependent, do nothing until instantiation time. + return new (Context) CoreturnStmt(Loc, E, nullptr, IsImplicit); + ExprResult PC; if (E && (isa(E) || !E->getType()->isVoidType())) { getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn); @@ -991,8 +996,7 @@ Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); - Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); - return Res; + return new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); } /// Look up the std::nothrow object. Index: clang/test/SemaCXX/coroutine-dependent.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/coroutine-dependent.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++17 -fcoroutines-ts -fsyntax-only %s -verify +// RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify +// expected-no-diagnostics + +#include "Inputs/std-coroutine.h" + +// Dependent return that ends up void +namespace Void { +struct Task { + struct promise_type { + std::suspend_always initial_suspend() noexcept; + std::suspend_always final_suspend() noexcept; + + Task get_return_object() noexcept; + void unhandled_exception() noexcept; + void return_void() noexcept; + }; +}; + +template +Task Foo() noexcept { + co_return T(0); +} +template Task Foo() noexcept; +} // namespace Void + +// Dependent return that ends up non-void +namespace Value { +struct Task { + struct promise_type { + std::suspend_always initial_suspend() noexcept; + std::suspend_always final_suspend() noexcept; + + Task get_return_object() noexcept; + void unhandled_exception() noexcept; + void return_value(int value) noexcept; + }; +}; + +template +Task Foo() noexcept { + co_return T(0); +} +template Task Foo() noexcept; +} // namespace Value