[wpiutil] Upgrade to LLVM 18.1.1 (#6405)

This commit is contained in:
Tyler Veness
2024-03-17 18:39:03 -07:00
committed by GitHub
parent fd4424eb89
commit b4674bacb9
62 changed files with 964 additions and 664 deletions

View File

@@ -351,10 +351,10 @@ struct UniquePtrCast : public CastIsPossible<To, From *> {
static inline CastResultType castFailed() { return CastResultType(nullptr); }
static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
if (!Self::isPossible(f))
static inline CastResultType doCastIfPossible(std::unique_ptr<From> &f) {
if (!Self::isPossible(f.get()))
return castFailed();
return doCast(f);
return doCast(std::move(f));
}
};
@@ -664,10 +664,9 @@ template <typename To, typename From>
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &Val) {
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
std::forward<std::unique_ptr<From> &&>(Val));
return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(Val);
}
/// isa_and_present<X> - Functionally identical to isa, except that a null value

View File

@@ -32,6 +32,19 @@ namespace sys {
template <typename D = std::chrono::nanoseconds>
using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
// utc_clock and utc_time are only available since C++20. Add enough code to
// support formatting date/time in UTC.
class UtcClock : public std::chrono::system_clock {};
template <typename D = std::chrono::nanoseconds>
using UtcTime = std::chrono::time_point<UtcClock, D>;
/// Convert a std::time_t to a UtcTime
inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
using namespace std::chrono;
return UtcTime<seconds>(seconds(T));
}
/// Convert a TimePoint to std::time_t
inline std::time_t toTimeT(TimePoint<> TP) {
using namespace std::chrono;
@@ -39,6 +52,13 @@ inline std::time_t toTimeT(TimePoint<> TP) {
time_point_cast<system_clock::time_point::duration>(TP));
}
/// Convert a UtcTime to std::time_t
inline std::time_t toTimeT(UtcTime<> TP) {
using namespace std::chrono;
return system_clock::to_time_t(time_point<system_clock, seconds>(
duration_cast<seconds>(TP.time_since_epoch())));
}
/// Convert a std::time_t to a TimePoint
inline TimePoint<std::chrono::seconds>
toTimePoint(std::time_t T) {
@@ -57,6 +77,7 @@ toTimePoint(std::time_t T, uint32_t nsec) {
} // namespace sys
raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);
} // namespace wpi

View File

@@ -162,6 +162,25 @@
#define LLVM_DEPRECATED(MSG, FIX) [[deprecated(MSG)]]
#endif
// clang-format off
#if defined(__clang__) || defined(__GNUC__)
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
_Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
_Pragma("warning(push)") \
_Pragma("warning(disable : 4996)")
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
_Pragma("warning(pop)")
#else
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP
#endif
// clang-format on
// Indicate that a non-static, non-const C++ member function reinitializes
// the entire object to a known state, independent of the previous state of
// the object.
@@ -330,6 +349,12 @@
#define LLVM_GSL_POINTER
#endif
#if LLVM_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L
#define LLVM_CTOR_NODISCARD [[nodiscard]]
#else
#define LLVM_CTOR_NODISCARD
#endif
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifndef LLVM_EXTENSION
@@ -598,4 +623,12 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
#endif
/// \macro LLVM_PREFERRED_TYPE
/// Adjust type of bit-field in debug info.
#if __has_attribute(preferred_type)
#define LLVM_PREFERRED_TYPE(T) __attribute__((preferred_type(T)))
#else
#define LLVM_PREFERRED_TYPE(T)
#endif
#endif

View File

@@ -13,6 +13,7 @@
#ifndef WPIUTIL_WPI_ENDIAN_H
#define WPIUTIL_WPI_ENDIAN_H
#include "wpi/bit.h"
#include "wpi/Compiler.h"
#include "wpi/SwapByteOrder.h"
#include <cassert>
@@ -24,8 +25,6 @@
namespace wpi {
namespace support {
enum endianness {big, little, native};
// These are named values for common alignments.
enum {aligned = 0, unaligned = 1};
@@ -41,28 +40,24 @@ struct PickAlignment {
namespace endian {
constexpr endianness system_endianness() {
return sys::IsBigEndianHost ? big : little;
}
template <typename value_type>
inline value_type byte_swap(value_type value, endianness endian) {
if ((endian != native) && (endian != system_endianness()))
[[nodiscard]] inline value_type byte_swap(value_type value, endianness endian) {
if (endian != wpi::endianness::native)
sys::swapByteOrder(value);
return value;
}
/// Swap the bytes of value to match the given endianness.
template<typename value_type, endianness endian>
inline value_type byte_swap(value_type value) {
if constexpr ((endian != native) && (endian != system_endianness()))
template <typename value_type, endianness endian>
[[nodiscard]] inline value_type byte_swap(value_type value) {
if constexpr (endian != wpi::endianness::native)
sys::swapByteOrder(value);
return value;
}
/// Read a value of a particular endianness from memory.
template <typename value_type, std::size_t alignment>
inline value_type read(const void *memory, endianness endian) {
template <typename value_type, std::size_t alignment = unaligned>
[[nodiscard]] inline value_type read(const void *memory, endianness endian) {
value_type ret;
memcpy(&ret,
@@ -72,30 +67,29 @@ inline value_type read(const void *memory, endianness endian) {
return byte_swap<value_type>(ret, endian);
}
template<typename value_type,
endianness endian,
std::size_t alignment>
inline value_type read(const void *memory) {
template <typename value_type, endianness endian, std::size_t alignment>
[[nodiscard]] inline value_type read(const void *memory) {
return read<value_type, alignment>(memory, endian);
}
/// Read a value of a particular endianness from a buffer, and increment the
/// buffer past that value.
template <typename value_type, std::size_t alignment, typename CharT>
inline value_type readNext(const CharT *&memory, endianness endian) {
[[nodiscard]] inline value_type readNext(const CharT *&memory,
endianness endian) {
value_type ret = read<value_type, alignment>(memory, endian);
memory += sizeof(value_type);
return ret;
}
template<typename value_type, endianness endian, std::size_t alignment,
typename CharT>
inline value_type readNext(const CharT *&memory) {
template <typename value_type, endianness endian, std::size_t alignment,
typename CharT>
[[nodiscard]] inline value_type readNext(const CharT *&memory) {
return readNext<value_type, alignment, CharT>(memory, endian);
}
/// Write a value to memory with a particular endianness.
template <typename value_type, std::size_t alignment>
template <typename value_type, std::size_t alignment = unaligned>
inline void write(void *memory, value_type value, endianness endian) {
value = byte_swap<value_type>(value, endian);
memcpy(LLVM_ASSUME_ALIGNED(
@@ -116,7 +110,8 @@ using make_unsigned_t = std::make_unsigned_t<value_type>;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
template <typename value_type, endianness endian, std::size_t alignment>
inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
[[nodiscard]] inline value_type readAtBitAlignment(const void *memory,
uint64_t startBit) {
assert(startBit < 8);
if (startBit == 0)
return read<value_type, endian, alignment>(memory);
@@ -269,125 +264,164 @@ public:
} // end namespace detail
using ulittle16_t =
detail::packed_endian_specific_integral<uint16_t, little, unaligned>;
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::little,
unaligned>;
using ulittle32_t =
detail::packed_endian_specific_integral<uint32_t, little, unaligned>;
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::little,
unaligned>;
using ulittle64_t =
detail::packed_endian_specific_integral<uint64_t, little, unaligned>;
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::little,
unaligned>;
using little16_t =
detail::packed_endian_specific_integral<int16_t, little, unaligned>;
detail::packed_endian_specific_integral<int16_t, wpi::endianness::little,
unaligned>;
using little32_t =
detail::packed_endian_specific_integral<int32_t, little, unaligned>;
detail::packed_endian_specific_integral<int32_t, wpi::endianness::little,
unaligned>;
using little64_t =
detail::packed_endian_specific_integral<int64_t, little, unaligned>;
detail::packed_endian_specific_integral<int64_t, wpi::endianness::little,
unaligned>;
using aligned_ulittle16_t =
detail::packed_endian_specific_integral<uint16_t, little, aligned>;
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::little,
aligned>;
using aligned_ulittle32_t =
detail::packed_endian_specific_integral<uint32_t, little, aligned>;
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::little,
aligned>;
using aligned_ulittle64_t =
detail::packed_endian_specific_integral<uint64_t, little, aligned>;
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::little,
aligned>;
using aligned_little16_t =
detail::packed_endian_specific_integral<int16_t, little, aligned>;
detail::packed_endian_specific_integral<int16_t, wpi::endianness::little,
aligned>;
using aligned_little32_t =
detail::packed_endian_specific_integral<int32_t, little, aligned>;
detail::packed_endian_specific_integral<int32_t, wpi::endianness::little,
aligned>;
using aligned_little64_t =
detail::packed_endian_specific_integral<int64_t, little, aligned>;
detail::packed_endian_specific_integral<int64_t, wpi::endianness::little,
aligned>;
using ubig16_t =
detail::packed_endian_specific_integral<uint16_t, big, unaligned>;
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::big,
unaligned>;
using ubig32_t =
detail::packed_endian_specific_integral<uint32_t, big, unaligned>;
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::big,
unaligned>;
using ubig64_t =
detail::packed_endian_specific_integral<uint64_t, big, unaligned>;
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::big,
unaligned>;
using big16_t =
detail::packed_endian_specific_integral<int16_t, big, unaligned>;
detail::packed_endian_specific_integral<int16_t, wpi::endianness::big,
unaligned>;
using big32_t =
detail::packed_endian_specific_integral<int32_t, big, unaligned>;
detail::packed_endian_specific_integral<int32_t, wpi::endianness::big,
unaligned>;
using big64_t =
detail::packed_endian_specific_integral<int64_t, big, unaligned>;
detail::packed_endian_specific_integral<int64_t, wpi::endianness::big,
unaligned>;
using aligned_ubig16_t =
detail::packed_endian_specific_integral<uint16_t, big, aligned>;
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::big,
aligned>;
using aligned_ubig32_t =
detail::packed_endian_specific_integral<uint32_t, big, aligned>;
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::big,
aligned>;
using aligned_ubig64_t =
detail::packed_endian_specific_integral<uint64_t, big, aligned>;
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::big,
aligned>;
using aligned_big16_t =
detail::packed_endian_specific_integral<int16_t, big, aligned>;
detail::packed_endian_specific_integral<int16_t, wpi::endianness::big,
aligned>;
using aligned_big32_t =
detail::packed_endian_specific_integral<int32_t, big, aligned>;
detail::packed_endian_specific_integral<int32_t, wpi::endianness::big,
aligned>;
using aligned_big64_t =
detail::packed_endian_specific_integral<int64_t, big, aligned>;
detail::packed_endian_specific_integral<int64_t, wpi::endianness::big,
aligned>;
using unaligned_uint16_t =
detail::packed_endian_specific_integral<uint16_t, native, unaligned>;
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::native,
unaligned>;
using unaligned_uint32_t =
detail::packed_endian_specific_integral<uint32_t, native, unaligned>;
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::native,
unaligned>;
using unaligned_uint64_t =
detail::packed_endian_specific_integral<uint64_t, native, unaligned>;
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::native,
unaligned>;
using unaligned_int16_t =
detail::packed_endian_specific_integral<int16_t, native, unaligned>;
detail::packed_endian_specific_integral<int16_t, wpi::endianness::native,
unaligned>;
using unaligned_int32_t =
detail::packed_endian_specific_integral<int32_t, native, unaligned>;
detail::packed_endian_specific_integral<int32_t, wpi::endianness::native,
unaligned>;
using unaligned_int64_t =
detail::packed_endian_specific_integral<int64_t, native, unaligned>;
detail::packed_endian_specific_integral<int64_t, wpi::endianness::native,
unaligned>;
template <typename T>
using little_t = detail::packed_endian_specific_integral<T, little, unaligned>;
using little_t =
detail::packed_endian_specific_integral<T, wpi::endianness::little,
unaligned>;
template <typename T>
using big_t = detail::packed_endian_specific_integral<T, big, unaligned>;
using big_t = detail::packed_endian_specific_integral<T, wpi::endianness::big,
unaligned>;
template <typename T>
using aligned_little_t =
detail::packed_endian_specific_integral<T, little, aligned>;
detail::packed_endian_specific_integral<T, wpi::endianness::little,
aligned>;
template <typename T>
using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>;
using aligned_big_t =
detail::packed_endian_specific_integral<T, wpi::endianness::big, aligned>;
namespace endian {
template <typename T> inline T read(const void *P, endianness E) {
return read<T, unaligned>(P, E);
}
template <typename T, endianness E> inline T read(const void *P) {
template <typename T, endianness E> [[nodiscard]] inline T read(const void *P) {
return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
}
inline uint16_t read16(const void *P, endianness E) {
[[nodiscard]] inline uint16_t read16(const void *P, endianness E) {
return read<uint16_t>(P, E);
}
inline uint32_t read32(const void *P, endianness E) {
[[nodiscard]] inline uint32_t read32(const void *P, endianness E) {
return read<uint32_t>(P, E);
}
inline uint64_t read64(const void *P, endianness E) {
[[nodiscard]] inline uint64_t read64(const void *P, endianness E) {
return read<uint64_t>(P, E);
}
template <endianness E> inline uint16_t read16(const void *P) {
template <endianness E> [[nodiscard]] inline uint16_t read16(const void *P) {
return read<uint16_t, E>(P);
}
template <endianness E> inline uint32_t read32(const void *P) {
template <endianness E> [[nodiscard]] inline uint32_t read32(const void *P) {
return read<uint32_t, E>(P);
}
template <endianness E> inline uint64_t read64(const void *P) {
template <endianness E> [[nodiscard]] inline uint64_t read64(const void *P) {
return read<uint64_t, E>(P);
}
inline uint16_t read16le(const void *P) { return read16<little>(P); }
inline uint32_t read32le(const void *P) { return read32<little>(P); }
inline uint64_t read64le(const void *P) { return read64<little>(P); }
inline uint16_t read16be(const void *P) { return read16<big>(P); }
inline uint32_t read32be(const void *P) { return read32<big>(P); }
inline uint64_t read64be(const void *P) { return read64<big>(P); }
template <typename T> inline void write(void *P, T V, endianness E) {
write<T, unaligned>(P, V, E);
[[nodiscard]] inline uint16_t read16le(const void *P) {
return read16<wpi::endianness::little>(P);
}
[[nodiscard]] inline uint32_t read32le(const void *P) {
return read32<wpi::endianness::little>(P);
}
[[nodiscard]] inline uint64_t read64le(const void *P) {
return read64<wpi::endianness::little>(P);
}
[[nodiscard]] inline uint16_t read16be(const void *P) {
return read16<wpi::endianness::big>(P);
}
[[nodiscard]] inline uint32_t read32be(const void *P) {
return read32<wpi::endianness::big>(P);
}
[[nodiscard]] inline uint64_t read64be(const void *P) {
return read64<wpi::endianness::big>(P);
}
template <typename T, endianness E> inline void write(void *P, T V) {
@@ -414,12 +448,24 @@ template <endianness E> inline void write64(void *P, uint64_t V) {
write<uint64_t, E>(P, V);
}
inline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
inline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
inline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
inline void write16le(void *P, uint16_t V) {
write16<wpi::endianness::little>(P, V);
}
inline void write32le(void *P, uint32_t V) {
write32<wpi::endianness::little>(P, V);
}
inline void write64le(void *P, uint64_t V) {
write64<wpi::endianness::little>(P, V);
}
inline void write16be(void *P, uint16_t V) {
write16<wpi::endianness::big>(P, V);
}
inline void write32be(void *P, uint32_t V) {
write32<wpi::endianness::big>(P, V);
}
inline void write64be(void *P, uint64_t V) {
write64<wpi::endianness::big>(P, V);
}
} // end namespace endian

View File

@@ -35,6 +35,7 @@
#include "wpi/PointerIntPair.h"
#include "wpi/PointerUnion.h"
#include "wpi/STLForwardCompat.h"
#include "wpi/Compiler.h"
#include "wpi/MemAlloc.h"
#include "wpi/type_traits.h"
#include <cstddef>
@@ -324,8 +325,10 @@ protected:
// Clear the old callback and inline flag to get back to as-if-null.
RHS.CallbackAndInlineFlag = {};
#ifndef NDEBUG
// In debug builds, we also scribble across the rest of the storage.
#if !defined(NDEBUG) && !LLVM_ADDRESS_SANITIZER_BUILD
// In debug builds without ASan, we also scribble across the rest of the
// storage. Scribbling under AddressSanitizer (ASan) is disabled to prevent
// overwriting poisoned objects (e.g., annotated short strings).
memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
#endif
}

View File

@@ -682,12 +682,26 @@ template <typename T> hash_code hash_value(const std::optional<T> &arg) {
template <> struct DenseMapInfo<hash_code, void> {
static inline hash_code getEmptyKey() { return hash_code(-1); }
static inline hash_code getTombstoneKey() { return hash_code(-2); }
static unsigned getHashValue(hash_code val) { return val; }
static unsigned getHashValue(hash_code val) {
return static_cast<unsigned>(size_t(val));
}
static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
};
} // namespace wpi
/// Implement std::hash so that hash_code can be used in STL containers.
namespace std {
template<>
struct hash<wpi::hash_code> {
size_t operator()(wpi::hash_code const& Val) const {
return Val;
}
};
} // namespace std;
#ifdef _WIN32
#pragma warning(pop)
#endif

View File

@@ -114,29 +114,50 @@ public:
return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
}
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
auto &I = Result.first->second;
if (Result.second) {
Vector.push_back(std::make_pair(KV.first, KV.second));
I = Vector.size() - 1;
template <typename... Ts>
std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
auto [It, Inserted] = Map.insert(std::make_pair(Key, 0));
if (Inserted) {
It->second = Vector.size();
Vector.emplace_back(std::piecewise_construct, std::forward_as_tuple(Key),
std::forward_as_tuple(std::forward<Ts>(Args)...));
return std::make_pair(std::prev(end()), true);
}
return std::make_pair(begin() + I, false);
return std::make_pair(begin() + It->second, false);
}
template <typename... Ts>
std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
auto [It, Inserted] = Map.insert(std::make_pair(Key, 0));
if (Inserted) {
It->second = Vector.size();
Vector.emplace_back(std::piecewise_construct,
std::forward_as_tuple(std::move(Key)),
std::forward_as_tuple(std::forward<Ts>(Args)...));
return std::make_pair(std::prev(end()), true);
}
return std::make_pair(begin() + It->second, false);
}
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
return try_emplace(KV.first, KV.second);
}
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
// Copy KV.first into the map, then move it into the vector.
std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
auto &I = Result.first->second;
if (Result.second) {
Vector.push_back(std::move(KV));
I = Vector.size() - 1;
return std::make_pair(std::prev(end()), true);
}
return std::make_pair(begin() + I, false);
return try_emplace(std::move(KV.first), std::move(KV.second));
}
template <typename V>
std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
auto Ret = try_emplace(Key, std::forward<V>(Val));
if (!Ret.second)
Ret.first->second = std::forward<V>(Val);
return Ret;
}
template <typename V>
std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
if (!Ret.second)
Ret.first->second = std::forward<V>(Val);
return Ret;
}
bool contains(const KeyT &Key) const { return Map.find(Key) != Map.end(); }

View File

@@ -333,9 +333,9 @@ constexpr inline uint64_t NextPowerOf2(uint64_t A) {
/// Returns the power of two which is greater than or equal to the given value.
/// Essentially, it is a ceil operation across the domain of powers of two.
inline uint64_t PowerOf2Ceil(uint64_t A) {
if (!A)
if (!A || A > UINT64_MAX / 2)
return 0;
return NextPowerOf2(A - 1);
return UINT64_C(1) << Log2_64_Ceil(A);
}
/// Returns the next integer (mod 2**64) that is greater than or equal to

View File

@@ -72,7 +72,7 @@ LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
/// Allocate a buffer of memory with the given size and alignment.
///
/// When the compiler supports aligned operator new, this will use it to to
/// When the compiler supports aligned operator new, this will use it to
/// handle even over-aligned allocations.
///
/// However, this doesn't make any attempt to leverage the fancier techniques

View File

@@ -60,6 +60,13 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
return std::nullopt;
}
/// Returns underlying integer value of an enum. Backport of C++23
/// std::to_underlying.
template <typename Enum>
[[nodiscard]] constexpr std::underlying_type_t<Enum> to_underlying(Enum E) {
return static_cast<std::underlying_type_t<Enum>>(E);
}
} // namespace wpi
#endif // WPIUTIL_WPI_STLFORWARDCOMPAT_H

View File

@@ -88,9 +88,10 @@ public:
/// @name String Comparison
/// @{
/// Compare two strings; the result is -1, 0, or 1 if this string is
/// lexicographically less than, equal to, or greater than the \p RHS.
int compare(std::string_view RHS) const {
/// compare - Compare two strings; the result is negative, zero, or positive
/// if this string is lexicographically less than, equal to, or greater than
/// the \p RHS.
[[nodiscard]] int compare(std::string_view RHS) const {
return str().compare(RHS);
}
@@ -102,7 +103,7 @@ public:
///
/// \return - The index of the first occurrence of \p C, or npos if not
/// found.
size_t find(char C, size_t From = 0) const {
[[nodiscard]] size_t find(char C, size_t From = 0) const {
return str().find(C, From);
}
@@ -110,7 +111,7 @@ public:
///
/// \returns The index of the first occurrence of \p Str, or npos if not
/// found.
size_t find(std::string_view Str, size_t From = 0) const {
[[nodiscard]] size_t find(std::string_view Str, size_t From = 0) const {
return str().find(Str, From);
}
@@ -118,7 +119,8 @@ public:
///
/// \returns The index of the last occurrence of \p C, or npos if not
/// found.
size_t rfind(char C, size_t From = std::string_view::npos) const {
[[nodiscard]] size_t rfind(char C,
size_t From = std::string_view::npos) const {
return str().rfind(C, From);
}
@@ -126,13 +128,13 @@ public:
///
/// \returns The index of the last occurrence of \p Str, or npos if not
/// found.
size_t rfind(std::string_view Str) const {
[[nodiscard]] size_t rfind(std::string_view Str) const {
return str().rfind(Str);
}
/// Find the first character in the string that is \p C, or npos if not
/// found. Same as find.
size_t find_first_of(char C, size_t From = 0) const {
[[nodiscard]] size_t find_first_of(char C, size_t From = 0) const {
return str().find_first_of(C, From);
}
@@ -140,13 +142,14 @@ public:
/// not found.
///
/// Complexity: O(size() + Chars.size())
size_t find_first_of(std::string_view Chars, size_t From = 0) const {
[[nodiscard]] size_t find_first_of(std::string_view Chars,
size_t From = 0) const {
return str().find_first_of(Chars, From);
}
/// Find the first character in the string that is not \p C or npos if not
/// found.
size_t find_first_not_of(char C, size_t From = 0) const {
[[nodiscard]] size_t find_first_not_of(char C, size_t From = 0) const {
return str().find_first_not_of(C, From);
}
@@ -154,13 +157,15 @@ public:
/// \p Chars, or npos if not found.
///
/// Complexity: O(size() + Chars.size())
size_t find_first_not_of(std::string_view Chars, size_t From = 0) const {
[[nodiscard]] size_t find_first_not_of(std::string_view Chars,
size_t From = 0) const {
return str().find_first_not_of(Chars, From);
}
/// Find the last character in the string that is \p C, or npos if not
/// found.
size_t find_last_of(char C, size_t From = std::string_view::npos) const {
[[nodiscard]] size_t find_last_of(
char C, size_t From = std::string_view::npos) const {
return str().find_last_of(C, From);
}
@@ -168,7 +173,7 @@ public:
/// found.
///
/// Complexity: O(size() + Chars.size())
size_t find_last_of(
[[nodiscard]] size_t find_last_of(
std::string_view Chars, size_t From = std::string_view::npos) const {
return str().find_last_of(Chars, From);
}
@@ -178,7 +183,9 @@ public:
// Extra methods.
/// Explicit conversion to std::string_view.
std::string_view str() const { return std::string_view(this->begin(), this->size()); }
[[nodiscard]] std::string_view str() const {
return std::string_view(this->begin(), this->size());
}
// TODO: Make this const, if it's safe...
const char* c_str() {

View File

@@ -61,7 +61,7 @@ protected:
void *BeginX;
unsigned Size = 0, Capacity;
/// The maximum value of the Size_T used.
/// The maximum value of the unsigned used.
static constexpr size_t SizeTypeMax() {
return (std::numeric_limits<unsigned>::max)();
}
@@ -106,9 +106,19 @@ protected:
///
/// This does not construct or destroy any elements in the vector.
void set_size(size_t N) {
assert(N <= capacity());
assert(N <= capacity()); // implies no overflow in assignment
Size = static_cast<unsigned>(N);
}
/// Set the array data pointer to \p Begin and capacity to \p N.
///
/// This does not construct or destroy any elements in the vector.
// This does not clean up any existing allocation.
void set_allocation_range(void *Begin, size_t N) {
assert(N <= SizeTypeMax());
BeginX = Begin;
Capacity = static_cast<unsigned>(N);
}
};
/// Figure out the offset of the first element.
@@ -469,8 +479,7 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
if (!this->isSmall())
free(this->begin());
this->BeginX = NewElts;
this->Capacity = static_cast<unsigned>(NewCapacity);
this->set_allocation_range(NewElts, NewCapacity);
}
/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
@@ -603,9 +612,6 @@ protected:
RHS.resetToSmall();
}
public:
SmallVectorImpl(const SmallVectorImpl &) = delete;
~SmallVectorImpl() {
// Subclass has already destructed this vector's elements.
// If this wasn't grown from the inline copy, deallocate the old space.
@@ -613,6 +619,9 @@ public:
free(this->begin());
}
public:
SmallVectorImpl(const SmallVectorImpl &) = delete;
void clear() {
this->destroy_range(this->begin(), this->end());
this->Size = 0;

View File

@@ -14,45 +14,17 @@
#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
#define WPIUTIL_WPI_SWAPBYTEORDER_H
#include "wpi/STLForwardCompat.h"
#include "wpi/bit.h"
#include <cstddef>
#include <cstdint>
#include <type_traits>
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
#include <endian.h>
#elif defined(_AIX)
#include <sys/machine.h>
#elif defined(__sun)
/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
#include <sys/types.h>
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234
#if defined(_BIG_ENDIAN)
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#elif defined(__MVS__)
#define BIG_ENDIAN 4321
#define LITTLE_ENDIAN 1234
#define BYTE_ORDER BIG_ENDIAN
#else
#if !defined(BYTE_ORDER) && !defined(_WIN32)
#include <machine/endian.h>
#endif
#endif
namespace wpi {
namespace sys {
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
constexpr bool IsBigEndianHost = true;
#else
constexpr bool IsBigEndianHost = false;
#endif
constexpr bool IsBigEndianHost =
wpi::endianness::native == wpi::endianness::big;
static const bool IsLittleEndianHost = !IsBigEndianHost;
@@ -73,29 +45,16 @@ inline unsigned long long getSwappedBytes(unsigned long long C) { return wpi::by
inline signed long long getSwappedBytes( signed long long C) { return wpi::byteswap(C); }
inline float getSwappedBytes(float C) {
union {
uint32_t i;
float f;
} in, out;
in.f = C;
out.i = wpi::byteswap(in.i);
return out.f;
return wpi::bit_cast<float>(wpi::byteswap(wpi::bit_cast<uint32_t>(C)));
}
inline double getSwappedBytes(double C) {
union {
uint64_t i;
double d;
} in, out;
in.d = C;
out.i = wpi::byteswap(in.i);
return out.d;
return wpi::bit_cast<double>(wpi::byteswap(wpi::bit_cast<uint64_t>(C)));
}
template <typename T>
inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) {
return static_cast<T>(
wpi::byteswap(static_cast<std::underlying_type_t<T>>(C)));
return static_cast<T>(wpi::byteswap(wpi::to_underlying(C)));
}
template<typename T>

View File

@@ -16,14 +16,12 @@
#include "wpi/DenseMapInfo.h"
#include "wpi/Hashing.h"
#include "wpi/Endian.h"
#include <optional>
#include <string>
#include <tuple>
namespace wpi {
template <typename HasherT, support::endianness Endianness>
class HashBuilderImpl;
template <typename HasherT, wpi::endianness Endianness> class HashBuilder;
class raw_ostream;
/// Represents a version number in the form major[.minor[.subminor[.build]]].

View File

@@ -29,6 +29,16 @@
namespace wpi {
enum class endianness {
big,
little,
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
native = big
#else
native = little
#endif
};
// This implementation of bit_cast is different from the C++20 one in two ways:
// - It isn't constexpr because that requires compiler support.
// - It requires trivially-constructible To, to avoid UB in the implementation.

View File

@@ -43,8 +43,8 @@ class iterator_range {
IteratorT begin_iterator, end_iterator;
public:
#if __GNUC__ == 7
// Be careful no to break gcc-7 on the mlir target.
#if __GNUC__ == 7 || (__GNUC__ == 8 && __GNUC_MINOR__ < 4)
// Be careful no to break gcc-7 and gcc-8 < 8.4 on the mlir target.
// See https://github.com/llvm/llvm-project/issues/63843
template <typename Container>
#else
@@ -53,8 +53,7 @@ public:
detail::IterOfRange<Container>, IteratorT>::value> * = nullptr>
#endif
iterator_range(Container &&c)
: begin_iterator(adl_begin(std::forward<Container>(c))),
end_iterator(adl_end(std::forward<Container>(c))) {
: begin_iterator(adl_begin(c)), end_iterator(adl_end(c)) {
}
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
: begin_iterator(std::move(begin_iterator)),