[wpiutil] Vendor llvm and update to 13.0.0 (#4224)

This commit is contained in:
PJ Reiniger
2022-05-20 18:59:53 -04:00
committed by GitHub
parent 5aa67f56e6
commit c3b223ce60
106 changed files with 16897 additions and 1895 deletions

View File

@@ -49,6 +49,7 @@
#include "wpi/Errc.h"
#include "wpi/Errno.h"
#include "wpi/MappedFileRegion.h"
#include "wpi/MathExtras.h"
#include "wpi/SmallVector.h"
#include "wpi/SmallVectorMemoryBuffer.h"
#include "wpi/fs.h"

View File

@@ -1,9 +1,8 @@
/*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
*===------------------------------------------------------------------------=*/
/*
@@ -829,6 +828,6 @@ std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
#endif // _WIN32
} // namespace llvm
} // namespace wpi
ConvertUTF_RESTORE_WARNINGS

View File

@@ -1,19 +1,68 @@
//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "wpi/span.h"
#include "wpi/ConvertUTF.h"
#include "wpi/SmallVector.h"
#include "wpi/ErrorHandling.h"
#include "wpi/SwapByteOrder.h"
#include <string>
#include <string_view>
#include <vector>
namespace wpi {
bool ConvertUTF8toWide(unsigned WideCharWidth, std::string_view Source,
char *&ResultPtr, const UTF8 *&ErrorPtr) {
assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4);
ConversionResult result = conversionOK;
// Copy the character span over.
if (WideCharWidth == 1) {
const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.data());
if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.data() + Source.size()))) {
result = sourceIllegal;
ErrorPtr = Pos;
} else {
memcpy(ResultPtr, Source.data(), Source.size());
ResultPtr += Source.size();
}
} else if (WideCharWidth == 2) {
const UTF8 *sourceStart = (const UTF8*)Source.data();
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF16(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
ErrorPtr = sourceStart;
} else if (WideCharWidth == 4) {
const UTF8 *sourceStart = (const UTF8*)Source.data();
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF32(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
ErrorPtr = sourceStart;
}
assert((result != targetExhausted)
&& "ConvertUTF8toUTFXX exhausted target buffer");
return result == conversionOK;
}
bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
const UTF32 *SourceStart = &Source;
const UTF32 *SourceEnd = SourceStart + 1;
@@ -35,23 +84,28 @@ bool hasUTF16ByteOrderMark(span<const char> S) {
(S[0] == '\xfe' && S[1] == '\xff')));
}
bool convertUTF16ToUTF8String(span<const UTF16> SrcUTF16,
SmallVectorImpl<char> &DstUTF8) {
assert(DstUTF8.empty());
bool convertUTF16ToUTF8String(span<const char> SrcBytes, SmallVectorImpl<char> &Out) {
assert(Out.empty());
// Error out on an uneven byte count.
if (SrcBytes.size() % 2)
return false;
// Avoid OOB by returning early on empty input.
if (SrcUTF16.empty())
if (SrcBytes.empty())
return true;
const UTF16 *Src = SrcUTF16.begin();
const UTF16 *SrcEnd = SrcUTF16.end();
const UTF16 *Src = reinterpret_cast<const UTF16 *>(SrcBytes.begin());
const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(SrcBytes.end());
assert((uintptr_t)Src % sizeof(UTF16) == 0);
// Byteswap if necessary.
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] = (ByteSwapped[I] << 8) | (ByteSwapped[I] >> 8);
ByteSwapped[I] = wpi::ByteSwap_16(ByteSwapped[I]);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
@@ -62,25 +116,32 @@ bool convertUTF16ToUTF8String(span<const UTF16> SrcUTF16,
// Just allocate enough space up front. We'll shrink it later. Allocate
// enough that we can fit a null terminator without reallocating.
DstUTF8.resize(SrcUTF16.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
UTF8 *Dst = reinterpret_cast<UTF8*>(&DstUTF8[0]);
UTF8 *DstEnd = Dst + DstUTF8.size();
Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
UTF8 *DstEnd = Dst + Out.size();
ConversionResult CR =
ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
assert(CR != targetExhausted);
if (CR != conversionOK) {
DstUTF8.clear();
Out.clear();
return false;
}
DstUTF8.resize(reinterpret_cast<char*>(Dst) - &DstUTF8[0]);
DstUTF8.push_back(0);
DstUTF8.pop_back();
Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
Out.push_back(0);
Out.pop_back();
return true;
}
bool convertUTF16ToUTF8String(span<const UTF16> Src, SmallVectorImpl<char> &Out)
{
return convertUTF16ToUTF8String(
span<const char>(reinterpret_cast<const char *>(Src.data()),
Src.size() * sizeof(UTF16)), Out);
}
bool convertUTF8ToUTF16String(std::string_view SrcUTF8,
SmallVectorImpl<UTF16> &DstUTF16) {
assert(DstUTF16.empty());
@@ -119,5 +180,74 @@ bool convertUTF8ToUTF16String(std::string_view SrcUTF8,
return true;
}
static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
sizeof(wchar_t) == 4,
"Expected wchar_t to be 1, 2, or 4 bytes");
template <typename TResult>
static inline bool ConvertUTF8toWideInternal(std::string_view Source,
TResult &Result) {
// Even in the case of UTF-16, the number of bytes in a UTF-8 string is
// at least as large as the number of elements in the resulting wide
// string, because surrogate pairs take at least 4 bytes in UTF-8.
Result.resize(Source.size() + 1);
char *ResultPtr = reinterpret_cast<char *>(&Result[0]);
const UTF8 *ErrorPtr;
if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) {
Result.clear();
return false;
}
Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]);
return true;
}
bool ConvertUTF8toWide(std::string_view Source, std::wstring &Result) {
return ConvertUTF8toWideInternal(Source, Result);
}
bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
if (!Source) {
Result.clear();
return true;
}
return ConvertUTF8toWide(std::string_view(Source), Result);
}
bool convertWideToUTF8(const std::wstring &Source, SmallVectorImpl<char> &Result) {
if (sizeof(wchar_t) == 1) {
const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
const UTF8 *End =
reinterpret_cast<const UTF8 *>(Source.data() + Source.size());
if (!isLegalUTF8String(&Start, End))
return false;
Result.resize(Source.size());
memcpy(&Result[0], Source.data(), Source.size());
return true;
} else if (sizeof(wchar_t) == 2) {
return convertUTF16ToUTF8String(
span<const UTF16>(reinterpret_cast<const UTF16 *>(Source.data()),
Source.size()),
Result);
} else if (sizeof(wchar_t) == 4) {
const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data());
const UTF32 *End =
reinterpret_cast<const UTF32 *>(Source.data() + Source.size());
Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size());
UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]);
UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size());
if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd,
strictConversion) == conversionOK) {
Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]);
return true;
} else {
Result.clear();
return false;
}
} else {
wpi_unreachable(
"Control should never reach this point; see static_assert further up");
}
}
} // end namespace wpi

View File

@@ -1,9 +1,8 @@
//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -14,10 +13,10 @@
#include "wpi/ErrorHandling.h"
#include "wpi/SmallVector.h"
#include "wpi/Errc.h"
#include "wpi/WindowsError.h"
#include "fmt/format.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <mutex>
#include <new>
@@ -25,7 +24,6 @@
#ifndef _WIN32
#include <unistd.h>
#endif
#if defined(_MSC_VER)
#include <io.h>
#endif
@@ -53,7 +51,7 @@ static std::mutex ErrorHandlerMutex;
static std::mutex BadAllocErrorHandlerMutex;
void wpi::install_fatal_error_handler(fatal_error_handler_t handler,
void *user_data) {
void *user_data) {
std::scoped_lock Lock(ErrorHandlerMutex);
assert(!ErrorHandler && "Error handler already registered!\n");
ErrorHandler = handler;
@@ -95,7 +93,7 @@ void wpi::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
}
void wpi::install_bad_alloc_error_handler(fatal_error_handler_t handler,
void *user_data) {
void *user_data) {
std::scoped_lock Lock(BadAllocErrorHandlerMutex);
assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
BadAllocErrorHandler = handler;
@@ -126,13 +124,17 @@ void wpi::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
// Don't call the normal error handler. It may allocate memory. Directly write
// an OOM to stderr and abort.
char OOMMessage[] = "LLVM ERROR: out of memory\n";
const char *OOMMessage = "LLVM ERROR: out of memory\n";
const char *Newline = "\n";
#ifdef _WIN32
int written = ::_write(2, OOMMessage, strlen(OOMMessage));
(void)!::_write(2, OOMMessage, strlen(OOMMessage));
(void)!::_write(2, Reason, strlen(Reason));
(void)!::_write(2, Newline, strlen(Newline));
#else
ssize_t written = ::write(2, OOMMessage, strlen(OOMMessage));
(void)!::write(2, OOMMessage, strlen(OOMMessage));
(void)!::write(2, Reason, strlen(Reason));
(void)!::write(2, Newline, strlen(Newline));
#endif
(void)written;
abort();
}
@@ -142,28 +144,17 @@ static void out_of_memory_new_handler() {
wpi::report_bad_alloc_error("Allocation failed");
}
// Installs new handler that causes crash on allocation failure. It does not
// need to be called explicitly, if this file is linked to application, because
// in this case it is called during construction of 'new_handler_installer'.
// Installs new handler that causes crash on allocation failure. It is called by
// InitLLVM.
void wpi::install_out_of_memory_new_handler() {
static bool out_of_memory_new_handler_installed = false;
if (!out_of_memory_new_handler_installed) {
std::set_new_handler(out_of_memory_new_handler);
out_of_memory_new_handler_installed = true;
}
std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
(void)old;
assert((old == nullptr || old == out_of_memory_new_handler) &&
"new-handler already installed");
}
// Static object that causes installation of 'out_of_memory_new_handler' before
// execution of 'main'.
static class NewHandlerInstaller {
public:
NewHandlerInstaller() {
install_out_of_memory_new_handler();
}
} new_handler_installer;
void wpi::wpi_unreachable_internal(const char *msg, const char *file,
unsigned line) {
unsigned line) {
// This code intentionally doesn't call the ErrorHandler callback, because
// wpi_unreachable is intended to be used to indicate "impossible"
// situations, and not legitimate runtime errors.
@@ -183,7 +174,6 @@ void wpi::wpi_unreachable_internal(const char *msg, const char *file,
#ifdef _WIN32
#include <system_error>
#include <winerror.h>
// I'd rather not double the line count of the following.

View File

@@ -1,9 +1,8 @@
//===-------------- lib/Support/Hashing.cpp -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

View File

@@ -1,9 +1,8 @@
//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -18,43 +17,32 @@
using namespace wpi;
static const ManagedStaticBase *StaticList = nullptr;
static wpi::mutex *ManagedStaticMutex = nullptr;
static std::once_flag mutex_init_flag;
static void initializeMutex() {
ManagedStaticMutex = new wpi::mutex();
}
static wpi::mutex* getManagedStaticMutex() {
std::call_once(mutex_init_flag, initializeMutex);
return ManagedStaticMutex;
}
void ManagedStaticBase::RegisterManagedStatic(void* created,
void (*Deleter)(void*)) const {
std::scoped_lock Lock(*getManagedStaticMutex());
if (!Ptr.load(std::memory_order_relaxed)) {
void *Tmp = created;
Ptr.store(Tmp, std::memory_order_release);
DeleterFn = Deleter;
// Add to list of managed statics.
Next = StaticList;
StaticList = this;
}
static wpi::mutex *getManagedStaticMutex() {
static wpi::mutex m;
return &m;
}
void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
std::scoped_lock Lock(*getManagedStaticMutex());
if (1) {
std::scoped_lock Lock(*getManagedStaticMutex());
if (!Ptr.load(std::memory_order_relaxed)) {
void *Tmp = Creator();
if (!Ptr.load(std::memory_order_relaxed)) {
void *Tmp = Creator();
Ptr.store(Tmp, std::memory_order_release);
Ptr.store(Tmp, std::memory_order_release);
DeleterFn = Deleter;
// Add to list of managed statics.
Next = StaticList;
StaticList = this;
}
} else {
assert(!Ptr && !DeleterFn && !Next &&
"Partially initialized ManagedStatic!?");
Ptr = Creator();
DeleterFn = Deleter;
// Add to list of managed statics.
@@ -80,9 +68,10 @@ void ManagedStaticBase::destroy() const {
}
/// wpi_shutdown - Deallocate and destroy all ManagedStatic variables.
/// IMPORTANT: it's only safe to call wpi_shutdown() in single thread,
/// without any other threads executing LLVM APIs.
/// wpi_shutdown() should be the last use of LLVM APIs.
void wpi::wpi_shutdown() {
std::scoped_lock Lock(*getManagedStaticMutex());
while (StaticList)
StaticList->destroy();
}

View File

@@ -0,0 +1,34 @@
//===- MemAlloc.cpp - Memory allocation functions -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "wpi/MemAlloc.h"
// These are out of line to have __cpp_aligned_new not affect ABI.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
wpi::allocate_buffer(size_t Size, size_t Alignment) {
return ::operator new(Size
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}
void wpi::deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
::operator delete(Ptr
#ifdef __cpp_sized_deallocation
,
Size
#endif
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}

View File

@@ -1,9 +1,8 @@
//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -14,9 +13,9 @@
#include "wpi/SmallPtrSet.h"
#include "wpi/DenseMapInfo.h"
#include "wpi/ErrorHandling.h"
#include "wpi/MathExtras.h"
#include "wpi/MemAlloc.h"
#include "wpi/ErrorHandling.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>

View File

@@ -1,9 +1,8 @@
//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,21 +11,99 @@
//===----------------------------------------------------------------------===//
#include "wpi/SmallVector.h"
#include "wpi/MemAlloc.h"
#include <cstdint>
#ifdef LLVM_ENABLE_EXCEPTIONS
#include <stdexcept>
#endif
using namespace wpi;
/// grow_pod - This is an implementation of the grow() method which only works
/// on POD-like datatypes and is out of line to reduce code duplication.
void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,
size_t TSize) {
// Ensure we can fit the new capacity in 32 bits.
if (MinCapacity > UINT32_MAX)
report_bad_alloc_error("SmallVector capacity overflow during allocation");
// Check that no bytes are wasted and everything is well-aligned.
namespace {
struct Struct16B {
alignas(16) void *X;
};
struct Struct32B {
alignas(32) void *X;
};
}
static_assert(sizeof(SmallVector<void *, 0>) ==
sizeof(unsigned) * 2 + sizeof(void *),
"wasted space in SmallVector size 0");
static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
"wrong alignment for 16-byte aligned T");
static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
"wrong alignment for 32-byte aligned T");
static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
"missing padding for 16-byte aligned T");
static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
"missing padding for 32-byte aligned T");
static_assert(sizeof(SmallVector<void *, 1>) ==
sizeof(unsigned) * 2 + sizeof(void *) * 2,
"wasted space in SmallVector size 1");
size_t NewCapacity = 2 * capacity() + 1; // Always grow.
NewCapacity =
std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));
/// 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);
static void report_size_overflow(size_t MinSize, size_t MaxSize) {
std::string Reason = "SmallVector unable to grow. Requested capacity (" +
std::to_string(MinSize) +
") is larger than maximum value for size type (" +
std::to_string(MaxSize) + ")";
#ifdef LLVM_ENABLE_EXCEPTIONS
throw std::length_error(Reason);
#else
report_fatal_error(Reason);
#endif
}
/// 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);
static void report_at_maximum_capacity(size_t MaxSize) {
std::string Reason =
"SmallVector capacity unable to grow. Already at maximum size " +
std::to_string(MaxSize);
#ifdef LLVM_ENABLE_EXCEPTIONS
throw std::length_error(Reason);
#else
report_fatal_error(Reason);
#endif
}
// Note: Moving this function into the header may cause performance regression.
static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
constexpr size_t MaxSize = std::numeric_limits<unsigned>::max();
// Ensure we can fit the new capacity.
// This is only going to be applicable when the capacity is 32 bit.
if (MinSize > MaxSize)
report_size_overflow(MinSize, MaxSize);
// Ensure we can meet the guarantee of space for at least one more element.
// The above check alone will not catch the case where grow is called with a
// default MinSize of 0, but the current capacity cannot be increased.
// This is only going to be applicable when the capacity is 32 bit.
if (OldCapacity == MaxSize)
report_at_maximum_capacity(MaxSize);
// In theory 2*capacity can overflow if the capacity is 64 bit, but the
// original capacity would never be large enough for this to be a problem.
size_t NewCapacity = 2 * OldCapacity + 1; // Always grow.
return (std::min)((std::max)(NewCapacity, MinSize), MaxSize);
}
// Note: Moving this function into the header may cause performance regression.
void *SmallVectorBase::mallocForGrow(size_t MinSize, size_t TSize,
size_t &NewCapacity) {
NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
return wpi::safe_malloc(NewCapacity * TSize);
}
// Note: Moving this function into the header may cause performance regression.
void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize,
size_t TSize) {
size_t NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
void *NewElts;
if (BeginX == FirstEl) {
NewElts = safe_malloc(NewCapacity * TSize);

View File

@@ -1,9 +1,8 @@
//===--- StringMap.cpp - String Hash table map implementation -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -15,7 +14,6 @@
#include "wpi/StringExtras.h"
#include "wpi/Compiler.h"
#include "wpi/MathExtras.h"
#include <cassert>
using namespace wpi;
@@ -65,23 +63,22 @@ StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
}
void StringMapImpl::init(unsigned InitSize) {
assert((InitSize & (InitSize-1)) == 0 &&
assert((InitSize & (InitSize - 1)) == 0 &&
"Init Size must be a power of 2 or zero!");
unsigned NewNumBuckets = InitSize ? InitSize : 16;
NumItems = 0;
NumTombstones = 0;
TheTable = static_cast<StringMapEntryBase **>(
safe_calloc(NewNumBuckets+1,
sizeof(StringMapEntryBase **) + sizeof(unsigned)));
TheTable = static_cast<StringMapEntryBase **>(safe_calloc(
NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned)));
// Set the member only if TheTable was successfully allocated
NumBuckets = NewNumBuckets;
// Allocate one extra bucket, set it to look filled so the iterators stop at
// end.
TheTable[NumBuckets] = (StringMapEntryBase*)2;
TheTable[NumBuckets] = (StringMapEntryBase *)2;
}
/// LookupBucketFor - Look up the bucket that the specified string should end
@@ -91,12 +88,12 @@ void StringMapImpl::init(unsigned InitSize) {
/// of the string.
unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
unsigned HTSize = NumBuckets;
if (HTSize == 0) { // Hash table unallocated so far?
if (HTSize == 0) { // Hash table unallocated so far?
init(16);
HTSize = NumBuckets;
}
unsigned FullHashValue = HashString(Name);
unsigned BucketNo = FullHashValue & (HTSize-1);
unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned ProbeAmt = 1;
@@ -118,7 +115,8 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
if (BucketItem == getTombstoneVal()) {
// Skip over tombstones. However, remember the first one we see.
if (FirstTombstone == -1) FirstTombstone = BucketNo;
if (FirstTombstone == -1)
FirstTombstone = BucketNo;
} else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
// If the full hash value matches, check deeply for a match. The common
// case here is that we are only looking at the buckets (for item info
@@ -127,7 +125,7 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
// Do the comparison like this because Name isn't necessarily
// null-terminated!
char *ItemStr = (char*)BucketItem+ItemSize;
char *ItemStr = (char *)BucketItem + ItemSize;
if (Name == std::string_view(ItemStr, BucketItem->getKeyLength())) {
// We found a match!
return BucketNo;
@@ -135,7 +133,7 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
}
// Okay, we didn't find the item. Probe to the next bucket.
BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -148,9 +146,10 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
/// This does not modify the map.
int StringMapImpl::FindKey(std::string_view Key) const {
unsigned HTSize = NumBuckets;
if (HTSize == 0) return -1; // Really empty table?
if (HTSize == 0)
return -1; // Really empty table?
unsigned FullHashValue = HashString(Key);
unsigned BucketNo = FullHashValue & (HTSize-1);
unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned ProbeAmt = 1;
@@ -170,7 +169,7 @@ int StringMapImpl::FindKey(std::string_view Key) const {
// Do the comparison like this because NameStart isn't necessarily
// null-terminated!
char *ItemStr = (char*)BucketItem+ItemSize;
char *ItemStr = (char *)BucketItem + ItemSize;
if (Key == std::string_view(ItemStr, BucketItem->getKeyLength())) {
// We found a match!
return BucketNo;
@@ -178,7 +177,7 @@ int StringMapImpl::FindKey(std::string_view Key) const {
}
// Okay, we didn't find the item. Probe to the next bucket.
BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -189,7 +188,7 @@ int StringMapImpl::FindKey(std::string_view Key) const {
/// RemoveKey - Remove the specified StringMapEntry from the table, but do not
/// delete it. This aborts if the value isn't in the table.
void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
const char *VStr = (char*)V + ItemSize;
const char *VStr = (char *)V + ItemSize;
StringMapEntryBase *V2 = RemoveKey(std::string_view(VStr, V->getKeyLength()));
(void)V2;
assert(V == V2 && "Didn't find key?");
@@ -199,7 +198,8 @@ void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
/// table, returning it. If the key is not in the table, this returns null.
StringMapEntryBase *StringMapImpl::RemoveKey(std::string_view Key) {
int Bucket = FindKey(Key);
if (Bucket == -1) return nullptr;
if (Bucket == -1)
return nullptr;
StringMapEntryBase *Result = TheTable[Bucket];
TheTable[Bucket] = getTombstoneVal();
@@ -220,7 +220,7 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
// the buckets are empty (meaning that many are filled with tombstones),
// grow/rehash the table.
if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
NewSize = NumBuckets*2;
NewSize = NumBuckets * 2;
} else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
NumBuckets / 8)) {
NewSize = NumBuckets;
@@ -231,11 +231,11 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
unsigned NewBucketNo = BucketNo;
// Allocate one extra bucket which will always be non-empty. This allows the
// iterators to stop at end.
auto NewTableArray = static_cast<StringMapEntryBase **>(
safe_calloc(NewSize+1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
auto NewTableArray = static_cast<StringMapEntryBase **>(safe_calloc(
NewSize + 1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
NewTableArray[NewSize] = (StringMapEntryBase*)2;
NewTableArray[NewSize] = (StringMapEntryBase *)2;
// Rehash all the items into their new buckets. Luckily :) we already have
// the hash values available, so we don't have to rehash any strings.
@@ -244,10 +244,10 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
if (Bucket && Bucket != getTombstoneVal()) {
// Fast case, bucket available.
unsigned FullHash = HashTable[I];
unsigned NewBucket = FullHash & (NewSize-1);
unsigned NewBucket = FullHash & (NewSize - 1);
if (!NewTableArray[NewBucket]) {
NewTableArray[FullHash & (NewSize-1)] = Bucket;
NewHashArray[FullHash & (NewSize-1)] = FullHash;
NewTableArray[FullHash & (NewSize - 1)] = Bucket;
NewHashArray[FullHash & (NewSize - 1)] = FullHash;
if (I == BucketNo)
NewBucketNo = NewBucket;
continue;
@@ -256,7 +256,7 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
// Otherwise probe for a spot.
unsigned ProbeSize = 1;
do {
NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1);
} while (NewTableArray[NewBucket]);
// Finally found a slot. Fill it in.

View File

@@ -1,9 +1,8 @@
//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,8 +18,8 @@
//=== is guaranteed to work on *all* Win32 variants.
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
#define LLVM_SUPPORT_WINDOWSSUPPORT_H
#ifndef WPIUTIL_WPI_WINDOWSSUPPORT_H
#define WPIUTIL_WPI_WINDOWSSUPPORT_H
// mingw-w64 tends to define it as 0x0502 in its headers.
#undef _WIN32_WINNT
@@ -38,10 +37,10 @@
#include "wpi/StringExtras.h"
#include "wpi/Chrono.h"
#include "wpi/Compiler.h"
#include "wpi/ErrorHandling.h"
#include "wpi/VersionTuple.h"
#include <cassert>
#include <string>
#include <string_view>
#include <system_error>
#define WIN32_NO_STATUS
#include <windows.h>
@@ -49,6 +48,9 @@
#include <winternl.h>
#include <ntstatus.h>
// Must be included after windows.h
#include <wincrypt.h>
namespace wpi {
/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
@@ -81,23 +83,19 @@ inline bool RunningWindows8OrGreater() {
return GetWindowsOSVersion() >= wpi::VersionTuple(6, 2, 0, 0);
}
inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
if (!ErrMsg)
return true;
char *buffer = NULL;
DWORD LastError = GetLastError();
DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
if (R)
*ErrMsg = prefix + ": " + buffer;
else
*ErrMsg = prefix + ": Unknown error";
*ErrMsg += " (0x" + wpi::utohexstr(LastError) + ")";
/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
/// GetVersionEx is deprecated, but this API exposes the build number which can
/// be useful for working around certain kernel bugs.
wpi::VersionTuple GetWindowsOSVersion();
LocalFree(buffer);
return R != 0;
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) {
std::string ErrMsg;
MakeErrMsg(&ErrMsg, Msg);
wpi::report_fatal_error(ErrMsg);
}
template <typename HandleTraits>
@@ -164,6 +162,22 @@ struct JobHandleTraits : CommonHandleTraits {
}
};
struct CryptContextTraits : CommonHandleTraits {
typedef HCRYPTPROV handle_type;
static handle_type GetInvalid() {
return 0;
}
static void Close(handle_type h) {
::CryptReleaseContext(h, 0);
}
static bool IsValid(handle_type h) {
return h != GetInvalid();
}
};
struct RegTraits : CommonHandleTraits {
typedef HKEY handle_type;
@@ -190,6 +204,7 @@ struct FileHandleTraits : CommonHandleTraits {};
typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
typedef ScopedHandle<RegTraits> ScopedRegHandle;
typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;

View File

@@ -1,9 +1,8 @@
//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

View File

@@ -1,9 +1,8 @@
//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -21,19 +20,17 @@
#include "wpi/StringExtras.h"
#include "wpi/Compiler.h"
#include "wpi/ErrorHandling.h"
#include "wpi/MathExtras.h"
#include "wpi/WindowsError.h"
#include "wpi/fs.h"
#include "wpi/MathExtras.h"
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <cstdio>
#include <iterator>
#include <sys/stat.h>
#include <system_error>
// <fcntl.h> may provide O_BINARY.
#include <fcntl.h>
# include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
@@ -64,6 +61,17 @@
using namespace wpi;
constexpr raw_ostream::Colors raw_ostream::BLACK;
constexpr raw_ostream::Colors raw_ostream::RED;
constexpr raw_ostream::Colors raw_ostream::GREEN;
constexpr raw_ostream::Colors raw_ostream::YELLOW;
constexpr raw_ostream::Colors raw_ostream::BLUE;
constexpr raw_ostream::Colors raw_ostream::MAGENTA;
constexpr raw_ostream::Colors raw_ostream::CYAN;
constexpr raw_ostream::Colors raw_ostream::WHITE;
constexpr raw_ostream::Colors raw_ostream::SAVEDCOLOR;
constexpr raw_ostream::Colors raw_ostream::RESET;
namespace {
// Find the length of an array.
template <class T, std::size_t N>
@@ -78,13 +86,10 @@ raw_ostream::~raw_ostream() {
assert(OutBufCur == OutBufStart &&
"raw_ostream destructor called with non-empty buffer!");
if (BufferMode == InternalBuffer)
if (BufferMode == BufferKind::InternalBuffer)
delete [] OutBufStart;
}
// An out of line virtual method to provide a home for the class vtable.
void raw_ostream::handle() {}
size_t raw_ostream::preferred_buffer_size() const {
// BUFSIZ is intended to be a reasonable default.
return BUFSIZ;
@@ -101,14 +106,14 @@ void raw_ostream::SetBuffered() {
void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
BufferKind Mode) {
assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
(Mode != Unbuffered && BufferStart && Size != 0)) &&
assert(((Mode == BufferKind::Unbuffered && !BufferStart && Size == 0) ||
(Mode != BufferKind::Unbuffered && BufferStart && Size != 0)) &&
"stream must be unbuffered or have at least one byte");
// Make sure the current buffer is free of content (we can't flush here; the
// child buffer management logic will be in write_impl).
assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
if (BufferMode == InternalBuffer)
if (BufferMode == BufferKind::InternalBuffer)
delete [] OutBufStart;
OutBufStart = BufferStart;
OutBufEnd = OutBufStart+Size;
@@ -162,15 +167,15 @@ void raw_ostream::flush_nonempty() {
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
size_t Length = OutBufCur - OutBufStart;
OutBufCur = OutBufStart;
write_impl(OutBufStart, Length);
flush_tied_then_write(OutBufStart, Length);
}
raw_ostream &raw_ostream::write(unsigned char C) {
// Group exceptional cases into a single branch.
if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
if (LLVM_UNLIKELY(!OutBufStart)) {
if (BufferMode == Unbuffered) {
write_impl(reinterpret_cast<char*>(&C), 1);
if (BufferMode == BufferKind::Unbuffered) {
flush_tied_then_write(reinterpret_cast<char *>(&C), 1);
return *this;
}
// Set up a buffer and start over.
@@ -189,8 +194,8 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
// Group exceptional cases into a single branch.
if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
if (LLVM_UNLIKELY(!OutBufStart)) {
if (BufferMode == Unbuffered) {
write_impl(Ptr, Size);
if (BufferMode == BufferKind::Unbuffered) {
flush_tied_then_write(Ptr, Size);
return *this;
}
// Set up a buffer and start over.
@@ -206,7 +211,7 @@ raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {
assert(NumBytes != 0 && "undefined behavior");
size_t BytesToWrite = Size - (Size % NumBytes);
write_impl(Ptr, BytesToWrite);
flush_tied_then_write(Ptr, BytesToWrite);
size_t BytesRemaining = Size - BytesToWrite;
if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {
// Too much left over to copy into our buffer.
@@ -247,6 +252,13 @@ void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
OutBufCur += Size;
}
void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) {
if (TiedStream)
TiedStream->flush();
write_impl(Ptr, Size);
}
template <char C>
static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
@@ -294,8 +306,7 @@ static int getFD(std::string_view Filename, std::error_code &EC,
// the owner of stdout and may set the "binary" flag globally based on Flags.
if (Filename == "-") {
EC = std::error_code();
// If user requested binary then put stdout into binary mode if
// possible.
// Change stdout's text/binary mode based on the Flags.
if (!(Flags & fs::OF_Text)) {
#if defined(_WIN32)
_setmode(_fileno(stdout), _O_BINARY);
@@ -305,11 +316,10 @@ static int getFD(std::string_view Filename, std::error_code &EC,
}
fs::file_t F;
if (Access & fs::FA_Read) {
if (Access & fs::FA_Read)
F = fs::OpenFileForReadWrite(fs::path{std::string_view{Filename.data(), Filename.size()}}, EC, Disp, Flags);
} else {
else
F = fs::OpenFileForWrite(fs::path{std::string_view{Filename.data(), Filename.size()}}, EC, Disp, Flags);
}
if (EC)
return -1;
int FD = fs::FileToFd(F, EC, Flags);
@@ -345,13 +355,16 @@ raw_fd_ostream::raw_fd_ostream(std::string_view Filename, std::error_code &EC,
/// FD is the file descriptor that this writes to. If ShouldClose is true, this
/// closes the file when the stream is destroyed.
raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
: raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose) {
raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
OStreamKind K)
: raw_pwrite_stream(unbuffered, K), FD(fd), ShouldClose(shouldClose) {
if (FD < 0 ) {
ShouldClose = false;
return;
}
enable_colors(true);
// Do not attempt to close stdout or stderr. We used to try to maintain the
// property that tools that support writing file to stdout should not also
// write informational output to stdout, but in practice we were never able to
@@ -370,7 +383,6 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
// Get the starting position.
off_t loc = ::lseek(FD, 0, SEEK_CUR);
#ifdef _WIN32
// MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
SupportsSeeking = loc != (off_t)-1 && ::GetFileType(reinterpret_cast<HANDLE>(::_get_osfhandle(FD))) != FILE_TYPE_PIPE;
#else
SupportsSeeking = loc != (off_t)-1;
@@ -402,7 +414,7 @@ raw_fd_ostream::~raw_fd_ostream() {
// destructing raw_ostream objects which may have errors.
if (has_error())
report_fatal_error("IO failure on output stream: " + error().message(),
/*GenCrashDiag=*/false);
/*gen_crash_diag=*/false);
}
#if defined(_WIN32)
@@ -565,7 +577,7 @@ size_t raw_fd_ostream::preferred_buffer_size() const {
// If this is a terminal, don't use buffering. Line buffering
// would be a more traditional thing to do, but it's not worth
// the complexity.
if (S_ISCHR(statbuf.st_mode) && isatty(FD))
if (S_ISCHR(statbuf.st_mode) && is_displayed())
return 0;
// Return the preferred block size.
return statbuf.st_blksize;
@@ -580,28 +592,45 @@ void raw_fd_ostream::anchor() {}
// outs(), errs(), nulls()
//===----------------------------------------------------------------------===//
/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
raw_ostream &wpi::outs() {
raw_fd_ostream &wpi::outs() {
// Set buffer settings to model stdout behavior.
std::error_code EC;
static raw_fd_ostream* S = new raw_fd_ostream("-", EC, fs::F_None);
static raw_fd_ostream* S = new raw_fd_ostream("-", EC, fs::OF_None);
assert(!EC);
return *S;
}
/// errs() - This returns a reference to a raw_ostream for standard error.
/// Use it like: errs() << "foo" << "bar";
raw_ostream &wpi::errs() {
// Set standard error to be unbuffered by default.
raw_fd_ostream &wpi::errs() {
// Set standard error to be unbuffered and tied to outs() by default.
static raw_fd_ostream* S = new raw_fd_ostream(STDERR_FILENO, false, true);
return *S;
}
/// nulls() - This returns a reference to a raw_ostream which discards output.
raw_ostream &wpi::nulls() {
static raw_null_ostream* S = new raw_null_ostream;
return *S;
static raw_null_ostream S;
return S;
}
//===----------------------------------------------------------------------===//
// File Streams
//===----------------------------------------------------------------------===//
raw_fd_stream::raw_fd_stream(std::string_view Filename, std::error_code &EC)
: raw_fd_ostream(getFD(Filename, EC, fs::CD_CreateAlways,
fs::FA_Write | fs::FA_Read,
fs::OF_None),
true, false, OStreamKind::OK_FDStream) {
if (EC)
return;
// Do not support non-seekable files.
if (!supportsSeeking())
EC = std::make_error_code(std::errc::invalid_argument);
}
bool raw_fd_stream::classof(const raw_ostream *OS) {
return OS->get_kind() == OStreamKind::OK_FDStream;
}
//===----------------------------------------------------------------------===//
@@ -691,15 +720,18 @@ raw_null_ostream::~raw_null_ostream() {
#endif
}
void raw_null_ostream::write_impl(const char * /*Ptr*/, size_t /*Size*/) {}
void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
}
uint64_t raw_null_ostream::current_pos() const {
return 0;
}
void raw_null_ostream::pwrite_impl(const char * /*Ptr*/, size_t /*Size*/,
uint64_t /*Offset*/) {}
void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
uint64_t Offset) {}
void raw_pwrite_stream::anchor() {}
void buffer_ostream::anchor() {}
void buffer_unique_ostream::anchor() {}