/// Look up the std::experimental::coroutine_handle<PromiseType>. static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc) { if (PromiseType.isNull()) return QualType(); NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); assert(StdExp && "Should already be diagnosed"); LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, StdExp)) { S.Diag(Loc, diag::err_implied_coroutine_type_not_found) << "std::experimental::coroutine_handle"; return QualType(); } ClassTemplateDecl *CoroHandle = Result.getAsSingle<ClassTemplateDecl>(); if (!CoroHandle) { 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_handle); return QualType(); } // Form template argument list for coroutine_handle<Promise>. TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(TemplateArgumentLoc( TemplateArgument(PromiseType), S.Context.getTrivialTypeSourceInfo(PromiseType, Loc))); // Build the template-id. QualType CoroHandleType = S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args); if (CoroHandleType.isNull()) return QualType(); if (S.RequireCompleteType(Loc, CoroHandleType, diag::err_coroutine_type_missing_specialization)) return QualType(); return CoroHandleType; }
/// Look up the std::coroutine_traits<...>::promise_type for the given /// function type. static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType, SourceLocation KwLoc, SourceLocation FuncLoc) { // FIXME: Cache std::coroutine_traits once we've found it. NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace(); if (!StdExp) { S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) << "std::experimental::coroutine_traits"; return QualType(); } LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"), FuncLoc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, StdExp)) { S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found) << "std::experimental::coroutine_traits"; 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(KwLoc, KwLoc); Args.addArgument(TemplateArgumentLoc( TemplateArgument(FnType->getReturnType()), S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), KwLoc))); // 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, KwLoc))); // Build the template-id. QualType CoroTrait = S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); if (CoroTrait.isNull()) return QualType(); if (S.RequireCompleteType(KwLoc, CoroTrait, diag::err_coroutine_type_missing_specialization)) return QualType(); auto *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"), KwLoc, Sema::LookupOrdinaryName); S.LookupQualifiedName(R, RD); auto *Promise = R.getAsSingle<TypeDecl>(); if (!Promise) { S.Diag(FuncLoc, 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); auto buildElaboratedType = [&]() { auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp); NNS = NestedNameSpecifier::Create(S.Context, NNS, false, CoroTrait.getTypePtr()); return S.Context.getElaboratedType(ETK_None, NNS, PromiseType); }; if (!PromiseType->getAsCXXRecordDecl()) { S.Diag(FuncLoc, diag::err_implied_std_coroutine_traits_promise_type_not_class) << buildElaboratedType(); return QualType(); } if (S.RequireCompleteType(FuncLoc, buildElaboratedType(), diag::err_coroutine_promise_type_incomplete)) return QualType(); return PromiseType; }