clang 19.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#include <optional>
23#include <vector>
24
25namespace llvm {
26 class StringRef;
27 class APSInt;
28}
29
30namespace clang {
31
32class ASTContext;
33class VarDecl;
34class CXXRecordDecl;
35class Sema;
36class QualType;
37class NamespaceDecl;
38
39/// An enumeration representing the different comparison categories
40/// types.
41///
42/// C++20 [cmp.categories.pre] The types partial_ordering, weak_ordering, and
43/// strong_ordering are collectively termed the comparison category types.
44enum class ComparisonCategoryType : unsigned char {
50};
51
52/// Determine the common comparison type, as defined in C++2a
53/// [class.spaceship]p4.
56 return A < B ? A : B;
57}
58
59/// Get the comparison category that should be used when comparing values of
60/// type \c T.
61std::optional<ComparisonCategoryType>
63
64/// An enumeration representing the possible results of a three-way
65/// comparison. These values map onto instances of comparison category types
66/// defined in the standard library. e.g. 'std::strong_ordering::less'.
67enum class ComparisonCategoryResult : unsigned char {
68 Equal,
70 Less,
71 Greater,
74};
75
78 friend class Sema;
79
80public:
83 : Ctx(Ctx), Record(RD), Kind(Kind) {}
84
85 struct ValueInfo {
88
90 : Kind(Kind), VD(VD) {}
91
92 /// True iff we've successfully evaluated the variable as a constant
93 /// expression and extracted its integer value.
94 bool hasValidIntValue() const;
95
96 /// Get the constant integer value used by this variable to represent
97 /// the comparison category result type.
98 llvm::APSInt getIntValue() const;
99 };
100private:
101 const ASTContext &Ctx;
102
103 /// A map containing the comparison category result decls from the
104 /// standard library. The key is a value of ComparisonCategoryResult.
105 mutable llvm::SmallVector<
106 ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
107 Objects;
108
109 /// Lookup the ValueInfo struct for the specified ValueKind. If the
110 /// VarDecl for the value cannot be found, nullptr is returned.
111 ///
112 /// If the ValueInfo does not have a valid integer value the variable
113 /// is evaluated as a constant expression to determine that value.
114 ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
115
116public:
117 /// The declaration for the comparison category type from the
118 /// standard library.
119 const CXXRecordDecl *Record = nullptr;
120
121 /// The Kind of the comparison category type
123
124public:
125 QualType getType() const;
126
128 ValueInfo *Info = lookupValueInfo(ValueKind);
129 assert(Info &&
130 "comparison category does not contain the specified result kind");
131 assert(Info->hasValidIntValue() &&
132 "couldn't determine the integer constant for this value");
133 return Info;
134 }
135
136 /// True iff the comparison is "strong". i.e. it checks equality and
137 /// not equivalence.
138 bool isStrong() const {
139 using CCK = ComparisonCategoryType;
140 return Kind == CCK::StrongOrdering;
141 }
142
143 /// True iff the comparison is not totally ordered.
144 bool isPartial() const {
145 using CCK = ComparisonCategoryType;
146 return Kind == CCK::PartialOrdering;
147 }
148
149 /// Converts the specified result kind into the correct result kind
150 /// for this category. Specifically it lowers strong equality results to
151 /// weak equivalence if needed.
153 using CCR = ComparisonCategoryResult;
154 if (!isStrong() && Res == CCR::Equal)
155 return CCR::Equivalent;
156 return Res;
157 }
158
159 const ValueInfo *getEqualOrEquiv() const {
161 }
162 const ValueInfo *getLess() const {
164 }
165 const ValueInfo *getGreater() const {
167 }
168 const ValueInfo *getUnordered() const {
169 assert(isPartial());
171 }
172};
173
175public:
176 static StringRef getCategoryString(ComparisonCategoryType Kind);
177 static StringRef getResultString(ComparisonCategoryResult Kind);
178
179 /// Return the list of results which are valid for the specified
180 /// comparison category type.
181 static std::vector<ComparisonCategoryResult>
183
184 /// Return the comparison category information for the category
185 /// specified by 'Kind'.
188 assert(Result != nullptr &&
189 "information for specified comparison category has not been built");
190 return *Result;
191 }
192
193 /// Return the comparison category information as specified by
194 /// `getCategoryForType(Ty)`. If the information is not already cached,
195 /// the declaration is looked up and a cache entry is created.
196 /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
197 /// possible.
199
200public:
201 /// Return the cached comparison category information for the
202 /// specified 'Kind'. If no cache entry is present the comparison category
203 /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
204 /// new cache entry is created and returned
206
208 const auto &This = *this;
209 return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
210 }
211
213
214private:
215 friend class ASTContext;
216
217 explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
218
219 const ASTContext &Ctx;
220
221 /// A map from the ComparisonCategoryType (represented as 'char') to the
222 /// cached information for the specified category.
223 mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
224 mutable NamespaceDecl *StdNS = nullptr;
225};
226
227} // namespace clang
228
229#endif
llvm::APSInt APSInt
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::Record Record
Definition: MachO.h:28
const char * Data
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
const ComparisonCategoryInfo * lookupInfoForType(QualType Ty) const
ComparisonCategoryInfo * lookupInfo(ComparisonCategoryType Kind)
const ComparisonCategoryInfo & getInfoForType(QualType Ty) const
Return the comparison category information as specified by getCategoryForType(Ty).
const ComparisonCategoryInfo * lookupInfo(ComparisonCategoryType Kind) const
Return the cached comparison category information for the specified 'Kind'.
const ComparisonCategoryInfo & getInfo(ComparisonCategoryType Kind) const
Return the comparison category information for the category specified by 'Kind'.
static StringRef getCategoryString(ComparisonCategoryType Kind)
static StringRef getResultString(ComparisonCategoryResult Kind)
static std::vector< ComparisonCategoryResult > getPossibleResultsForType(ComparisonCategoryType Type)
Return the list of results which are valid for the specified comparison category type.
bool isPartial() const
True iff the comparison is not totally ordered.
const ValueInfo * getLess() const
const ValueInfo * getUnordered() const
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
ComparisonCategoryType Kind
The Kind of the comparison category type.
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getGreater() const
const ValueInfo * getEqualOrEquiv() const
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const
Converts the specified result kind into the correct result kind for this category.
ComparisonCategoryInfo(const ASTContext &Ctx, const CXXRecordDecl *RD, ComparisonCategoryType Kind)
Represent a C++ namespace.
Definition: Decl.h:547
A (possibly-)qualified type.
Definition: Type.h:738
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:426
The base class of the type hierarchy.
Definition: Type.h:1607
Represents a variable declaration or definition.
Definition: Decl.h:918
The JSON file list parser is used to communicate input to InstallAPI.
std::optional< ComparisonCategoryType > getComparisonCategoryForBuiltinCmp(QualType T)
Get the comparison category that should be used when comparing values of type T.
ComparisonCategoryType commonComparisonType(ComparisonCategoryType A, ComparisonCategoryType B)
Determine the common comparison type, as defined in C++2a [class.spaceship]p4.
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Result
The result type of a method or function.
ComparisonCategoryType
An enumeration representing the different comparison categories types.
YAML serialization mapping.
Definition: Dominators.h:30
ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
bool hasValidIntValue() const
True iff we've successfully evaluated the variable as a constant expression and extracted its integer...
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...