Coverage Report

Created: 2018-09-21 05:35

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/AST/ComparisonCategories.h
Line
Count
Source
1
//===- ComparisonCategories.h - Three Way Comparison Data -------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//  This file defines the Comparison Category enum and data types, which
11
//  store the types and expressions needed to support operator<=>
12
//
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H
16
#define LLVM_CLANG_AST_COMPARISONCATEGORIES_H
17
18
#include "clang/Basic/LLVM.h"
19
#include "llvm/ADT/APSInt.h"
20
#include "llvm/ADT/DenseMap.h"
21
#include <array>
22
#include <cassert>
23
24
namespace llvm {
25
  class StringRef;
26
  class APSInt;
27
}
28
29
namespace clang {
30
31
class ASTContext;
32
class VarDecl;
33
class CXXRecordDecl;
34
class Sema;
35
class QualType;
36
class NamespaceDecl;
37
38
/// An enumeration representing the different comparison categories
39
/// types.
40
///
41
/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality,
42
/// partial_ordering, weak_ordering, and strong_ordering are collectively
43
/// termed the comparison category types.
44
enum class ComparisonCategoryType : unsigned char {
45
  WeakEquality,
46
  StrongEquality,
47
  PartialOrdering,
48
  WeakOrdering,
49
  StrongOrdering,
50
  First = WeakEquality,
51
  Last = StrongOrdering
52
};
53
54
/// An enumeration representing the possible results of a three-way
55
/// comparison. These values map onto instances of comparison category types
56
/// defined in the standard library. e.g. 'std::strong_ordering::less'.
57
enum class ComparisonCategoryResult : unsigned char {
58
  Equal,
59
  Equivalent,
60
  Nonequivalent,
61
  Nonequal,
62
  Less,
63
  Greater,
64
  Unordered,
65
  Last = Unordered
66
};
67
68
class ComparisonCategoryInfo {
69
  friend class ComparisonCategories;
70
  friend class Sema;
71
72
public:
73
  ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD,
74
                         ComparisonCategoryType Kind)
75
18
      : Ctx(Ctx), Record(RD), Kind(Kind) {}
76
77
  struct ValueInfo {
78
    ComparisonCategoryResult Kind;
79
    VarDecl *VD;
80
81
    ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
82
51
        : Kind(Kind), VD(VD) {}
83
84
    /// True iff we've successfully evaluated the variable as a constant
85
    /// expression and extracted its integer value.
86
    bool hasValidIntValue() const;
87
88
    /// Get the constant integer value used by this variable to represent
89
    /// the comparison category result type.
90
    llvm::APSInt getIntValue() const;
91
  };
92
private:
93
  const ASTContext &Ctx;
94
95
  /// A map containing the comparison category result decls from the
96
  /// standard library. The key is a value of ComparisonCategoryResult.
97
  mutable llvm::SmallVector<
98
      ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
99
      Objects;
100
101
  /// Lookup the ValueInfo struct for the specified ValueKind. If the
102
  /// VarDecl for the value cannot be found, nullptr is returned.
103
  ///
104
  /// If the ValueInfo does not have a valid integer value the variable
105
  /// is evaluated as a constant expression to determine that value.
106
  ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
107
108
public:
109
  /// The declaration for the comparison category type from the
110
  /// standard library.
111
  // FIXME: Make this const
112
  CXXRecordDecl *Record = nullptr;
113
114
  /// The Kind of the comparison category type
115
  ComparisonCategoryType Kind;
116
117
public:
118
  QualType getType() const;
119
120
119
  const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
121
119
    ValueInfo *Info = lookupValueInfo(ValueKind);
122
119
    assert(Info &&
123
119
           "comparison category does not contain the specified result kind");
124
119
    assert(Info->hasValidIntValue() &&
125
119
           "couldn't determine the integer constant for this value");
126
119
    return Info;
127
119
  }
128
129
  /// True iff the comparison category is an equality comparison.
130
251
  bool isEquality() const { return !isOrdered(); }
131
132
  /// True iff the comparison category is a relational comparison.
133
486
  bool isOrdered() const {
134
486
    using CCK = ComparisonCategoryType;
135
486
    return Kind == CCK::PartialOrdering || 
Kind == CCK::WeakOrdering449
||
136
486
           
Kind == CCK::StrongOrdering449
;
137
486
  }
138
139
  /// True iff the comparison is "strong". i.e. it checks equality and
140
  /// not equivalence.
141
96
  bool isStrong() const {
142
96
    using CCK = ComparisonCategoryType;
143
96
    return Kind == CCK::StrongEquality || 
Kind == CCK::StrongOrdering58
;
144
96
  }
145
146
  /// True iff the comparison is not totally ordered.
147
11
  bool isPartial() const {
148
11
    using CCK = ComparisonCategoryType;
149
11
    return Kind == CCK::PartialOrdering;
150
11
  }
151
152
  /// Converts the specified result kind into the the correct result kind
153
  /// for this category. Specifically it lowers strong equality results to
154
  /// weak equivalence if needed.
155
96
  ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
156
96
    using CCR = ComparisonCategoryResult;
157
96
    if (!isStrong()) {
158
15
      if (Res == CCR::Equal)
159
6
        return CCR::Equivalent;
160
9
      if (Res == CCR::Nonequal)
161
3
        return CCR::Nonequivalent;
162
87
    }
163
87
    return Res;
164
87
  }
165
166
17
  const ValueInfo *getEqualOrEquiv() const {
167
17
    return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
168
17
  }
169
5
  const ValueInfo *getNonequalOrNonequiv() const {
170
5
    assert(isEquality());
171
5
    return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal));
172
5
  }
173
11
  const ValueInfo *getLess() const {
174
11
    assert(isOrdered());
175
11
    return getValueInfo(ComparisonCategoryResult::Less);
176
11
  }
177
11
  const ValueInfo *getGreater() const {
178
11
    assert(isOrdered());
179
11
    return getValueInfo(ComparisonCategoryResult::Greater);
180
11
  }
181
1
  const ValueInfo *getUnordered() const {
182
1
    assert(isPartial());
183
1
    return getValueInfo(ComparisonCategoryResult::Unordered);
184
1
  }
185
};
186
187
class ComparisonCategories {
188
public:
189
  static StringRef getCategoryString(ComparisonCategoryType Kind);
190
  static StringRef getResultString(ComparisonCategoryResult Kind);
191
192
  /// Return the list of results which are valid for the specified
193
  /// comparison category type.
194
  static std::vector<ComparisonCategoryResult>
195
  getPossibleResultsForType(ComparisonCategoryType Type);
196
197
  /// Return the comparison category information for the category
198
  /// specified by 'Kind'.
199
  const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const {
200
    const ComparisonCategoryInfo *Result = lookupInfo(Kind);
201
    assert(Result != nullptr &&
202
           "information for specified comparison category has not been built");
203
    return *Result;
204
  }
205
206
  /// Return the comparison category information as specified by
207
  /// `getCategoryForType(Ty)`. If the information is not already cached,
208
  /// the declaration is looked up and a cache entry is created.
209
  /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
210
  /// possible.
211
  const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
212
213
public:
214
  /// Return the cached comparison category information for the
215
  /// specified 'Kind'. If no cache entry is present the comparison category
216
  /// type is looked up. If lookup fails nullptr is returned. Otherwise, a
217
  /// new cache entry is created and returned
218
  const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
219
220
189
  ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
221
189
    const auto &This = *this;
222
189
    return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
223
189
  }
224
225
private:
226
  const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
227
228
private:
229
  friend class ASTContext;
230
231
37.5k
  explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
232
233
  const ASTContext &Ctx;
234
235
  /// A map from the ComparisonCategoryType (represented as 'char') to the
236
  /// cached information for the specified category.
237
  mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
238
  mutable NamespaceDecl *StdNS = nullptr;
239
};
240
241
} // namespace clang
242
243
#endif