mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
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
This commit is contained in:
parent
ac71050514
commit
2fc9f32ca3
@ -118,13 +118,6 @@ private:
|
||||
|
||||
reference operator*() const { return base_type::wrapped()->V; }
|
||||
pointer operator->() const { return &operator*(); }
|
||||
|
||||
friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) {
|
||||
return L.wrapped() == R.wrapped();
|
||||
}
|
||||
friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) {
|
||||
return !(L == R);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -1242,22 +1242,18 @@ public:
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const T &RHS) const {
|
||||
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
|
||||
friend bool operator==(const DenseMapIterator &LHS,
|
||||
const DenseMapIterator &RHS) {
|
||||
assert((!LHS.Ptr || LHS.isHandleInSync()) && "handle not in sync!");
|
||||
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
|
||||
assert(getEpochAddress() == RHS.getEpochAddress() &&
|
||||
assert(LHS.getEpochAddress() == RHS.getEpochAddress() &&
|
||||
"comparing incomparable iterators!");
|
||||
return Ptr == RHS.Ptr;
|
||||
return LHS.Ptr == RHS.Ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const T &RHS) const {
|
||||
assert((!Ptr || isHandleInSync()) && "handle not in sync!");
|
||||
assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
|
||||
assert(getEpochAddress() == RHS.getEpochAddress() &&
|
||||
"comparing incomparable iterators!");
|
||||
return Ptr != RHS.Ptr;
|
||||
friend bool operator!=(const DenseMapIterator &LHS,
|
||||
const DenseMapIterator &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
inline DenseMapIterator& operator++() { // Preincrement
|
||||
|
@ -130,8 +130,12 @@ public:
|
||||
|
||||
Iterator& operator++() { ++I; return *this; }
|
||||
Iterator operator++(int) { auto T = *this; ++I; return T; }
|
||||
bool operator==(const ConstIterator& X) const { return I == X.I; }
|
||||
bool operator!=(const ConstIterator& X) const { return I != X.I; }
|
||||
friend bool operator==(const Iterator &X, const Iterator &Y) {
|
||||
return X.I == Y.I;
|
||||
}
|
||||
friend bool operator!=(const Iterator &X, const Iterator &Y) {
|
||||
return X.I != Y.I;
|
||||
}
|
||||
};
|
||||
|
||||
class ConstIterator {
|
||||
@ -155,8 +159,12 @@ public:
|
||||
|
||||
ConstIterator& operator++() { ++I; return *this; }
|
||||
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
|
||||
bool operator==(const ConstIterator& X) const { return I == X.I; }
|
||||
bool operator!=(const ConstIterator& X) const { return I != X.I; }
|
||||
friend bool operator==(const ConstIterator &X, const ConstIterator &Y) {
|
||||
return X.I == Y.I;
|
||||
}
|
||||
friend bool operator!=(const ConstIterator &X, const ConstIterator &Y) {
|
||||
return X.I != Y.I;
|
||||
}
|
||||
};
|
||||
|
||||
using iterator = Iterator;
|
||||
|
@ -38,8 +38,10 @@ public:
|
||||
|
||||
/// Static polymorphism: delegate implementation (via isEqualTo) to the
|
||||
/// derived class.
|
||||
bool operator==(const EdgeType &E) const { return getDerived().isEqualTo(E); }
|
||||
bool operator!=(const EdgeType &E) const { return !operator==(E); }
|
||||
bool operator==(const DGEdge &E) const {
|
||||
return getDerived().isEqualTo(E.getDerived());
|
||||
}
|
||||
bool operator!=(const DGEdge &E) const { return !operator==(E); }
|
||||
|
||||
/// Retrieve the target node this edge connects to.
|
||||
const NodeType &getTargetNode() const { return TargetNode; }
|
||||
@ -91,8 +93,12 @@ public:
|
||||
|
||||
/// Static polymorphism: delegate implementation (via isEqualTo) to the
|
||||
/// derived class.
|
||||
bool operator==(const NodeType &N) const { return getDerived().isEqualTo(N); }
|
||||
bool operator!=(const NodeType &N) const { return !operator==(N); }
|
||||
friend bool operator==(const NodeType &M, const NodeType &N) {
|
||||
return M.isEqualTo(N);
|
||||
}
|
||||
friend bool operator!=(const NodeType &M, const NodeType &N) {
|
||||
return !(M == N);
|
||||
}
|
||||
|
||||
const_iterator begin() const { return Edges.begin(); }
|
||||
const_iterator end() const { return Edges.end(); }
|
||||
|
@ -555,12 +555,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
using BaseT::operator==;
|
||||
bool operator==(const early_inc_iterator_impl &RHS) const {
|
||||
friend bool operator==(const early_inc_iterator_impl &LHS,
|
||||
const early_inc_iterator_impl &RHS) {
|
||||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
|
||||
assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
|
||||
assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!");
|
||||
#endif
|
||||
return BaseT::operator==(RHS);
|
||||
return (const BaseT &)LHS == (const BaseT &)RHS;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -389,7 +389,9 @@ public:
|
||||
return static_cast<DerivedTy &>(*this);
|
||||
}
|
||||
|
||||
bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
|
||||
friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) {
|
||||
return LHS.Ptr == RHS.Ptr;
|
||||
}
|
||||
|
||||
DerivedTy &operator++() { // Preincrement
|
||||
++Ptr;
|
||||
|
@ -142,28 +142,30 @@ public:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#ifndef __cpp_impl_three_way_comparison
|
||||
bool operator!=(const DerivedT &RHS) const {
|
||||
return !static_cast<const DerivedT *>(this)->operator==(RHS);
|
||||
return !(static_cast<const DerivedT &>(*this) == RHS);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator>(const DerivedT &RHS) const {
|
||||
static_assert(
|
||||
IsRandomAccess,
|
||||
"Relational operators are only defined for random access iterators.");
|
||||
return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
|
||||
!static_cast<const DerivedT *>(this)->operator==(RHS);
|
||||
return !(static_cast<const DerivedT &>(*this) < RHS) &&
|
||||
!(static_cast<const DerivedT &>(*this) == RHS);
|
||||
}
|
||||
bool operator<=(const DerivedT &RHS) const {
|
||||
static_assert(
|
||||
IsRandomAccess,
|
||||
"Relational operators are only defined for random access iterators.");
|
||||
return !static_cast<const DerivedT *>(this)->operator>(RHS);
|
||||
return !(static_cast<const DerivedT &>(*this) > RHS);
|
||||
}
|
||||
bool operator>=(const DerivedT &RHS) const {
|
||||
static_assert(
|
||||
IsRandomAccess,
|
||||
"Relational operators are only defined for random access iterators.");
|
||||
return !static_cast<const DerivedT *>(this)->operator<(RHS);
|
||||
return !(static_cast<const DerivedT &>(*this) < RHS);
|
||||
}
|
||||
|
||||
PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
|
||||
@ -260,12 +262,16 @@ public:
|
||||
return *static_cast<DerivedT *>(this);
|
||||
}
|
||||
|
||||
bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
|
||||
bool operator<(const DerivedT &RHS) const {
|
||||
friend bool operator==(const iterator_adaptor_base &LHS,
|
||||
const iterator_adaptor_base &RHS) {
|
||||
return LHS.I == RHS.I;
|
||||
}
|
||||
friend bool operator<(const iterator_adaptor_base &LHS,
|
||||
const iterator_adaptor_base &RHS) {
|
||||
static_assert(
|
||||
BaseT::IsRandomAccess,
|
||||
"Relational operators are only defined for random access iterators.");
|
||||
return I < RHS.I;
|
||||
return LHS.I < RHS.I;
|
||||
}
|
||||
|
||||
ReferenceT operator*() const { return *I; }
|
||||
|
@ -590,7 +590,6 @@ public:
|
||||
T &operator*() const { return *static_cast<T *>(N); }
|
||||
|
||||
bool operator==(const iterator &X) const { return N == X.N; }
|
||||
bool operator!=(const iterator &X) const { return N != X.N; }
|
||||
};
|
||||
|
||||
class const_iterator
|
||||
@ -613,7 +612,6 @@ public:
|
||||
const T &operator*() const { return *static_cast<const T *>(N); }
|
||||
|
||||
bool operator==(const const_iterator &X) const { return N == X.N; }
|
||||
bool operator!=(const const_iterator &X) const { return N != X.N; }
|
||||
};
|
||||
|
||||
iterator begin() {
|
||||
|
@ -736,10 +736,10 @@ namespace llvm {
|
||||
++*this;
|
||||
return res;
|
||||
}
|
||||
bool operator!=(const SingleLinkedListIterator<T> &Other) {
|
||||
bool operator!=(const SingleLinkedListIterator<T> &Other) const {
|
||||
return P != Other.operator->();
|
||||
}
|
||||
bool operator==(const SingleLinkedListIterator<T> &Other) {
|
||||
bool operator==(const SingleLinkedListIterator<T> &Other) const {
|
||||
return P == Other.operator->();
|
||||
}
|
||||
T &operator*() const {
|
||||
|
@ -382,11 +382,6 @@ inline bool operator==(const DWARFDie::iterator &LHS,
|
||||
return LHS.Die == RHS.Die;
|
||||
}
|
||||
|
||||
inline bool operator!=(const DWARFDie::iterator &LHS,
|
||||
const DWARFDie::iterator &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
// These inline functions must follow the DWARFDie::iterator definition above
|
||||
// as they use functions from that class.
|
||||
inline DWARFDie::iterator DWARFDie::begin() const {
|
||||
@ -468,11 +463,6 @@ inline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS,
|
||||
return LHS.equals(RHS);
|
||||
}
|
||||
|
||||
inline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS,
|
||||
const std::reverse_iterator<DWARFDie::iterator> &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
inline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const {
|
||||
return llvm::make_reverse_iterator(end());
|
||||
}
|
||||
|
@ -167,10 +167,5 @@ inline bool operator==(const DWARFExpression::iterator &LHS,
|
||||
const DWARFExpression::iterator &RHS) {
|
||||
return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
|
||||
}
|
||||
|
||||
inline bool operator!=(const DWARFExpression::iterator &LHS,
|
||||
const DWARFExpression::iterator &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -938,10 +938,8 @@ public:
|
||||
|
||||
bool td_empty() const { return TargetDepAttrs.empty(); }
|
||||
|
||||
bool operator==(const AttrBuilder &B);
|
||||
bool operator!=(const AttrBuilder &B) {
|
||||
return !(*this == B);
|
||||
}
|
||||
bool operator==(const AttrBuilder &B) const;
|
||||
bool operator!=(const AttrBuilder &B) const { return !(*this == B); }
|
||||
};
|
||||
|
||||
namespace AttributeFuncs {
|
||||
|
@ -327,7 +327,9 @@ public:
|
||||
phi_iterator_impl() = default;
|
||||
|
||||
// Allow conversion between instantiations where valid.
|
||||
template <typename PHINodeU, typename BBIteratorU>
|
||||
template <typename PHINodeU, typename BBIteratorU,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<PHINodeU *, PHINodeT *>::value>>
|
||||
phi_iterator_impl(const phi_iterator_impl<PHINodeU, BBIteratorU> &Arg)
|
||||
: PN(Arg.PN) {}
|
||||
|
||||
|
@ -36,11 +36,13 @@ public:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const AccessorIterator &Other) {
|
||||
bool operator==(const AccessorIterator &Other) const {
|
||||
return A.P == Other.A.P;
|
||||
}
|
||||
|
||||
bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
|
||||
bool operator!=(const AccessorIterator &Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
AccessorT& operator*() { return A; }
|
||||
AccessorT* operator->() { return &A; }
|
||||
|
@ -67,10 +67,10 @@ public:
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const CoverageMappingIterator &RHS) {
|
||||
bool operator==(const CoverageMappingIterator &RHS) const {
|
||||
return Reader == RHS.Reader;
|
||||
}
|
||||
bool operator!=(const CoverageMappingIterator &RHS) {
|
||||
bool operator!=(const CoverageMappingIterator &RHS) const {
|
||||
return Reader != RHS.Reader;
|
||||
}
|
||||
Expected<CoverageMappingRecord &> operator*() {
|
||||
|
@ -50,8 +50,12 @@ public:
|
||||
InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
|
||||
|
||||
InstrProfIterator &operator++() { Increment(); return *this; }
|
||||
bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; }
|
||||
bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; }
|
||||
bool operator==(const InstrProfIterator &RHS) const {
|
||||
return Reader == RHS.Reader;
|
||||
}
|
||||
bool operator!=(const InstrProfIterator &RHS) const {
|
||||
return Reader != RHS.Reader;
|
||||
}
|
||||
value_type &operator*() { return Record; }
|
||||
value_type *operator->() { return &Record; }
|
||||
};
|
||||
|
@ -121,12 +121,12 @@ public:
|
||||
|
||||
bool valid() const { return BorrowedImpl != nullptr; }
|
||||
|
||||
bool operator==(const RefType &Other) const {
|
||||
if (BorrowedImpl != Other.BorrowedImpl)
|
||||
friend bool operator==(const RefType &LHS, const RefType &RHS) {
|
||||
if (LHS.BorrowedImpl != RHS.BorrowedImpl)
|
||||
return false;
|
||||
if (ViewOffset != Other.ViewOffset)
|
||||
if (LHS.ViewOffset != RHS.ViewOffset)
|
||||
return false;
|
||||
if (Length != Other.Length)
|
||||
if (LHS.Length != RHS.Length)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -322,10 +322,10 @@ public:
|
||||
return It;
|
||||
}
|
||||
|
||||
bool operator==(const RepeatedSubstringIterator &Other) {
|
||||
bool operator==(const RepeatedSubstringIterator &Other) const {
|
||||
return N == Other.N;
|
||||
}
|
||||
bool operator!=(const RepeatedSubstringIterator &Other) {
|
||||
bool operator!=(const RepeatedSubstringIterator &Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ namespace {
|
||||
return RegSrcs[Idx].SubReg;
|
||||
}
|
||||
|
||||
bool operator==(const ValueTrackerResult &Other) {
|
||||
bool operator==(const ValueTrackerResult &Other) const {
|
||||
if (Other.getInst() != getInst())
|
||||
return false;
|
||||
|
||||
|
@ -1856,7 +1856,7 @@ bool AttrBuilder::hasAlignmentAttr() const {
|
||||
return Alignment != 0;
|
||||
}
|
||||
|
||||
bool AttrBuilder::operator==(const AttrBuilder &B) {
|
||||
bool AttrBuilder::operator==(const AttrBuilder &B) const {
|
||||
if (Attrs != B.Attrs)
|
||||
return false;
|
||||
|
||||
|
@ -650,7 +650,7 @@ Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {
|
||||
writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
|
||||
|
||||
for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
|
||||
if (TableEntry.SegSelectorSize != 0)
|
||||
if (TableEntry.SegSelectorSize != yaml::Hex8{0})
|
||||
if (Error Err = writeVariableSizedInteger(Pair.Segment,
|
||||
TableEntry.SegSelectorSize,
|
||||
OS, DI.IsLittleEndian))
|
||||
|
@ -149,8 +149,8 @@ struct CHIArg {
|
||||
// The instruction (VN) which uses the values flowing out of CHI.
|
||||
Instruction *I;
|
||||
|
||||
bool operator==(const CHIArg &A) { return VN == A.VN; }
|
||||
bool operator!=(const CHIArg &A) { return !(*this == A); }
|
||||
bool operator==(const CHIArg &A) const { return VN == A.VN; }
|
||||
bool operator!=(const CHIArg &A) const { return !(*this == A); }
|
||||
};
|
||||
|
||||
using CHIIt = SmallVectorImpl<CHIArg>::iterator;
|
||||
|
@ -806,19 +806,19 @@ public:
|
||||
bool IsASCII = DbgVariables == DVASCII;
|
||||
switch (C) {
|
||||
case LineChar::RangeStart:
|
||||
return IsASCII ? "^" : u8"\u2548";
|
||||
return IsASCII ? "^" : (const char *)u8"\u2548";
|
||||
case LineChar::RangeMid:
|
||||
return IsASCII ? "|" : u8"\u2503";
|
||||
return IsASCII ? "|" : (const char *)u8"\u2503";
|
||||
case LineChar::RangeEnd:
|
||||
return IsASCII ? "v" : u8"\u253b";
|
||||
return IsASCII ? "v" : (const char *)u8"\u253b";
|
||||
case LineChar::LabelVert:
|
||||
return IsASCII ? "|" : u8"\u2502";
|
||||
return IsASCII ? "|" : (const char *)u8"\u2502";
|
||||
case LineChar::LabelCornerNew:
|
||||
return IsASCII ? "/" : u8"\u250c";
|
||||
return IsASCII ? "/" : (const char *)u8"\u250c";
|
||||
case LineChar::LabelCornerActive:
|
||||
return IsASCII ? "|" : u8"\u2520";
|
||||
return IsASCII ? "|" : (const char *)u8"\u2520";
|
||||
case LineChar::LabelHoriz:
|
||||
return IsASCII ? "-" : u8"\u2500";
|
||||
return IsASCII ? "-" : (const char *)u8"\u2500";
|
||||
}
|
||||
llvm_unreachable("Unhandled LineChar enum");
|
||||
}
|
||||
|
@ -472,21 +472,21 @@ TEST(STLExtrasTest, to_address) {
|
||||
|
||||
// Check fancy pointer overload for unique_ptr
|
||||
std::unique_ptr<int> V2 = std::make_unique<int>(0);
|
||||
EXPECT_EQ(V2.get(), to_address(V2));
|
||||
EXPECT_EQ(V2.get(), llvm::to_address(V2));
|
||||
|
||||
V2.reset(V1);
|
||||
EXPECT_EQ(V1, to_address(V2));
|
||||
EXPECT_EQ(V1, llvm::to_address(V2));
|
||||
V2.release();
|
||||
|
||||
// Check fancy pointer overload for shared_ptr
|
||||
std::shared_ptr<int> V3 = std::make_shared<int>(0);
|
||||
std::shared_ptr<int> V4 = V3;
|
||||
EXPECT_EQ(V3.get(), V4.get());
|
||||
EXPECT_EQ(V3.get(), to_address(V3));
|
||||
EXPECT_EQ(V4.get(), to_address(V4));
|
||||
EXPECT_EQ(V3.get(), llvm::to_address(V3));
|
||||
EXPECT_EQ(V4.get(), llvm::to_address(V4));
|
||||
|
||||
V3.reset(V1);
|
||||
EXPECT_EQ(V1, to_address(V3));
|
||||
EXPECT_EQ(V1, llvm::to_address(V3));
|
||||
}
|
||||
|
||||
TEST(STLExtrasTest, partition_point) {
|
||||
|
Loading…
Reference in New Issue
Block a user