Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
 
25
namespace llvm {
26
  class StringRef;
27
  class APSInt;
28
}
29
 
30
namespace clang {
31
 
32
class ASTContext;
33
class VarDecl;
34
class CXXRecordDecl;
35
class Sema;
36
class QualType;
37
class 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.
45
enum class ComparisonCategoryType : unsigned char {
46
  PartialOrdering,
47
  WeakOrdering,
48
  StrongOrdering,
49
  First = PartialOrdering,
50
  Last = StrongOrdering
51
};
52
 
53
/// Determine the common comparison type, as defined in C++2a
54
/// [class.spaceship]p4.
55
inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
56
                                                   ComparisonCategoryType B) {
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.
62
std::optional<ComparisonCategoryType>
63
getComparisonCategoryForBuiltinCmp(QualType T);
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'.
68
enum class ComparisonCategoryResult : unsigned char {
69
  Equal,
70
  Equivalent,
71
  Less,
72
  Greater,
73
  Unordered,
74
  Last = Unordered
75
};
76
 
77
class ComparisonCategoryInfo {
78
  friend class ComparisonCategories;
79
  friend class Sema;
80
 
81
public:
82
  ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD,
83
                         ComparisonCategoryType Kind)
84
      : Ctx(Ctx), Record(RD), Kind(Kind) {}
85
 
86
  struct ValueInfo {
87
    ComparisonCategoryResult Kind;
88
    VarDecl *VD;
89
 
90
    ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
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
  };
101
private:
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
 
117
public:
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
123
  ComparisonCategoryType Kind;
124
 
125
public:
126
  QualType getType() const;
127
 
128
  const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
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.
153
  ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
154
    using CCR = ComparisonCategoryResult;
155
    if (!isStrong() && Res == CCR::Equal)
156
      return CCR::Equivalent;
157
    return Res;
158
  }
159
 
160
  const ValueInfo *getEqualOrEquiv() const {
161
    return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
162
  }
163
  const ValueInfo *getLess() const {
164
    return getValueInfo(ComparisonCategoryResult::Less);
165
  }
166
  const ValueInfo *getGreater() const {
167
    return getValueInfo(ComparisonCategoryResult::Greater);
168
  }
169
  const ValueInfo *getUnordered() const {
170
    assert(isPartial());
171
    return getValueInfo(ComparisonCategoryResult::Unordered);
172
  }
173
};
174
 
175
class ComparisonCategories {
176
public:
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>
183
  getPossibleResultsForType(ComparisonCategoryType Type);
184
 
185
  /// Return the comparison category information for the category
186
  /// specified by 'Kind'.
187
  const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const {
188
    const ComparisonCategoryInfo *Result = lookupInfo(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.
199
  const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
200
 
201
public:
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
206
  const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
207
 
208
  ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
209
    const auto &This = *this;
210
    return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
211
  }
212
 
213
  const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
214
 
215
private:
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