clang 17.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++2a [cmp.categories.pre] The types weak_equality, strong_equality,
43/// partial_ordering, weak_ordering, and strong_ordering are collectively
44/// termed the comparison category types.
45enum class ComparisonCategoryType : unsigned char {
51};
52
53/// Determine the common comparison type, as defined in C++2a
54/// [class.spaceship]p4.
57 return A < B ? A : B;
58}
59
60/// Get the comparison category that should be used when comparing values of
61/// type \c T.
62std::optional<ComparisonCategoryType>
64
65/// An enumeration representing the possible results of a three-way
66/// comparison. These values map onto instances of comparison category types
67/// defined in the standard library. e.g. 'std::strong_ordering::less'.
68enum class ComparisonCategoryResult : unsigned char {
69 Equal,
71 Less,
72 Greater,
75};
76
79 friend class Sema;
80
81public:
84 : Ctx(Ctx), Record(RD), Kind(Kind) {}
85
86 struct ValueInfo {
89
91 : Kind(Kind), VD(VD) {}
92
93 /// True iff we've successfully evaluated the variable as a constant
94 /// expression and extracted its integer value.
95 bool hasValidIntValue() const;
96
97 /// Get the constant integer value used by this variable to represent
98 /// the comparison category result type.
99 llvm::APSInt getIntValue() const;
100 };
101private:
102 const ASTContext &Ctx;
103
104 /// A map containing the comparison category result decls from the
105 /// standard library. The key is a value of ComparisonCategoryResult.
106 mutable llvm::SmallVector<
107 ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
108 Objects;
109
110 /// Lookup the ValueInfo struct for the specified ValueKind. If the
111 /// VarDecl for the value cannot be found, nullptr is returned.
112 ///
113 /// If the ValueInfo does not have a valid integer value the variable
114 /// is evaluated as a constant expression to determine that value.
115 ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
116
117public:
118 /// The declaration for the comparison category type from the
119 /// standard library.
120 const CXXRecordDecl *Record = nullptr;
121
122 /// The Kind of the comparison category type
124
125public:
126 QualType getType() const;
127
129 ValueInfo *Info = lookupValueInfo(ValueKind);
130 assert(Info &&
131 "comparison category does not contain the specified result kind");
132 assert(Info->hasValidIntValue() &&
133 "couldn't determine the integer constant for this value");
134 return Info;
135 }
136
137 /// True iff the comparison is "strong". i.e. it checks equality and
138 /// not equivalence.
139 bool isStrong() const {
140 using CCK = ComparisonCategoryType;
141 return Kind == CCK::StrongOrdering;
142 }
143
144 /// True iff the comparison is not totally ordered.
145 bool isPartial() const {
146 using CCK = ComparisonCategoryType;
147 return Kind == CCK::PartialOrdering;
148 }
149
150 /// Converts the specified result kind into the correct result kind
151 /// for this category. Specifically it lowers strong equality results to
152 /// weak equivalence if needed.
154 using CCR = ComparisonCategoryResult;
155 if (!isStrong() && Res == CCR::Equal)
156 return CCR::Equivalent;
157 return Res;
158 }
159
160 const ValueInfo *getEqualOrEquiv() const {
162 }
163 const ValueInfo *getLess() const {
165 }
166 const ValueInfo *getGreater() const {
168 }
169 const ValueInfo *getUnordered() const {
170 assert(isPartial());
172 }
173};
174
176public:
177 static StringRef getCategoryString(ComparisonCategoryType Kind);
178 static StringRef getResultString(ComparisonCategoryResult Kind);
179
180 /// Return the list of results which are valid for the specified
181 /// comparison category type.
182 static std::vector<ComparisonCategoryResult>
184
185 /// Return the comparison category information for the category
186 /// specified by 'Kind'.
189 assert(Result != nullptr &&
190 "information for specified comparison category has not been built");
191 return *Result;
192 }
193
194 /// Return the comparison category information as specified by
195 /// `getCategoryForType(Ty)`. If the information is not already cached,
196 /// the declaration is looked up and a cache entry is created.
197 /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
198 /// possible.
200
201public:
202 /// Return the cached comparison category information for the
203 /// specified 'Kind'. If no cache entry is present the comparison category
204 /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
205 /// new cache entry is created and returned
207
209 const auto &This = *this;
210 return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
211 }
212
214
215private:
216 friend class ASTContext;
217
218 explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
219
220 const ASTContext &Ctx;
221
222 /// A map from the ComparisonCategoryType (represented as 'char') to the
223 /// cached information for the specified category.
224 mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
225 mutable NamespaceDecl *StdNS = nullptr;
226};
227
228} // namespace clang
229
230#endif
llvm::APSInt APSInt
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
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:254
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 CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
ComparisonCategoryType Kind
The Kind of the comparison category type.
bool isStrong() const
True iff the comparison is "strong".
ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD, ComparisonCategoryType Kind)
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.
Represent a C++ namespace.
Definition: Decl.h:542
A (possibly-)qualified type.
Definition: Type.h:736
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:356
The base class of the type hierarchy.
Definition: Type.h:1566
Represents a variable declaration or definition.
Definition: Decl.h:913
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...