Clang Project

clang_source_code/include/clang/AST/ComparisonCategories.h
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
23namespace llvm {
24  class StringRef;
25  class APSInt;
26}
27
28namespace clang {
29
30class ASTContext;
31class VarDecl;
32class CXXRecordDecl;
33class Sema;
34class QualType;
35class NamespaceDecl;
36
37/// An enumeration representing the different comparison categories
38/// types.
39///
40/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality,
41/// partial_ordering, weak_ordering, and strong_ordering are collectively
42/// termed the comparison category types.
43enum class ComparisonCategoryType : unsigned char {
44  WeakEquality,
45  StrongEquality,
46  PartialOrdering,
47  WeakOrdering,
48  StrongOrdering,
49  First = WeakEquality,
50  Last = StrongOrdering
51};
52
53/// An enumeration representing the possible results of a three-way
54/// comparison. These values map onto instances of comparison category types
55/// defined in the standard library. e.g. 'std::strong_ordering::less'.
56enum class ComparisonCategoryResult : unsigned char {
57  Equal,
58  Equivalent,
59  Nonequivalent,
60  Nonequal,
61  Less,
62  Greater,
63  Unordered,
64  Last = Unordered
65};
66
67class ComparisonCategoryInfo {
68  friend class ComparisonCategories;
69  friend class Sema;
70
71public:
72  ComparisonCategoryInfo(const ASTContext &CtxCXXRecordDecl *RD,
73                         ComparisonCategoryType Kind)
74      : Ctx(Ctx), Record(RD), Kind(Kind) {}
75
76  struct ValueInfo {
77    ComparisonCategoryResult Kind;
78    VarDecl *VD;
79
80    ValueInfo(ComparisonCategoryResult KindVarDecl *VD)
81        : Kind(Kind), VD(VD) {}
82
83    /// True iff we've successfully evaluated the variable as a constant
84    /// expression and extracted its integer value.
85    bool hasValidIntValue() const;
86
87    /// Get the constant integer value used by this variable to represent
88    /// the comparison category result type.
89    llvm::APSInt getIntValue() const;
90  };
91private:
92  const ASTContext &Ctx;
93
94  /// A map containing the comparison category result decls from the
95  /// standard library. The key is a value of ComparisonCategoryResult.
96  mutable llvm::SmallVector<
97      ValueInfostatic_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
98      Objects;
99
100  /// Lookup the ValueInfo struct for the specified ValueKind. If the
101  /// VarDecl for the value cannot be found, nullptr is returned.
102  ///
103  /// If the ValueInfo does not have a valid integer value the variable
104  /// is evaluated as a constant expression to determine that value.
105  ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKindconst;
106
107public:
108  /// The declaration for the comparison category type from the
109  /// standard library.
110  // FIXME: Make this const
111  CXXRecordDecl *Record = nullptr;
112
113  /// The Kind of the comparison category type
114  ComparisonCategoryType Kind;
115
116public:
117  QualType getType() const;
118
119  const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKindconst {
120    ValueInfo *Info = lookupValueInfo(ValueKind);
121     (0) . __assert_fail ("Info && \"comparison category does not contain the specified result kind\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 122, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Info &&
122 (0) . __assert_fail ("Info && \"comparison category does not contain the specified result kind\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 122, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">           "comparison category does not contain the specified result kind");
123     (0) . __assert_fail ("Info->hasValidIntValue() && \"couldn't determine the integer constant for this value\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 124, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Info->hasValidIntValue() &&
124 (0) . __assert_fail ("Info->hasValidIntValue() && \"couldn't determine the integer constant for this value\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 124, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">           "couldn't determine the integer constant for this value");
125    return Info;
126  }
127
128  /// True iff the comparison category is an equality comparison.
129  bool isEquality() const { return !isOrdered(); }
130
131  /// True iff the comparison category is a relational comparison.
132  bool isOrdered() const {
133    using CCK = ComparisonCategoryType;
134    return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering ||
135           Kind == CCK::StrongOrdering;
136  }
137
138  /// True iff the comparison is "strong". i.e. it checks equality and
139  /// not equivalence.
140  bool isStrong() const {
141    using CCK = ComparisonCategoryType;
142    return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering;
143  }
144
145  /// True iff the comparison is not totally ordered.
146  bool isPartial() const {
147    using CCK = ComparisonCategoryType;
148    return Kind == CCK::PartialOrdering;
149  }
150
151  /// Converts the specified result kind into the the correct result kind
152  /// for this category. Specifically it lowers strong equality results to
153  /// weak equivalence if needed.
154  ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Resconst {
155    using CCR = ComparisonCategoryResult;
156    if (!isStrong()) {
157      if (Res == CCR::Equal)
158        return CCR::Equivalent;
159      if (Res == CCR::Nonequal)
160        return CCR::Nonequivalent;
161    }
162    return Res;
163  }
164
165  const ValueInfo *getEqualOrEquiv() const {
166    return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
167  }
168  const ValueInfo *getNonequalOrNonequiv() const {
169    assert(isEquality());
170    return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal));
171  }
172  const ValueInfo *getLess() const {
173    assert(isOrdered());
174    return getValueInfo(ComparisonCategoryResult::Less);
175  }
176  const ValueInfo *getGreater() const {
177    assert(isOrdered());
178    return getValueInfo(ComparisonCategoryResult::Greater);
179  }
180  const ValueInfo *getUnordered() const {
181    assert(isPartial());
182    return getValueInfo(ComparisonCategoryResult::Unordered);
183  }
184};
185
186class ComparisonCategories {
187public:
188  static StringRef getCategoryString(ComparisonCategoryType Kind);
189  static StringRef getResultString(ComparisonCategoryResult Kind);
190
191  /// Return the list of results which are valid for the specified
192  /// comparison category type.
193  static std::vector<ComparisonCategoryResult>
194  getPossibleResultsForType(ComparisonCategoryType Type);
195
196  /// Return the comparison category information for the category
197  /// specified by 'Kind'.
198  const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kindconst {
199    const ComparisonCategoryInfo *Result = lookupInfo(Kind);
200     (0) . __assert_fail ("Result != nullptr && \"information for specified comparison category has not been built\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 201, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Result != nullptr &&
201 (0) . __assert_fail ("Result != nullptr && \"information for specified comparison category has not been built\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/ComparisonCategories.h", 201, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">           "information for specified comparison category has not been built");
202    return *Result;
203  }
204
205  /// Return the comparison category information as specified by
206  /// `getCategoryForType(Ty)`. If the information is not already cached,
207  /// the declaration is looked up and a cache entry is created.
208  /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
209  /// possible.
210  const ComparisonCategoryInfo &getInfoForType(QualType Tyconst;
211
212public:
213  /// Return the cached comparison category information for the
214  /// specified 'Kind'. If no cache entry is present the comparison category
215  /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
216  /// new cache entry is created and returned
217  const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kindconst;
218
219  ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
220    const auto &This = *this;
221    return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
222  }
223
224private:
225  const ComparisonCategoryInfo *lookupInfoForType(QualType Tyconst;
226
227private:
228  friend class ASTContext;
229
230  explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
231
232  const ASTContext &Ctx;
233
234  /// A map from the ComparisonCategoryType (represented as 'char') to the
235  /// cached information for the specified category.
236  mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
237  mutable NamespaceDecl *StdNS = nullptr;
238};
239
240// namespace clang
241
242#endif
243
clang::ComparisonCategoryInfo::ValueInfo
clang::ComparisonCategoryInfo::ValueInfo::Kind
clang::ComparisonCategoryInfo::ValueInfo::VD
clang::ComparisonCategoryInfo::ValueInfo::hasValidIntValue
clang::ComparisonCategoryInfo::ValueInfo::getIntValue
clang::ComparisonCategoryInfo::Ctx
clang::ComparisonCategoryInfo::Objects
clang::ComparisonCategoryInfo::lookupValueInfo
clang::ComparisonCategoryInfo::Record
clang::ComparisonCategoryInfo::Kind
clang::ComparisonCategoryInfo::getType
clang::ComparisonCategoryInfo::getValueInfo
clang::ComparisonCategoryInfo::isEquality
clang::ComparisonCategoryInfo::isOrdered
clang::ComparisonCategoryInfo::isStrong
clang::ComparisonCategoryInfo::isPartial
clang::ComparisonCategoryInfo::makeWeakResult
clang::ComparisonCategoryInfo::getEqualOrEquiv
clang::ComparisonCategoryInfo::getNonequalOrNonequiv
clang::ComparisonCategoryInfo::getLess
clang::ComparisonCategoryInfo::getGreater
clang::ComparisonCategoryInfo::getUnordered
clang::ComparisonCategories::getCategoryString
clang::ComparisonCategories::getResultString
clang::ComparisonCategories::getPossibleResultsForType
clang::ComparisonCategories::getInfo
clang::ComparisonCategories::getInfoForType
clang::ComparisonCategories::lookupInfo
clang::ComparisonCategories::lookupInfo
clang::ComparisonCategories::lookupInfoForType
clang::ComparisonCategories::Ctx
clang::ComparisonCategories::Data
clang::ComparisonCategories::StdNS