]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/include/clang/AST/ComparisonCategories.h
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / 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
23 namespace llvm {
24   class StringRef;
25   class APSInt;
26 }
27
28 namespace clang {
29
30 class ASTContext;
31 class VarDecl;
32 class CXXRecordDecl;
33 class Sema;
34 class QualType;
35 class 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.
43 enum 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'.
56 enum class ComparisonCategoryResult : unsigned char {
57   Equal,
58   Equivalent,
59   Nonequivalent,
60   Nonequal,
61   Less,
62   Greater,
63   Unordered,
64   Last = Unordered
65 };
66
67 class ComparisonCategoryInfo {
68   friend class ComparisonCategories;
69   friend class Sema;
70
71 public:
72   ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *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 Kind, VarDecl *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   };
91 private:
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       ValueInfo, static_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 ValueKind) const;
106
107 public:
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
116 public:
117   QualType getType() const;
118
119   const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
120     ValueInfo *Info = lookupValueInfo(ValueKind);
121     assert(Info &&
122            "comparison category does not contain the specified result kind");
123     assert(Info->hasValidIntValue() &&
124            "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 Res) const {
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
186 class ComparisonCategories {
187 public:
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 Kind) const {
199     const ComparisonCategoryInfo *Result = lookupInfo(Kind);
200     assert(Result != nullptr &&
201            "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 Ty) const;
211
212 public:
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 Kind) const;
218
219   ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
220     const auto &This = *this;
221     return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
222   }
223
224 private:
225   const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
226
227 private:
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