// that may fail.
ScopeInfo->setNeedsCoroutineSuspends(false);
- // The new CoroutinePromise object needs to be built and put into the current
- // FunctionScopeInfo before any transformations or rebuilding occurs.
+ // We re-build the coroutine promise object (and the coroutine parameters its
+ // type and constructor depend on) based on the types used in our current
+ // function. We must do so, and set it on the current FunctionScopeInfo,
+ // before attempting to transform the other parts of the coroutine body
+ // statement, such as the implicit suspend statements (because those
+ // statements reference the FunctionScopeInfo::CoroutinePromise).
if (!SemaRef.buildCoroutineParameterMoves(FD->getLocation()))
return StmtError();
auto *Promise = SemaRef.buildCoroutinePromise(FD->getLocation());
getDerived().transformedLocalDecl(S->getPromiseDecl(), {Promise});
ScopeInfo->CoroutinePromise = Promise;
- // Transform the implicit coroutine statements we built during the initial
- // parse.
+ // Transform the implicit coroutine statements constructed using dependent
+ // types during the previous parse: initial and final suspensions, the return
+ // object, and others. We also transform the coroutine function's body.
StmtResult InitSuspend = getDerived().TransformStmt(S->getInitSuspendStmt());
if (InitSuspend.isInvalid())
return StmtError();
return StmtError();
Builder.ReturnValue = Res.get();
+ // If during the previous parse the coroutine still had a dependent promise
+ // statement, we may need to build some implicit coroutine statements
+ // (such as exception and fallthrough handlers) for the first time.
if (S->hasDependentPromiseType()) {
- // PR41909: We may find a generic coroutine lambda definition within a
- // template function that is being instantiated. In this case, the lambda
- // will have a dependent promise type, until it is used in an expression
- // that creates an instantiation with a non-dependent promise type. We
- // should not assert or build coroutine dependent statements for such a
- // generic lambda.
- auto *MD = dyn_cast_or_null<CXXMethodDecl>(FD);
- if (!MD || !MD->getParent()->isGenericLambda()) {
- assert(!Promise->getType()->isDependentType() &&
- "the promise type must no longer be dependent");
+ // We can only build these statements, however, if the current promise type
+ // is not dependent.
+ if (!Promise->getType()->isDependentType()) {
assert(!S->getFallthroughHandler() && !S->getExceptionHandler() &&
!S->getReturnStmtOnAllocFailure() && !S->getDeallocate() &&
"these nodes should not have been built yet");