mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-27 02:01:42 +00:00
Update LLVM from stable upstream (#1653)
Replace CheckedMalloc with upstream safe_malloc.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "wpi/iterator.h"
|
||||
#include "wpi/iterator_range.h"
|
||||
#include "wpi/optional.h"
|
||||
#include "wpi/ErrorHandling.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
@@ -52,6 +53,29 @@ using ValueOfRange = typename std::remove_reference<decltype(
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <type_traits>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template <typename T>
|
||||
struct negation : std::integral_constant<bool, !bool(T::value)> {};
|
||||
|
||||
template <typename...> struct conjunction : std::true_type {};
|
||||
template <typename B1> struct conjunction<B1> : B1 {};
|
||||
template <typename B1, typename... Bn>
|
||||
struct conjunction<B1, Bn...>
|
||||
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
|
||||
|
||||
template <typename T> struct make_const_ptr {
|
||||
using type =
|
||||
typename std::add_pointer<typename std::add_const<T>::type>::type;
|
||||
};
|
||||
|
||||
template <typename T> struct make_const_ref {
|
||||
using type = typename std::add_lvalue_reference<
|
||||
typename std::add_const<T>::type>::type;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <functional>
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -176,6 +200,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept(
|
||||
adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
|
||||
}
|
||||
|
||||
/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
|
||||
template <typename T>
|
||||
constexpr bool empty(const T &RangeOrContainer) {
|
||||
return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
|
||||
}
|
||||
|
||||
// mapped_iterator - This is a simple iterator adapter that causes a function to
|
||||
// be applied whenever operator* is invoked on the iterator.
|
||||
|
||||
@@ -403,6 +433,8 @@ make_filter_range(RangeT &&Range, PredicateT Pred) {
|
||||
// forward declarations required by zip_shortest/zip_first
|
||||
template <typename R, typename UnaryPredicate>
|
||||
bool all_of(R &&range, UnaryPredicate P);
|
||||
template <typename R, typename UnaryPredicate>
|
||||
bool any_of(R &&range, UnaryPredicate P);
|
||||
|
||||
template <size_t... I> struct index_sequence;
|
||||
|
||||
@@ -553,6 +585,132 @@ detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
|
||||
std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename Iter>
|
||||
static Iter next_or_end(const Iter &I, const Iter &End) {
|
||||
if (I == End)
|
||||
return End;
|
||||
return std::next(I);
|
||||
}
|
||||
|
||||
template <typename Iter>
|
||||
static auto deref_or_none(const Iter &I, const Iter &End)
|
||||
-> wpi::optional<typename std::remove_const<
|
||||
typename std::remove_reference<decltype(*I)>::type>::type> {
|
||||
if (I == End)
|
||||
return nullopt;
|
||||
return *I;
|
||||
}
|
||||
|
||||
template <typename Iter> struct ZipLongestItemType {
|
||||
using type =
|
||||
wpi::optional<typename std::remove_const<typename std::remove_reference<
|
||||
decltype(*std::declval<Iter>())>::type>::type>;
|
||||
};
|
||||
|
||||
template <typename... Iters> struct ZipLongestTupleType {
|
||||
using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
|
||||
};
|
||||
|
||||
template <typename... Iters>
|
||||
class zip_longest_iterator
|
||||
: public iterator_facade_base<
|
||||
zip_longest_iterator<Iters...>,
|
||||
typename std::common_type<
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<Iters>::iterator_category...>::type,
|
||||
typename ZipLongestTupleType<Iters...>::type,
|
||||
typename std::iterator_traits<typename std::tuple_element<
|
||||
0, std::tuple<Iters...>>::type>::difference_type,
|
||||
typename ZipLongestTupleType<Iters...>::type *,
|
||||
typename ZipLongestTupleType<Iters...>::type> {
|
||||
public:
|
||||
using value_type = typename ZipLongestTupleType<Iters...>::type;
|
||||
|
||||
private:
|
||||
std::tuple<Iters...> iterators;
|
||||
std::tuple<Iters...> end_iterators;
|
||||
|
||||
template <size_t... Ns>
|
||||
bool test(const zip_longest_iterator<Iters...> &other,
|
||||
index_sequence<Ns...>) const {
|
||||
return wpi::any_of(
|
||||
std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
|
||||
std::get<Ns>(other.iterators)...},
|
||||
identity<bool>{});
|
||||
}
|
||||
|
||||
template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
|
||||
return value_type(
|
||||
deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
|
||||
}
|
||||
|
||||
template <size_t... Ns>
|
||||
decltype(iterators) tup_inc(index_sequence<Ns...>) const {
|
||||
return std::tuple<Iters...>(
|
||||
next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
|
||||
}
|
||||
|
||||
public:
|
||||
zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
|
||||
: iterators(std::forward<Iters>(ts.first)...),
|
||||
end_iterators(std::forward<Iters>(ts.second)...) {}
|
||||
|
||||
value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
|
||||
|
||||
value_type operator*() const { return deref(index_sequence_for<Iters...>{}); }
|
||||
|
||||
zip_longest_iterator<Iters...> &operator++() {
|
||||
iterators = tup_inc(index_sequence_for<Iters...>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const zip_longest_iterator<Iters...> &other) const {
|
||||
return !test(other, index_sequence_for<Iters...>{});
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args> class zip_longest_range {
|
||||
public:
|
||||
using iterator =
|
||||
zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
|
||||
using iterator_category = typename iterator::iterator_category;
|
||||
using value_type = typename iterator::value_type;
|
||||
using difference_type = typename iterator::difference_type;
|
||||
using pointer = typename iterator::pointer;
|
||||
using reference = typename iterator::reference;
|
||||
|
||||
private:
|
||||
std::tuple<Args...> ts;
|
||||
|
||||
template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
|
||||
return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
|
||||
adl_end(std::get<Ns>(ts)))...);
|
||||
}
|
||||
|
||||
template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
|
||||
return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
|
||||
adl_end(std::get<Ns>(ts)))...);
|
||||
}
|
||||
|
||||
public:
|
||||
zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
|
||||
|
||||
iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
|
||||
iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// Iterate over two or more iterators at the same time. Iteration continues
|
||||
/// until all iterators reach the end. The wpi::optional only contains a value
|
||||
/// if the iterator has not reached the end.
|
||||
template <typename T, typename U, typename... Args>
|
||||
detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
|
||||
Args &&... args) {
|
||||
return detail::zip_longest_range<T, U, Args...>(
|
||||
std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Iterator wrapper that concatenates sequences together.
|
||||
///
|
||||
/// This can concatenate different iterators, even with different types, into
|
||||
@@ -575,18 +733,20 @@ class concat_iterator
|
||||
/// Note that something like iterator_range seems nice at first here, but the
|
||||
/// range properties are of little benefit and end up getting in the way
|
||||
/// because we need to do mutation on the current iterators.
|
||||
std::tuple<std::pair<IterTs, IterTs>...> IterPairs;
|
||||
std::tuple<IterTs...> Begins;
|
||||
std::tuple<IterTs...> Ends;
|
||||
|
||||
/// Attempts to increment a specific iterator.
|
||||
///
|
||||
/// Returns true if it was able to increment the iterator. Returns false if
|
||||
/// the iterator is already at the end iterator.
|
||||
template <size_t Index> bool incrementHelper() {
|
||||
auto &IterPair = std::get<Index>(IterPairs);
|
||||
if (IterPair.first == IterPair.second)
|
||||
auto &Begin = std::get<Index>(Begins);
|
||||
auto &End = std::get<Index>(Ends);
|
||||
if (Begin == End)
|
||||
return false;
|
||||
|
||||
++IterPair.first;
|
||||
++Begin;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -610,11 +770,12 @@ class concat_iterator
|
||||
/// dereferences the iterator and returns the address of the resulting
|
||||
/// reference.
|
||||
template <size_t Index> ValueT *getHelper() const {
|
||||
auto &IterPair = std::get<Index>(IterPairs);
|
||||
if (IterPair.first == IterPair.second)
|
||||
auto &Begin = std::get<Index>(Begins);
|
||||
auto &End = std::get<Index>(Ends);
|
||||
if (Begin == End)
|
||||
return nullptr;
|
||||
|
||||
return &*IterPair.first;
|
||||
return &*Begin;
|
||||
}
|
||||
|
||||
/// Finds the first non-end iterator, dereferences, and returns the resulting
|
||||
@@ -641,7 +802,7 @@ public:
|
||||
/// iterators.
|
||||
template <typename... RangeTs>
|
||||
explicit concat_iterator(RangeTs &&... Ranges)
|
||||
: IterPairs({std::begin(Ranges), std::end(Ranges)}...) {}
|
||||
: Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
|
||||
|
||||
using BaseT::operator++;
|
||||
|
||||
@@ -653,7 +814,7 @@ public:
|
||||
ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
|
||||
|
||||
bool operator==(const concat_iterator &RHS) const {
|
||||
return IterPairs == RHS.IterPairs;
|
||||
return Begins == RHS.Begins && Ends == RHS.Ends;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -722,6 +883,19 @@ struct less_second {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Function object to apply a binary function to the first component of
|
||||
/// a std::pair.
|
||||
template<typename FuncTy>
|
||||
struct on_first {
|
||||
FuncTy func;
|
||||
|
||||
template <typename T>
|
||||
auto operator()(const T &lhs, const T &rhs) const
|
||||
-> decltype(func(lhs.first, rhs.first)) {
|
||||
return func(lhs.first, rhs.first);
|
||||
}
|
||||
};
|
||||
|
||||
// A subset of N3658. More stuff can be added as-needed.
|
||||
|
||||
/// Represents a compile-time sequence of integers.
|
||||
@@ -862,6 +1036,18 @@ void DeleteContainerSeconds(Container &C) {
|
||||
C.clear();
|
||||
}
|
||||
|
||||
/// Get the size of a range. This is a wrapper function around std::distance
|
||||
/// which is only enabled when the operation is O(1).
|
||||
template <typename R>
|
||||
auto size(R &&Range, typename std::enable_if<
|
||||
std::is_same<typename std::iterator_traits<decltype(
|
||||
Range.begin())>::iterator_category,
|
||||
std::random_access_iterator_tag>::value,
|
||||
void>::type * = nullptr)
|
||||
-> decltype(std::distance(Range.begin(), Range.end())) {
|
||||
return std::distance(Range.begin(), Range.end());
|
||||
}
|
||||
|
||||
/// Provide wrappers to std::for_each which take ranges instead of having to
|
||||
/// pass begin/end explicitly.
|
||||
template <typename R, typename UnaryPredicate>
|
||||
@@ -972,6 +1158,33 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
|
||||
return std::lower_bound(adl_begin(Range), adl_end(Range), I);
|
||||
}
|
||||
|
||||
template <typename R, typename ForwardIt, typename Compare>
|
||||
auto lower_bound(R &&Range, ForwardIt I, Compare C)
|
||||
-> decltype(adl_begin(Range)) {
|
||||
return std::lower_bound(adl_begin(Range), adl_end(Range), I, C);
|
||||
}
|
||||
|
||||
/// Provide wrappers to std::upper_bound which take ranges instead of having to
|
||||
/// pass begin/end explicitly.
|
||||
template <typename R, typename ForwardIt>
|
||||
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) {
|
||||
return std::upper_bound(adl_begin(Range), adl_end(Range), I);
|
||||
}
|
||||
|
||||
template <typename R, typename ForwardIt, typename Compare>
|
||||
auto upper_bound(R &&Range, ForwardIt I, Compare C)
|
||||
-> decltype(adl_begin(Range)) {
|
||||
return std::upper_bound(adl_begin(Range), adl_end(Range), I, C);
|
||||
}
|
||||
/// Wrapper function around std::equal to detect if all elements
|
||||
/// in a container are same.
|
||||
template <typename R>
|
||||
bool is_splat(R &&Range) {
|
||||
size_t range_size = size(Range);
|
||||
return range_size != 0 && (range_size == 1 ||
|
||||
std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
|
||||
}
|
||||
|
||||
/// Given a range of type R, iterate the entire range and return a
|
||||
/// SmallVector with elements of the vector. This is useful, for example,
|
||||
/// when you want to iterate a range and then sort the results.
|
||||
@@ -993,18 +1206,6 @@ void erase_if(Container &C, UnaryPredicate P) {
|
||||
C.erase(remove_if(C, P), C.end());
|
||||
}
|
||||
|
||||
/// Get the size of a range. This is a wrapper function around std::distance
|
||||
/// which is only enabled when the operation is O(1).
|
||||
template <typename R>
|
||||
auto size(R &&Range, typename std::enable_if<
|
||||
std::is_same<typename std::iterator_traits<decltype(
|
||||
Range.begin())>::iterator_category,
|
||||
std::random_access_iterator_tag>::value,
|
||||
void>::type * = nullptr)
|
||||
-> decltype(std::distance(Range.begin(), Range.end())) {
|
||||
return std::distance(Range.begin(), Range.end());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <memory>
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -1217,6 +1418,40 @@ auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
|
||||
Indices{});
|
||||
}
|
||||
|
||||
/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
|
||||
/// time. Not meant for use with random-access iterators.
|
||||
template <typename IterTy>
|
||||
bool hasNItems(
|
||||
IterTy &&Begin, IterTy &&End, unsigned N,
|
||||
typename std::enable_if<
|
||||
!std::is_same<
|
||||
typename std::iterator_traits<typename std::remove_reference<
|
||||
decltype(Begin)>::type>::iterator_category,
|
||||
std::random_access_iterator_tag>::value,
|
||||
void>::type * = nullptr) {
|
||||
for (; N; --N, ++Begin)
|
||||
if (Begin == End)
|
||||
return false; // Too few.
|
||||
return Begin == End;
|
||||
}
|
||||
|
||||
/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
|
||||
/// time. Not meant for use with random-access iterators.
|
||||
template <typename IterTy>
|
||||
bool hasNItemsOrMore(
|
||||
IterTy &&Begin, IterTy &&End, unsigned N,
|
||||
typename std::enable_if<
|
||||
!std::is_same<
|
||||
typename std::iterator_traits<typename std::remove_reference<
|
||||
decltype(Begin)>::type>::iterator_category,
|
||||
std::random_access_iterator_tag>::value,
|
||||
void>::type * = nullptr) {
|
||||
for (; N; --N, ++Begin)
|
||||
if (Begin == End)
|
||||
return false; // Too few.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace wpi
|
||||
|
||||
#endif // LLVM_ADT_STLEXTRAS_H
|
||||
|
||||
Reference in New Issue
Block a user