9#ifndef LLVM_ADT_FALLIBLE_ITERATOR_H
10#define LLVM_ADT_FALLIBLE_ITERATOR_H
68template <
typename Underlying>
class fallible_iterator {
70 template <typename T, typename U = decltype(std::declval<T>().operator->())>
71 using enable_if_struct_deref_supported =
72 std::enable_if_t<!std::is_void_v<U>, U>;
83 static fallible_iterator
itr(Underlying I,
Error &Err) {
85 return fallible_iterator(std::move(I), &Err);
93 static fallible_iterator
end(Underlying I) {
94 return fallible_iterator(std::move(I),
nullptr);
98 decltype(
auto)
operator*() {
return *I; }
101 decltype(
auto)
operator*()
const {
return *I; }
105 template <
typename T = Underlying>
107 return I.operator->();
112 template <
typename T = Underlying>
113 enable_if_struct_deref_supported<const T>
operator->()
const {
114 return I.operator->();
125 assert(getErrPtr() &&
"Cannot increment end iterator");
126 if (
auto Err = I.inc())
127 handleError(std::move(Err));
141 assert(getErrPtr() &&
"Cannot decrement end iterator");
142 if (
auto Err = I.dec())
143 handleError(std::move(Err));
162 const fallible_iterator &
RHS) {
165 if (
LHS.isEnd() &&
RHS.isEnd())
169 "Invalid iterators can only be compared against end");
171 bool Equal =
LHS.I ==
RHS.I;
177 (void)!!*
RHS.getErrPtr();
179 (
void)!!*
LHS.getErrPtr();
189 const fallible_iterator &
RHS) {
197 Error *getErrPtr()
const {
return ErrState.getPointer(); }
199 bool isEnd()
const {
return getErrPtr() ==
nullptr; }
201 bool isValid()
const {
return !ErrState.getInt(); }
203 void handleError(
Error Err) {
204 *getErrPtr() = std::move(Err);
205 ErrState.setPointer(
nullptr);
206 ErrState.setInt(
true);
209 void resetCheckedFlag() {
214 mutable PointerIntPair<Error *, 1> ErrState;
219template <
typename Underlying>
226template <
typename Underlying>
231template <
typename Underlying>
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the PointerIntPair class.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
A wrapper class for fallible iterators.
static fallible_iterator end(Underlying I)
Construct a fallible iterator that can be used as an end-of-range value.
friend bool operator!=(const fallible_iterator &LHS, const fallible_iterator &RHS)
Compare fallible iterators for inequality.
static fallible_iterator itr(Underlying I, Error &Err)
Construct a fallible iterator that cannot be used as an end-of-range value.
fallible_iterator & operator--()
Decrement the fallible iterator.
friend bool operator==(const fallible_iterator &LHS, const fallible_iterator &RHS)
Compare fallible iterators for equality.
fallible_iterator & operator++()
Increment the fallible iterator.
enable_if_struct_deref_supported< const T > operator->() const
Forward const structure dereference to the underlying iterator (if the underlying iterator supports i...
enable_if_struct_deref_supported< T > operator->()
Forward structure dereference to the underlying iterator (if the underlying iterator supports it).
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
constexpr std::underlying_type_t< E > Underlying(E Val)
Check that Val is in range for E, and return Val cast to E's underlying type.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
fallible_iterator< Underlying > make_fallible_itr(Underlying I, Error &Err)
Convenience wrapper to make a fallible_iterator value from an instance of an underlying iterator and ...
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
fallible_iterator< Underlying > make_fallible_end(Underlying E)
Convenience wrapper to make a fallible_iterator end value from an instance of an underlying iterator.
iterator_range< fallible_iterator< Underlying > > make_fallible_range(Underlying I, Underlying E, Error &Err)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.