clang  10.0.0git
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 {
48  Last = StrongOrdering
49 };
50 
51 /// Determine the common comparison type, as defined in C++2a
52 /// [class.spaceship]p4.
55  return A < B ? A : B;
56 }
57 
58 /// Get the comparison category that should be used when comparing values of
59 /// type \c T.
61 
62 /// An enumeration representing the possible results of a three-way
63 /// comparison. These values map onto instances of comparison category types
64 /// defined in the standard library. e.g. 'std::strong_ordering::less'.
65 enum class ComparisonCategoryResult : unsigned char {
66  Equal,
67  Equivalent,
68  Less,
69  Greater,
70  Unordered,
71  Last = Unordered
72 };
73 
75  friend class ComparisonCategories;
76  friend class Sema;
77 
78 public:
81  : Ctx(Ctx), Record(RD), Kind(Kind) {}
82 
83  struct ValueInfo {
86 
88  : Kind(Kind), VD(VD) {}
89 
90  /// True iff we've successfully evaluated the variable as a constant
91  /// expression and extracted its integer value.
92  bool hasValidIntValue() const;
93 
94  /// Get the constant integer value used by this variable to represent
95  /// the comparison category result type.
96  llvm::APSInt getIntValue() const;
97  };
98 private:
99  const ASTContext &Ctx;
100 
101  /// A map containing the comparison category result decls from the
102  /// standard library. The key is a value of ComparisonCategoryResult.
103  mutable llvm::SmallVector<
104  ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
105  Objects;
106 
107  /// Lookup the ValueInfo struct for the specified ValueKind. If the
108  /// VarDecl for the value cannot be found, nullptr is returned.
109  ///
110  /// If the ValueInfo does not have a valid integer value the variable
111  /// is evaluated as a constant expression to determine that value.
112  ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
113 
114 public:
115  /// The declaration for the comparison category type from the
116  /// standard library.
117  // FIXME: Make this const
118  CXXRecordDecl *Record = nullptr;
119 
120  /// The Kind of the comparison category type
122 
123 public:
124  QualType getType() const;
125 
126  const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
127  ValueInfo *Info = lookupValueInfo(ValueKind);
128  assert(Info &&
129  "comparison category does not contain the specified result kind");
130  assert(Info->hasValidIntValue() &&
131  "couldn't determine the integer constant for this value");
132  return Info;
133  }
134 
135  /// True iff the comparison is "strong". i.e. it checks equality and
136  /// not equivalence.
137  bool isStrong() const {
138  using CCK = ComparisonCategoryType;
139  return Kind == CCK::StrongOrdering;
140  }
141 
142  /// True iff the comparison is not totally ordered.
143  bool isPartial() const {
144  using CCK = ComparisonCategoryType;
145  return Kind == CCK::PartialOrdering;
146  }
147 
148  /// Converts the specified result kind into the the correct result kind
149  /// for this category. Specifically it lowers strong equality results to
150  /// weak equivalence if needed.
152  using CCR = ComparisonCategoryResult;
153  if (!isStrong() && Res == CCR::Equal)
154  return CCR::Equivalent;
155  return Res;
156  }
157 
158  const ValueInfo *getEqualOrEquiv() const {
159  return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
160  }
161  const ValueInfo *getLess() const {
162  return getValueInfo(ComparisonCategoryResult::Less);
163  }
164  const ValueInfo *getGreater() const {
165  return getValueInfo(ComparisonCategoryResult::Greater);
166  }
167  const ValueInfo *getUnordered() const {
168  assert(isPartial());
169  return getValueInfo(ComparisonCategoryResult::Unordered);
170  }
171 };
172 
174 public:
175  static StringRef getCategoryString(ComparisonCategoryType Kind);
176  static StringRef getResultString(ComparisonCategoryResult Kind);
177 
178  /// Return the list of results which are valid for the specified
179  /// comparison category type.
180  static std::vector<ComparisonCategoryResult>
181  getPossibleResultsForType(ComparisonCategoryType Type);
182 
183  /// Return the comparison category information for the category
184  /// specified by 'Kind'.
186  const ComparisonCategoryInfo *Result = lookupInfo(Kind);
187  assert(Result != nullptr &&
188  "information for specified comparison category has not been built");
189  return *Result;
190  }
191 
192  /// Return the comparison category information as specified by
193  /// `getCategoryForType(Ty)`. If the information is not already cached,
194  /// the declaration is looked up and a cache entry is created.
195  /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
196  /// possible.
197  const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
198 
199 public:
200  /// Return the cached comparison category information for the
201  /// specified 'Kind'. If no cache entry is present the comparison category
202  /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
203  /// new cache entry is created and returned
204  const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
205 
207  const auto &This = *this;
208  return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
209  }
210 
211  const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
212 
213 private:
214  friend class ASTContext;
215 
216  explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
217 
218  const ASTContext &Ctx;
219 
220  /// A map from the ComparisonCategoryType (represented as 'char') to the
221  /// cached information for the specified category.
222  mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
223  mutable NamespaceDecl *StdNS = nullptr;
224 };
225 
226 } // namespace clang
227 
228 #endif
A (possibly-)qualified type.
Definition: Type.h:654
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:1450
Represent a C++ namespace.
Definition: Decl.h:497
Represents a variable declaration or definition.
Definition: Decl.h:820
bool This(InterpState &S, CodePtr OpPC)
Definition: Interp.h:827
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:168
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...
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:336
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
llvm::APSInt APSInt
const ValueInfo * getLess() const
Optional< ComparisonCategoryType > getComparisonCategoryForBuiltinCmp(QualType T)
Get the comparison category that should be used when comparing values of type T.
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:253
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
ComparisonCategoryType commonComparisonType(ComparisonCategoryType A, ComparisonCategoryType B)
Determine the common comparison type, as defined in C++2a [class.spaceship]p4.
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const
Converts the specified result kind into the the correct result kind for this category.