mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-30 02:31:44 +00:00
Update LLVM libraries to 14.0.6 (#4350)
The main noticeable change is the SmallString conversion operator to std::string is now explicit instead of implicit.
This commit is contained in:
@@ -754,7 +754,7 @@ std::error_code CodePageToUTF16(unsigned codepage,
|
||||
}
|
||||
|
||||
utf16.reserve(len + 1);
|
||||
utf16.set_size(len);
|
||||
utf16.resize_for_overwrite(len);
|
||||
|
||||
len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
|
||||
original.size(), utf16.begin(), utf16.size());
|
||||
@@ -795,7 +795,7 @@ std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16,
|
||||
}
|
||||
|
||||
converted.reserve(len);
|
||||
converted.set_size(len);
|
||||
converted.resize_for_overwrite(len);
|
||||
|
||||
// Now do the actual conversion.
|
||||
len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.data(),
|
||||
|
||||
@@ -104,8 +104,8 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, SmallVectorImpl<char> &
|
||||
std::vector<UTF16> ByteSwapped;
|
||||
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
|
||||
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
|
||||
for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I)
|
||||
ByteSwapped[I] = wpi::ByteSwap_16(ByteSwapped[I]);
|
||||
for (UTF16 &I : ByteSwapped)
|
||||
I = wpi::ByteSwap_16(I);
|
||||
Src = &ByteSwapped[0];
|
||||
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ void wpi::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
handler(handlerData, std::string{Reason}, GenCrashDiag);
|
||||
handler(handlerData, std::string{Reason}.c_str(), GenCrashDiag);
|
||||
} else {
|
||||
fmt::print(stderr, "LLVM ERROR: {}\n", Reason);
|
||||
}
|
||||
@@ -185,7 +185,10 @@ std::error_code wpi::mapWindowsError(unsigned EV) {
|
||||
switch (EV) {
|
||||
MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_PATHNAME, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
|
||||
MAP_ERR_TO_COND(ERROR_BROKEN_PIPE, broken_pipe);
|
||||
MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
|
||||
MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
|
||||
@@ -207,18 +210,20 @@ std::error_code wpi::mapWindowsError(unsigned EV) {
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
|
||||
MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
|
||||
MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
|
||||
MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
|
||||
MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
|
||||
MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED, not_supported);
|
||||
MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
|
||||
MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
|
||||
MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
|
||||
MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID, invalid_argument);
|
||||
MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
|
||||
MAP_ERR_TO_COND(ERROR_SEEK, io_error);
|
||||
MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include <new>
|
||||
|
||||
// These are out of line to have __cpp_aligned_new not affect ABI.
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ static std::unique_ptr<WritableMemoryBuffer> GetMemoryBufferForStream(
|
||||
#endif
|
||||
// Read into Buffer until we hit EOF.
|
||||
do {
|
||||
buffer.reserve(buffer.size() + ChunkSize);
|
||||
buffer.resize_for_overwrite(buffer.size() + ChunkSize);
|
||||
#ifdef _WIN32
|
||||
if (!ReadFile(f, buffer.end(), ChunkSize, &readBytes, nullptr)) {
|
||||
ec = mapWindowsError(GetLastError());
|
||||
@@ -250,7 +250,6 @@ static std::unique_ptr<WritableMemoryBuffer> GetMemoryBufferForStream(
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
buffer.set_size(buffer.size() + readBytes);
|
||||
} while (readBytes != 0);
|
||||
|
||||
return GetMemBufferCopyImpl(buffer, bufferName, ec);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "wpi/SmallPtrSet.h"
|
||||
#include "wpi/DenseMapInfo.h"
|
||||
#include "wpi/ErrorHandling.h"
|
||||
#include "wpi/MathExtras.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include <algorithm>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/SmallVector.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include <cstdint>
|
||||
#ifdef LLVM_ENABLE_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
@@ -19,12 +20,21 @@ using namespace wpi;
|
||||
|
||||
// Check that no bytes are wasted and everything is well-aligned.
|
||||
namespace {
|
||||
// These structures may cause binary compat warnings on AIX. Suppress the
|
||||
// warning since we are only using these types for the static assertions below.
|
||||
#if defined(_AIX)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Waix-compat"
|
||||
#endif
|
||||
struct Struct16B {
|
||||
alignas(16) void *X;
|
||||
};
|
||||
struct Struct32B {
|
||||
alignas(32) void *X;
|
||||
};
|
||||
#if defined(_AIX)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
static_assert(sizeof(SmallVector<void *, 0>) ==
|
||||
sizeof(unsigned) * 2 + sizeof(void *),
|
||||
@@ -43,8 +53,7 @@ static_assert(sizeof(SmallVector<void *, 1>) ==
|
||||
|
||||
/// Report that MinSize doesn't fit into this vector's size type. Throws
|
||||
/// std::length_error or calls report_fatal_error.
|
||||
LLVM_ATTRIBUTE_NORETURN
|
||||
static void report_size_overflow(size_t MinSize, size_t MaxSize);
|
||||
[[noreturn]] static void report_size_overflow(size_t MinSize, size_t MaxSize);
|
||||
static void report_size_overflow(size_t MinSize, size_t MaxSize) {
|
||||
std::string Reason = "SmallVector unable to grow. Requested capacity (" +
|
||||
std::to_string(MinSize) +
|
||||
@@ -59,7 +68,7 @@ static void report_size_overflow(size_t MinSize, size_t MaxSize) {
|
||||
|
||||
/// Report that this vector is already at maximum capacity. Throws
|
||||
/// std::length_error or calls report_fatal_error.
|
||||
LLVM_ATTRIBUTE_NORETURN static void report_at_maximum_capacity(size_t MaxSize);
|
||||
[[noreturn]] static void report_at_maximum_capacity(size_t MaxSize);
|
||||
static void report_at_maximum_capacity(size_t MaxSize) {
|
||||
std::string Reason =
|
||||
"SmallVector capacity unable to grow. Already at maximum size " +
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/StringMap.h"
|
||||
#include "wpi/StringExtras.h"
|
||||
#include "wpi/DJB.h"
|
||||
#include "wpi/MathExtras.h"
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ wpi::VersionTuple GetWindowsOSVersion();
|
||||
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
|
||||
|
||||
// Include GetLastError() in a fatal error message.
|
||||
LLVM_ATTRIBUTE_NORETURN inline void ReportLastErrorFatal(const char *Msg) {
|
||||
[[noreturn]] inline void ReportLastErrorFatal(const char *Msg) {
|
||||
std::string ErrMsg;
|
||||
MakeErrMsg(&ErrMsg, Msg);
|
||||
wpi::report_fatal_error(ErrMsg);
|
||||
|
||||
@@ -23,10 +23,8 @@
|
||||
#include "wpi/fs.h"
|
||||
#include "wpi/MathExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <iterator>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// <fcntl.h> may provide O_BINARY.
|
||||
@@ -148,7 +146,7 @@ raw_ostream &raw_ostream::write_escaped(std::string_view Str,
|
||||
// Write out the escaped representation.
|
||||
if (UseHexEscapes) {
|
||||
*this << '\\' << 'x';
|
||||
*this << hexdigit((c >> 4 & 0xF));
|
||||
*this << hexdigit((c >> 4) & 0xF);
|
||||
*this << hexdigit((c >> 0) & 0xF);
|
||||
} else {
|
||||
// Always use a full 3-character octal escape.
|
||||
@@ -385,7 +383,7 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
|
||||
#ifdef _WIN32
|
||||
SupportsSeeking = loc != (off_t)-1 && ::GetFileType(reinterpret_cast<HANDLE>(::_get_osfhandle(FD))) != FILE_TYPE_PIPE;
|
||||
#else
|
||||
SupportsSeeking = loc != (off_t)-1;
|
||||
SupportsSeeking = !EC && loc != (off_t)-1;
|
||||
#endif
|
||||
if (!SupportsSeeking)
|
||||
pos = 0;
|
||||
@@ -624,8 +622,7 @@ raw_fd_stream::raw_fd_stream(std::string_view Filename, std::error_code &EC)
|
||||
if (EC)
|
||||
return;
|
||||
|
||||
// Do not support non-seekable files.
|
||||
if (!supportsSeeking())
|
||||
if (!isRegularFile())
|
||||
EC = std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
@@ -637,10 +634,6 @@ bool raw_fd_stream::classof(const raw_ostream *OS) {
|
||||
// raw_string_ostream
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
raw_string_ostream::~raw_string_ostream() {
|
||||
flush();
|
||||
}
|
||||
|
||||
void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
|
||||
OS.append(Ptr, Size);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <ratio>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
@@ -22,12 +23,12 @@ namespace sys {
|
||||
|
||||
/// A time point on the system clock. This is provided for two reasons:
|
||||
/// - to insulate us against subtle differences in behavior to differences in
|
||||
/// system clock precision (which is implementation-defined and differs between
|
||||
/// platforms).
|
||||
/// system clock precision (which is implementation-defined and differs
|
||||
/// between platforms).
|
||||
/// - to shorten the type name
|
||||
/// The default precision is nanoseconds. If need a specific precision specify
|
||||
/// it explicitly. If unsure, use the default. If you need a time point on a
|
||||
/// clock other than the system_clock, use std::chrono directly.
|
||||
/// The default precision is nanoseconds. If you need a specific precision
|
||||
/// specify it explicitly. If unsure, use the default. If you need a time point
|
||||
/// on a clock other than the system_clock, use std::chrono directly.
|
||||
template <typename D = std::chrono::nanoseconds>
|
||||
using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
#define WPIUTIL_WPI_COMPILER_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <new>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
@@ -79,13 +76,24 @@
|
||||
/// * 1916: VS2017, version 15.9
|
||||
/// * 1920: VS2019, version 16.0
|
||||
/// * 1921: VS2019, version 16.1
|
||||
/// * 1922: VS2019, version 16.2
|
||||
/// * 1923: VS2019, version 16.3
|
||||
/// * 1924: VS2019, version 16.4
|
||||
/// * 1925: VS2019, version 16.5
|
||||
/// * 1926: VS2019, version 16.6
|
||||
/// * 1927: VS2019, version 16.7
|
||||
/// * 1928: VS2019, version 16.8 + 16.9
|
||||
/// * 1929: VS2019, version 16.10 + 16.11
|
||||
/// * 1930: VS2022, version 17.0
|
||||
#ifndef LLVM_MSC_PREREQ
|
||||
#ifdef _MSC_VER
|
||||
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
|
||||
|
||||
// We require at least MSVC 2017.
|
||||
#if !LLVM_MSC_PREREQ(1910)
|
||||
#error LLVM requires at least MSVC 2017.
|
||||
// We require at least VS 2019.
|
||||
#if !defined(LLVM_FORCE_USE_OLD_TOOLCHAIN)
|
||||
#if !LLVM_MSC_PREREQ(1920)
|
||||
#error LLVM requires at least VS 2019.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
@@ -98,14 +106,8 @@
|
||||
/// Sadly, this is separate from just rvalue reference support because GCC
|
||||
/// and MSVC implemented this later than everything else. This appears to be
|
||||
/// corrected in MSVC 2019 but not MSVC 2017.
|
||||
#ifndef LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||
#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) || \
|
||||
LLVM_MSC_PREREQ(1920)
|
||||
/// FIXME: Remove LLVM_HAS_RVALUE_REFERENCE_THIS macro
|
||||
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
|
||||
#else
|
||||
#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Expands to '&' if ref-qualifiers for *this are supported.
|
||||
///
|
||||
@@ -128,10 +130,14 @@
|
||||
/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
|
||||
/// this attribute will be made public and visible outside of any shared library
|
||||
/// they are linked in to.
|
||||
#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
|
||||
!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)
|
||||
#if __has_attribute(visibility) && !defined(__MINGW32__) && \
|
||||
!defined(__CYGWIN__) && !defined(_WIN32)
|
||||
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
|
||||
#define LLVM_EXTERNAL_VISIBILITY __attribute__ ((visibility("default")))
|
||||
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
|
||||
#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LLVM_EXTERNAL_VISIBILITY
|
||||
#endif
|
||||
#else
|
||||
#define LLVM_LIBRARY_VISIBILITY
|
||||
#define LLVM_EXTERNAL_VISIBILITY
|
||||
@@ -146,7 +152,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef LLVM_ATTRIBUTE_USED
|
||||
#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
|
||||
#if __has_attribute(used)
|
||||
#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_USED
|
||||
@@ -194,7 +200,7 @@
|
||||
// (void)unused_var_name;
|
||||
// Prefer cast-to-void wherever it is sufficient.
|
||||
#ifndef LLVM_ATTRIBUTE_UNUSED
|
||||
#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
|
||||
#if __has_attribute(unused)
|
||||
#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_UNUSED
|
||||
@@ -202,8 +208,8 @@
|
||||
#endif
|
||||
|
||||
// FIXME: Provide this for PE/COFF targets.
|
||||
#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
|
||||
(!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32))
|
||||
#if __has_attribute(weak) && !defined(__MINGW32__) && !defined(__CYGWIN__) && \
|
||||
!defined(_WIN32)
|
||||
#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_WEAK
|
||||
@@ -229,8 +235,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __has_attribute(minsize)
|
||||
#define LLVM_ATTRIBUTE_MINSIZE __attribute__((minsize))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_MINSIZE
|
||||
#endif
|
||||
|
||||
#ifndef LLVM_LIKELY
|
||||
#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||
#if __has_builtin(__builtin_expect) || defined(__GNUC__)
|
||||
#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
|
||||
#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
|
||||
#else
|
||||
@@ -242,7 +254,7 @@
|
||||
/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
|
||||
/// mark a method "not for inlining".
|
||||
#ifndef LLVM_ATTRIBUTE_NOINLINE
|
||||
#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
|
||||
#if __has_attribute(noinline)
|
||||
#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
|
||||
@@ -252,11 +264,9 @@
|
||||
#endif
|
||||
|
||||
/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
|
||||
/// so, mark a method "always inline" because it is performance sensitive. GCC
|
||||
/// 3.4 supported this but is buggy in various cases and produces unimplemented
|
||||
/// errors, just use it in GCC 4.0 and later.
|
||||
/// so, mark a method "always inline" because it is performance sensitive.
|
||||
#ifndef LLVM_ATTRIBUTE_ALWAYS_INLINE
|
||||
#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||
#if __has_attribute(always_inline)
|
||||
#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
|
||||
@@ -265,18 +275,17 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LLVM_ATTRIBUTE_NORETURN
|
||||
#ifdef __GNUC__
|
||||
#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn)
|
||||
/// LLVM_ATTRIBUTE_NO_DEBUG - On compilers where we have a directive to do
|
||||
/// so, mark a method "no debug" because debug info makes the debugger
|
||||
/// experience worse.
|
||||
#if __has_attribute(nodebug)
|
||||
#define LLVM_ATTRIBUTE_NODEBUG __attribute__((nodebug))
|
||||
#else
|
||||
#define LLVM_ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
#define LLVM_ATTRIBUTE_NODEBUG
|
||||
#endif
|
||||
|
||||
#ifndef LLVM_ATTRIBUTE_RETURNS_NONNULL
|
||||
#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
|
||||
#if __has_attribute(returns_nonnull)
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
|
||||
@@ -358,17 +367,19 @@
|
||||
/// to an expression which states that it is undefined behavior for the
|
||||
/// compiler to reach this point. Otherwise is not defined.
|
||||
#ifndef LLVM_BUILTIN_UNREACHABLE
|
||||
#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
|
||||
#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
|
||||
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
|
||||
#else
|
||||
# define LLVM_BUILTIN_UNREACHABLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
|
||||
/// which causes the program to exit abnormally.
|
||||
#ifndef LLVM_BUILTIN_TRAP
|
||||
#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
|
||||
#if __has_builtin(__builtin_trap) || defined(__GNUC__)
|
||||
# define LLVM_BUILTIN_TRAP __builtin_trap()
|
||||
#elif defined(_MSC_VER)
|
||||
// The __debugbreak intrinsic is supported by MSVC, does not require forward
|
||||
@@ -403,7 +414,7 @@
|
||||
/// \macro LLVM_ASSUME_ALIGNED
|
||||
/// Returns a pointer with an assumed alignment.
|
||||
#ifndef LLVM_ASSUME_ALIGNED
|
||||
#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
|
||||
#if __has_builtin(__builtin_assume_aligned) || defined(__GNUC__)
|
||||
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
|
||||
#elif defined(LLVM_BUILTIN_UNREACHABLE)
|
||||
# define LLVM_ASSUME_ALIGNED(p, a) \
|
||||
@@ -596,4 +607,13 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
|
||||
#define LLVM_ENABLE_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
|
||||
/// Disable the profile instrument for a function.
|
||||
#if __has_attribute(no_profile_instrument_function)
|
||||
#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION \
|
||||
__attribute__((no_profile_instrument_function))
|
||||
#else
|
||||
#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DenseMap class.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the DenseMap class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_DENSEMAP_H
|
||||
|
||||
@@ -5,18 +5,19 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines DenseMapInfo traits for DenseMap.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines DenseMapInfo traits for DenseMap.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_DENSEMAPINFO_H
|
||||
#define WPIUTIL_WPI_DENSEMAPINFO_H
|
||||
|
||||
#include "wpi/Hashing.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace wpi {
|
||||
@@ -39,7 +40,12 @@ static inline unsigned combineHashValue(unsigned a, unsigned b) {
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
template<typename T>
|
||||
/// An information struct used to provide DenseMap with the various necessary
|
||||
/// components for a given value type `T`. `Enable` is an optional additional
|
||||
/// parameter that is used to support SFINAE (generally using std::enable_if_t)
|
||||
/// in derived DenseMapInfo specializations; in non-SFINAE use cases this should
|
||||
/// just be `void`.
|
||||
template<typename T, typename Enable = void>
|
||||
struct DenseMapInfo {
|
||||
//static inline T getEmptyKey();
|
||||
//static inline T getTombstoneKey();
|
||||
@@ -282,13 +288,6 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct DenseMapInfo<hash_code> {
|
||||
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 static_cast<unsigned>(val); }
|
||||
static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
|
||||
};
|
||||
|
||||
} // end namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_DENSEMAPINFO_H
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
|
||||
// These can be used to write iterators that are fail-fast when LLVM is built
|
||||
// with asserts enabled.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
|
||||
/// These can be used to write iterators that are fail-fast when LLVM is built
|
||||
/// with asserts enabled.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_EPOCHTRACKER_H
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace wpi {
|
||||
|
||||
/// An error handler callback.
|
||||
typedef void (*fatal_error_handler_t)(void *user_data,
|
||||
const std::string& reason,
|
||||
const char *reason,
|
||||
bool gen_crash_diag);
|
||||
|
||||
/// install_fatal_error_handler - Installs a new error handler to be used
|
||||
@@ -67,12 +67,12 @@ namespace wpi {
|
||||
/// standard error, followed by a newline.
|
||||
/// After the error handler is called this function will call abort(), it
|
||||
/// does not return.
|
||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
|
||||
bool gen_crash_diag = true);
|
||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
|
||||
bool gen_crash_diag = true);
|
||||
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(std::string_view reason,
|
||||
bool gen_crash_diag = true);
|
||||
[[noreturn]] void report_fatal_error(const char *reason,
|
||||
bool gen_crash_diag = true);
|
||||
[[noreturn]] void report_fatal_error(const std::string &reason,
|
||||
bool gen_crash_diag = true);
|
||||
[[noreturn]] void report_fatal_error(std::string_view reason,
|
||||
bool gen_crash_diag = true);
|
||||
|
||||
/// Installs a new bad alloc error handler that should be used whenever a
|
||||
/// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
|
||||
@@ -110,13 +110,13 @@ void install_out_of_memory_new_handler();
|
||||
/// If no error handler is installed (default), throws a bad_alloc exception
|
||||
/// if LLVM is compiled with exception support. Otherwise prints the error
|
||||
/// to standard error and calls abort().
|
||||
LLVM_ATTRIBUTE_NORETURN void report_bad_alloc_error(const char *Reason,
|
||||
bool GenCrashDiag = true);
|
||||
[[noreturn]] void report_bad_alloc_error(const char *Reason,
|
||||
bool GenCrashDiag = true);
|
||||
|
||||
/// This function calls abort(), and prints the optional message to stderr.
|
||||
/// Use the wpi_unreachable macro (that adds location info), instead of
|
||||
/// calling this function directly.
|
||||
LLVM_ATTRIBUTE_NORETURN void
|
||||
[[noreturn]] void
|
||||
wpi_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
|
||||
unsigned line = 0);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "wpi/STLForwardCompat.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include "wpi/type_traits.h"
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -57,6 +58,7 @@ template <typename FunctionT> class unique_function;
|
||||
// GCC warns on OutOfLineStorage
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
@@ -70,11 +72,16 @@ template <typename CallableT, typename ThisT>
|
||||
using EnableUnlessSameType =
|
||||
std::enable_if_t<!std::is_same<remove_cvref_t<CallableT>, ThisT>::value>;
|
||||
template <typename CallableT, typename Ret, typename... Params>
|
||||
using EnableIfCallable =
|
||||
std::enable_if_t<std::is_void<Ret>::value ||
|
||||
std::is_convertible<decltype(std::declval<CallableT>()(
|
||||
std::declval<Params>()...)),
|
||||
Ret>::value>;
|
||||
using EnableIfCallable = std::enable_if_t<wpi::disjunction<
|
||||
std::is_void<Ret>,
|
||||
std::is_same<decltype(std::declval<CallableT>()(std::declval<Params>()...)),
|
||||
Ret>,
|
||||
std::is_same<const decltype(std::declval<CallableT>()(
|
||||
std::declval<Params>()...)),
|
||||
Ret>,
|
||||
std::is_convertible<decltype(std::declval<CallableT>()(
|
||||
std::declval<Params>()...)),
|
||||
Ret>>::value>;
|
||||
|
||||
template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
|
||||
protected:
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#endif
|
||||
|
||||
namespace wpi {
|
||||
template <typename T, typename Enable> struct DenseMapInfo;
|
||||
|
||||
/// An opaque object representing a hash code.
|
||||
///
|
||||
@@ -681,6 +682,13 @@ hash_code hash_value(const std::basic_string<T> &arg) {
|
||||
return hash_combine_range(arg.begin(), arg.end());
|
||||
}
|
||||
|
||||
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 bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a map that provides insertion order iteration. The
|
||||
// interface is purposefully minimal. The key is assumed to be cheap to copy
|
||||
// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
|
||||
// a std::vector.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file implements a map that provides insertion order iteration. The
|
||||
/// interface is purposefully minimal. The key is assumed to be cheap to copy
|
||||
/// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
|
||||
/// a std::vector.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_MAPVECTOR_H
|
||||
@@ -18,7 +19,6 @@
|
||||
|
||||
#include "wpi/DenseMap.h"
|
||||
#include "wpi/SmallVector.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
@@ -43,6 +43,7 @@ class MapVector {
|
||||
"The mapped_type of the specified Map must be an integral type");
|
||||
|
||||
public:
|
||||
using key_type = KeyT;
|
||||
using value_type = typename VectorType::value_type;
|
||||
using size_type = typename VectorType::size_type;
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the PointerIntPair class.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the PointerIntPair class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_POINTERINTPAIR_H
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
template <typename T> struct DenseMapInfo;
|
||||
template <typename T, typename Enable> struct DenseMapInfo;
|
||||
template <typename PointerT, unsigned IntBits, typename PtrTraits>
|
||||
struct PointerIntPairInfo;
|
||||
|
||||
@@ -180,7 +181,7 @@ struct PointerIntPairInfo {
|
||||
|
||||
// Provide specialization of DenseMapInfo for PointerIntPair.
|
||||
template <typename PointerTy, unsigned IntBits, typename IntType>
|
||||
struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> {
|
||||
struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>, void> {
|
||||
using Ty = PointerIntPair<PointerTy, IntBits, IntType>;
|
||||
|
||||
static Ty getEmptyKey() {
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the PointerUnion class, which is a discriminated union of
|
||||
// pointer types.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the PointerUnion class, which is a discriminated union of
|
||||
/// pointer types.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_POINTERUNION_H
|
||||
@@ -17,41 +18,58 @@
|
||||
#include "wpi/DenseMapInfo.h"
|
||||
#include "wpi/PointerIntPair.h"
|
||||
#include "wpi/PointerLikeTypeTraits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
template <typename T> struct PointerUnionTypeSelectorReturn {
|
||||
using Return = T;
|
||||
};
|
||||
namespace detail {
|
||||
template <typename T, typename... Us> struct TypesAreDistinct;
|
||||
template <typename T, typename... Us>
|
||||
struct TypesAreDistinct
|
||||
: std::integral_constant<bool, !std::disjunction_v<std::is_same<T, Us>...> &&
|
||||
TypesAreDistinct<Us...>::value> {};
|
||||
template <typename T> struct TypesAreDistinct<T> : std::true_type {};
|
||||
} // namespace detail
|
||||
|
||||
/// Get a type based on whether two types are the same or not.
|
||||
/// Determine if all types in Ts are distinct.
|
||||
///
|
||||
/// For:
|
||||
/// Useful to statically assert when Ts is intended to describe a non-multi set
|
||||
/// of types.
|
||||
///
|
||||
/// \code
|
||||
/// using Ret = typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return;
|
||||
/// \endcode
|
||||
///
|
||||
/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
|
||||
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelector {
|
||||
using Return = typename PointerUnionTypeSelectorReturn<RET_NE>::Return;
|
||||
};
|
||||
/// Expensive (currently quadratic in sizeof(Ts...)), and so should only be
|
||||
/// asserted once per instantiation of a type which requires it.
|
||||
template <typename... Ts> struct TypesAreDistinct;
|
||||
template <> struct TypesAreDistinct<> : std::true_type {};
|
||||
template <typename... Ts>
|
||||
struct TypesAreDistinct
|
||||
: std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
|
||||
|
||||
template <typename T, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
|
||||
using Return = typename PointerUnionTypeSelectorReturn<RET_EQ>::Return;
|
||||
};
|
||||
/// Find the first index where a type appears in a list of types.
|
||||
///
|
||||
/// FirstIndexOfType<T, Us...>::value is the first index of T in Us.
|
||||
///
|
||||
/// Typically only meaningful when it is otherwise statically known that the
|
||||
/// type pack has no duplicate types. This should be guaranteed explicitly with
|
||||
/// static_assert(TypesAreDistinct<Us...>::value).
|
||||
///
|
||||
/// It is a compile-time error to instantiate when T is not present in Us, i.e.
|
||||
/// if is_one_of<T, Us...>::value is false.
|
||||
template <typename T, typename... Us> struct FirstIndexOfType;
|
||||
template <typename T, typename U, typename... Us>
|
||||
struct FirstIndexOfType<T, U, Us...>
|
||||
: std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
|
||||
template <typename T, typename... Us>
|
||||
struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {};
|
||||
|
||||
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelectorReturn<
|
||||
PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> {
|
||||
using Return =
|
||||
typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return;
|
||||
};
|
||||
/// Find the type at a given index in a list of types.
|
||||
///
|
||||
/// TypeAtIndex<I, Ts...> is the type at index I in Ts.
|
||||
template <size_t I, typename... Ts>
|
||||
using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>;
|
||||
|
||||
namespace pointer_union_detail {
|
||||
/// Determine the number of bits required to store integers with values < n.
|
||||
@@ -64,21 +82,6 @@ namespace pointer_union_detail {
|
||||
return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
|
||||
}
|
||||
|
||||
/// Find the index of a type in a list of types. TypeIndex<T, Us...>::Index
|
||||
/// is the index of T in Us, or sizeof...(Us) if T does not appear in the
|
||||
/// list.
|
||||
template <typename T, typename ...Us> struct TypeIndex;
|
||||
template <typename T, typename ...Us> struct TypeIndex<T, T, Us...> {
|
||||
static constexpr int Index = 0;
|
||||
};
|
||||
template <typename T, typename U, typename... Us>
|
||||
struct TypeIndex<T, U, Us...> {
|
||||
static constexpr int Index = 1 + TypeIndex<T, Us...>::Index;
|
||||
};
|
||||
template <typename T> struct TypeIndex<T> {
|
||||
static constexpr int Index = 0;
|
||||
};
|
||||
|
||||
/// Find the first type in a list of types.
|
||||
template <typename T, typename...> struct GetFirstType {
|
||||
using type = T;
|
||||
@@ -145,6 +148,7 @@ namespace pointer_union_detail {
|
||||
/// P = (float*)0;
|
||||
/// Y = P.get<float*>(); // ok.
|
||||
/// X = P.get<int*>(); // runtime assertion failure.
|
||||
/// PointerUnion<int*, int*> Q; // compile time failure.
|
||||
template <typename... PTs>
|
||||
class PointerUnion
|
||||
: public pointer_union_detail::PointerUnionMembers<
|
||||
@@ -153,12 +157,14 @@ class PointerUnion
|
||||
void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
|
||||
pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
|
||||
0, PTs...> {
|
||||
static_assert(TypesAreDistinct<PTs...>::value,
|
||||
"PointerUnion alternative types cannot be repeated");
|
||||
// The first type is special because we want to directly cast a pointer to a
|
||||
// default-initialized union to a pointer to the first type. But we don't
|
||||
// want PointerUnion to be a 'template <typename First, typename ...Rest>'
|
||||
// because it's much more convenient to have a name for the whole pack. So
|
||||
// split off the first type here.
|
||||
using First = typename pointer_union_detail::GetFirstType<PTs...>::type;
|
||||
using First = TypeAtIndex<0, PTs...>;
|
||||
using Base = typename PointerUnion::PointerUnionMembers;
|
||||
|
||||
public:
|
||||
@@ -175,10 +181,7 @@ public:
|
||||
|
||||
/// Test if the Union currently holds the type matching T.
|
||||
template <typename T> bool is() const {
|
||||
constexpr int Index = pointer_union_detail::TypeIndex<T, PTs...>::Index;
|
||||
static_assert(Index < sizeof...(PTs),
|
||||
"PointerUnion::is<T> given type not in the union");
|
||||
return this->Val.getInt() == Index;
|
||||
return this->Val.getInt() == FirstIndexOfType<T, PTs...>::value;
|
||||
}
|
||||
|
||||
/// Returns the value of the specified pointer type.
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains library features backported from future STL versions.
|
||||
//
|
||||
// These should be replaced with their STL counterparts as the C++ version LLVM
|
||||
// is compiled with is updated.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains library features backported from future STL versions.
|
||||
///
|
||||
/// These should be replaced with their STL counterparts as the C++ version LLVM
|
||||
/// is compiled with is updated.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_STLFORWARDCOMPAT_H
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SmallPtrSet class. See the doxygen comment for
|
||||
// SmallPtrSetImplBase for more details on the algorithm used.
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the SmallPtrSet class. See the doxygen comment for
|
||||
/// SmallPtrSetImplBase for more details on the algorithm used.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SmallSet class.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the SmallSet class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_SMALLSET_H
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SmallString class.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the SmallString class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_SMALLSTRING_H
|
||||
@@ -15,6 +16,7 @@
|
||||
|
||||
#include "wpi/SmallVector.h"
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace wpi {
|
||||
@@ -70,16 +72,16 @@ public:
|
||||
|
||||
/// Append from a list of std::string_views.
|
||||
void append(std::initializer_list<std::string_view> Refs) {
|
||||
size_t SizeNeeded = this->size();
|
||||
size_t CurrentSize = this->size();
|
||||
size_t SizeNeeded = CurrentSize;
|
||||
for (std::string_view Ref : Refs)
|
||||
SizeNeeded += Ref.size();
|
||||
this->reserve(SizeNeeded);
|
||||
auto CurEnd = this->end();
|
||||
this->resize_for_overwrite(SizeNeeded);
|
||||
for (std::string_view Ref : Refs) {
|
||||
this->uninitialized_copy(Ref.begin(), Ref.end(), CurEnd);
|
||||
CurEnd += Ref.size();
|
||||
std::copy(Ref.begin(), Ref.end(), this->begin() + CurrentSize);
|
||||
CurrentSize += Ref.size();
|
||||
}
|
||||
this->set_size(SizeNeeded);
|
||||
assert(CurrentSize == this->size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -188,11 +190,9 @@ public:
|
||||
/// Implicit conversion to std::string_view.
|
||||
operator std::string_view() const { return str(); }
|
||||
|
||||
/// Explicit conversion to std::string.
|
||||
std::string string() const { return {this->begin(), this->size()}; }
|
||||
|
||||
/// Implicit conversion to std::string.
|
||||
operator std::string() const { return string(); }
|
||||
explicit operator std::string() const {
|
||||
return std::string(this->data(), this->size());
|
||||
}
|
||||
|
||||
// Extra operators.
|
||||
SmallString &operator=(std::string_view RHS) {
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SmallVector class.
|
||||
//
|
||||
///
|
||||
/// /file
|
||||
/// This file defines the SmallVector class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_SMALLVECTOR_H
|
||||
@@ -21,10 +22,7 @@
|
||||
#pragma GCC diagnostic warning "-Wclass-memaccess"
|
||||
#endif
|
||||
|
||||
#include "wpi/iterator_range.h"
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/ErrorHandling.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include "wpi/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@@ -42,6 +40,8 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
template <typename IteratorT> class iterator_range;
|
||||
|
||||
/// This is all the stuff common to all SmallVectors.
|
||||
///
|
||||
/// The template parameter specifies the type which should be used to hold the
|
||||
@@ -80,15 +80,11 @@ public:
|
||||
|
||||
LLVM_NODISCARD bool empty() const { return !Size; }
|
||||
|
||||
protected:
|
||||
/// Set the array size to \p N, which the current array must have enough
|
||||
/// capacity for.
|
||||
///
|
||||
/// This does not construct or destroy any elements in the vector.
|
||||
///
|
||||
/// Clients can use this in conjunction with capacity() to write past the end
|
||||
/// of the buffer when they know that more elements are available, and only
|
||||
/// update the size later. This avoids the cost of value initializing elements
|
||||
/// which will only be overwritten.
|
||||
void set_size(size_t N) {
|
||||
assert(N <= capacity());
|
||||
Size = static_cast<unsigned>(N);
|
||||
@@ -575,6 +571,16 @@ protected:
|
||||
explicit SmallVectorImpl(unsigned N)
|
||||
: SmallVectorTemplateBase<T>(N) {}
|
||||
|
||||
void assignRemote(SmallVectorImpl &&RHS) {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
if (!this->isSmall())
|
||||
free(this->begin());
|
||||
this->BeginX = RHS.BeginX;
|
||||
this->Size = RHS.Size;
|
||||
this->Capacity = RHS.Capacity;
|
||||
RHS.resetToSmall();
|
||||
}
|
||||
|
||||
public:
|
||||
SmallVectorImpl(const SmallVectorImpl &) = delete;
|
||||
|
||||
@@ -591,18 +597,25 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Make set_size() private to avoid misuse in subclasses.
|
||||
using SuperClass::set_size;
|
||||
|
||||
template <bool ForOverwrite> void resizeImpl(size_type N) {
|
||||
if (N == this->size())
|
||||
return;
|
||||
|
||||
if (N < this->size()) {
|
||||
this->pop_back_n(this->size() - N);
|
||||
} else if (N > this->size()) {
|
||||
this->reserve(N);
|
||||
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
|
||||
if (ForOverwrite)
|
||||
new (&*I) T;
|
||||
else
|
||||
new (&*I) T();
|
||||
this->set_size(N);
|
||||
this->truncate(N);
|
||||
return;
|
||||
}
|
||||
|
||||
this->reserve(N);
|
||||
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
|
||||
if (ForOverwrite)
|
||||
new (&*I) T;
|
||||
else
|
||||
new (&*I) T();
|
||||
this->set_size(N);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -611,12 +624,19 @@ public:
|
||||
/// Like resize, but \ref T is POD, the new values won't be initialized.
|
||||
void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
|
||||
|
||||
/// Like resize, but requires that \p N is less than \a size().
|
||||
void truncate(size_type N) {
|
||||
assert(this->size() >= N && "Cannot increase size with truncate");
|
||||
this->destroy_range(this->begin() + N, this->end());
|
||||
this->set_size(N);
|
||||
}
|
||||
|
||||
void resize(size_type N, ValueParamT NV) {
|
||||
if (N == this->size())
|
||||
return;
|
||||
|
||||
if (N < this->size()) {
|
||||
this->pop_back_n(this->size() - N);
|
||||
this->truncate(N);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -631,8 +651,7 @@ public:
|
||||
|
||||
void pop_back_n(size_type NumItems) {
|
||||
assert(this->size() >= NumItems);
|
||||
this->destroy_range(this->end() - NumItems, this->end());
|
||||
this->set_size(this->size() - NumItems);
|
||||
truncate(this->size() - NumItems);
|
||||
}
|
||||
|
||||
LLVM_NODISCARD T pop_back_val() {
|
||||
@@ -1026,12 +1045,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
|
||||
|
||||
// If the RHS isn't small, clear this vector and then steal its buffer.
|
||||
if (!RHS.isSmall()) {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
if (!this->isSmall()) free(this->begin());
|
||||
this->BeginX = RHS.BeginX;
|
||||
this->Size = RHS.Size;
|
||||
this->Capacity = RHS.Capacity;
|
||||
RHS.resetToSmall();
|
||||
this->assignRemote(std::move(RHS));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1222,7 +1236,20 @@ public:
|
||||
}
|
||||
|
||||
SmallVector &operator=(SmallVector &&RHS) {
|
||||
SmallVectorImpl<T>::operator=(::std::move(RHS));
|
||||
if (N) {
|
||||
SmallVectorImpl<T>::operator=(::std::move(RHS));
|
||||
return *this;
|
||||
}
|
||||
// SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
|
||||
// case.
|
||||
if (this == &RHS)
|
||||
return *this;
|
||||
if (RHS.empty()) {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->Size = 0;
|
||||
} else {
|
||||
this->assignRemote(std::move(RHS));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1242,13 +1269,22 @@ inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
|
||||
return X.capacity_in_bytes();
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
using ValueTypeFromRangeType =
|
||||
typename std::remove_const<typename std::remove_reference<
|
||||
decltype(*std::begin(std::declval<RangeType &>()))>::type>::type;
|
||||
|
||||
/// 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.
|
||||
template <unsigned Size, typename R>
|
||||
SmallVector<typename std::remove_const<typename std::remove_reference<
|
||||
decltype(*std::begin(std::declval<R &>()))>::type>::type,
|
||||
Size>
|
||||
SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R &&Range) {
|
||||
return {std::begin(Range), std::end(Range)};
|
||||
}
|
||||
template <typename R>
|
||||
SmallVector<ValueTypeFromRangeType<R>,
|
||||
CalculateSmallVectorDefaultInlinedElements<
|
||||
ValueTypeFromRangeType<R>>::value>
|
||||
to_vector(R &&Range) {
|
||||
return {std::begin(Range), std::end(Range)};
|
||||
}
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the StringMap class.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the StringMap class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_STRINGMAP_H
|
||||
#define WPIUTIL_WPI_STRINGMAP_H
|
||||
|
||||
#include "wpi/StringMapEntry.h"
|
||||
#include "wpi/iterator.h"
|
||||
#include "wpi/AllocatorBase.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include "wpi/SmallVector.h"
|
||||
@@ -130,9 +132,7 @@ public:
|
||||
|
||||
StringMap(std::initializer_list<std::pair<std::string_view, ValueTy>> List)
|
||||
: StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
|
||||
for (const auto &P : List) {
|
||||
insert(P);
|
||||
}
|
||||
insert(List);
|
||||
}
|
||||
|
||||
StringMap(StringMap &&RHS)
|
||||
@@ -301,6 +301,21 @@ public:
|
||||
return try_emplace(KV.first, std::move(KV.second));
|
||||
}
|
||||
|
||||
/// Inserts elements from range [first, last). If multiple elements in the
|
||||
/// range have keys that compare equivalent, it is unspecified which element
|
||||
/// is inserted .
|
||||
template <typename InputIt> void insert(InputIt First, InputIt Last) {
|
||||
for (InputIt It = First; It != Last; ++It)
|
||||
insert(*It);
|
||||
}
|
||||
|
||||
/// Inserts elements from initializer list ilist. If multiple elements in
|
||||
/// the range have keys that compare equivalent, it is unspecified which
|
||||
/// element is inserted
|
||||
void insert(std::initializer_list<std::pair<std::string_view, ValueTy>> List) {
|
||||
insert(List.begin(), List.end());
|
||||
}
|
||||
|
||||
/// Inserts an element or assigns to the current element if the key already
|
||||
/// exists. The return type is the same as try_emplace.
|
||||
template <typename V>
|
||||
@@ -485,13 +500,7 @@ public:
|
||||
explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
|
||||
: base(std::move(Iter)) {}
|
||||
|
||||
std::string_view &operator*() {
|
||||
Key = this->wrapped()->getKey();
|
||||
return Key;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string_view Key;
|
||||
std::string_view operator*() const { return this->wrapped()->getKey(); }
|
||||
};
|
||||
|
||||
template <typename ValueTy>
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the StringMapEntry class - it is intended to be a low
|
||||
// dependency implementation detail of StringMap that is more suitable for
|
||||
// inclusion in public headers than StringMap.h itself is.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// This file defines the StringMapEntry class - it is intended to be a low
|
||||
/// dependency implementation detail of StringMap that is more suitable for
|
||||
/// inclusion in public headers than StringMap.h itself is.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef WPIUTIL_WPI_STRINGMAPENTRY_H
|
||||
|
||||
@@ -35,6 +35,21 @@ namespace wpi {
|
||||
/// terms of addition of one. These aren't equivalent for all iterator
|
||||
/// categories, and respecting that adds a lot of complexity for little gain.
|
||||
///
|
||||
/// Iterators are expected to have const rules analogous to pointers, with a
|
||||
/// single, const-qualified operator*() that returns ReferenceT. This matches
|
||||
/// the second and third pointers in the following example:
|
||||
/// \code
|
||||
/// int Value;
|
||||
/// { int *I = &Value; } // ReferenceT 'int&'
|
||||
/// { int *const I = &Value; } // ReferenceT 'int&'; const
|
||||
/// { const int *I = &Value; } // ReferenceT 'const int&'
|
||||
/// { const int *const I = &Value; } // ReferenceT 'const int&'; const
|
||||
/// \endcode
|
||||
/// If an iterator facade returns a handle to its own state, then T (and
|
||||
/// PointerT and ReferenceT) should usually be const-qualified. Otherwise, if
|
||||
/// clients are expected to modify the handle itself, the field can be declared
|
||||
/// mutable or use const_cast.
|
||||
///
|
||||
/// Classes wishing to use `iterator_facade_base` should implement the following
|
||||
/// methods:
|
||||
///
|
||||
@@ -42,8 +57,7 @@ namespace wpi {
|
||||
/// (All of the following methods)
|
||||
/// - DerivedT &operator=(const DerivedT &R);
|
||||
/// - bool operator==(const DerivedT &R) const;
|
||||
/// - const T &operator*() const;
|
||||
/// - T &operator*();
|
||||
/// - T &operator*() const;
|
||||
/// - DerivedT &operator++();
|
||||
///
|
||||
/// Bidirectional Iterators:
|
||||
@@ -95,6 +109,22 @@ protected:
|
||||
operator ReferenceT() const { return *I; }
|
||||
};
|
||||
|
||||
/// A proxy object for computing a pointer via indirecting a copy of a
|
||||
/// reference. This is used in APIs which need to produce a pointer but for
|
||||
/// which the reference might be a temporary. The proxy preserves the
|
||||
/// reference internally and exposes the pointer via a arrow operator.
|
||||
class PointerProxy {
|
||||
friend iterator_facade_base;
|
||||
|
||||
ReferenceT R;
|
||||
|
||||
template <typename RefT>
|
||||
PointerProxy(RefT &&R) : R(std::forward<RefT>(R)) {}
|
||||
|
||||
public:
|
||||
PointerT operator->() const { return &R; }
|
||||
};
|
||||
|
||||
public:
|
||||
DerivedT operator+(DifferenceTypeT n) const {
|
||||
static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
|
||||
@@ -172,19 +202,13 @@ public:
|
||||
return !(static_cast<const DerivedT &>(*this) < RHS);
|
||||
}
|
||||
|
||||
PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
|
||||
PointerT operator->() const {
|
||||
return &static_cast<const DerivedT *>(this)->operator*();
|
||||
}
|
||||
ReferenceProxy operator[](DifferenceTypeT n) {
|
||||
static_assert(IsRandomAccess,
|
||||
"Subscripting is only defined for random access iterators.");
|
||||
return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
|
||||
PointerProxy operator->() const {
|
||||
return static_cast<const DerivedT *>(this)->operator*();
|
||||
}
|
||||
ReferenceProxy operator[](DifferenceTypeT n) const {
|
||||
static_assert(IsRandomAccess,
|
||||
"Subscripting is only defined for random access iterators.");
|
||||
return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
|
||||
return static_cast<const DerivedT *>(this)->operator+(n);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -330,8 +354,7 @@ public:
|
||||
explicit pointer_iterator(WrappedIteratorT u)
|
||||
: pointer_iterator::iterator_adaptor_base(std::move(u)) {}
|
||||
|
||||
T &operator*() { return Ptr = &*this->I; }
|
||||
const T &operator*() const { return Ptr = &*this->I; }
|
||||
T &operator*() const { return Ptr = &*this->I; }
|
||||
};
|
||||
|
||||
template <typename RangeT, typename WrappedIteratorT =
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "wpi/SmallVector.h"
|
||||
#include "wpi/span.h"
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@@ -306,6 +305,8 @@ public:
|
||||
// changeColor() has no effect until enable_colors(true) is called.
|
||||
virtual void enable_colors(bool /*enable*/) {}
|
||||
|
||||
bool colors_enabled() const { return false; }
|
||||
|
||||
/// Tie this stream to the specified stream. Replaces any existing tied-to
|
||||
/// stream. Specifying a nullptr unties the stream.
|
||||
void tie(raw_ostream *TieTo) { TiedStream = TieTo; }
|
||||
@@ -414,6 +415,7 @@ class raw_fd_ostream : public raw_pwrite_stream {
|
||||
int FD;
|
||||
bool ShouldClose;
|
||||
bool SupportsSeeking = false;
|
||||
bool IsRegularFile = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
/// True if this fd refers to a Windows console device. Mintty and other
|
||||
@@ -483,6 +485,8 @@ public:
|
||||
|
||||
bool supportsSeeking() const { return SupportsSeeking; }
|
||||
|
||||
bool isRegularFile() const { return IsRegularFile; }
|
||||
|
||||
/// Flushes the stream and repositions the underlying file descriptor position
|
||||
/// to the offset specified from the beginning of the file.
|
||||
uint64_t seek(uint64_t off);
|
||||
@@ -544,6 +548,9 @@ public:
|
||||
|
||||
/// A raw_ostream that writes to an std::string. This is a simple adaptor
|
||||
/// class. This class does not encounter output errors.
|
||||
/// raw_string_ostream operates without a buffer, delegating all memory
|
||||
/// management to the std::string. Thus the std::string is always up-to-date,
|
||||
/// may be used directly and there is no need to call flush().
|
||||
class raw_string_ostream : public raw_ostream {
|
||||
std::string &OS;
|
||||
|
||||
@@ -558,14 +565,11 @@ public:
|
||||
explicit raw_string_ostream(std::string &O) : OS(O) {
|
||||
SetUnbuffered();
|
||||
}
|
||||
~raw_string_ostream() override;
|
||||
|
||||
/// Flushes the stream contents to the target string and returns the string's
|
||||
/// reference.
|
||||
std::string& str() {
|
||||
flush();
|
||||
return OS;
|
||||
}
|
||||
/// Returns the string's reference. In most cases it is better to simply use
|
||||
/// the underlying std::string directly.
|
||||
/// TODO: Consider removing this API.
|
||||
std::string &str() { return OS; }
|
||||
|
||||
void reserveExtraSpace(uint64_t ExtraSize) override {
|
||||
OS.reserve(tell() + ExtraSize);
|
||||
@@ -745,7 +749,11 @@ class buffer_unique_ostream : public raw_svector_ostream {
|
||||
|
||||
public:
|
||||
buffer_unique_ostream(std::unique_ptr<raw_ostream> OS)
|
||||
: raw_svector_ostream(Buffer), OS(std::move(OS)) {}
|
||||
: raw_svector_ostream(Buffer), OS(std::move(OS)) {
|
||||
// Turn off buffering on OS, which we now own, to avoid allocating a buffer
|
||||
// when the destructor writes only to be immediately flushed again.
|
||||
this->OS->SetUnbuffered();
|
||||
}
|
||||
~buffer_unique_ostream() override { *OS << str(); }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user