Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- ComparisonCategories.h - Three Way Comparison Data -------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines the Comparison Category enum and data types, which
  10. //  store the types and expressions needed to support operator<=>
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H
  15. #define LLVM_CLANG_AST_COMPARISONCATEGORIES_H
  16.  
  17. #include "clang/Basic/LLVM.h"
  18. #include "llvm/ADT/APSInt.h"
  19. #include "llvm/ADT/DenseMap.h"
  20. #include <array>
  21. #include <cassert>
  22. #include <optional>
  23. #include <vector>
  24.  
  25. namespace llvm {
  26.   class StringRef;
  27.   class APSInt;
  28. }
  29.  
  30. namespace clang {
  31.  
  32. class ASTContext;
  33. class VarDecl;
  34. class CXXRecordDecl;
  35. class Sema;
  36. class QualType;
  37. class NamespaceDecl;
  38.  
  39. /// An enumeration representing the different comparison categories
  40. /// types.
  41. ///
  42. /// C++2a [cmp.categories.pre] The types weak_equality, strong_equality,
  43. /// partial_ordering, weak_ordering, and strong_ordering are collectively
  44. /// termed the comparison category types.
  45. enum class ComparisonCategoryType : unsigned char {
  46.   PartialOrdering,
  47.   WeakOrdering,
  48.   StrongOrdering,
  49.   First = PartialOrdering,
  50.   Last = StrongOrdering
  51. };
  52.  
  53. /// Determine the common comparison type, as defined in C++2a
  54. /// [class.spaceship]p4.
  55. inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
  56.                                                    ComparisonCategoryType B) {
  57.   return A < B ? A : B;
  58. }
  59.  
  60. /// Get the comparison category that should be used when comparing values of
  61. /// type \c T.
  62. std::optional<ComparisonCategoryType>
  63. getComparisonCategoryForBuiltinCmp(QualType T);
  64.  
  65. /// An enumeration representing the possible results of a three-way
  66. /// comparison. These values map onto instances of comparison category types
  67. /// defined in the standard library. e.g. 'std::strong_ordering::less'.
  68. enum class ComparisonCategoryResult : unsigned char {
  69.   Equal,
  70.   Equivalent,
  71.   Less,
  72.   Greater,
  73.   Unordered,
  74.   Last = Unordered
  75. };
  76.  
  77. class ComparisonCategoryInfo {
  78.   friend class ComparisonCategories;
  79.   friend class Sema;
  80.  
  81. public:
  82.   ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD,
  83.                          ComparisonCategoryType Kind)
  84.       : Ctx(Ctx), Record(RD), Kind(Kind) {}
  85.  
  86.   struct ValueInfo {
  87.     ComparisonCategoryResult Kind;
  88.     VarDecl *VD;
  89.  
  90.     ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
  91.         : Kind(Kind), VD(VD) {}
  92.  
  93.     /// True iff we've successfully evaluated the variable as a constant
  94.     /// expression and extracted its integer value.
  95.     bool hasValidIntValue() const;
  96.  
  97.     /// Get the constant integer value used by this variable to represent
  98.     /// the comparison category result type.
  99.     llvm::APSInt getIntValue() const;
  100.   };
  101. private:
  102.   const ASTContext &Ctx;
  103.  
  104.   /// A map containing the comparison category result decls from the
  105.   /// standard library. The key is a value of ComparisonCategoryResult.
  106.   mutable llvm::SmallVector<
  107.       ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
  108.       Objects;
  109.  
  110.   /// Lookup the ValueInfo struct for the specified ValueKind. If the
  111.   /// VarDecl for the value cannot be found, nullptr is returned.
  112.   ///
  113.   /// If the ValueInfo does not have a valid integer value the variable
  114.   /// is evaluated as a constant expression to determine that value.
  115.   ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
  116.  
  117. public:
  118.   /// The declaration for the comparison category type from the
  119.   /// standard library.
  120.   const CXXRecordDecl *Record = nullptr;
  121.  
  122.   /// The Kind of the comparison category type
  123.   ComparisonCategoryType Kind;
  124.  
  125. public:
  126.   QualType getType() const;
  127.  
  128.   const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
  129.     ValueInfo *Info = lookupValueInfo(ValueKind);
  130.     assert(Info &&
  131.            "comparison category does not contain the specified result kind");
  132.     assert(Info->hasValidIntValue() &&
  133.            "couldn't determine the integer constant for this value");
  134.     return Info;
  135.   }
  136.  
  137.   /// True iff the comparison is "strong". i.e. it checks equality and
  138.   /// not equivalence.
  139.   bool isStrong() const {
  140.     using CCK = ComparisonCategoryType;
  141.     return Kind == CCK::StrongOrdering;
  142.   }
  143.  
  144.   /// True iff the comparison is not totally ordered.
  145.   bool isPartial() const {
  146.     using CCK = ComparisonCategoryType;
  147.     return Kind == CCK::PartialOrdering;
  148.   }
  149.  
  150.   /// Converts the specified result kind into the correct result kind
  151.   /// for this category. Specifically it lowers strong equality results to
  152.   /// weak equivalence if needed.
  153.   ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
  154.     using CCR = ComparisonCategoryResult;
  155.     if (!isStrong() && Res == CCR::Equal)
  156.       return CCR::Equivalent;
  157.     return Res;
  158.   }
  159.  
  160.   const ValueInfo *getEqualOrEquiv() const {
  161.     return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
  162.   }
  163.   const ValueInfo *getLess() const {
  164.     return getValueInfo(ComparisonCategoryResult::Less);
  165.   }
  166.   const ValueInfo *getGreater() const {
  167.     return getValueInfo(ComparisonCategoryResult::Greater);
  168.   }
  169.   const ValueInfo *getUnordered() const {
  170.     assert(isPartial());
  171.     return getValueInfo(ComparisonCategoryResult::Unordered);
  172.   }
  173. };
  174.  
  175. class ComparisonCategories {
  176. public:
  177.   static StringRef getCategoryString(ComparisonCategoryType Kind);
  178.   static StringRef getResultString(ComparisonCategoryResult Kind);
  179.  
  180.   /// Return the list of results which are valid for the specified
  181.   /// comparison category type.
  182.   static std::vector<ComparisonCategoryResult>
  183.   getPossibleResultsForType(ComparisonCategoryType Type);
  184.  
  185.   /// Return the comparison category information for the category
  186.   /// specified by 'Kind'.
  187.   const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const {
  188.     const ComparisonCategoryInfo *Result = lookupInfo(Kind);
  189.     assert(Result != nullptr &&
  190.            "information for specified comparison category has not been built");
  191.     return *Result;
  192.   }
  193.  
  194.   /// Return the comparison category information as specified by
  195.   /// `getCategoryForType(Ty)`. If the information is not already cached,
  196.   /// the declaration is looked up and a cache entry is created.
  197.   /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
  198.   /// possible.
  199.   const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
  200.  
  201. public:
  202.   /// Return the cached comparison category information for the
  203.   /// specified 'Kind'. If no cache entry is present the comparison category
  204.   /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
  205.   /// new cache entry is created and returned
  206.   const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
  207.  
  208.   ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
  209.     const auto &This = *this;
  210.     return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
  211.   }
  212.  
  213.   const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
  214.  
  215. private:
  216.   friend class ASTContext;
  217.  
  218.   explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
  219.  
  220.   const ASTContext &Ctx;
  221.  
  222.   /// A map from the ComparisonCategoryType (represented as 'char') to the
  223.   /// cached information for the specified category.
  224.   mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
  225.   mutable NamespaceDecl *StdNS = nullptr;
  226. };
  227.  
  228. } // namespace clang
  229.  
  230. #endif
  231.