Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -824,6 +824,10 @@ /// \. ClassTemplateDecl *StdInitializerList; + /// The C++ "std::coroutine_traits" template, which is defined in + /// \ + ClassTemplateDecl *StdCoroutineTraitsCache; + /// The C++ "type_info" declaration, which is defined in \. RecordDecl *CXXTypeInfoDecl; @@ -8536,6 +8540,8 @@ bool buildCoroutineParameterMoves(SourceLocation Loc); VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc); //===--------------------------------------------------------------------===// // OpenCL extensions. Index: cfe/trunk/lib/Sema/Sema.cpp =================================================================== --- cfe/trunk/lib/Sema/Sema.cpp +++ cfe/trunk/lib/Sema/Sema.cpp @@ -131,9 +131,9 @@ IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), - NSValueDecl(nullptr), NSStringDecl(nullptr), - StringWithUTF8StringMethod(nullptr), + StdCoroutineTraitsCache(nullptr), CXXTypeInfoDecl(nullptr), + MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSValueDecl(nullptr), + NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), Index: cfe/trunk/lib/Sema/SemaCoroutine.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaCoroutine.cpp +++ cfe/trunk/lib/Sema/SemaCoroutine.cpp @@ -60,20 +60,8 @@ 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 *CoroTraits = S.lookupCoroutineTraits(KwLoc, FuncLoc); 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(); } @@ -1538,3 +1526,27 @@ return StmtError(); return Res; } + +ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc) { + if (!StdCoroutineTraitsCache) { + if (auto StdExp = lookupStdExperimentalNamespace()) { + LookupResult Result(*this, + &PP.getIdentifierTable().get("coroutine_traits"), + FuncLoc, LookupOrdinaryName); + if (!LookupQualifiedName(Result, StdExp)) { + Diag(KwLoc, diag::err_implied_coroutine_type_not_found) + << "std::experimental::coroutine_traits"; + return nullptr; + } + if (!(StdCoroutineTraitsCache = + Result.getAsSingle())) { + Result.suppressDiagnostics(); + NamedDecl *Found = *Result.begin(); + Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits); + return nullptr; + } + } + } + return StdCoroutineTraitsCache; +}