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:
Tyler Veness
2022-08-15 05:38:15 -07:00
committed by GitHub
parent c5db23f296
commit 0e0786331a
70 changed files with 1211 additions and 823 deletions

View File

@@ -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(),

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "wpi/MemAlloc.h"
#include <new>
// These are out of line to have __cpp_aligned_new not affect ABI.

View File

@@ -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);

View File

@@ -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>

View File

@@ -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 " +

View File

@@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//
#include "wpi/StringMap.h"
#include "wpi/StringExtras.h"
#include "wpi/DJB.h"
#include "wpi/MathExtras.h"

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -21,6 +21,7 @@
#include "wpi/Compiler.h"
#include "wpi/MemAlloc.h"
#include <type_traits>
namespace wpi {

View File

@@ -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>;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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.

View File

@@ -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

View File

@@ -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.
//
//===----------------------------------------------------------------------===//

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)};
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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 =

View File

@@ -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(); }
};