[clang] d4de2a4 - [clang][NFC] Refactor coroutine_traits lookup

Nathan Sidwell via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 21 07:29:18 PST 2021


Author: Nathan Sidwell
Date: 2021-12-21T10:29:01-05:00
New Revision: d4de2a4d5905beb0602a615593daf003378ddb64

URL: https://github.com/llvm/llvm-project/commit/d4de2a4d5905beb0602a615593daf003378ddb64
DIFF: https://github.com/llvm/llvm-project/commit/d4de2a4d5905beb0602a615593daf003378ddb64.diff

LOG: [clang][NFC] Refactor coroutine_traits lookup

To allow transition from the TS-specified
std::experimental::coroutine_traits to the C++20-specified
std::coroutine_traits, we lookup in both places and provide helpful
diagnostics. This refactors the code to avoid separate paths to
std::experimental lookups.

Reviewed By: ChuanqiXu

Differential Revision: https://reviews.llvm.org/D116029

Added: 
    

Modified: 
    clang/lib/Sema/SemaCoroutine.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index d4a919e8c1656..27ba49fb001c0 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1661,45 +1661,53 @@ ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
                                                SourceLocation FuncLoc,
                                                NamespaceDecl *&Namespace) {
   if (!StdCoroutineTraitsCache) {
-    NamespaceDecl *CoroNamespace = getStdNamespace();
-    LookupResult Result(*this, &PP.getIdentifierTable().get("coroutine_traits"),
-                        FuncLoc, LookupOrdinaryName);
-
-    if (!CoroNamespace || !LookupQualifiedName(Result, CoroNamespace)) {
-      /// Look up in namespace std::experimental, for compatibility.
-      /// TODO: Remove this extra lookup when <experimental/coroutine> is
-      /// removed.
-      CoroNamespace = lookupStdExperimentalNamespace();
-      if (!CoroNamespace || !LookupQualifiedName(Result, CoroNamespace)) {
-        Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
-            << "std::coroutine_traits";
-        return nullptr;
-      }
+    // Because coroutines moved from std::experimental in the TS to std in
+    // C++20, we look in both places to give users time to transition their
+    // TS-specific code to C++20.  Diagnostics are given when the TS usage is
+    // discovered.
+    // TODO: Become stricter when <experimental/coroutine> is removed.
+
+    auto const &TraitIdent = PP.getIdentifierTable().get("coroutine_traits");
+
+    NamespaceDecl *StdSpace = getStdNamespace();
+    LookupResult ResStd(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
+    bool InStd = StdSpace && LookupQualifiedName(ResStd, StdSpace);
+
+    NamespaceDecl *ExpSpace = lookupStdExperimentalNamespace();
+    LookupResult ResExp(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
+    bool InExp = ExpSpace && LookupQualifiedName(ResExp, ExpSpace);
+
+    if (!InStd && !InExp) {
+      // The goggles, they found nothing!
+      Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
+          << "std::coroutine_traits";
+      return nullptr;
+    }
+
+    if (!InStd) {
+      // Found only in std::experimental.
       Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
           << "coroutine_traits";
-    } else {
-      /// When we found coroutine_traits in std namespace. Make sure there is no
-      /// misleading definition in std::experimental namespace.
-      NamespaceDecl *ExpNamespace = lookupStdExperimentalNamespace();
-      LookupResult ExpResult(*this,
-                             &PP.getIdentifierTable().get("coroutine_traits"),
-                             FuncLoc, LookupOrdinaryName);
-      if (ExpNamespace && LookupQualifiedName(ExpResult, ExpNamespace)) {
-        Diag(KwLoc,
-             diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
-        Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
-            << "coroutine_traits";
-        return nullptr;
-      }
+    } else if (InExp) {
+      // Found in std and std::experimental.
+      Diag(KwLoc,
+           diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
+      Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
+          << "coroutine_traits";
+      return nullptr;
     }
 
+    // Prefer ::std to std::experimental.
+    auto &Result = InStd ? ResStd : ResExp;
+    CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
+
+    // coroutine_traits is required to be a class template.
     if (!(StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>())) {
       Result.suppressDiagnostics();
       NamedDecl *Found = *Result.begin();
       Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
       return nullptr;
     }
-    CoroTraitsNamespaceCache = CoroNamespace;
   }
   Namespace = CoroTraitsNamespaceCache;
   return StdCoroutineTraitsCache;


        


More information about the cfe-commits mailing list