/// Look up the std::coroutine_traits<...>::promise_type for the given /// function type. static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, SourceLocation Loc) { // FIXME: Cache std::coroutine_traits once we've found it. NamespaceDecl *Std = S.getStdNamespace(); if (!Std) { S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found); return QualType(); } LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, Std)) { S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found); return QualType(); } ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>(); if (!CoroTraits) { Result.suppressDiagnostics(); // We found something weird. Complain about the first thing we found. NamedDecl *Found = *Result.begin(); S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); return QualType(); } // Form template argument list for coroutine_traits<R, P1, P2, ...>. TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(TemplateArgumentLoc( TemplateArgument(FnType->getReturnType()), S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc))); // FIXME: If the function is a non-static member function, add the type // of the implicit object parameter before the formal parameters. for (QualType T : FnType->getParamTypes()) Args.addArgument(TemplateArgumentLoc( TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc))); // Build the template-id. QualType CoroTrait = S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args); if (CoroTrait.isNull()) return QualType(); if (S.RequireCompleteType(Loc, CoroTrait, diag::err_coroutine_traits_missing_specialization)) return QualType(); CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl(); assert(RD && "specialization of class template is not a class?"); // Look up the ::promise_type member. LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc, Sema::LookupOrdinaryName); S.LookupQualifiedName(R, RD); auto *Promise = R.getAsSingle<TypeDecl>(); if (!Promise) { S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found) << RD; return QualType(); } // The promise type is required to be a class type. QualType PromiseType = S.Context.getTypeDeclType(Promise); if (!PromiseType->getAsCXXRecordDecl()) { // Use the fully-qualified name of the type. auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std); NNS = NestedNameSpecifier::Create(S.Context, NNS, false, CoroTrait.getTypePtr()); PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType); S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class) << PromiseType; return QualType(); } return PromiseType; }