123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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 <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.
- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|