Skip to content

Commit fac79c2

Browse files
brevzinpfez
authored andcommitted
Make LLVM build in C++20 mode
Part of the <=> changes in C++20 make certain patterns of writing equality operators ambiguous with themselves (sorry!). This patch goes through and adjusts all the comparison operators such that they should work in both C++17 and C++20 modes. It also makes two other small C++20-specific changes (adding a constructor to a type that cases to be an aggregate, and adding casts from u8 literals which no longer have type const char*). There were four categories of errors that this review fixes. Here are canonical examples of them, ordered from most to least common: // 1) Missing const namespace missing_const { struct A { #ifndef FIXED bool operator==(A const&); #else bool operator==(A const&) const; #endif }; bool a = A{} == A{}; // error } // 2) Type mismatch on CRTP namespace crtp_mismatch { template <typename Derived> struct Base { #ifndef FIXED bool operator==(Derived const&) const; #else // in one case changed to taking Base const& friend bool operator==(Derived const&, Derived const&); #endif }; struct D : Base<D> { }; bool b = D{} == D{}; // error } // 3) iterator/const_iterator with only mixed comparison namespace iter_const_iter { template <bool Const> struct iterator { using const_iterator = iterator<true>; iterator(); template <bool B, std::enable_if_t<(Const && !B), int> = 0> iterator(iterator<B> const&); #ifndef FIXED bool operator==(const_iterator const&) const; #else friend bool operator==(iterator const&, iterator const&); #endif }; bool c = iterator<false>{} == iterator<false>{} // error || iterator<false>{} == iterator<true>{} || iterator<true>{} == iterator<false>{} || iterator<true>{} == iterator<true>{}; } // 4) Same-type comparison but only have mixed-type operator namespace ambiguous_choice { enum Color { Red }; struct C { C(); C(Color); operator Color() const; bool operator==(Color) const; friend bool operator==(C, C); }; bool c = C{} == C{}; // error bool d = C{} == Red; } Differential revision: https://reviews.llvm.org/D78938
1 parent 0f20e48 commit fac79c2

25 files changed

Lines changed: 99 additions & 88 deletions

File tree

clang/include/clang/AST/StmtIterator.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,13 @@ class StmtIteratorImpl : public StmtIteratorBase,
104104
return tmp;
105105
}
106106

107-
bool operator==(const DERIVED& RHS) const {
108-
return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr;
107+
friend bool operator==(const DERIVED &LHS, const DERIVED &RHS) {
108+
return LHS.stmt == RHS.stmt && LHS.DGI == RHS.DGI &&
109+
LHS.RawVAPtr == RHS.RawVAPtr;
109110
}
110111

111-
bool operator!=(const DERIVED& RHS) const {
112-
return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr;
112+
friend bool operator!=(const DERIVED &LHS, const DERIVED &RHS) {
113+
return !(LHS == RHS);
113114
}
114115

115116
REFERENCE operator*() const {

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ enum OpenMPDirectiveKindEx {
5454
struct OpenMPDirectiveKindExWrapper {
5555
OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
5656
OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
57+
bool operator==(OpenMPDirectiveKindExWrapper V) const {
58+
return Value == V.Value;
59+
}
60+
bool operator!=(OpenMPDirectiveKindExWrapper V) const {
61+
return Value != V.Value;
62+
}
5763
bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
5864
bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
5965
bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }

clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class GenericTaintChecker
101101

102102
struct FunctionData {
103103
FunctionData() = delete;
104+
FunctionData(const FunctionDecl *FDecl, StringRef Name,
105+
std::string FullName)
106+
: FDecl(FDecl), Name(Name), FullName(std::move(FullName)) {}
104107
FunctionData(const FunctionData &) = default;
105108
FunctionData(FunctionData &&) = default;
106109
FunctionData &operator=(const FunctionData &) = delete;
@@ -118,7 +121,7 @@ class GenericTaintChecker
118121
if (Name.empty() || FullName.empty())
119122
return None;
120123

121-
return FunctionData{FDecl, Name, FullName};
124+
return FunctionData{FDecl, Name, std::move(FullName)};
122125
}
123126

124127
bool isInScope(StringRef Scope) const {

llvm/include/llvm/ADT/AllocatorList.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,6 @@ template <class T, class AllocatorT> class AllocatorList : AllocatorT {
118118

119119
reference operator*() const { return base_type::wrapped()->V; }
120120
pointer operator->() const { return &operator*(); }
121-
122-
friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) {
123-
return L.wrapped() == R.wrapped();
124-
}
125-
friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) {
126-
return !(L == R);
127-
}
128121
};
129122

130123
public:

llvm/include/llvm/ADT/DenseMap.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,22 +1211,18 @@ class DenseMapIterator : DebugEpochBase::HandleBase {
12111211
return Ptr;
12121212
}
12131213

1214-
template <typename T>
1215-
bool operator==(const T &RHS) const {
1216-
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1214+
friend bool operator==(const DenseMapIterator &LHS,
1215+
const DenseMapIterator &RHS) {
1216+
assert((!LHS.Ptr || LHS.isHandleInSync()) && "handle not in sync!");
12171217
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1218-
assert(getEpochAddress() == RHS.getEpochAddress() &&
1218+
assert(LHS.getEpochAddress() == RHS.getEpochAddress() &&
12191219
"comparing incomparable iterators!");
1220-
return Ptr == RHS.Ptr;
1220+
return LHS.Ptr == RHS.Ptr;
12211221
}
12221222

1223-
template <typename T>
1224-
bool operator!=(const T &RHS) const {
1225-
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1226-
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1227-
assert(getEpochAddress() == RHS.getEpochAddress() &&
1228-
"comparing incomparable iterators!");
1229-
return Ptr != RHS.Ptr;
1223+
friend bool operator!=(const DenseMapIterator &LHS,
1224+
const DenseMapIterator &RHS) {
1225+
return !(LHS == RHS);
12301226
}
12311227

12321228
inline DenseMapIterator& operator++() { // Preincrement

llvm/include/llvm/ADT/DenseSet.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,12 @@ class DenseSetImpl {
124124

125125
Iterator& operator++() { ++I; return *this; }
126126
Iterator operator++(int) { auto T = *this; ++I; return T; }
127-
bool operator==(const ConstIterator& X) const { return I == X.I; }
128-
bool operator!=(const ConstIterator& X) const { return I != X.I; }
127+
friend bool operator==(const Iterator &X, const Iterator &Y) {
128+
return X.I == Y.I;
129+
}
130+
friend bool operator!=(const Iterator &X, const Iterator &Y) {
131+
return X.I != Y.I;
132+
}
129133
};
130134

131135
class ConstIterator {
@@ -149,8 +153,12 @@ class DenseSetImpl {
149153

150154
ConstIterator& operator++() { ++I; return *this; }
151155
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
152-
bool operator==(const ConstIterator& X) const { return I == X.I; }
153-
bool operator!=(const ConstIterator& X) const { return I != X.I; }
156+
friend bool operator==(const ConstIterator &X, const ConstIterator &Y) {
157+
return X.I == Y.I;
158+
}
159+
friend bool operator!=(const ConstIterator &X, const ConstIterator &Y) {
160+
return X.I != Y.I;
161+
}
154162
};
155163

156164
using iterator = Iterator;

llvm/include/llvm/ADT/DirectedGraph.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ template <class NodeType, class EdgeType> class DGEdge {
3838

3939
/// Static polymorphism: delegate implementation (via isEqualTo) to the
4040
/// derived class.
41-
bool operator==(const EdgeType &E) const { return getDerived().isEqualTo(E); }
42-
bool operator!=(const EdgeType &E) const { return !operator==(E); }
41+
bool operator==(const DGEdge &E) const {
42+
return getDerived().isEqualTo(E.getDerived());
43+
}
44+
bool operator!=(const DGEdge &E) const { return !operator==(E); }
4345

4446
/// Retrieve the target node this edge connects to.
4547
const NodeType &getTargetNode() const { return TargetNode; }
@@ -91,8 +93,12 @@ template <class NodeType, class EdgeType> class DGNode {
9193

9294
/// Static polymorphism: delegate implementation (via isEqualTo) to the
9395
/// derived class.
94-
bool operator==(const NodeType &N) const { return getDerived().isEqualTo(N); }
95-
bool operator!=(const NodeType &N) const { return !operator==(N); }
96+
friend bool operator==(const NodeType &M, const NodeType &N) {
97+
return M.isEqualTo(N);
98+
}
99+
friend bool operator!=(const NodeType &M, const NodeType &N) {
100+
return !(M == N);
101+
}
96102

97103
const_iterator begin() const { return Edges.begin(); }
98104
const_iterator end() const { return Edges.end(); }

llvm/include/llvm/ADT/STLExtras.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -486,12 +486,12 @@ class early_inc_iterator_impl
486486
return *this;
487487
}
488488

489-
using BaseT::operator==;
490-
bool operator==(const early_inc_iterator_impl &RHS) const {
489+
friend bool operator==(const early_inc_iterator_impl &LHS,
490+
const early_inc_iterator_impl &RHS) {
491491
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
492-
assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
492+
assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!");
493493
#endif
494-
return BaseT::operator==(RHS);
494+
return (const BaseT &)LHS == (const BaseT &)RHS;
495495
}
496496
};
497497

llvm/include/llvm/ADT/StringMap.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,9 @@ class StringMapIterBase
505505
return static_cast<DerivedTy &>(*this);
506506
}
507507

508-
bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
508+
friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) {
509+
return LHS.Ptr == RHS.Ptr;
510+
}
509511

510512
DerivedTy &operator++() { // Preincrement
511513
++Ptr;

llvm/include/llvm/ADT/iterator.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,28 +142,30 @@ class iterator_facade_base
142142
return tmp;
143143
}
144144

145+
#ifndef __cpp_impl_three_way_comparison
145146
bool operator!=(const DerivedT &RHS) const {
146-
return !static_cast<const DerivedT *>(this)->operator==(RHS);
147+
return !(static_cast<const DerivedT &>(*this) == RHS);
147148
}
149+
#endif
148150

149151
bool operator>(const DerivedT &RHS) const {
150152
static_assert(
151153
IsRandomAccess,
152154
"Relational operators are only defined for random access iterators.");
153-
return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
154-
!static_cast<const DerivedT *>(this)->operator==(RHS);
155+
return !(static_cast<const DerivedT &>(*this) < RHS) &&
156+
!(static_cast<const DerivedT &>(*this) == RHS);
155157
}
156158
bool operator<=(const DerivedT &RHS) const {
157159
static_assert(
158160
IsRandomAccess,
159161
"Relational operators are only defined for random access iterators.");
160-
return !static_cast<const DerivedT *>(this)->operator>(RHS);
162+
return !(static_cast<const DerivedT &>(*this) > RHS);
161163
}
162164
bool operator>=(const DerivedT &RHS) const {
163165
static_assert(
164166
IsRandomAccess,
165167
"Relational operators are only defined for random access iterators.");
166-
return !static_cast<const DerivedT *>(this)->operator<(RHS);
168+
return !(static_cast<const DerivedT &>(*this) < RHS);
167169
}
168170

169171
PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
@@ -260,12 +262,16 @@ class iterator_adaptor_base
260262
return *static_cast<DerivedT *>(this);
261263
}
262264

263-
bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
264-
bool operator<(const DerivedT &RHS) const {
265+
friend bool operator==(const iterator_adaptor_base &LHS,
266+
const iterator_adaptor_base &RHS) {
267+
return LHS.I == RHS.I;
268+
}
269+
friend bool operator<(const iterator_adaptor_base &LHS,
270+
const iterator_adaptor_base &RHS) {
265271
static_assert(
266272
BaseT::IsRandomAccess,
267273
"Relational operators are only defined for random access iterators.");
268-
return I < RHS.I;
274+
return LHS.I < RHS.I;
269275
}
270276

271277
ReferenceT operator*() const { return *I; }

0 commit comments

Comments
 (0)