clang  7.0.0
ComparisonCategories.h
Go to the documentation of this file.
1 //===- ComparisonCategories.h - Three Way Comparison Data -------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the Comparison Category enum and data types, which
11 // store the types and expressions needed to support operator<=>
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H
16 #define LLVM_CLANG_AST_COMPARISONCATEGORIES_H
17 
18 #include "clang/Basic/LLVM.h"
19 #include "llvm/ADT/APSInt.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include <array>
22 #include <cassert>
23 
24 namespace llvm {
25  class StringRef;
26  class APSInt;
27 }
28 
29 namespace clang {
30 
31 class ASTContext;
32 class VarDecl;
33 class CXXRecordDecl;
34 class Sema;
35 class QualType;
36 class NamespaceDecl;
37 
38 /// An enumeration representing the different comparison categories
39 /// types.
40 ///
41 /// C++2a [cmp.categories.pre] The types weak_equality, strong_equality,
42 /// partial_ordering, weak_ordering, and strong_ordering are collectively
43 /// termed the comparison category types.
44 enum class ComparisonCategoryType : unsigned char {
51  Last = StrongOrdering
52 };
53 
54 /// An enumeration representing the possible results of a three-way
55 /// comparison. These values map onto instances of comparison category types
56 /// defined in the standard library. e.g. 'std::strong_ordering::less'.
57 enum class ComparisonCategoryResult : unsigned char {
58  Equal,
59  Equivalent,
61  Nonequal,
62  Less,
63  Greater,
64  Unordered,
65  Last = Unordered
66 };
67 
69  friend class ComparisonCategories;
70  friend class Sema;
71 
72 public:
75  : Ctx(Ctx), Record(RD), Kind(Kind) {}
76 
77  struct ValueInfo {
80 
82  : Kind(Kind), VD(VD) {}
83 
84  /// True iff we've successfully evaluated the variable as a constant
85  /// expression and extracted its integer value.
86  bool hasValidIntValue() const;
87 
88  /// Get the constant integer value used by this variable to represent
89  /// the comparison category result type.
90  llvm::APSInt getIntValue() const;
91  };
92 private:
93  const ASTContext &Ctx;
94 
95  /// A map containing the comparison category result decls from the
96  /// standard library. The key is a value of ComparisonCategoryResult.
97  mutable llvm::SmallVector<
98  ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
99  Objects;
100 
101  /// Lookup the ValueInfo struct for the specified ValueKind. If the
102  /// VarDecl for the value cannot be found, nullptr is returned.
103  ///
104  /// If the ValueInfo does not have a valid integer value the variable
105  /// is evaluated as a constant expression to determine that value.
106  ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
107 
108 public:
109  /// The declaration for the comparison category type from the
110  /// standard library.
111  // FIXME: Make this const
112  CXXRecordDecl *Record = nullptr;
113 
114  /// The Kind of the comparison category type
116 
117 public:
118  QualType getType() const;
119 
120  const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
121  ValueInfo *Info = lookupValueInfo(ValueKind);
122  assert(Info &&
123  "comparison category does not contain the specified result kind");
124  assert(Info->hasValidIntValue() &&
125  "couldn't determine the integer constant for this value");
126  return Info;
127  }
128 
129  /// True iff the comparison category is an equality comparison.
130  bool isEquality() const { return !isOrdered(); }
131 
132  /// True iff the comparison category is a relational comparison.
133  bool isOrdered() const {
134  using CCK = ComparisonCategoryType;
135  return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering ||
136  Kind == CCK::StrongOrdering;
137  }
138 
139  /// True iff the comparison is "strong". i.e. it checks equality and
140  /// not equivalence.
141  bool isStrong() const {
142  using CCK = ComparisonCategoryType;
143  return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering;
144  }
145 
146  /// True iff the comparison is not totally ordered.
147  bool isPartial() const {
148  using CCK = ComparisonCategoryType;
149  return Kind == CCK::PartialOrdering;
150  }
151 
152  /// Converts the specified result kind into the the correct result kind
153  /// for this category. Specifically it lowers strong equality results to
154  /// weak equivalence if needed.
156  using CCR = ComparisonCategoryResult;
157  if (!isStrong()) {
158  if (Res == CCR::Equal)
159  return CCR::Equivalent;
160  if (Res == CCR::Nonequal)
161  return CCR::Nonequivalent;
162  }
163  return Res;
164  }
165 
166  const ValueInfo *getEqualOrEquiv() const {
167  return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
168  }
169  const ValueInfo *getNonequalOrNonequiv() const {
170  assert(isEquality());
171  return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal));
172  }
173  const ValueInfo *getLess() const {
174  assert(isOrdered());
175  return getValueInfo(ComparisonCategoryResult::Less);
176  }
177  const ValueInfo *getGreater() const {
178  assert(isOrdered());
179  return getValueInfo(ComparisonCategoryResult::Greater);
180  }
181  const ValueInfo *getUnordered() const {
182  assert(isPartial());
183  return getValueInfo(ComparisonCategoryResult::Unordered);
184  }
185 };
186 
188 public:
189  static StringRef getCategoryString(ComparisonCategoryType Kind);
190  static StringRef getResultString(ComparisonCategoryResult Kind);
191 
192  /// Return the list of results which are valid for the specified
193  /// comparison category type.
194  static std::vector<ComparisonCategoryResult>
195  getPossibleResultsForType(ComparisonCategoryType Type);
196 
197  /// Return the comparison category information for the category
198  /// specified by 'Kind'.
200  const ComparisonCategoryInfo *Result = lookupInfo(Kind);
201  assert(Result != nullptr &&
202  "information for specified comparison category has not been built");
203  return *Result;
204  }
205 
206  /// Return the comparison category information as specified by
207  /// `getCategoryForType(Ty)`. If the information is not already cached,
208  /// the declaration is looked up and a cache entry is created.
209  /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
210  /// possible.
211  const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
212 
213 public:
214  /// Return the cached comparison category information for the
215  /// specified 'Kind'. If no cache entry is present the comparison category
216  /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
217  /// new cache entry is created and returned
218  const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
219 
221  const auto &This = *this;
222  return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
223  }
224 
225 private:
226  const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
227 
228 private:
229  friend class ASTContext;
230 
231  explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
232 
233  const ASTContext &Ctx;
234 
235  /// A map from the ComparisonCategoryType (represented as 'char') to the
236  /// cached information for the specified category.
237  mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
238  mutable NamespaceDecl *StdNS = nullptr;
239 };
240 
241 } // namespace clang
242 
243 #endif
A (possibly-)qualified type.
Definition: Type.h:655
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
ComparisonCategoryType Kind
The Kind of the comparison category type.
The base class of the type hierarchy.
Definition: Type.h:1428
Represent a C++ namespace.
Definition: Decl.h:514
Represents a variable declaration or definition.
Definition: Decl.h:814
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:150
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
bool isPartial() const
True iff the comparison is not totally ordered.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
bool isEquality() const
True iff the comparison category is an equality comparison.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:277
const ValueInfo * getNonequalOrNonequiv() const
bool hasValidIntValue() const
True iff we&#39;ve successfully evaluated the variable as a constant expression and extracted its integer...
const ValueInfo * getGreater() const
Kind
bool isOrdered() const
True iff the comparison category is a relational comparison.
const ValueInfo * getLess() const
ComparisonCategoryInfo * lookupInfo(ComparisonCategoryType Kind)
Dataflow Directional Tag Classes.
ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD, ComparisonCategoryType Kind)
Represents a C++ struct/union/class.
Definition: DeclCXX.h:302
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getEqualOrEquiv() const
const ComparisonCategoryInfo & getInfo(ComparisonCategoryType Kind) const
Return the comparison category information for the category specified by &#39;Kind&#39;.
ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
ComparisonCategoryType
An enumeration representing the different comparison categories types.
const ValueInfo * getUnordered() const
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const
Converts the specified result kind into the the correct result kind for this category.