- //===- ComparisonCategories.h - Three Way Comparison Data -------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- //  This file defines the Comparison Category enum and data types, which 
- //  store the types and expressions needed to support operator<=> 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H 
- #define LLVM_CLANG_AST_COMPARISONCATEGORIES_H 
-   
- #include "clang/Basic/LLVM.h" 
- #include "llvm/ADT/APSInt.h" 
- #include "llvm/ADT/DenseMap.h" 
- #include <array> 
- #include <cassert> 
- #include <optional> 
- #include <vector> 
-   
- namespace llvm { 
-   class StringRef; 
-   class APSInt; 
- } 
-   
- namespace clang { 
-   
- class ASTContext; 
- class VarDecl; 
- class CXXRecordDecl; 
- class Sema; 
- class QualType; 
- class NamespaceDecl; 
-   
- /// An enumeration representing the different comparison categories 
- /// types. 
- /// 
- /// C++2a [cmp.categories.pre] The types weak_equality, strong_equality, 
- /// partial_ordering, weak_ordering, and strong_ordering are collectively 
- /// termed the comparison category types. 
- enum class ComparisonCategoryType : unsigned char { 
-   PartialOrdering, 
-   WeakOrdering, 
-   StrongOrdering, 
-   First = PartialOrdering, 
-   Last = StrongOrdering 
- }; 
-   
- /// Determine the common comparison type, as defined in C++2a 
- /// [class.spaceship]p4. 
- inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A, 
-                                                    ComparisonCategoryType B) { 
-   return A < B ? A : B; 
- } 
-   
- /// Get the comparison category that should be used when comparing values of 
- /// type \c T. 
- std::optional<ComparisonCategoryType> 
- getComparisonCategoryForBuiltinCmp(QualType T); 
-   
- /// An enumeration representing the possible results of a three-way 
- /// comparison. These values map onto instances of comparison category types 
- /// defined in the standard library. e.g. 'std::strong_ordering::less'. 
- enum class ComparisonCategoryResult : unsigned char { 
-   Equal, 
-   Equivalent, 
-   Less, 
-   Greater, 
-   Unordered, 
-   Last = Unordered 
- }; 
-   
- class ComparisonCategoryInfo { 
-   friend class ComparisonCategories; 
-   friend class Sema; 
-   
- public: 
-   ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD, 
-                          ComparisonCategoryType Kind) 
-       : Ctx(Ctx), Record(RD), Kind(Kind) {} 
-   
-   struct ValueInfo { 
-     ComparisonCategoryResult Kind; 
-     VarDecl *VD; 
-   
-     ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD) 
-         : Kind(Kind), VD(VD) {} 
-   
-     /// True iff we've successfully evaluated the variable as a constant 
-     /// expression and extracted its integer value. 
-     bool hasValidIntValue() const; 
-   
-     /// Get the constant integer value used by this variable to represent 
-     /// the comparison category result type. 
-     llvm::APSInt getIntValue() const; 
-   }; 
- private: 
-   const ASTContext &Ctx; 
-   
-   /// A map containing the comparison category result decls from the 
-   /// standard library. The key is a value of ComparisonCategoryResult. 
-   mutable llvm::SmallVector< 
-       ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1> 
-       Objects; 
-   
-   /// Lookup the ValueInfo struct for the specified ValueKind. If the 
-   /// VarDecl for the value cannot be found, nullptr is returned. 
-   /// 
-   /// If the ValueInfo does not have a valid integer value the variable 
-   /// is evaluated as a constant expression to determine that value. 
-   ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const; 
-   
- public: 
-   /// The declaration for the comparison category type from the 
-   /// standard library. 
-   const CXXRecordDecl *Record = nullptr; 
-   
-   /// The Kind of the comparison category type 
-   ComparisonCategoryType Kind; 
-   
- public: 
-   QualType getType() const; 
-   
-   const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const { 
-     ValueInfo *Info = lookupValueInfo(ValueKind); 
-     assert(Info && 
-            "comparison category does not contain the specified result kind"); 
-     assert(Info->hasValidIntValue() && 
-            "couldn't determine the integer constant for this value"); 
-     return Info; 
-   } 
-   
-   /// True iff the comparison is "strong". i.e. it checks equality and 
-   /// not equivalence. 
-   bool isStrong() const { 
-     using CCK = ComparisonCategoryType; 
-     return Kind == CCK::StrongOrdering; 
-   } 
-   
-   /// True iff the comparison is not totally ordered. 
-   bool isPartial() const { 
-     using CCK = ComparisonCategoryType; 
-     return Kind == CCK::PartialOrdering; 
-   } 
-   
-   /// Converts the specified result kind into the correct result kind 
-   /// for this category. Specifically it lowers strong equality results to 
-   /// weak equivalence if needed. 
-   ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const { 
-     using CCR = ComparisonCategoryResult; 
-     if (!isStrong() && Res == CCR::Equal) 
-       return CCR::Equivalent; 
-     return Res; 
-   } 
-   
-   const ValueInfo *getEqualOrEquiv() const { 
-     return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal)); 
-   } 
-   const ValueInfo *getLess() const { 
-     return getValueInfo(ComparisonCategoryResult::Less); 
-   } 
-   const ValueInfo *getGreater() const { 
-     return getValueInfo(ComparisonCategoryResult::Greater); 
-   } 
-   const ValueInfo *getUnordered() const { 
-     assert(isPartial()); 
-     return getValueInfo(ComparisonCategoryResult::Unordered); 
-   } 
- }; 
-   
- class ComparisonCategories { 
- public: 
-   static StringRef getCategoryString(ComparisonCategoryType Kind); 
-   static StringRef getResultString(ComparisonCategoryResult Kind); 
-   
-   /// Return the list of results which are valid for the specified 
-   /// comparison category type. 
-   static std::vector<ComparisonCategoryResult> 
-   getPossibleResultsForType(ComparisonCategoryType Type); 
-   
-   /// Return the comparison category information for the category 
-   /// specified by 'Kind'. 
-   const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const { 
-     const ComparisonCategoryInfo *Result = lookupInfo(Kind); 
-     assert(Result != nullptr && 
-            "information for specified comparison category has not been built"); 
-     return *Result; 
-   } 
-   
-   /// Return the comparison category information as specified by 
-   /// `getCategoryForType(Ty)`. If the information is not already cached, 
-   /// the declaration is looked up and a cache entry is created. 
-   /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is 
-   /// possible. 
-   const ComparisonCategoryInfo &getInfoForType(QualType Ty) const; 
-   
- public: 
-   /// Return the cached comparison category information for the 
-   /// specified 'Kind'. If no cache entry is present the comparison category 
-   /// type is looked up. If lookup fails nullptr is returned. Otherwise, a 
-   /// new cache entry is created and returned 
-   const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const; 
-   
-   ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) { 
-     const auto &This = *this; 
-     return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind)); 
-   } 
-   
-   const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const; 
-   
- private: 
-   friend class ASTContext; 
-   
-   explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {} 
-   
-   const ASTContext &Ctx; 
-   
-   /// A map from the ComparisonCategoryType (represented as 'char') to the 
-   /// cached information for the specified category. 
-   mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data; 
-   mutable NamespaceDecl *StdNS = nullptr; 
- }; 
-   
- } // namespace clang 
-   
- #endif 
-