Coverage Report

Created: 2019-07-24 05:18

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