clang  10.0.0svn
ComparisonCategories.h
Go to the documentation of this file.
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 {
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,
60  Nonequal,
61  Less,
62  Greater,
63  Unordered,
64  Last = Unordered
65 };
66 
68  friend class ComparisonCategories;
69  friend class Sema;
70 
71 public:
74  : Ctx(Ctx), Record(RD), Kind(Kind) {}
75 
76  struct ValueInfo {
79 
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
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.
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 
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'.
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 
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
A (possibly-)qualified type.
Definition: Type.h:643
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
Definition: Dominators.h:30
ComparisonCategoryType Kind
The Kind of the comparison category type.
The base class of the type hierarchy.
Definition: Type.h:1436
Represent a C++ namespace.
Definition: Decl.h:514
Represents a variable declaration or definition.
Definition: Decl.h:812
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:830
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
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:328
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.
llvm::APSInt APSInt
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:254
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.