[wpiutil] Upgrade to LLVM 16.0.6 (#5435)

Fixes #5332.
This commit is contained in:
Tyler Veness
2023-07-12 22:50:13 -07:00
committed by GitHub
parent 701df9eb87
commit 828bc5276f
77 changed files with 3798 additions and 1879 deletions

View File

@@ -73,6 +73,7 @@ doxygen {
// LLVM
exclude 'wpi/AlignOf.h'
exclude 'wpi/Casting.h'
exclude 'wpi/Chrono.h'
exclude 'wpi/Compiler.h'
exclude 'wpi/ConvertUTF.h'
@@ -83,6 +84,7 @@ doxygen {
exclude 'wpi/Errc.h'
exclude 'wpi/Errno.h'
exclude 'wpi/ErrorHandling.h'
exclude 'wpi/bit.h'
exclude 'wpi/fs.h'
exclude 'wpi/FunctionExtras.h'
exclude 'wpi/function_ref.h'

View File

@@ -39,11 +39,20 @@ git fetch origin 2.0
git fetch --depth 1 origin tag 2.0
```
Rebase any patches onto the new version.
Rebase any patches onto the new version. If the old version and new version are
on the same branch, run the following.
```bash
git rebase 2.0
```
If the old version and new version are on different branches (e.g.,
llvm-project), use interactive rebase instead and remove commits that are common
between the two branches from the list of commits to rebase. In other words,
only commits representing downstream patches should be listed.
```bash
git rebase -i 2.0
```
Generate patch files for the new version.
```bash
git format-patch 2.0..HEAD --zero-commit --abbrev=40 --no-signature

View File

@@ -8,7 +8,7 @@ Subject: [PATCH 01/30] Fix spelling/language errors
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Support/ErrorHandling.h b/llvm/include/llvm/Support/ErrorHandling.h
index f980510d37f0644bceea5b54e1469625b8115c97..6791df6be3362fa199556ecb2131f971cfef5210 100644
index 9c8e3448f3a03e3540adb8b9dd730c77dd9b20ba..dd1384a63af71b50ba1ccbb5933a1e472f50a39b 100644
--- a/llvm/include/llvm/Support/ErrorHandling.h
+++ b/llvm/include/llvm/Support/ErrorHandling.h
@@ -44,7 +44,7 @@ namespace llvm {

View File

@@ -8,14 +8,13 @@ Subject: [PATCH 03/30] Wrap std::min/max calls in parens, for Windows warnings
llvm/include/llvm/ADT/SmallVector.h | 12 ++++++------
llvm/include/llvm/Support/ConvertUTF.h | 2 +-
llvm/include/llvm/Support/MathExtras.h | 22 +++++++++++-----------
llvm/lib/Support/SmallVector.cpp | 2 +-
5 files changed, 21 insertions(+), 21 deletions(-)
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 7673b66ca42a0c9c16b7cadd6cc21c14a4d21d43..975c3b97e2cbf09225299c421406ad2bbe4ef125 100644
index 7adc6710cfa86db119446580246fc94a16dd9b3c..7f4ddc256a207289980b60385f02da69f7119578 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -390,7 +390,7 @@ protected:
@@ -389,7 +389,7 @@ protected:
return 0;
// +1 is required because of the strict equality.
// For example if NumEntries is 48, we need to return 401.
@@ -24,7 +23,7 @@ index 7673b66ca42a0c9c16b7cadd6cc21c14a4d21d43..975c3b97e2cbf09225299c421406ad2b
}
void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
@@ -826,7 +826,7 @@ public:
@@ -825,7 +825,7 @@ public:
// Reduce the number of buckets.
unsigned NewNumBuckets = 0;
if (OldNumEntries)
@@ -34,10 +33,10 @@ index 7673b66ca42a0c9c16b7cadd6cc21c14a4d21d43..975c3b97e2cbf09225299c421406ad2b
this->BaseT::initEmpty();
return;
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d3a4b4160 100644
index 92cccb130466a47127fbf8092286f9c5052dd26c..4a93f4c1d8102fc322ebde9c3c697877a1b9048a 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -49,12 +49,12 @@ protected:
@@ -55,12 +55,12 @@ protected:
/// The maximum value of the Size_T used.
static constexpr size_t SizeTypeMax() {
@@ -52,7 +51,7 @@ index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d
/// This is a helper for \a grow() that's out of line to reduce code
/// duplication. This function will report a fatal error if it can't grow at
@@ -79,7 +79,7 @@ protected:
@@ -99,7 +99,7 @@ protected:
/// This does not construct or destroy any elements in the vector.
void set_size(size_t N) {
assert(N <= capacity());
@@ -61,7 +60,7 @@ index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d
}
};
@@ -259,7 +259,7 @@ public:
@@ -279,7 +279,7 @@ public:
size_type size_in_bytes() const { return size() * sizeof(T); }
size_type max_size() const {
@@ -70,7 +69,7 @@ index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d
}
size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
@@ -444,7 +444,7 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
@@ -467,7 +467,7 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
free(this->begin());
this->BeginX = NewElts;
@@ -79,7 +78,7 @@ index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d
}
/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
@@ -693,7 +693,7 @@ public:
@@ -712,7 +712,7 @@ public:
}
// Assign over existing elements.
@@ -89,10 +88,10 @@ index a4a790323a6b80950de087f623668ab6ad3d935c..8686f7bb5407611979e8cecfe9da292d
std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
else if (NumElts < this->size())
diff --git a/llvm/include/llvm/Support/ConvertUTF.h b/llvm/include/llvm/Support/ConvertUTF.h
index 7f1527f51cdf59238607becfb2fdaf4afc91d4b6..b085c8a179e8767a258f9feafc8d1111828f10b1 100644
index 5c0e3009c25446a34882fb98329b1d955231bb39..72321022beb373945f7935ed72944fd68eb7d02f 100644
--- a/llvm/include/llvm/Support/ConvertUTF.h
+++ b/llvm/include/llvm/Support/ConvertUTF.h
@@ -112,7 +112,7 @@ namespace llvm {
@@ -127,7 +127,7 @@ namespace llvm {
typedef unsigned int UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
typedef unsigned char UTF8; /* typically 8 bits */
@@ -102,29 +101,20 @@ index 7f1527f51cdf59238607becfb2fdaf4afc91d4b6..b085c8a179e8767a258f9feafc8d1111
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 753b1998c40c0f9d2a178b5e748d620ffd23ac7e..db9fbc148ae3064faa94a23713d1def3b466e899 100644
index ff136ba2a8848e61fc85923e031fb3d60904a33d..45840976a09a733b69dee4070f2f9f8339455da2 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -97,7 +97,7 @@ template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
// Bisection method.
unsigned ZeroBits = 0;
T Shift = std::numeric_limits<T>::digits >> 1;
- T Mask = std::numeric_limits<T>::max() >> Shift;
+ T Mask = (std::numeric_limits<T>::max)() >> Shift;
while (Shift) {
if ((Val & Mask) == 0) {
Val >>= Shift;
@@ -238,7 +238,7 @@ unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
/// valid arguments.
@@ -100,7 +100,7 @@ template <typename T> unsigned countLeadingZeros(T Val) {
/// \param ZB the behavior on an input of 0.
template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
- return std::numeric_limits<T>::max();
+ return (std::numeric_limits<T>::max)();
return countTrailingZeros(Val, ZB_Undefined);
return llvm::countr_zero(Val);
}
@@ -279,7 +279,7 @@ template <typename T> T maskLeadingZeros(unsigned N) {
/// valid arguments.
@@ -140,7 +140,7 @@ template <typename T> T maskLeadingZeros(unsigned N) {
/// \param ZB the behavior on an input of 0.
template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
- return std::numeric_limits<T>::max();
@@ -132,38 +122,38 @@ index 753b1998c40c0f9d2a178b5e748d620ffd23ac7e..db9fbc148ae3064faa94a23713d1def3
// Use ^ instead of - because both gcc and llvm can remove the associated ^
// in the __builtin_clz intrinsic on x86.
@@ -594,26 +594,26 @@ inline double Log2(double Value) {
@@ -407,26 +407,26 @@ template <> constexpr inline size_t CTLog2<1>() { return 0; }
/// (32 bit edition.)
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
inline unsigned Log2_32(uint32_t Value) {
- return 31 - countLeadingZeros(Value);
+ return static_cast<unsigned>(31 - countLeadingZeros(Value));
- return 31 - llvm::countl_zero(Value);
+ return static_cast<unsigned>(31 - llvm::countl_zero(Value));
}
/// Return the floor log base 2 of the specified value, -1 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64(uint64_t Value) {
- return 63 - countLeadingZeros(Value);
+ return static_cast<unsigned>(63 - countLeadingZeros(Value));
- return 63 - llvm::countl_zero(Value);
+ return static_cast<unsigned>(63 - llvm::countl_zero(Value));
}
/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
/// (32 bit edition).
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
inline unsigned Log2_32_Ceil(uint32_t Value) {
- return 32 - countLeadingZeros(Value - 1);
+ return static_cast<unsigned>(32 - countLeadingZeros(Value - 1));
- return 32 - llvm::countl_zero(Value - 1);
+ return static_cast<unsigned>(32 - llvm::countl_zero(Value - 1));
}
/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64_Ceil(uint64_t Value) {
- return 64 - countLeadingZeros(Value - 1);
+ return static_cast<unsigned>(64 - countLeadingZeros(Value - 1));
- return 64 - llvm::countl_zero(Value - 1);
+ return static_cast<unsigned>(64 - llvm::countl_zero(Value - 1));
}
/// Return the greatest common divisor of the values using Euclid's algorithm.
@@ -807,7 +807,7 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
/// This function takes a 64-bit integer and returns the bit equivalent double.
@@ -609,7 +609,7 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
T Z = X + Y;
Overflowed = (Z < X || Z < Y);
if (Overflowed)
@@ -172,7 +162,16 @@ index 753b1998c40c0f9d2a178b5e748d620ffd23ac7e..db9fbc148ae3064faa94a23713d1def3
else
return Z;
}
@@ -832,7 +832,7 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
@@ -622,7 +622,7 @@ std::enable_if_t<std::is_unsigned_v<T>, T> SaturatingAdd(T X, T Y, T Z,
bool Overflowed = false;
T XY = SaturatingAdd(X, Y, &Overflowed);
if (Overflowed)
- return SaturatingAdd(std::numeric_limits<T>::max(), T(1), Args...);
+ return SaturatingAdd((std::numeric_limits<T>::max)(), T(1), Args...);
return SaturatingAdd(XY, Z, Args...);
}
@@ -646,7 +646,7 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
// Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z
// will necessarily be less than Log2Max as desired.
int Log2Z = Log2_64(X) + Log2_64(Y);
@@ -181,7 +180,7 @@ index 753b1998c40c0f9d2a178b5e748d620ffd23ac7e..db9fbc148ae3064faa94a23713d1def3
int Log2Max = Log2_64(Max);
if (Log2Z < Log2Max) {
return X * Y;
@@ -952,9 +952,9 @@ std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
@@ -766,9 +766,9 @@ std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
// Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
// positive) divided by an argument compares to the other.
if (IsNegative)
@@ -193,16 +192,3 @@ index 753b1998c40c0f9d2a178b5e748d620ffd23ac7e..db9fbc148ae3064faa94a23713d1def3
}
} // End llvm namespace
diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp
index 8bad715e45cdf894e811020f3c146fc234e8e9f0..a2b4899e1ffe0ae19d236f43e2e2e2fe1db14110 100644
--- a/llvm/lib/Support/SmallVector.cpp
+++ b/llvm/lib/Support/SmallVector.cpp
@@ -104,7 +104,7 @@ static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
// 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);
+ return (std::min)((std::max)(NewCapacity, MinSize), MaxSize);
}
// Note: Moving this function into the header may cause performance regression.

View File

@@ -8,10 +8,10 @@ Subject: [PATCH 04/30] Change unique_function storage size
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h
index 5a37417ddde5ddf116dd63939c41064330d539d2..8a9d78f41f540f51559c11c1f9f40645165796e5 100644
index 8f04277cdf0e5b3d3b0be4a307cf0e4fada810fd..ba145bf783775042ff4a2d4be4bb048f16db669d 100644
--- a/llvm/include/llvm/ADT/FunctionExtras.h
+++ b/llvm/include/llvm/ADT/FunctionExtras.h
@@ -78,7 +78,7 @@ using EnableIfCallable = std::enable_if_t<llvm::disjunction<
@@ -78,7 +78,7 @@ using EnableIfCallable = std::enable_if_t<std::disjunction<
template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
protected:
@@ -28,4 +28,4 @@ index 5a37417ddde5ddf116dd63939c41064330d539d2..8a9d78f41f540f51559c11c1f9f40645
+ // provide four pointers worth of storage here.
// This is mutable as an inlined `const unique_function<void() const>` may
// still modify its own mutable members.
mutable
mutable std::aligned_storage_t<InlineStorageSize, alignof(void *)>

View File

@@ -12,10 +12,10 @@ Subject: [PATCH 05/30] Threading updates
3 files changed, 11 insertions(+), 43 deletions(-)
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index f5d726ec8a2c4c39a31a6a557591a99a64caea3a..ede1cb1726f2d2dd89e588489e062368763a4b68 100644
index 4a54933031baa90c6f21138fb1f04c5da89878a4..ef9c0d1a73aec870b924faace3b4a32b187e197f 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -540,7 +540,6 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
@@ -518,7 +518,6 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
/// initialize to some constant value. In almost all circumstances this is most
/// appropriate for use with a pointer, integer, or small aggregation of
/// pointers and integers.
@@ -23,7 +23,7 @@ index f5d726ec8a2c4c39a31a6a557591a99a64caea3a..ede1cb1726f2d2dd89e588489e062368
#if __has_feature(cxx_thread_local) || defined(_MSC_VER)
#define LLVM_THREAD_LOCAL thread_local
#else
@@ -548,11 +547,6 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
@@ -526,11 +525,6 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
// we only need the restricted functionality that provides.
#define LLVM_THREAD_LOCAL __thread
#endif
@@ -36,7 +36,7 @@ index f5d726ec8a2c4c39a31a6a557591a99a64caea3a..ede1cb1726f2d2dd89e588489e062368
/// \macro LLVM_ENABLE_EXCEPTIONS
/// Whether LLVM is built with exception support.
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67aea1486b 100644
index 0aa13a0f78eb370b2a673ca4a773f26820575052..637b669a7d0dae69ef4b34955f21a9fb8ba1276e 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -44,7 +44,6 @@ static void *ErrorHandlerUserData = nullptr;
@@ -83,7 +83,7 @@ index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67
handler = ErrorHandler;
handlerData = ErrorHandlerUserData;
}
@@ -123,18 +115,14 @@ void llvm::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
@@ -126,18 +118,14 @@ void llvm::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
void *user_data) {
@@ -104,7 +104,7 @@ index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67
BadAllocErrorHandler = nullptr;
BadAllocErrorHandlerUserData = nullptr;
}
@@ -145,9 +133,7 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
@@ -148,9 +136,7 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
{
// Only acquire the mutex while reading the handler, so as not to invoke a
// user-supplied callback under a lock.
@@ -115,7 +115,7 @@ index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67
Handler = BadAllocErrorHandler;
HandlerData = BadAllocErrorHandlerUserData;
}
@@ -157,10 +143,6 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
@@ -160,10 +146,6 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
llvm_unreachable("bad alloc handler should not return");
}
@@ -126,7 +126,7 @@ index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67
// Don't call the normal error handler. It may allocate memory. Directly write
// an OOM to stderr and abort.
const char *OOMMessage = "LLVM ERROR: out of memory\n";
@@ -169,15 +151,8 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
@@ -172,15 +154,8 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
(void)!::write(2, Reason, strlen(Reason));
(void)!::write(2, Newline, strlen(Newline));
abort();
@@ -142,7 +142,7 @@ index 8ae8fb8b40079a5da59f4008b9dc8de258d8cb5a..89440b5ab872cbeb5e3fbebfa4550e67
// Causes crash on allocation failure. It is called prior to the handler set by
// 'install_bad_alloc_error_handler'.
static void out_of_memory_new_handler() {
@@ -192,7 +167,6 @@ void llvm::install_out_of_memory_new_handler() {
@@ -195,7 +170,6 @@ void llvm::install_out_of_memory_new_handler() {
assert((old == nullptr || old == out_of_memory_new_handler) &&
"new-handler already installed");
}

View File

@@ -5,14 +5,14 @@ Subject: [PATCH 06/30] \#ifdef guard safety
Prevents redefinition if someone is pulling in real LLVM, since the macros are in global namespace
---
llvm/include/llvm/Support/Compiler.h | 50 ++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
llvm/include/llvm/Support/Compiler.h | 42 ++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h
index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b82763088bb74a8 100644
index ef9c0d1a73aec870b924faace3b4a32b187e197f..53c272034ae8f735d02556ced5bae93a1c8644c4 100644
--- a/llvm/include/llvm/Support/Compiler.h
+++ b/llvm/include/llvm/Support/Compiler.h
@@ -86,6 +86,7 @@
@@ -90,6 +90,7 @@
/// * 1928: VS2019, version 16.8 + 16.9
/// * 1929: VS2019, version 16.10 + 16.11
/// * 1930: VS2022, version 17.0
@@ -20,29 +20,15 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#ifdef _MSC_VER
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
@@ -99,6 +100,7 @@
@@ -103,6 +104,7 @@
#else
#define LLVM_MSC_PREREQ(version) 0
#endif
+#endif
/// Does the compiler support ref-qualifiers for *this?
///
@@ -112,11 +114,13 @@
///
/// This can be used to provide lvalue/rvalue overrides of member functions.
/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
+#ifndef LLVM_LVALUE_FUNCTION
#if LLVM_HAS_RVALUE_REFERENCE_THIS
#define LLVM_LVALUE_FUNCTION &
#else
#define LLVM_LVALUE_FUNCTION
#endif
+#endif
/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
/// into a shared library, then the class should be private to the library and
@@ -140,21 +144,26 @@
@@ -127,17 +129,21 @@
#define LLVM_EXTERNAL_VISIBILITY
#endif
@@ -62,22 +48,9 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#endif
+#endif
/// LLVM_NODISCARD - Warn if a type or return value is discarded.
// Use the 'nodiscard' attribute in C++17 or newer mode.
+#ifndef LLVM_NODISCARD
#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
#define LLVM_NODISCARD [[nodiscard]]
#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
@@ -168,6 +177,7 @@
#else
#define LLVM_NODISCARD
#endif
+#endif
// Indicate that a non-static, non-const C++ member function reinitializes
// the entire object to a known state, independent of the previous state of
@@ -190,11 +200,13 @@
#if defined(__clang__)
#define LLVM_DEPRECATED(MSG, FIX) __attribute__((deprecated(MSG, FIX)))
@@ -166,11 +172,13 @@
// more portable solution:
// (void)unused_var_name;
// Prefer cast-to-void wherever it is sufficient.
@@ -91,7 +64,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
// FIXME: Provide this for PE/COFF targets.
#if __has_attribute(weak) && !defined(__MINGW32__) && !defined(__CYGWIN__) && \
@@ -204,6 +216,7 @@
@@ -180,6 +188,7 @@
#define LLVM_ATTRIBUTE_WEAK
#endif
@@ -99,7 +72,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
// Prior to clang 3.2, clang did not accept any spelling of
// __has_attribute(const), so assume it is supported.
#if defined(__clang__) || defined(__GNUC__)
@@ -212,13 +225,16 @@
@@ -188,13 +197,16 @@
#else
#define LLVM_READNONE
#endif
@@ -116,7 +89,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_attribute(minsize)
#define LLVM_ATTRIBUTE_MINSIZE __attribute__((minsize))
@@ -226,6 +242,7 @@
@@ -202,6 +214,7 @@
#define LLVM_ATTRIBUTE_MINSIZE
#endif
@@ -124,7 +97,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#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)
@@ -233,9 +250,11 @@
@@ -209,9 +222,11 @@
#define LLVM_LIKELY(EXPR) (EXPR)
#define LLVM_UNLIKELY(EXPR) (EXPR)
#endif
@@ -136,7 +109,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_attribute(noinline)
#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
@@ -243,9 +262,11 @@
@@ -219,9 +234,11 @@
#else
#define LLVM_ATTRIBUTE_NOINLINE
#endif
@@ -148,7 +121,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_attribute(always_inline)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))
#elif defined(_MSC_VER)
@@ -253,6 +274,7 @@
@@ -229,6 +246,7 @@
#else
#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline
#endif
@@ -156,7 +129,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
/// 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
@@ -263,6 +285,7 @@
@@ -239,6 +257,7 @@
#define LLVM_ATTRIBUTE_NODEBUG
#endif
@@ -164,7 +137,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_attribute(returns_nonnull)
#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
#elif defined(_MSC_VER)
@@ -270,9 +293,11 @@
@@ -246,9 +265,11 @@
#else
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
#endif
@@ -176,7 +149,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#ifdef __GNUC__
#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
#elif defined(_MSC_VER)
@@ -280,8 +305,10 @@
@@ -256,8 +277,10 @@
#else
#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
#endif
@@ -187,7 +160,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(fallthrough)
#define LLVM_FALLTHROUGH [[fallthrough]]
#elif LLVM_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
@@ -293,6 +320,7 @@
@@ -269,6 +292,7 @@
#else
#define LLVM_FALLTHROUGH
#endif
@@ -195,7 +168,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
/// they are constant initialized.
@@ -321,20 +349,25 @@
@@ -297,11 +321,13 @@
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
@@ -207,23 +180,17 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#endif
+#endif
// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
// This macro will be removed.
// Use C++14's attribute instead: [[deprecated("message")]]
+#ifndef LLVM_ATTRIBUTE_DEPRECATED
#define LLVM_ATTRIBUTE_DEPRECATED(decl, message) [[deprecated(message)]] decl
+#endif
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
/// compiler to reach this point. Otherwise is not defined.
@@ -310,14 +336,17 @@
/// '#else' is intentionally left out so that other macro logic (e.g.,
/// LLVM_ASSUME_ALIGNED and llvm_unreachable()) can detect whether
/// LLVM_BUILTIN_UNREACHABLE has a definition.
+#ifndef LLVM_BUILTIN_UNREACHABLE
#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
@@ -342,9 +375,11 @@
#else
# define LLVM_BUILTIN_UNREACHABLE
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
#endif
+#endif
@@ -233,7 +200,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_builtin(__builtin_trap) || defined(__GNUC__)
# define LLVM_BUILTIN_TRAP __builtin_trap()
#elif defined(_MSC_VER)
@@ -356,10 +391,12 @@
@@ -329,10 +358,12 @@
#else
# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
#endif
@@ -246,7 +213,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_builtin(__builtin_debugtrap)
# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
#elif defined(_MSC_VER)
@@ -373,9 +410,11 @@
@@ -346,9 +377,11 @@
// program to abort if encountered.
# define LLVM_BUILTIN_DEBUGTRAP
#endif
@@ -258,7 +225,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if __has_builtin(__builtin_assume_aligned) || defined(__GNUC__)
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
@@ -384,6 +423,7 @@
@@ -357,6 +390,7 @@
#else
# define LLVM_ASSUME_ALIGNED(p, a) (p)
#endif
@@ -266,7 +233,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
/// \macro LLVM_PACKED
/// Used to specify a packed structure.
@@ -403,6 +443,7 @@
@@ -376,6 +410,7 @@
/// long long l;
/// };
/// LLVM_PACKED_END
@@ -274,29 +241,15 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#ifdef _MSC_VER
# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
# define LLVM_PACKED_START __pragma(pack(push, 1))
@@ -412,11 +453,13 @@
@@ -385,6 +420,7 @@
# define LLVM_PACKED_START _Pragma("pack(push, 1)")
# define LLVM_PACKED_END _Pragma("pack(pop)")
#endif
+#endif
/// \macro LLVM_PTR_SIZE
/// A constant integer equivalent to the value of sizeof(void*).
/// Generally used in combination with alignas or when doing computation in the
/// preprocessor.
+#ifndef LLVM_PTR_SIZE
#ifdef __SIZEOF_POINTER__
# define LLVM_PTR_SIZE __SIZEOF_POINTER__
#elif defined(_WIN64)
@@ -428,6 +471,7 @@
#else
# define LLVM_PTR_SIZE sizeof(void *)
#endif
+#endif
/// \macro LLVM_MEMORY_SANITIZER_BUILD
/// Whether LLVM itself is built with MemorySanitizer instrumentation.
@@ -498,11 +542,13 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
@@ -476,11 +512,13 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
/// \macro LLVM_NO_SANITIZE
/// Disable a particular sanitizer for a function.
@@ -310,7 +263,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
/// Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
@@ -510,17 +556,20 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
@@ -488,17 +526,20 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
/// get stripped in release builds.
// FIXME: Move this to a private config.h as it's not usable in public headers.
@@ -331,7 +284,7 @@ index ede1cb1726f2d2dd89e588489e062368763a4b68..8b8260b50504876d79bd94ae5b827630
#if defined(_MSC_VER)
#define LLVM_PRETTY_FUNCTION __FUNCSIG__
#elif defined(__GNUC__) || defined(__clang__)
@@ -528,6 +577,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
@@ -506,6 +547,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#else
#define LLVM_PRETTY_FUNCTION __func__
#endif

View File

@@ -4,18 +4,18 @@ Date: Sat, 7 May 2022 22:37:34 -0400
Subject: [PATCH 07/30] Explicitly use std::
---
llvm/include/llvm/ADT/SmallSet.h | 2 +-
llvm/include/llvm/Support/MathExtras.h | 2 +-
llvm/lib/Support/ErrorHandling.cpp | 2 +-
llvm/unittests/ADT/SmallPtrSetTest.cpp | 2 +-
llvm/unittests/ADT/StringMapTest.cpp | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
llvm/include/llvm/ADT/SmallSet.h | 2 +-
llvm/lib/Support/ErrorHandling.cpp | 2 +-
llvm/unittests/ADT/SmallPtrSetTest.cpp | 2 +-
llvm/unittests/ADT/SmallSetTest.cpp | 10 +++++-----
llvm/unittests/ADT/StringMapTest.cpp | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h
index bfe93e997fc896e82a9b96219967f754df82bcfb..403e108fd361d314762acc317ba6dce7226bb6e5 100644
index 06bc9b5556dd76432552ee79aa916b850f829f4d..630a79c21efeaed6822e7bcad85db0b0d5e42526 100644
--- a/llvm/include/llvm/ADT/SmallSet.h
+++ b/llvm/include/llvm/ADT/SmallSet.h
@@ -270,7 +270,7 @@ bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
@@ -267,7 +267,7 @@ bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
return false;
// All elements in LHS must also be in RHS
@@ -24,24 +24,11 @@ index bfe93e997fc896e82a9b96219967f754df82bcfb..403e108fd361d314762acc317ba6dce7
}
/// Inequality comparison for SmallSet.
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index db9fbc148ae3064faa94a23713d1def3b466e899..da843ef79ff9fd1e2b702763fcdc6f33771bef94 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -586,7 +586,7 @@ inline double Log2(double Value) {
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
return __builtin_log(Value) / __builtin_log(2.0);
#else
- return log2(Value);
+ return std::log2(Value);
#endif
}
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index 89440b5ab872cbeb5e3fbebfa4550e67aea1486b..f80e28e8710817aa19ca7c012a0a4eaecc801c83 100644
index 637b669a7d0dae69ef4b34955f21a9fb8ba1276e..0b87b375de67dc18647e3ebe646bf323dd05e8c5 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -210,7 +210,7 @@ void LLVMResetFatalErrorHandler() {
@@ -213,7 +213,7 @@ void LLVMResetFatalErrorHandler() {
// I'd rather not double the line count of the following.
#define MAP_ERR_TO_COND(x, y) \
case x: \
@@ -51,20 +38,70 @@ index 89440b5ab872cbeb5e3fbebfa4550e67aea1486b..f80e28e8710817aa19ca7c012a0a4eae
std::error_code llvm::mapWindowsError(unsigned EV) {
switch (EV) {
diff --git a/llvm/unittests/ADT/SmallPtrSetTest.cpp b/llvm/unittests/ADT/SmallPtrSetTest.cpp
index 6f3c94eed2737d4e35995454ec7d007cedb1235a..531f81ab5b3fc1dcff731230f3cb7649cb90aedf 100644
index 7ed8670fd31ea2a14e6ba7f59a8ac8e35046890c..531f81ab5b3fc1dcff731230f3cb7649cb90aedf 100644
--- a/llvm/unittests/ADT/SmallPtrSetTest.cpp
+++ b/llvm/unittests/ADT/SmallPtrSetTest.cpp
@@ -298,7 +298,7 @@ TEST(SmallPtrSetTest, dereferenceAndIterate) {
// Sort. We should hit the first element just once and the final element N
// times.
- llvm::sort(std::begin(Found), std::end(Found));
- llvm::sort(Found);
+ std::sort(std::begin(Found), std::end(Found));
for (auto F = std::begin(Found), E = std::end(Found); F != E; ++F)
EXPECT_EQ(F - Found + 1, *F);
}
diff --git a/llvm/unittests/ADT/SmallSetTest.cpp b/llvm/unittests/ADT/SmallSetTest.cpp
index b50b368ae663614f050c220432c05b32c201db00..f9d84fa8a42a7feaaffa3aa080e84574dc3671b3 100644
--- a/llvm/unittests/ADT/SmallSetTest.cpp
+++ b/llvm/unittests/ADT/SmallSetTest.cpp
@@ -11,8 +11,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/STLExtras.h"
#include "gtest/gtest.h"
+#include <algorithm>
#include <string>
using namespace llvm;
@@ -94,7 +94,7 @@ TEST(SmallSetTest, IteratorInt) {
std::vector<int> V(s1.begin(), s1.end());
// Make sure the elements are in the expected order.
- llvm::sort(V);
+ std::sort(V.begin(), V.end());
for (int i = 0; i < 3; i++)
EXPECT_EQ(i, V[i]);
@@ -105,7 +105,7 @@ TEST(SmallSetTest, IteratorInt) {
V.assign(s1.begin(), s1.end());
// Make sure the elements are in the expected order.
- llvm::sort(V);
+ std::sort(V.begin(), V.end());
for (int i = 0; i < 6; i++)
EXPECT_EQ(i, V[i]);
}
@@ -120,7 +120,7 @@ TEST(SmallSetTest, IteratorString) {
s1.insert("str 1");
std::vector<std::string> V(s1.begin(), s1.end());
- llvm::sort(V);
+ std::sort(V.begin(), V.end());
EXPECT_EQ(2u, s1.size());
EXPECT_EQ("str 1", V[0]);
EXPECT_EQ("str 2", V[1]);
@@ -131,7 +131,7 @@ TEST(SmallSetTest, IteratorString) {
V.assign(s1.begin(), s1.end());
// Make sure the elements are in the expected order.
- llvm::sort(V);
+ std::sort(V.begin(), V.end());
EXPECT_EQ(4u, s1.size());
EXPECT_EQ("str 0", V[0]);
EXPECT_EQ("str 1", V[1]);
diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp
index 86907ab61a2c24effcef3b88c7849482eadd314d..6d0c0942cdc256a01afbeb1902f53bc9c53198d9 100644
index ff68c66bd1eda0aa4fb78702875ff734557eb07d..d12c585660ba8d00556c37bd1e5e41fbc953acc1 100644
--- a/llvm/unittests/ADT/StringMapTest.cpp
+++ b/llvm/unittests/ADT/StringMapTest.cpp
@@ -329,7 +329,7 @@ TEST_F(StringMapTest, IterMapKeysSmallVector) {

View File

@@ -137,10 +137,10 @@ index a7dea19d9193bcff4bc6b553b80a10b2bc7b64af..9f9a2b5cab270327898cee3f97d9ae7c
#endif // LLVM_SUPPORT_CHRONO_H
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index 9a1dd7a6070c20609660bfc63db10a509e54fe2f..a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e 100644
index c8a94f46fab18dabc123fd709974138c8b0b0beb..0bf165c55921d7e09208a8fa8df7f9f5ad68d1e2 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -28,12 +28,6 @@
@@ -27,12 +27,6 @@
namespace llvm {
@@ -150,7 +150,7 @@ index 9a1dd7a6070c20609660bfc63db10a509e54fe2f..a25ca5b7b556fd9ccd08ad13a6ceae6b
-class FormattedString;
-class FormattedNumber;
-class FormattedBytes;
template <class T> class LLVM_NODISCARD Expected;
template <class T> class [[nodiscard]] Expected;
namespace sys {
diff --git a/llvm/unittests/Support/Chrono.cpp b/llvm/unittests/Support/Chrono.cpp

View File

@@ -17,7 +17,7 @@ Subject: [PATCH 09/30] Add compiler warning pragmas
10 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h
index 8a9d78f41f540f51559c11c1f9f40645165796e5..3efa73587071b12af07398a4879e7b38c114867f 100644
index ba145bf783775042ff4a2d4be4bb048f16db669d..07f9632bb871b1915b3016348d58938e738b3331 100644
--- a/llvm/include/llvm/ADT/FunctionExtras.h
+++ b/llvm/include/llvm/ADT/FunctionExtras.h
@@ -55,6 +55,13 @@ namespace llvm {
@@ -34,7 +34,7 @@ index 8a9d78f41f540f51559c11c1f9f40645165796e5..3efa73587071b12af07398a4879e7b38
namespace detail {
template <typename T>
@@ -411,6 +418,10 @@ public:
@@ -410,6 +417,10 @@ public:
}
};
@@ -46,10 +46,10 @@ index 8a9d78f41f540f51559c11c1f9f40645165796e5..3efa73587071b12af07398a4879e7b38
#endif // LLVM_ADT_FUNCTIONEXTRAS_H
diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h
index 74a87a3d8dbbd1b13604fac694ad0294c53ee11c..47ff1b2bcbc14bf522abb66a1728123581c148d8 100644
index 463a8d572aa17c415b0ca160b7580862aa9ae197..13e79a12a4f8449c764c9fcf85194bcc2b52b74a 100644
--- a/llvm/include/llvm/ADT/Hashing.h
+++ b/llvm/include/llvm/ADT/Hashing.h
@@ -55,6 +55,11 @@
@@ -56,6 +56,11 @@
#include <tuple>
#include <utility>
@@ -61,7 +61,7 @@ index 74a87a3d8dbbd1b13604fac694ad0294c53ee11c..47ff1b2bcbc14bf522abb66a17281235
namespace llvm {
template <typename T, typename Enable> struct DenseMapInfo;
@@ -687,4 +692,8 @@ template <> struct DenseMapInfo<hash_code, void> {
@@ -678,4 +683,8 @@ template <> struct DenseMapInfo<hash_code, void> {
} // namespace llvm
@@ -71,7 +71,7 @@ index 74a87a3d8dbbd1b13604fac694ad0294c53ee11c..47ff1b2bcbc14bf522abb66a17281235
+
#endif
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 8686f7bb5407611979e8cecfe9da292d3a4b4160..1e311ea56fd1d35505ca6740922c713d97636f09 100644
index 4a93f4c1d8102fc322ebde9c3c697877a1b9048a..70c77618b307acfee816006d54eeddc422ab619b 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -14,6 +14,14 @@
@@ -90,10 +90,10 @@ index 8686f7bb5407611979e8cecfe9da292d3a4b4160..1e311ea56fd1d35505ca6740922c713d
#include "llvm/Support/type_traits.h"
#include <algorithm>
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index da843ef79ff9fd1e2b702763fcdc6f33771bef94..fac12dd0e4c6316ff4887542dd59adc954f099e4 100644
index 45840976a09a733b69dee4070f2f9f8339455da2..062ed2f4057820547cc6bfc4c91e7a13ceaa2f8a 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -435,6 +435,11 @@ inline uint64_t maxUIntN(uint64_t N) {
@@ -268,6 +268,11 @@ inline uint64_t maxUIntN(uint64_t N) {
return UINT64_MAX >> (64 - N);
}
@@ -105,7 +105,7 @@ index da843ef79ff9fd1e2b702763fcdc6f33771bef94..fac12dd0e4c6316ff4887542dd59adc9
/// Gets the minimum value for a N-bit signed integer.
inline int64_t minIntN(int64_t N) {
assert(N > 0 && N <= 64 && "integer width out of range");
@@ -442,6 +447,10 @@ inline int64_t minIntN(int64_t N) {
@@ -275,6 +280,10 @@ inline int64_t minIntN(int64_t N) {
return UINT64_C(1) + ~(UINT64_C(1) << (N - 1));
}
@@ -146,7 +146,7 @@ index d6012bd5a6985d8405136039aa85931605cd8a40..01007deb89bba625b1b3ad3e703d0c16
+
#endif
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index e4c318eb8265c588f1d84dd1abeafc7fd0d055de..ee01a95220806c500d2c0149e9f1e667ea8bf28b 100644
index ce3ffa575995b9f00f8d569176c7aeae7892d30d..a2778407119ccd73031b22a5a091e21923905aa9 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -10,6 +10,10 @@
@@ -158,10 +158,10 @@ index e4c318eb8265c588f1d84dd1abeafc7fd0d055de..ee01a95220806c500d2c0149e9f1e667
+#endif
+
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/STLArrayExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index e505b19070bfdc9af45e0c2ae017e6ea50d81c98..9fe83a45d751719b9f99d57f8f5e983824d108f0 100644
index ab575dfe920e314489025bb68e6113f6227fe41f..d83ba0009c8a70e64a4e3a43a7f3b58663711b87 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -6,6 +6,10 @@
@@ -173,8 +173,8 @@ index e505b19070bfdc9af45e0c2ae017e6ea50d81c98..9fe83a45d751719b9f99d57f8f5e9838
+#endif
+
#include "llvm/ADT/DenseMap.h"
#include "gtest/gtest.h"
#include <map>
#include "llvm/ADT/DenseMapInfo.h"
#include "gmock/gmock.h"
diff --git a/llvm/unittests/ADT/MapVectorTest.cpp b/llvm/unittests/ADT/MapVectorTest.cpp
index 552f9956bdc2c6148f2e338b02074b7c479994a9..20ebcd753bcce0112f6a2d96ea23ccb6662996bb 100644
--- a/llvm/unittests/ADT/MapVectorTest.cpp
@@ -194,11 +194,11 @@ index 552f9956bdc2c6148f2e338b02074b7c479994a9..20ebcd753bcce0112f6a2d96ea23ccb6
#include "llvm/ADT/iterator_range.h"
#include "gtest/gtest.h"
diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp
index fe827546aef2c26b8c5372b2643e84d60683a19a..0e68bad6c4d70737d42fdf385512d117ca7aac4c 100644
index e1090e6f605696f60a82d1708605ddd45f4e15f8..26ef3aee0bebf351c148a3ce9eaada24d365f603 100644
--- a/llvm/unittests/ADT/SmallVectorTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -17,6 +17,10 @@
#include <list>
#include <span>
#include <stdarg.h>
+#if defined(__GNUC__)

View File

@@ -4,18 +4,18 @@ Date: Sun, 8 May 2022 13:43:50 -0400
Subject: [PATCH 10/30] Remove unused functions
---
llvm/include/llvm/ADT/SmallString.h | 80 ------
llvm/include/llvm/ADT/SmallString.h | 85 +-----
llvm/include/llvm/Support/Errno.h | 9 -
llvm/include/llvm/Support/VersionTuple.h | 40 ---
llvm/include/llvm/Support/raw_ostream.h | 115 +-------
llvm/lib/Support/raw_ostream.cpp | 328 -----------------------
5 files changed, 8 insertions(+), 564 deletions(-)
llvm/include/llvm/Support/VersionTuple.h | 39 ---
llvm/include/llvm/Support/raw_ostream.h | 127 +--------
llvm/lib/Support/raw_ostream.cpp | 329 -----------------------
5 files changed, 10 insertions(+), 579 deletions(-)
diff --git a/llvm/include/llvm/ADT/SmallString.h b/llvm/include/llvm/ADT/SmallString.h
index 50cbdade405770e80a6a45521a446a28e4177d11..bfa965fd68a09d7ca3b332e38585ae37a5982ed0 100644
index 4d673cc8b1c49cf8a3f19653de53881cd12662ee..bfa965fd68a09d7ca3b332e38585ae37a5982ed0 100644
--- a/llvm/include/llvm/ADT/SmallString.h
+++ b/llvm/include/llvm/ADT/SmallString.h
@@ -88,48 +88,12 @@ public:
@@ -88,49 +88,12 @@ public:
/// @name String Comparison
/// @{
@@ -30,8 +30,11 @@ index 50cbdade405770e80a6a45521a446a28e4177d11..bfa965fd68a09d7ca3b332e38585ae37
- return str().equals_insensitive(RHS);
- }
-
/// Compare two strings; the result is -1, 0, or 1 if this string is
/// lexicographically less than, equal to, or greater than the \p RHS.
- /// compare - Compare two strings; the result is negative, zero, or positive
- /// if this string is lexicographically less than, equal to, or greater than
- /// the \p RHS.
+ /// Compare two strings; the result is -1, 0, or 1 if this string is
+ /// lexicographically less than, equal to, or greater than the \p RHS.
int compare(std::string_view RHS) const {
return str().compare(RHS);
}
@@ -64,7 +67,7 @@ index 50cbdade405770e80a6a45521a446a28e4177d11..bfa965fd68a09d7ca3b332e38585ae37
/// @}
/// @name String Searching
/// @{
@@ -210,50 +174,6 @@ public:
@@ -211,50 +174,6 @@ public:
}
/// @}
@@ -116,10 +119,10 @@ index 50cbdade405770e80a6a45521a446a28e4177d11..bfa965fd68a09d7ca3b332e38585ae37
// Extra methods.
diff --git a/llvm/include/llvm/Support/Errno.h b/llvm/include/llvm/Support/Errno.h
index 07df6765d9dbf5d6b88092737e081b441b1ccdc4..d9bf68bb369e524be5453c738ab9faa42f4b8cb8 100644
index e095c66b90860001d90b5c2eb74f6032de6de454..787805dac6c5e3c8cb85dabeb80254443d60806c 100644
--- a/llvm/include/llvm/Support/Errno.h
+++ b/llvm/include/llvm/Support/Errno.h
@@ -20,15 +20,6 @@
@@ -19,15 +19,6 @@
namespace llvm {
namespace sys {
@@ -136,24 +139,16 @@ index 07df6765d9dbf5d6b88092737e081b441b1ccdc4..d9bf68bb369e524be5453c738ab9faa4
inline decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F,
const Args &... As) {
diff --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h
index 3d6573bf5a96e115ef264c7885b91aa3b32ac91e..a28e12adcc251bc3673f6a7c07d96d447aa0da98 100644
index 953b40701dc934c1a356b5413c9c6c692d5f5679..30cf717973fb15ff65a47a2d80795c351b0d2768 100644
--- a/llvm/include/llvm/Support/VersionTuple.h
+++ b/llvm/include/llvm/Support/VersionTuple.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/HashBuilder.h"
#include <optional>
#include <string>
#include <tuple>
@@ -159,45 +158,6 @@ public:
@@ -168,45 +168,6 @@ public:
friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
return !(X < Y);
}
-
- friend llvm::hash_code hash_value(const VersionTuple &VT) {
- return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
- friend hash_code hash_value(const VersionTuple &VT) {
- return hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
- }
-
- template <typename HasherT, llvm::support::endianness Endianness>
@@ -194,10 +189,10 @@ index 3d6573bf5a96e115ef264c7885b91aa3b32ac91e..a28e12adcc251bc3673f6a7c07d96d44
} // end namespace llvm
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c410121c71f83 100644
index 0bf165c55921d7e09208a8fa8df7f9f5ad68d1e2..429d1dca24942d16e5c3a551035c0d459e7c5c00 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -248,32 +248,6 @@ public:
@@ -261,32 +261,6 @@ public:
return write(Str.data(), Str.size());
}
@@ -230,7 +225,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
/// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't
/// satisfy llvm::isPrint into an escape sequence.
raw_ostream &write_escaped(std::string_view Str, bool UseHexEscapes = false);
@@ -281,21 +255,6 @@ public:
@@ -294,21 +268,6 @@ public:
raw_ostream &write(unsigned char C);
raw_ostream &write(const char *Ptr, size_t Size);
@@ -252,7 +247,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
/// indent - Insert 'NumSpaces' spaces.
raw_ostream &indent(unsigned NumSpaces);
@@ -310,14 +269,19 @@ public:
@@ -323,14 +282,19 @@ public:
/// @param BG if true change the background, default: change foreground
/// @returns itself so it can be used within << invocations
virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
@@ -275,7 +270,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
/// This function determines if this stream is connected to a "tty" or
/// "console" window. That is, the output would be displayed to the user
@@ -392,10 +356,6 @@ private:
@@ -405,10 +369,6 @@ private:
/// unused bytes in the buffer.
void copy_to_buffer(const char *Ptr, size_t Size);
@@ -286,7 +281,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
/// Flush the tied-to stream (if present) and then write the required data.
void flush_tied_then_write(const char *Ptr, size_t Size);
@@ -447,7 +407,6 @@ class raw_fd_ostream : public raw_pwrite_stream {
@@ -460,7 +420,6 @@ class raw_fd_ostream : public raw_pwrite_stream {
bool ShouldClose;
bool SupportsSeeking = false;
bool IsRegularFile = false;
@@ -294,7 +289,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
#ifdef _WIN32
/// True if this fd refers to a Windows console device. Mintty and other
@@ -523,10 +482,6 @@ public:
@@ -536,10 +495,6 @@ public:
/// to the offset specified from the beginning of the file.
uint64_t seek(uint64_t off);
@@ -305,7 +300,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
std::error_code error() const { return EC; }
/// Return the value of the flag in this raw_fd_ostream indicating whether an
@@ -545,38 +500,6 @@ public:
@@ -558,38 +513,6 @@ public:
/// - from The Zen of Python, by Tim Peters
///
void clear_error() { EC = std::error_code(); }
@@ -330,7 +325,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
- /// });
- /// }
- /// @endcode
- LLVM_NODISCARD Expected<sys::fs::FileLocker> lock();
- [[nodiscard]] Expected<sys::fs::FileLocker> lock();
-
- /// Tries to lock the underlying file within the specified period.
- ///
@@ -339,12 +334,12 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
- /// error code.
- ///
- /// It is used as @ref lock.
- LLVM_NODISCARD
- Expected<sys::fs::FileLocker> tryLockFor(Duration const& Timeout);
- [[nodiscard]] Expected<sys::fs::FileLocker>
- tryLockFor(Duration const &Timeout);
};
/// This returns a reference to a raw_fd_ostream for standard output. Use it
@@ -606,17 +529,6 @@ public:
@@ -619,17 +542,6 @@ public:
/// immediately destroyed.
raw_fd_stream(std::string_view Filename, std::error_code &EC);
@@ -362,7 +357,7 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
/// Check if \p OS is a pointer of type raw_fd_stream*.
static bool classof(const raw_ostream *OS);
};
@@ -734,17 +646,6 @@ public:
@@ -747,29 +659,6 @@ public:
~buffer_unique_ostream() override { *OS << str(); }
};
@@ -376,15 +371,27 @@ index a25ca5b7b556fd9ccd08ad13a6ceae6bedbcb09e..d4521c8e285f3fc404d27a6c528c4101
-/// temporary file after the \p Write function is finished.
-Error writeToOutput(std::string_view OutputFileName,
- std::function<Error(raw_ostream &)> Write);
-
-raw_ostream &operator<<(raw_ostream &OS, std::nullopt_t);
-
-template <typename T, typename = decltype(std::declval<raw_ostream &>()
- << std::declval<const T &>())>
-raw_ostream &operator<<(raw_ostream &OS, const std::optional<T> &O) {
- if (O)
- OS << *O;
- else
- OS << std::nullopt;
- return OS;
-}
-
} // end namespace llvm
#endif // LLVM_SUPPORT_RAW_OSTREAM_H
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3ad8d2c74 100644
index a2778407119ccd73031b22a5a091e21923905aa9..76c32155b4296fbbf3f4b164cd58d63f472ccd5e 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -19,7 +19,6 @@
@@ -18,7 +18,6 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
@@ -392,7 +399,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
@@ -120,49 +119,6 @@ void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
@@ -127,49 +126,6 @@ void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
assert(OutBufStart <= OutBufEnd && "Invalid size!");
}
@@ -442,7 +449,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
raw_ostream &raw_ostream::write_escaped(std::string_view Str,
bool UseHexEscapes) {
for (unsigned char c : Str) {
@@ -308,172 +264,6 @@ void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) {
@@ -315,173 +271,6 @@ void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) {
write_impl(Ptr, Size);
}
@@ -550,7 +557,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
- const size_t Size = Bytes.size();
- HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;
- uint64_t OffsetWidth = 0;
- if (FB.FirstByteOffset.hasValue()) {
- if (FB.FirstByteOffset) {
- // Figure out how many nibbles are needed to print the largest offset
- // represented by this data set, so that we can align the offset field
- // to the right width.
@@ -570,8 +577,8 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
- while (!Bytes.empty()) {
- indent(FB.IndentLevel);
-
- if (FB.FirstByteOffset.hasValue()) {
- uint64_t Offset = FB.FirstByteOffset.getValue();
- if (FB.FirstByteOffset) {
- uint64_t Offset = *FB.FirstByteOffset;
- llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth);
- *this << ": ";
- }
@@ -612,10 +619,11 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
- }
- return *this;
-}
-
template <char C>
static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
@@ -506,63 +296,8 @@ raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) {
static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
@@ -512,63 +301,8 @@ raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) {
return write_padding<'\0'>(*this, NumZeros);
}
@@ -679,7 +687,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
//===----------------------------------------------------------------------===//
// raw_fd_ostream
//===----------------------------------------------------------------------===//
@@ -854,31 +589,6 @@ size_t raw_fd_ostream::preferred_buffer_size() const {
@@ -867,31 +601,6 @@ size_t raw_fd_ostream::preferred_buffer_size() const {
#endif
}
@@ -711,7 +719,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
void raw_fd_ostream::anchor() {}
//===----------------------------------------------------------------------===//
@@ -921,16 +631,6 @@ raw_fd_stream::raw_fd_stream(std::string_view Filename, std::error_code &EC)
@@ -934,16 +643,6 @@ raw_fd_stream::raw_fd_stream(std::string_view Filename, std::error_code &EC)
EC = std::make_error_code(std::errc::invalid_argument);
}
@@ -728,7 +736,7 @@ index ee01a95220806c500d2c0149e9f1e667ea8bf28b..875eda7ba440f2ae64dc32ebb0502ad3
bool raw_fd_stream::classof(const raw_ostream *OS) {
return OS->get_kind() == OStreamKind::OK_FDStream;
}
@@ -986,31 +686,3 @@ void raw_pwrite_stream::anchor() {}
@@ -999,31 +698,3 @@ void raw_pwrite_stream::anchor() {}
void buffer_ostream::anchor() {}
void buffer_unique_ostream::anchor() {}

View File

@@ -4,15 +4,15 @@ Date: Thu, 5 May 2022 23:18:34 -0400
Subject: [PATCH 11/30] Detemplatize SmallVectorBase
---
llvm/include/llvm/ADT/SmallVector.h | 21 +++++++-----------
llvm/lib/Support/SmallVector.cpp | 34 +++++------------------------
2 files changed, 13 insertions(+), 42 deletions(-)
llvm/include/llvm/ADT/SmallVector.h | 27 +++++++--------------
llvm/lib/Support/SmallVector.cpp | 37 +++++------------------------
2 files changed, 14 insertions(+), 50 deletions(-)
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 1e311ea56fd1d35505ca6740922c713d97636f09..4b6bbdeb2ea3e602978733351e352968ccdca36d 100644
index 70c77618b307acfee816006d54eeddc422ab619b..3c523c969bd6ee0cc2f19c923231e55787879df9 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -50,14 +50,14 @@ template <typename IteratorT> class iterator_range;
@@ -56,14 +56,14 @@ using EnableIfConvertibleToInputIterator = std::enable_if_t<std::is_convertible<
/// Using 64 bit size is desirable for cases like SmallVector<char>, where a
/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
/// buffering bitcode output - which can exceed 4GB.
@@ -30,14 +30,14 @@ index 1e311ea56fd1d35505ca6740922c713d97636f09..4b6bbdeb2ea3e602978733351e352968
}
SmallVectorBase() = delete;
@@ -91,15 +91,10 @@ protected:
@@ -111,15 +111,10 @@ protected:
}
};
-template <class T>
-using SmallVectorSizeType =
- typename std::conditional<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t,
- uint32_t>::type;
- std::conditional_t<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t,
- uint32_t>;
-
/// Figure out the offset of the first element.
template <class T, typename = void> struct SmallVectorAlignmentAndSize {
@@ -48,7 +48,7 @@ index 1e311ea56fd1d35505ca6740922c713d97636f09..4b6bbdeb2ea3e602978733351e352968
alignas(T) char FirstEl[sizeof(T)];
};
@@ -108,8 +103,8 @@ template <class T, typename = void> struct SmallVectorAlignmentAndSize {
@@ -128,8 +123,8 @@ template <class T, typename = void> struct SmallVectorAlignmentAndSize {
/// to avoid unnecessarily requiring T to be complete.
template <typename T, typename = void>
class SmallVectorTemplateCommon
@@ -57,19 +57,32 @@ index 1e311ea56fd1d35505ca6740922c713d97636f09..4b6bbdeb2ea3e602978733351e352968
+ : public SmallVectorBase {
+ using Base = SmallVectorBase;
protected:
/// Find the address of the first element. For this pointer math to be valid
/// with small-size of 0 for T with lots of alignment, it's important that
@@ -356,7 +351,7 @@ protected:
/// in \p NewCapacity. This is the first section of \a grow().
T *mallocForGrow(size_t MinSize, size_t &NewCapacity) {
return static_cast<T *>(
- SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow(
+ SmallVectorBase::mallocForGrow(
MinSize, sizeof(T), NewCapacity));
}
@@ -451,7 +446,7 @@ template <typename T, bool TriviallyCopyable>
T *SmallVectorTemplateBase<T, TriviallyCopyable>::mallocForGrow(
size_t MinSize, size_t &NewCapacity) {
return static_cast<T *>(
- SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow(
+ SmallVectorBase::mallocForGrow(
this->getFirstEl(), MinSize, sizeof(T), NewCapacity));
}
@@ -1319,12 +1314,6 @@ template <typename Out, typename R> SmallVector<Out> to_vector_of(R &&Range) {
return {std::begin(Range), std::end(Range)};
}
-// Explicit instantiations
-extern template class llvm::SmallVectorBase<uint32_t>;
-#if SIZE_MAX > UINT32_MAX
-extern template class llvm::SmallVectorBase<uint64_t>;
-#endif
-
} // end namespace llvm
namespace std {
diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp
index a2b4899e1ffe0ae19d236f43e2e2e2fe1db14110..bdfc963d7ff8ca684e37d08410b92a84d5d27730 100644
index 6cefdff7c28060ca18b522acf5279af3a206e23a..ae64a36dcf4b9ceaf8767adbf8100f164f3738ac 100644
--- a/llvm/lib/Support/SmallVector.cpp
+++ b/llvm/lib/Support/SmallVector.cpp
@@ -51,10 +51,6 @@ static_assert(sizeof(SmallVector<void *, 1>) ==
@@ -94,17 +107,31 @@ index a2b4899e1ffe0ae19d236f43e2e2e2fe1db14110..bdfc963d7ff8ca684e37d08410b92a84
// Ensure we can fit the new capacity.
// This is only going to be applicable when the capacity is 32 bit.
@@ -108,18 +103,16 @@ static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
@@ -107,8 +102,7 @@ static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
return std::clamp(NewCapacity, MinSize, MaxSize);
}
-template <class Size_T>
-void *SmallVectorBase<Size_T>::replaceAllocation(void *NewElts, size_t TSize,
+void *SmallVectorBase::replaceAllocation(void *NewElts, size_t TSize,
size_t NewCapacity,
size_t VSize) {
void *NewEltsReplace = llvm::safe_malloc(NewCapacity * TSize);
@@ -119,11 +113,10 @@ void *SmallVectorBase<Size_T>::replaceAllocation(void *NewElts, size_t TSize,
}
// Note: Moving this function into the header may cause performance regression.
-template <class Size_T>
-void *SmallVectorBase<Size_T>::mallocForGrow(size_t MinSize, size_t TSize,
+void *SmallVectorBase::mallocForGrow(size_t MinSize, size_t TSize,
-void *SmallVectorBase<Size_T>::mallocForGrow(void *FirstEl, size_t MinSize,
+void *SmallVectorBase::mallocForGrow(void *FirstEl, size_t MinSize,
size_t TSize,
size_t &NewCapacity) {
- NewCapacity = getNewCapacity<Size_T>(MinSize, TSize, this->capacity());
+ NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
return llvm::safe_malloc(NewCapacity * TSize);
// Even if capacity is not 0 now, if the vector was originally created with
// capacity 0, it's possible for the malloc to return FirstEl.
void *NewElts = llvm::safe_malloc(NewCapacity * TSize);
@@ -133,10 +126,9 @@ void *SmallVectorBase<Size_T>::mallocForGrow(void *FirstEl, size_t MinSize,
}
// Note: Moving this function into the header may cause performance regression.
@@ -116,8 +143,8 @@ index a2b4899e1ffe0ae19d236f43e2e2e2fe1db14110..bdfc963d7ff8ca684e37d08410b92a84
+ size_t NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
void *NewElts;
if (BeginX == FirstEl) {
NewElts = safe_malloc(NewCapacity * TSize);
@@ -134,20 +127,3 @@ void SmallVectorBase<Size_T>::grow_pod(void *FirstEl, size_t MinSize,
NewElts = llvm::safe_malloc(NewCapacity * TSize);
@@ -155,20 +147,3 @@ void SmallVectorBase<Size_T>::grow_pod(void *FirstEl, size_t MinSize,
this->BeginX = NewElts;
this->Capacity = NewCapacity;
}

View File

@@ -9,18 +9,18 @@ Subject: [PATCH 12/30] Add vectors to raw_ostream
2 files changed, 162 insertions(+)
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index d4521c8e285f3fc404d27a6c528c410121c71f83..bf5630ab549d39cedcdaac80672c5122883e125b 100644
index 429d1dca24942d16e5c3a551035c0d459e7c5c00..d656123867f331b32463f2da9e637892e0e39930 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -25,6 +25,7 @@
#endif
@@ -24,6 +24,7 @@
#include <string_view>
#include <system_error>
#include <type_traits>
+#include <vector>
namespace llvm {
@@ -248,12 +249,24 @@ public:
@@ -261,12 +262,24 @@ public:
return write(Str.data(), Str.size());
}
@@ -45,7 +45,7 @@ index d4521c8e285f3fc404d27a6c528c410121c71f83..bf5630ab549d39cedcdaac80672c5122
/// indent - Insert 'NumSpaces' spaces.
raw_ostream &indent(unsigned NumSpaces);
@@ -604,6 +617,108 @@ public:
@@ -617,6 +630,108 @@ public:
}
};
@@ -155,10 +155,10 @@ index d4521c8e285f3fc404d27a6c528c410121c71f83..bf5630ab549d39cedcdaac80672c5122
class raw_null_ostream : public raw_pwrite_stream {
/// See raw_ostream::write_impl.
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 875eda7ba440f2ae64dc32ebb0502ad3ad8d2c74..36faf744cf6c429917a793a363a7d3f22a6d7e67 100644
index 76c32155b4296fbbf3f4b164cd58d63f472ccd5e..dcdfdfd7a8e3fcc4019538a4fc9e158aeda0a8b8 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -658,6 +658,53 @@ void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
@@ -670,6 +670,53 @@ void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
memcpy(OS.data() + Offset, Ptr, Size);
}

View File

@@ -9,7 +9,7 @@ Subject: [PATCH 13/30] Extra collections features
2 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h
index 8747cdb353a89952e242ccfa5ea8a3e68571d456..16f13f048415182e061de6ba439eb23ddddb3bdc 100644
index 1c8cda7ef0f8e2984f2d7960260f2a109a2986f7..99a183772f909ed9eab8c8e0c0fc87f183d2c98d 100644
--- a/llvm/include/llvm/ADT/StringMap.h
+++ b/llvm/include/llvm/ADT/StringMap.h
@@ -42,7 +42,7 @@ protected:
@@ -142,7 +142,7 @@ index 8747cdb353a89952e242ccfa5ea8a3e68571d456..16f13f048415182e061de6ba439eb23d
#endif // LLVM_ADT_STRINGMAP_H
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 36faf744cf6c429917a793a363a7d3f22a6d7e67..95152849cb920a61b4906f886f78d76e3fa2b22c 100644
index dcdfdfd7a8e3fcc4019538a4fc9e158aeda0a8b8..b2a726633b48b179abfd24a5de110a2301e0f877 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -76,6 +76,14 @@ constexpr raw_ostream::Colors raw_ostream::WHITE;

View File

@@ -8,7 +8,7 @@ Subject: [PATCH 14/30] EpochTracker ABI macro
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/EpochTracker.h b/llvm/include/llvm/ADT/EpochTracker.h
index b06888494466496b0c768e824ee25e2154d20f15..f35461d1c6e424cea6f072d749a6324699f8edd4 100644
index a639d1b5b3ec4a18d3666ee62d83a9a382075d93..6fb2199ca3b9d7bb636a3e46e18b71f15bfa0494 100644
--- a/llvm/include/llvm/ADT/EpochTracker.h
+++ b/llvm/include/llvm/ADT/EpochTracker.h
@@ -22,7 +22,7 @@

View File

@@ -8,11 +8,11 @@ Subject: [PATCH 15/30] Delete numbers from MathExtras
1 file changed, 36 deletions(-)
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index fac12dd0e4c6316ff4887542dd59adc954f099e4..e8f1f2aca6106af3885468f686331d8b083630d7 100644
index 062ed2f4057820547cc6bfc4c91e7a13ceaa2f8a..cc0c1cbd1c8bb523bce720b9783afad7f602c88c 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -50,42 +50,6 @@ enum ZeroBehavior {
ZB_Width
@@ -32,42 +32,6 @@ enum ZeroBehavior {
ZB_Max
};
-/// Mathematical constants.
@@ -51,6 +51,6 @@ index fac12dd0e4c6316ff4887542dd59adc954f099e4..e8f1f2aca6106af3885468f686331d8b
- phif = 1.61803399F; // (0x1.9e377aP+0) https://oeis.org/A001622
-} // namespace numbers
-
namespace detail {
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
static unsigned count(T Val, ZeroBehavior) {
/// Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///

View File

@@ -8,10 +8,10 @@ Subject: [PATCH 16/30] Add lerp and sgn
1 file changed, 20 insertions(+)
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index e8f1f2aca6106af3885468f686331d8b083630d7..8116c58bd0d6d2b880a5a7c8c5f9ca07217987de 100644
index cc0c1cbd1c8bb523bce720b9783afad7f602c88c..fe9c5136f9f2f687577a0b1ecce69262568a9c3c 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -930,6 +930,26 @@ std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
@@ -744,6 +744,26 @@ std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
return UX > (static_cast<U>((std::numeric_limits<T>::max)())) / UY;
}

View File

@@ -9,14 +9,15 @@ Subject: [PATCH 17/30] Fixup includes
llvm/include/llvm/Support/PointerLikeTypeTraits.h | 1 +
llvm/lib/Support/ConvertUTFWrapper.cpp | 1 +
llvm/lib/Support/ErrorHandling.cpp | 7 +++----
llvm/lib/Support/raw_ostream.cpp | 12 ++++++------
llvm/lib/Support/raw_ostream.cpp | 11 ++++++-----
llvm/unittests/ADT/SmallPtrSetTest.cpp | 2 ++
llvm/unittests/ADT/SmallVectorTest.cpp | 1 +
llvm/unittests/ADT/StringMapTest.cpp | 1 +
llvm/unittests/Support/ConvertUTFTest.cpp | 2 ++
9 files changed, 24 insertions(+), 10 deletions(-)
10 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h
index 16f13f048415182e061de6ba439eb23ddddb3bdc..6ae0e39a125ef145ca0887763e55c8150a902047 100644
index 99a183772f909ed9eab8c8e0c0fc87f183d2c98d..2605dcd3dfd60a93d714caf8bc8058e3c983dbde 100644
--- a/llvm/include/llvm/ADT/StringMap.h
+++ b/llvm/include/llvm/ADT/StringMap.h
@@ -17,6 +17,10 @@
@@ -31,7 +32,7 @@ index 16f13f048415182e061de6ba439eb23ddddb3bdc..6ae0e39a125ef145ca0887763e55c815
#include <initializer_list>
#include <iterator>
diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h
index 39976a02b5ecbbf5d08a6073708cac0a5aef447d..cdefc5449236a34683e64c1f4eebceae28954017 100644
index 388e81c361642113937f7d5680de73a50635b07d..011806f5fd89ff738ed805a82b3ddbc6fc9b08ce 100644
--- a/llvm/include/llvm/ADT/StringMapEntry.h
+++ b/llvm/include/llvm/ADT/StringMapEntry.h
@@ -16,6 +16,10 @@
@@ -58,19 +59,19 @@ index 1b15f930bd87d97d51824af5e62ea5f222a6b4c9..acadd5e89a1651cfbad67a5b1b0933d1
namespace llvm {
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index 396ab0c655ed50707c8725ebd22b1f8be5e0e030..cff30f16ca907959843dd58ff30f58ead333f17f 100644
index bb5164ff9dce0271cafc5889a049b5d343530f8d..195071cc697070af2a75207fced50d49bae46c23 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -8,6 +8,7 @@
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/span.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SwapByteOrder.h"
#include <string>
#include <span>
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index f80e28e8710817aa19ca7c012a0a4eaecc801c83..ec1a1633ae2952857619ba5e55dee3be7bc6aed5 100644
index 0b87b375de67dc18647e3ebe646bf323dd05e8c5..3a88178cfbbcf7062a958c7de820247bc913ab33 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -28,12 +28,11 @@
@@ -90,20 +91,19 @@ index f80e28e8710817aa19ca7c012a0a4eaecc801c83..ec1a1633ae2952857619ba5e55dee3be
using namespace llvm;
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 95152849cb920a61b4906f886f78d76e3fa2b22c..878a3a5e99949da360a93dc51298460cc61d4f3f 100644
index b2a726633b48b179abfd24a5de110a2301e0f877..3b7d8d6db5f0df31e18b91be716a4fd21e7e3549 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -15,7 +15,8 @@
@@ -15,6 +15,8 @@
#endif
#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/STLArrayExtras.h"
+#include "wpi/SmallString.h"
+#include "wpi/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
@@ -33,12 +34,11 @@
@@ -32,12 +34,11 @@
#include <sys/stat.h>
// <fcntl.h> may provide O_BINARY.
@@ -119,10 +119,10 @@ index 95152849cb920a61b4906f886f78d76e3fa2b22c..878a3a5e99949da360a93dc51298460c
#endif
#if defined(__CYGWIN__)
@@ -60,7 +60,7 @@
@@ -60,7 +61,7 @@
#ifdef _WIN32
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/Windows/WindowsSupport.h"
+#include "Windows/WindowsSupport.h"
#endif
@@ -141,8 +141,20 @@ index 531f81ab5b3fc1dcff731230f3cb7649cb90aedf..3db8b6e37d31a0a3cc304da8fc4cbbe1
using namespace llvm;
TEST(SmallPtrSetTest, Assignment) {
diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp
index 26ef3aee0bebf351c148a3ce9eaada24d365f603..adb0755988c67ecd126931425296d32d833da561 100644
--- a/llvm/unittests/ADT/SmallVectorTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "gtest/gtest.h"
+#include <array>
#include <list>
#include <span>
#include <stdarg.h>
diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp
index 6d0c0942cdc256a01afbeb1902f53bc9c53198d9..de6daf3daf4e59b57fa43df2526c62e854fa65ee 100644
index d12c585660ba8d00556c37bd1e5e41fbc953acc1..a45dde69f833900fa1d7c5a1984edee3d501111d 100644
--- a/llvm/unittests/ADT/StringMapTest.cpp
+++ b/llvm/unittests/ADT/StringMapTest.cpp
@@ -9,6 +9,7 @@
@@ -154,7 +166,7 @@ index 6d0c0942cdc256a01afbeb1902f53bc9c53198d9..de6daf3daf4e59b57fa43df2526c62e8
#include <tuple>
using namespace llvm;
diff --git a/llvm/unittests/Support/ConvertUTFTest.cpp b/llvm/unittests/Support/ConvertUTFTest.cpp
index 9c798437a12d971a9206cbaff546ebc46c70f0d8..2fee8ad5c01294988457002517dcb8d983cac23d 100644
index 3b07d344f15a555f11ad5f8177a0a65b8a4fa472..77e70a46d3621ecfaed923d87256184addfda721 100644
--- a/llvm/unittests/Support/ConvertUTFTest.cpp
+++ b/llvm/unittests/Support/ConvertUTFTest.cpp
@@ -7,6 +7,8 @@

View File

@@ -4,38 +4,14 @@ Date: Sun, 8 May 2022 16:42:09 -0400
Subject: [PATCH 18/30] Use std::is_trivially_copy_constructible
---
llvm/include/llvm/ADT/PointerIntPair.h | 12 ----
llvm/include/llvm/Support/type_traits.h | 91 +------------------------
2 files changed, 2 insertions(+), 101 deletions(-)
llvm/include/llvm/Support/type_traits.h | 37 ++-----------------------
1 file changed, 2 insertions(+), 35 deletions(-)
diff --git a/llvm/include/llvm/ADT/PointerIntPair.h b/llvm/include/llvm/ADT/PointerIntPair.h
index b7ddf8855605d23ebe3d7587e4ccc694a72045ac..a48fb904bbf6fa70d8d81bffc34202978eccb71a 100644
--- a/llvm/include/llvm/ADT/PointerIntPair.h
+++ b/llvm/include/llvm/ADT/PointerIntPair.h
@@ -128,18 +128,6 @@ public:
}
};
-// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable
-// when compiled with gcc 4.9.
-template <typename PointerTy, unsigned IntBits, typename IntType,
- typename PtrTraits,
- typename Info>
-struct is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> : std::true_type {
-#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
- static_assert(std::is_trivially_copyable<PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>::value,
- "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
-#endif
-};
-
template <typename PointerT, unsigned IntBits, typename PtrTraits>
struct PointerIntPairInfo {
diff --git a/llvm/include/llvm/Support/type_traits.h b/llvm/include/llvm/Support/type_traits.h
index 7b7d5d991f3f51862fad3267798737bc6ef8c845..72a2e84ad452a609d42ce7a43a3d26d118a08043 100644
index a6046de87d1e3e1264a0040826ea347b870a8f9e..292a2cb78b93717647cf88d00f88c2eec14f52f6 100644
--- a/llvm/include/llvm/Support/type_traits.h
+++ b/llvm/include/llvm/Support/type_traits.h
@@ -92,98 +92,11 @@ union trivial_helper {
@@ -92,44 +92,11 @@ union trivial_helper {
} // end namespace detail
@@ -78,61 +54,7 @@ index 7b7d5d991f3f51862fad3267798737bc6ef8c845..72a2e84ad452a609d42ce7a43a3d26d1
- static std::false_type get(...);
- static constexpr bool value = decltype(get((T*)nullptr))::value;
-};
-
-
-// An implementation of `std::is_trivially_copyable` since STL version
-// is not equally supported by all compilers, especially GCC 4.9.
-// Uniform implementation of this trait is important for ABI compatibility
-// as it has an impact on SmallVector's ABI (among others).
-template <typename T>
-class is_trivially_copyable {
-
- // copy constructors
- static constexpr bool has_trivial_copy_constructor =
- std::is_copy_constructible<detail::trivial_helper<T>>::value;
- static constexpr bool has_deleted_copy_constructor =
- !std::is_copy_constructible<T>::value;
-
- // move constructors
- static constexpr bool has_trivial_move_constructor =
- std::is_move_constructible<detail::trivial_helper<T>>::value;
- static constexpr bool has_deleted_move_constructor =
- !std::is_move_constructible<T>::value;
-
- // copy assign
- static constexpr bool has_trivial_copy_assign =
- is_copy_assignable<detail::trivial_helper<T>>::value;
- static constexpr bool has_deleted_copy_assign =
- !is_copy_assignable<T>::value;
-
- // move assign
- static constexpr bool has_trivial_move_assign =
- is_move_assignable<detail::trivial_helper<T>>::value;
- static constexpr bool has_deleted_move_assign =
- !is_move_assignable<T>::value;
-
- // destructor
- static constexpr bool has_trivial_destructor =
- std::is_destructible<detail::trivial_helper<T>>::value;
-
- public:
-
- static constexpr bool value =
- has_trivial_destructor &&
- (has_deleted_move_assign || has_trivial_move_assign) &&
- (has_deleted_move_constructor || has_trivial_move_constructor) &&
- (has_deleted_copy_assign || has_trivial_copy_assign) &&
- (has_deleted_copy_constructor || has_trivial_copy_constructor);
-
-#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
- static_assert(value == std::is_trivially_copyable<T>::value,
- "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
-#endif
-};
-template <typename T>
-class is_trivially_copyable<T*> : public std::true_type {
-};
+using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>;
} // end namespace llvm

View File

@@ -6,10 +6,11 @@ Subject: [PATCH 19/30] Windows support
---
.../llvm/Support/Windows/WindowsSupport.h | 45 +++++----
llvm/lib/Support/ConvertUTF.cpp | 95 +++++++++++++++++++
2 files changed, 124 insertions(+), 16 deletions(-)
llvm/lib/Support/raw_ostream.cpp | 1 -
3 files changed, 124 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Support/Windows/WindowsSupport.h b/llvm/include/llvm/Support/Windows/WindowsSupport.h
index 180803fbd3104ddf32c183684f226954c4fb8b0e..31120cfa0e8cafa8d4f332bf2374a88a3418f748 100644
index aabdb2f14668a990329b57f5454a0d7db73e12ce..2ac474092a62d488da1ec7f07a1cd10b0781d938 100644
--- a/llvm/include/llvm/Support/Windows/WindowsSupport.h
+++ b/llvm/include/llvm/Support/Windows/WindowsSupport.h
@@ -35,8 +35,6 @@
@@ -67,9 +68,9 @@ index 180803fbd3104ddf32c183684f226954c4fb8b0e..31120cfa0e8cafa8d4f332bf2374a88a
+ return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
+}
/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
@@ -228,19 +254,6 @@ inline FILETIME toFILETIME(TimePoint<> TP) {
/// Determines if the program is running on Windows 11 or Windows Server 2022.
bool RunningWindows11OrGreater();
@@ -231,19 +257,6 @@ inline FILETIME toFILETIME(TimePoint<> TP) {
return Time;
}
@@ -90,10 +91,10 @@ index 180803fbd3104ddf32c183684f226954c4fb8b0e..31120cfa0e8cafa8d4f332bf2374a88a
} // end namespace llvm.
diff --git a/llvm/lib/Support/ConvertUTF.cpp b/llvm/lib/Support/ConvertUTF.cpp
index e24a918c5c898206dc8b401c6214e4e9c652e9a9..c906ded91dfeaa07b782e1eccc28643d5497cb94 100644
index bc04c5ab5113563fb82d7b3b168985369b611f4b..57eb64a6017a6964ab14b40b8c6b3563cd41ffac 100644
--- a/llvm/lib/Support/ConvertUTF.cpp
+++ b/llvm/lib/Support/ConvertUTF.cpp
@@ -51,6 +51,11 @@
@@ -67,6 +67,11 @@
#endif
#include <assert.h>
@@ -105,7 +106,7 @@ index e24a918c5c898206dc8b401c6214e4e9c652e9a9..c906ded91dfeaa07b782e1eccc28643d
/*
* This code extensively uses fall-through switches.
* Keep the compiler from warning about that.
@@ -733,6 +738,96 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
@@ -759,6 +764,96 @@ ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
--------------------------------------------------------------------- */
@@ -202,3 +203,15 @@ index e24a918c5c898206dc8b401c6214e4e9c652e9a9..c906ded91dfeaa07b782e1eccc28643d
} // namespace llvm
ConvertUTF_RESTORE_WARNINGS
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 3b7d8d6db5f0df31e18b91be716a4fd21e7e3549..4769d34a14f3f2cbaaa4df50ea7111fe9fa2792f 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -534,7 +534,6 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
DWORD WinLastError = GetLastError();
if (WinLastError == ERROR_BROKEN_PIPE ||
(WinLastError == ERROR_NO_DATA && errno == EINVAL)) {
- llvm::sys::CallOneShotPipeSignalHandler();
errno = EPIPE;
}
#endif

View File

@@ -8,7 +8,7 @@ Subject: [PATCH 20/30] Prefer fmtlib
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index ec1a1633ae2952857619ba5e55dee3be7bc6aed5..27ca15f7d239a8e5050cadd159dad96de150e444 100644
index 3a88178cfbbcf7062a958c7de820247bc913ab33..54137a331ca9e752b02c0f16ae996094a6f2fafa 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -22,7 +22,7 @@
@@ -37,7 +37,7 @@ index ec1a1633ae2952857619ba5e55dee3be7bc6aed5..27ca15f7d239a8e5050cadd159dad96d
}
// If we reached here, we are failing ungracefully. Run the interrupt handlers
@@ -173,11 +165,11 @@ void llvm::llvm_unreachable_internal(const char *msg, const char *file,
@@ -176,11 +168,11 @@ void llvm::llvm_unreachable_internal(const char *msg, const char *file,
// llvm_unreachable is intended to be used to indicate "impossible"
// situations, and not legitimate runtime errors.
if (msg)

View File

@@ -8,16 +8,16 @@ Subject: [PATCH 21/30] Prefer wpi's fs.h
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index bf5630ab549d39cedcdaac80672c5122883e125b..256bcec259a8026473a5f3926bd79b215bd5b888 100644
index d656123867f331b32463f2da9e637892e0e39930..582b731b0495ad2a38911ef1f9fe6d2aec58aea1 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -27,18 +27,15 @@
@@ -26,18 +26,15 @@
#include <type_traits>
#include <vector>
-namespace llvm {
-
-template <class T> class LLVM_NODISCARD Expected;
-template <class T> class [[nodiscard]] Expected;
-namespace sys {
namespace fs {

View File

@@ -7,9 +7,9 @@ Subject: [PATCH 22/30] Remove unused functions
llvm/include/llvm/Support/DJB.h | 3 -
llvm/include/llvm/Support/raw_ostream.h | 5 +-
llvm/lib/Support/ErrorHandling.cpp | 16 -----
llvm/lib/Support/raw_ostream.cpp | 49 +++++++--------
llvm/lib/Support/raw_ostream.cpp | 47 +++++++-------
llvm/unittests/ADT/SmallStringTest.cpp | 81 -------------------------
5 files changed, 23 insertions(+), 131 deletions(-)
5 files changed, 23 insertions(+), 129 deletions(-)
diff --git a/llvm/include/llvm/Support/DJB.h b/llvm/include/llvm/Support/DJB.h
index 8737cd144c37f9041a781a74e9f2b43384e85761..67b0ae91b4b1401374d7d39d859daaf30da17ee2 100644
@@ -26,10 +26,10 @@ index 8737cd144c37f9041a781a74e9f2b43384e85761..67b0ae91b4b1401374d7d39d859daaf3
#endif // LLVM_SUPPORT_DJB_H
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index 256bcec259a8026473a5f3926bd79b215bd5b888..9b3a87e1bbc0abe83b204bd8f889ffe3a3cafffa 100644
index 582b731b0495ad2a38911ef1f9fe6d2aec58aea1..3edc33b9dcc94a2ef68d52bc0af178121447acaa 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -71,7 +71,6 @@ private:
@@ -70,7 +70,6 @@ private:
/// for a \see write_impl() call to handle the data which has been put into
/// this buffer.
char *OutBufStart, *OutBufEnd, *OutBufCur;
@@ -37,7 +37,7 @@ index 256bcec259a8026473a5f3926bd79b215bd5b888..9b3a87e1bbc0abe83b204bd8f889ffe3
/// Optional stream this stream is tied to. If this stream is written to, the
/// tied-to stream will be flushed first.
@@ -304,9 +303,9 @@ public:
@@ -317,9 +316,9 @@ public:
// Enable or disable colors. Once enable_colors(false) is called,
// changeColor() has no effect until enable_colors(true) is called.
@@ -50,10 +50,10 @@ index 256bcec259a8026473a5f3926bd79b215bd5b888..9b3a87e1bbc0abe83b204bd8f889ffe3
/// Tie this stream to the specified stream. Replaces any existing tied-to
/// stream. Specifying a nullptr unties the stream.
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index 27ca15f7d239a8e5050cadd159dad96de150e444..53fe22b5eb8dad289cced414ed6f544fd0249504 100644
index 54137a331ca9e752b02c0f16ae996094a6f2fafa..e253d6f7a5ca3aee75823efdb9717dcd93fff5dc 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -178,22 +178,6 @@ void llvm::llvm_unreachable_internal(const char *msg, const char *file,
@@ -181,22 +181,6 @@ void llvm::llvm_unreachable_internal(const char *msg, const char *file,
#endif
}
@@ -77,10 +77,10 @@ index 27ca15f7d239a8e5050cadd159dad96de150e444..53fe22b5eb8dad289cced414ed6f544f
#include <winerror.h>
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf14093bc3 100644
index 4769d34a14f3f2cbaaa4df50ea7111fe9fa2792f..f9928ac969932b6baea60a80750477d78b6a5b02 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -167,16 +167,6 @@ raw_ostream &raw_ostream::write_escaped(std::string_view Str,
@@ -175,16 +175,6 @@ raw_ostream &raw_ostream::write_escaped(std::string_view Str,
return *this;
}
@@ -97,7 +97,7 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
void raw_ostream::flush_nonempty() {
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
size_t Length = OutBufCur - OutBufStart;
@@ -321,15 +311,22 @@ static int getFD(std::string_view Filename, std::error_code &EC,
@@ -327,15 +317,22 @@ static int getFD(std::string_view Filename, std::error_code &EC,
if (Filename == "-") {
EC = std::error_code();
// Change stdout's text/binary mode based on the Flags.
@@ -125,7 +125,7 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
if (EC)
return -1;
@@ -389,12 +386,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
@@ -395,12 +392,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
// Get the starting position.
off_t loc = ::lseek(FD, 0, SEEK_CUR);
@@ -139,7 +139,7 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
#else
SupportsSeeking = !EC && loc != (off_t)-1;
#endif
@@ -407,10 +400,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
@@ -413,10 +406,8 @@ raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
raw_fd_ostream::~raw_fd_ostream() {
if (FD >= 0) {
flush();
@@ -152,7 +152,7 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
}
#ifdef __MINGW32__
@@ -505,7 +496,11 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
@@ -511,7 +502,11 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
do {
size_t ChunkSize = std::min(Size, MaxWriteSize);
@@ -164,7 +164,7 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
if (ret < 0) {
// If it's a recoverable error, swallow it and retry the write.
@@ -540,8 +535,8 @@ void raw_fd_ostream::close() {
@@ -554,8 +549,8 @@ void raw_fd_ostream::close() {
assert(ShouldClose);
ShouldClose = false;
flush();
@@ -175,17 +175,8 @@ index 878a3a5e99949da360a93dc51298460cc61d4f3f..632b522358c969682f01dbbb9a6f86cf
FD = -1;
}
@@ -550,8 +545,6 @@ uint64_t raw_fd_ostream::seek(uint64_t off) {
flush();
#ifdef _WIN32
pos = ::_lseeki64(FD, off, SEEK_SET);
-#elif defined(HAVE_LSEEK64)
- pos = ::lseek64(FD, off, SEEK_SET);
#else
pos = ::lseek(FD, off, SEEK_SET);
#endif
diff --git a/llvm/unittests/ADT/SmallStringTest.cpp b/llvm/unittests/ADT/SmallStringTest.cpp
index bee3875d11c9b793d79ac442312559b11dba9f5f..87600ea4704bc98acab9085d16cfafd3d586714e 100644
index 6cf14700b34739420cd3dc4ff8a4c16ce162f715..87600ea4704bc98acab9085d16cfafd3d586714e 100644
--- a/llvm/unittests/ADT/SmallStringTest.cpp
+++ b/llvm/unittests/ADT/SmallStringTest.cpp
@@ -129,23 +129,6 @@ TEST_F(SmallStringTest, StdStringConversion) {
@@ -239,12 +230,12 @@ index bee3875d11c9b793d79ac442312559b11dba9f5f..87600ea4704bc98acab9085d16cfafd3
-}
-
-TEST_F(SmallStringTest, Comparisons) {
- EXPECT_EQ(-1, SmallString<10>("aab").compare("aad"));
- EXPECT_GT( 0, SmallString<10>("aab").compare("aad"));
- EXPECT_EQ( 0, SmallString<10>("aab").compare("aab"));
- EXPECT_EQ( 1, SmallString<10>("aab").compare("aaa"));
- EXPECT_EQ(-1, SmallString<10>("aab").compare("aabb"));
- EXPECT_EQ( 1, SmallString<10>("aab").compare("aa"));
- EXPECT_EQ( 1, SmallString<10>("\xFF").compare("\1"));
- EXPECT_LT( 0, SmallString<10>("aab").compare("aaa"));
- EXPECT_GT( 0, SmallString<10>("aab").compare("aabb"));
- EXPECT_LT( 0, SmallString<10>("aab").compare("aa"));
- EXPECT_LT( 0, SmallString<10>("\xFF").compare("\1"));
-
- EXPECT_EQ(-1, SmallString<10>("AaB").compare_insensitive("aAd"));
- EXPECT_EQ( 0, SmallString<10>("AaB").compare_insensitive("aab"));

View File

@@ -4,14 +4,14 @@ Date: Sun, 8 May 2022 19:30:43 -0400
Subject: [PATCH 23/30] OS-specific changes
---
llvm/lib/Support/ErrorHandling.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
llvm/lib/Support/ErrorHandling.cpp | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index 53fe22b5eb8dad289cced414ed6f544fd0249504..5c08e469e2e44b27e69f4aa974bc59deb8217c9b 100644
index e253d6f7a5ca3aee75823efdb9717dcd93fff5dc..5c08e469e2e44b27e69f4aa974bc59deb8217c9b 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -96,12 +96,7 @@ void llvm::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
@@ -96,15 +96,7 @@ void llvm::report_fatal_error(std::string_view Reason, bool GenCrashDiag) {
fmt::print(stderr, "LLVM ERROR: {}\n", Reason);
}
@@ -20,12 +20,15 @@ index 53fe22b5eb8dad289cced414ed6f544fd0249504..5c08e469e2e44b27e69f4aa974bc59de
- // files registered with RemoveFileOnSignal.
- sys::RunInterruptHandlers();
-
- abort();
- if (GenCrashDiag)
- abort();
- else
- exit(1);
+ exit(1);
}
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
@@ -138,9 +133,15 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
@@ -141,9 +133,15 @@ void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
// an OOM to stderr and abort.
const char *OOMMessage = "LLVM ERROR: out of memory\n";
const char *Newline = "\n";

View File

@@ -10,10 +10,10 @@ Subject: [PATCH 24/30] Use SmallVector for UTF conversion
3 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Support/ConvertUTF.h b/llvm/include/llvm/Support/ConvertUTF.h
index b085c8a179e8767a258f9feafc8d1111828f10b1..c82947006afb3f8b41c0369352de63fd62be574b 100644
index 72321022beb373945f7935ed72944fd68eb7d02f..5c8b966ce296699a0315d72cdfdcdb5af3d1d0b0 100644
--- a/llvm/include/llvm/Support/ConvertUTF.h
+++ b/llvm/include/llvm/Support/ConvertUTF.h
@@ -213,7 +213,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
@@ -233,7 +233,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
* Converts a std::wstring to a UTF-8 encoded std::string.
* \return true on success.
*/
@@ -22,7 +22,7 @@ index b085c8a179e8767a258f9feafc8d1111828f10b1..c82947006afb3f8b41c0369352de63fd
/**
@@ -268,7 +268,7 @@ bool hasUTF16ByteOrderMark(span<const char> SrcBytes);
@@ -288,7 +288,7 @@ bool hasUTF16ByteOrderMark(span<const char> SrcBytes);
* \param [out] Out Converted UTF-8 is stored here on success.
* \returns true on success
*/
@@ -31,7 +31,7 @@ index b085c8a179e8767a258f9feafc8d1111828f10b1..c82947006afb3f8b41c0369352de63fd
/**
* Converts a UTF16 string into a UTF8 std::string.
@@ -277,7 +277,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out);
@@ -297,7 +297,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out);
* \param [out] Out Converted UTF-8 is stored here on success.
* \returns true on success
*/
@@ -39,13 +39,13 @@ index b085c8a179e8767a258f9feafc8d1111828f10b1..c82947006afb3f8b41c0369352de63fd
+bool convertUTF16ToUTF8String(span<const UTF16> Src, SmallVectorImpl<char> &Out);
/**
* Converts a UTF-8 string into a UTF-16 string with native endianness.
* Converts a stream of raw bytes assumed to be UTF32 into a UTF8 std::string.
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index cff30f16ca907959843dd58ff30f58ead333f17f..d3689d92a45a289aaca30c47790a5e46c484344c 100644
index 195071cc697070af2a75207fced50d49bae46c23..d13d876d6c5c830bede6ed90ff2cfa6236a79504 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -84,7 +84,7 @@ bool hasUTF16ByteOrderMark(span<const char> S) {
(S[0] == '\xfe' && S[1] == '\xff')));
@@ -82,7 +82,7 @@ bool hasUTF16ByteOrderMark(span<const char> S) {
(S[0] == '\xfe' && S[1] == '\xff')));
}
-bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out) {
@@ -53,16 +53,16 @@ index cff30f16ca907959843dd58ff30f58ead333f17f..d3689d92a45a289aaca30c47790a5e46
assert(Out.empty());
// Error out on an uneven byte count.
@@ -135,7 +135,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out) {
@@ -133,7 +133,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out) {
return true;
}
-bool convertUTF16ToUTF8String(span<const UTF16> Src, std::string &Out)
+bool convertUTF16ToUTF8String(span<const UTF16> Src, SmallVectorImpl<char> &Out)
{
-bool convertUTF16ToUTF8String(span<const UTF16> Src, std::string &Out) {
+bool convertUTF16ToUTF8String(span<const UTF16> Src, SmallVectorImpl<char> &Out) {
return convertUTF16ToUTF8String(
span<const char>(reinterpret_cast<const char *>(Src.data()),
@@ -213,7 +213,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
Src.size() * sizeof(UTF16)),
@@ -269,7 +269,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
return ConvertUTF8toWide(std::string_view(Source), Result);
}
@@ -72,10 +72,10 @@ index cff30f16ca907959843dd58ff30f58ead333f17f..d3689d92a45a289aaca30c47790a5e46
const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
const UTF8 *End =
diff --git a/llvm/unittests/Support/ConvertUTFTest.cpp b/llvm/unittests/Support/ConvertUTFTest.cpp
index 2fee8ad5c01294988457002517dcb8d983cac23d..7d7650b1c077af7baed2b408584e857602bc329a 100644
index 77e70a46d3621ecfaed923d87256184addfda721..eb17a06c4369c9486c57b61f519a7429d9ef3d80 100644
--- a/llvm/unittests/Support/ConvertUTFTest.cpp
+++ b/llvm/unittests/Support/ConvertUTFTest.cpp
@@ -19,22 +19,22 @@ TEST(ConvertUTFTest, ConvertUTF16LittleEndianToUTF8String) {
@@ -19,11 +19,11 @@ TEST(ConvertUTFTest, ConvertUTF16LittleEndianToUTF8String) {
// Src is the look of disapproval.
alignas(UTF16) static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c";
span<const char> Ref(Src, sizeof(Src) - 1);
@@ -88,7 +88,8 @@ index 2fee8ad5c01294988457002517dcb8d983cac23d..7d7650b1c077af7baed2b408584e8576
+ EXPECT_EQ(Expected, std::string{Result});
}
TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
TEST(ConvertUTFTest, ConvertUTF32LittleEndianToUTF8String) {
@@ -42,11 +42,11 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
// Src is the look of disapproval.
alignas(UTF16) static const char Src[] = "\xfe\xff\x0c\xa0\x00_\x0c\xa0";
span<const char> Ref(Src, sizeof(Src) - 1);
@@ -101,8 +102,8 @@ index 2fee8ad5c01294988457002517dcb8d983cac23d..7d7650b1c077af7baed2b408584e8576
+ EXPECT_EQ(Expected, std::string{Result});
}
TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) {
@@ -51,16 +51,16 @@ TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) {
TEST(ConvertUTFTest, ConvertUTF32BigEndianToUTF8String) {
@@ -75,17 +75,17 @@ TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) {
}
TEST(ConvertUTFTest, OddLengthInput) {
@@ -115,14 +116,15 @@ index 2fee8ad5c01294988457002517dcb8d983cac23d..7d7650b1c077af7baed2b408584e8576
TEST(ConvertUTFTest, Empty) {
- std::string Result;
+ SmallString<20> Result;
bool Success = convertUTF16ToUTF8String(span<const char>(), Result);
bool Success =
convertUTF16ToUTF8String(span<const char>(), Result);
EXPECT_TRUE(Success);
- EXPECT_TRUE(Result.empty());
+ EXPECT_TRUE(std::string{Result}.empty());
}
TEST(ConvertUTFTest, HasUTF16BOM) {
@@ -83,11 +83,11 @@ TEST(ConvertUTFTest, UTF16WrappersForConvertUTF16ToUTF8String) {
@@ -108,11 +108,11 @@ TEST(ConvertUTFTest, UTF16WrappersForConvertUTF16ToUTF8String) {
// Src is the look of disapproval.
alignas(UTF16) static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c";
span<const UTF16> SrcRef((const UTF16 *)Src, 4);
@@ -136,7 +138,7 @@ index 2fee8ad5c01294988457002517dcb8d983cac23d..7d7650b1c077af7baed2b408584e8576
}
TEST(ConvertUTFTest, ConvertUTF8toWide) {
@@ -107,11 +107,11 @@ TEST(ConvertUTFTest, ConvertUTF8toWide) {
@@ -132,11 +132,11 @@ TEST(ConvertUTFTest, ConvertUTF8toWide) {
TEST(ConvertUTFTest, convertWideToUTF8) {
// Src is the look of disapproval.
static const wchar_t Src[] = L"\x0ca0_\x0ca0";

View File

@@ -9,10 +9,10 @@ See #1401
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 632b522358c969682f01dbbb9a6f86cf14093bc3..a703a75edb480b6499ea5ef5945237719b3c565a 100644
index f9928ac969932b6baea60a80750477d78b6a5b02..1de34976844d500970b833fca35324e2948733b7 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -599,15 +599,15 @@ void raw_fd_ostream::anchor() {}
@@ -613,15 +613,15 @@ void raw_fd_ostream::anchor() {}
raw_fd_ostream &llvm::outs() {
// Set buffer settings to model stdout behavior.
std::error_code EC;

View File

@@ -8,10 +8,10 @@ Subject: [PATCH 27/30] Copy type traits from STLExtras.h into PointerUnion.h
1 file changed, 46 insertions(+)
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index 1d4cc747ce320e27004170fb0aa76323d2ac22b1..7d090da591ad722a9cde7915bea48eec0ef1a408 100644
index 6abec033a4008057f30d445d47ab22ebbb046a2f..7303694ef3d0cb833db3cb9f86bd155ab6136511 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -22,9 +22,55 @@
@@ -23,9 +23,55 @@
#include <cassert>
#include <cstddef>
#include <cstdint>

View File

@@ -8,7 +8,7 @@ Subject: [PATCH 28/30] Remove StringMap test for llvm::sort()
1 file changed, 14 deletions(-)
diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp
index de6daf3daf4e59b57fa43df2526c62e854fa65ee..ca41631ccf9519740e9f5f303dfbfe31762e3ab8 100644
index a45dde69f833900fa1d7c5a1984edee3d501111d..d232c61e84a93fdc4d4c3a77b1f6124269d1fc05 100644
--- a/llvm/unittests/ADT/StringMapTest.cpp
+++ b/llvm/unittests/ADT/StringMapTest.cpp
@@ -308,20 +308,6 @@ TEST_F(StringMapTest, InsertOrAssignTest) {

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ryan Blue <ryanzblue@gmail.com>
Date: Thu, 8 Jun 2023 18:49:52 -0400
Subject: [PATCH 29/30] Fix docs typo in SmallVector
---
llvm/include/llvm/ADT/SmallVector.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 4b6bbdeb2ea3e602978733351e352968ccdca36d..84713da54c49125697635381002d81df954915d9 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
///
-/// /file
+/// \file
/// This file defines the SmallVector class.
///
//===----------------------------------------------------------------------===//

View File

@@ -1,17 +1,17 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Leander Schulten <Leander.Schulten@rwth-aachen.de>
Date: Mon, 10 Jul 2023 00:53:43 +0200
Subject: [PATCH 30/30] Unused variable in release mode
Subject: [PATCH 29/30] Unused variable in release mode
---
llvm/include/llvm/ADT/DenseMap.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 975c3b97e2cbf09225299c421406ad2bbe4ef125..ada70d6c826d8f5bb65e502be15317692febb55c 100644
index 7f4ddc256a207289980b60385f02da69f7119578..838a9b88648c7ce57b9ef4894573ddc25c74340a 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -126,7 +126,7 @@ public:
@@ -124,7 +124,7 @@ public:
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
P->getFirst() = EmptyKey;
} else {

View File

@@ -0,0 +1,436 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tyler Veness <calcmogul@gmail.com>
Date: Tue, 11 Jul 2023 22:56:09 -0700
Subject: [PATCH 30/30] Use C++20 <bit> header
---
llvm/include/llvm/ADT/bit.h | 256 -------------------------
llvm/include/llvm/Support/MathExtras.h | 37 ++--
2 files changed, 19 insertions(+), 274 deletions(-)
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
index d93023d88b4efe962f425d0b8fe98fc25394f1fe..0a4a3634820efbc0a8ca675e3ad7c98469260d0b 100644
--- a/llvm/include/llvm/ADT/bit.h
+++ b/llvm/include/llvm/ADT/bit.h
@@ -27,18 +27,6 @@
#include <cstdlib> // for _byteswap_{ushort,ulong,uint64}
#endif
-#ifdef _MSC_VER
-// Declare these intrinsics manually rather including intrin.h. It's very
-// expensive, and bit.h is popular via MathExtras.h.
-// #include <intrin.h>
-extern "C" {
-unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
-unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
-unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
-unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
-}
-#endif
-
namespace llvm {
// This implementation of bit_cast is different from the C++20 one in two ways:
@@ -106,250 +94,6 @@ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
}
}
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept {
- return (Value != 0) && ((Value & (Value - 1)) == 0);
-}
-
-namespace detail {
-template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
- static unsigned count(T Val) {
- if (!Val)
- return std::numeric_limits<T>::digits;
- if (Val & 0x1)
- return 0;
-
- // Bisection method.
- unsigned ZeroBits = 0;
- T Shift = std::numeric_limits<T>::digits >> 1;
- T Mask = std::numeric_limits<T>::max() >> Shift;
- while (Shift) {
- if ((Val & Mask) == 0) {
- Val >>= Shift;
- ZeroBits |= Shift;
- }
- Shift >>= 1;
- Mask >>= Shift;
- }
- return ZeroBits;
- }
-};
-
-#if defined(__GNUC__) || defined(_MSC_VER)
-template <typename T> struct TrailingZerosCounter<T, 4> {
- static unsigned count(T Val) {
- if (Val == 0)
- return 32;
-
-#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
- return __builtin_ctz(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanForward(&Index, Val);
- return Index;
-#endif
- }
-};
-
-#if !defined(_MSC_VER) || defined(_M_X64)
-template <typename T> struct TrailingZerosCounter<T, 8> {
- static unsigned count(T Val) {
- if (Val == 0)
- return 64;
-
-#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
- return __builtin_ctzll(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanForward64(&Index, Val);
- return Index;
-#endif
- }
-};
-#endif
-#endif
-} // namespace detail
-
-/// Count number of 0's from the least significant bit to the most
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countr_zero(T Val) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val);
-}
-
-namespace detail {
-template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
- static unsigned count(T Val) {
- if (!Val)
- return std::numeric_limits<T>::digits;
-
- // Bisection method.
- unsigned ZeroBits = 0;
- for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
- T Tmp = Val >> Shift;
- if (Tmp)
- Val = Tmp;
- else
- ZeroBits |= Shift;
- }
- return ZeroBits;
- }
-};
-
-#if defined(__GNUC__) || defined(_MSC_VER)
-template <typename T> struct LeadingZerosCounter<T, 4> {
- static unsigned count(T Val) {
- if (Val == 0)
- return 32;
-
-#if __has_builtin(__builtin_clz) || defined(__GNUC__)
- return __builtin_clz(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanReverse(&Index, Val);
- return Index ^ 31;
-#endif
- }
-};
-
-#if !defined(_MSC_VER) || defined(_M_X64)
-template <typename T> struct LeadingZerosCounter<T, 8> {
- static unsigned count(T Val) {
- if (Val == 0)
- return 64;
-
-#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
- return __builtin_clzll(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanReverse64(&Index, Val);
- return Index ^ 63;
-#endif
- }
-};
-#endif
-#endif
-} // namespace detail
-
-/// Count number of 0's from the most significant bit to the least
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countl_zero(T Val) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val);
-}
-
-/// Count the number of ones from the most significant bit to the first
-/// zero bit.
-///
-/// Ex. countl_one(0xFF0FFF00) == 8.
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countl_one(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::countl_zero<T>(~Value);
-}
-
-/// Count the number of ones from the least significant bit to the first
-/// zero bit.
-///
-/// Ex. countr_one(0x00FF00FF) == 8.
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countr_one(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::countr_zero<T>(~Value);
-}
-
-/// Returns the number of bits needed to represent Value if Value is nonzero.
-/// Returns 0 otherwise.
-///
-/// Ex. bit_width(5) == 3.
-template <typename T> [[nodiscard]] int bit_width(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
-}
-
-/// Returns the largest integral power of two no greater than Value if Value is
-/// nonzero. Returns 0 otherwise.
-///
-/// Ex. bit_floor(5) == 4.
-template <typename T> [[nodiscard]] T bit_floor(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (!Value)
- return 0;
- return T(1) << (llvm::bit_width(Value) - 1);
-}
-
-/// Returns the smallest integral power of two no smaller than Value if Value is
-/// nonzero. Returns 0 otherwise.
-///
-/// Ex. bit_ceil(5) == 8.
-///
-/// The return value is undefined if the input is larger than the largest power
-/// of two representable in T.
-template <typename T> [[nodiscard]] T bit_ceil(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (Value < 2)
- return 1;
- return T(1) << llvm::bit_width<T>(Value - 1u);
-}
-
-namespace detail {
-template <typename T, std::size_t SizeOfT> struct PopulationCounter {
- static int count(T Value) {
- // Generic version, forward to 32 bits.
- static_assert(SizeOfT <= 4, "Not implemented!");
-#if defined(__GNUC__)
- return (int)__builtin_popcount(Value);
-#else
- uint32_t v = Value;
- v = v - ((v >> 1) & 0x55555555);
- v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
- return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
-#endif
- }
-};
-
-template <typename T> struct PopulationCounter<T, 8> {
- static int count(T Value) {
-#if defined(__GNUC__)
- return (int)__builtin_popcountll(Value);
-#else
- uint64_t v = Value;
- v = v - ((v >> 1) & 0x5555555555555555ULL);
- v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
- v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
- return int((uint64_t)(v * 0x0101010101010101ULL) >> 56);
-#endif
- }
-};
-} // namespace detail
-
-/// Count the number of set bits in a value.
-/// Ex. popcount(0xF000F000) = 8
-/// Returns 0 if the word is zero.
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] inline int popcount(T Value) noexcept {
- return detail::PopulationCounter<T, sizeof(T)>::count(Value);
-}
-
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index fe9c5136f9f2f687577a0b1ecce69262568a9c3c..c269839c309e92d92ff8835127dcd2dfc0dd2c23 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/bit.h"
#include "llvm/Support/Compiler.h"
+#include <bit>
#include <cassert>
#include <climits>
#include <cstdint>
@@ -41,7 +42,7 @@ enum ZeroBehavior {
template <typename T> unsigned countTrailingZeros(T Val) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
- return llvm::countr_zero(Val);
+ return std::countr_zero(Val);
}
/// Count number of 0's from the most significant bit to the least
@@ -53,7 +54,7 @@ template <typename T> unsigned countTrailingZeros(T Val) {
template <typename T> unsigned countLeadingZeros(T Val) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
- return llvm::countl_zero(Val);
+ return std::countl_zero(Val);
}
/// Get the index of the first set bit starting from the least
@@ -66,7 +67,7 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return (std::numeric_limits<T>::max)();
- return llvm::countr_zero(Val);
+ return std::countr_zero(Val);
}
/// Create a bitmask with the N right-most bits set to 1, and all other
@@ -108,7 +109,7 @@ template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
// Use ^ instead of - because both gcc and llvm can remove the associated ^
// in the __builtin_clz intrinsic on x86.
- return llvm::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
+ return std::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
}
/// Macro compressed bit reversal table for 256 bits.
@@ -295,12 +296,12 @@ constexpr inline bool isShiftedMask_64(uint64_t Value) {
/// Return true if the argument is a power of two > 0.
/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
constexpr inline bool isPowerOf2_32(uint32_t Value) {
- return llvm::has_single_bit(Value);
+ return std::has_single_bit(Value);
}
/// Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr inline bool isPowerOf2_64(uint64_t Value) {
- return llvm::has_single_bit(Value);
+ return std::has_single_bit(Value);
}
/// Count the number of ones from the most significant bit to the first
@@ -313,7 +314,7 @@ constexpr inline bool isPowerOf2_64(uint64_t Value) {
template <typename T> unsigned countLeadingOnes(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
- return llvm::countl_one<T>(Value);
+ return std::countl_one<T>(Value);
}
/// Count the number of ones from the least significant bit to the first
@@ -326,7 +327,7 @@ template <typename T> unsigned countLeadingOnes(T Value) {
template <typename T> unsigned countTrailingOnes(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
- return llvm::countr_one<T>(Value);
+ return std::countr_one<T>(Value);
}
/// Count the number of set bits in a value.
@@ -336,7 +337,7 @@ template <typename T>
inline unsigned countPopulation(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
- return (unsigned)llvm::popcount(Value);
+ return (unsigned)std::popcount(Value);
}
/// Return true if the argument contains a non-empty sequence of ones with the
@@ -348,8 +349,8 @@ inline bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx,
unsigned &MaskLen) {
if (!isShiftedMask_32(Value))
return false;
- MaskIdx = llvm::countr_zero(Value);
- MaskLen = llvm::popcount(Value);
+ MaskIdx = std::countr_zero(Value);
+ MaskLen = std::popcount(Value);
return true;
}
@@ -361,8 +362,8 @@ inline bool isShiftedMask_64(uint64_t Value, unsigned &MaskIdx,
unsigned &MaskLen) {
if (!isShiftedMask_64(Value))
return false;
- MaskIdx = llvm::countr_zero(Value);
- MaskLen = llvm::popcount(Value);
+ MaskIdx = std::countr_zero(Value);
+ MaskLen = std::popcount(Value);
return true;
}
@@ -380,26 +381,26 @@ template <> constexpr inline size_t CTLog2<1>() { return 0; }
/// (32 bit edition.)
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
inline unsigned Log2_32(uint32_t Value) {
- return static_cast<unsigned>(31 - llvm::countl_zero(Value));
+ return static_cast<unsigned>(31 - std::countl_zero(Value));
}
/// Return the floor log base 2 of the specified value, -1 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64(uint64_t Value) {
- return static_cast<unsigned>(63 - llvm::countl_zero(Value));
+ return static_cast<unsigned>(63 - std::countl_zero(Value));
}
/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
/// (32 bit edition).
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
inline unsigned Log2_32_Ceil(uint32_t Value) {
- return static_cast<unsigned>(32 - llvm::countl_zero(Value - 1));
+ return static_cast<unsigned>(32 - std::countl_zero(Value - 1));
}
/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64_Ceil(uint64_t Value) {
- return static_cast<unsigned>(64 - llvm::countl_zero(Value - 1));
+ return static_cast<unsigned>(64 - std::countl_zero(Value - 1));
}
/// This function takes a 64-bit integer and returns the bit equivalent double.
@@ -456,7 +457,7 @@ constexpr inline uint64_t NextPowerOf2(uint64_t A) {
/// Returns the power of two which is less than or equal to the given value.
/// Essentially, it is a floor operation across the domain of powers of two.
inline uint64_t PowerOf2Floor(uint64_t A) {
- return llvm::bit_floor(A);
+ return std::bit_floor(A);
}
/// Returns the power of two which is greater than or equal to the given value.

View File

@@ -28,7 +28,7 @@ def run_global_replacements(wpiutil_llvm_files):
# Fix uses of span
content = content.replace("span", "std::span")
content = content.replace('include "wpi/std::span.h"', "include <span>")
content = content.replace("include <std::span>", "include <span>")
if wpi_file.endswith("ConvertUTFWrapper.cpp"):
content = content.replace(
"const UTF16 *Src = reinterpret_cast<const UTF16 *>(SrcBytes.begin());",
@@ -38,6 +38,14 @@ def run_global_replacements(wpiutil_llvm_files):
"const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(SrcBytes.end());",
"const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(&*SrcBytes.begin() + SrcBytes.size());",
)
content = content.replace(
"const UTF32 *Src = reinterpret_cast<const UTF32 *>(SrcBytes.begin());",
"const UTF32 *Src = reinterpret_cast<const UTF32 *>(&*SrcBytes.begin());",
)
content = content.replace(
"const UTF32 *SrcEnd = reinterpret_cast<const UTF32 *>(SrcBytes.end());",
"const UTF32 *SrcEnd = reinterpret_cast<const UTF32 *>(&*SrcBytes.begin() + SrcBytes.size());",
)
# Remove unused headers
content = content.replace('#include "llvm-c/ErrorHandling.h"\n', "")
@@ -163,7 +171,7 @@ def overwrite_tests(wpiutil_root, llvm_root):
def main():
upstream_root = clone_repo("https://github.com/llvm/llvm-project", "llvmorg-14.0.6")
upstream_root = clone_repo("https://github.com/llvm/llvm-project", "llvmorg-16.0.6")
wpilib_root = get_repo_root()
wpiutil = os.path.join(wpilib_root, "wpiutil")
@@ -198,8 +206,8 @@ def main():
"0026-constexpr-endian-byte-swap.patch",
"0027-Copy-type-traits-from-STLExtras.h-into-PointerUnion..patch",
"0028-Remove-StringMap-test-for-llvm-sort.patch",
"0029-Fix-docs-typo-in-SmallVector.patch",
"0030-Unused-variable-in-release-mode.patch",
"0029-Unused-variable-in-release-mode.patch",
"0030-Use-C-20-bit-header.patch",
]:
git_am(
os.path.join(wpilib_root, "upstream_utils/llvm_patches", f),

View File

@@ -18,7 +18,10 @@ def clone_repo(url, treeish, shallow=True):
root -- root directory of the cloned Git repository
"""
cwd = os.getcwd()
os.chdir(tempfile.gettempdir())
if url.startswith("file://"):
os.chdir(os.path.dirname(url[7:]))
else:
os.chdir(tempfile.gettempdir())
repo = os.path.basename(url)
dest = os.path.join(os.getcwd(), repo)

View File

@@ -6,25 +6,41 @@
*
*===------------------------------------------------------------------------=*/
/*
* Copyright 2001-2004 Unicode, Inc.
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in
* http://www.unicode.org/copyright.html.
*
* Disclaimer
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of the Unicode data files and any associated documentation
* (the "Data Files") or Unicode software and any associated documentation
* (the "Software") to deal in the Data Files or Software
* without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, and/or sell copies of
* the Data Files or Software, and to permit persons to whom the Data Files
* or Software are furnished to do so, provided that
* (a) this copyright and permission notice appear with all copies
* of the Data Files or Software,
* (b) this copyright and permission notice appear in associated
* documentation, and
* (c) there is clear notice in each modified Data File or in the Software
* as well as in the documentation associated with the Data File(s) or
* Software that the data or software has been modified.
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in these Data Files or Software without prior
* written authorization of the copyright holder.
*/
/* ---------------------------------------------------------------------
@@ -422,6 +438,16 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
return isLegalUTF8(source, length);
}
/*
* Exported function to return the size of the first utf-8 code unit sequence,
* Or 0 if the sequence is not valid;
*/
unsigned getUTF8SequenceSize(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source] + 1;
return (length <= sourceEnd - source && isLegalUTF8(source, length)) ? length
: 0;
}
/* --------------------------------------------------------------------- */
static unsigned

View File

@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
#include <span>
#include "wpi/ConvertUTF.h"
#include "wpi/SmallVector.h"
#include "wpi/ErrorHandling.h"
#include "wpi/SwapByteOrder.h"
#include <span>
#include <string>
#include <string_view>
#include <vector>
@@ -35,31 +35,31 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, std::string_view Source,
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);
UTF16 *targetStart = reinterpret_cast<UTF16 *>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF16(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
result =
ConvertUTF8toUTF16(&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
ResultPtr = reinterpret_cast<char *>(targetStart);
else
ErrorPtr = sourceStart;
} else if (WideCharWidth == 4) {
const UTF8 *sourceStart = (const UTF8*)Source.data();
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);
UTF32 *targetStart = reinterpret_cast<UTF32 *>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF32(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
result =
ConvertUTF8toUTF32(&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
ResultPtr = reinterpret_cast<char *>(targetStart);
else
ErrorPtr = sourceStart;
}
assert((result != targetExhausted)
&& "ConvertUTF8toUTFXX exhausted target buffer");
assert((result != targetExhausted) &&
"ConvertUTF8toUTFXX exhausted target buffer");
return result == conversionOK;
}
@@ -68,20 +68,18 @@ bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
const UTF32 *SourceEnd = SourceStart + 1;
UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
UTF8 *TargetEnd = TargetStart + 4;
ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
&TargetStart, TargetEnd,
strictConversion);
ConversionResult CR = ConvertUTF32toUTF8(
&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
if (CR != conversionOK)
return false;
ResultPtr = reinterpret_cast<char*>(TargetStart);
ResultPtr = reinterpret_cast<char *>(TargetStart);
return true;
}
bool hasUTF16ByteOrderMark(std::span<const char> S) {
return (S.size() >= 2 &&
((S[0] == '\xff' && S[1] == '\xfe') ||
(S[0] == '\xfe' && S[1] == '\xff')));
return (S.size() >= 2 && ((S[0] == '\xff' && S[1] == '\xfe') ||
(S[0] == '\xfe' && S[1] == '\xff')));
}
bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<char> &Out) {
@@ -135,11 +133,69 @@ bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<ch
return true;
}
bool convertUTF16ToUTF8String(std::span<const UTF16> Src, SmallVectorImpl<char> &Out)
{
bool convertUTF16ToUTF8String(std::span<const UTF16> Src, SmallVectorImpl<char> &Out) {
return convertUTF16ToUTF8String(
std::span<const char>(reinterpret_cast<const char *>(Src.data()),
Src.size() * sizeof(UTF16)), Out);
Src.size() * sizeof(UTF16)),
Out);
}
bool convertUTF32ToUTF8String(std::span<const char> SrcBytes, std::string &Out) {
assert(Out.empty());
// Error out on an uneven byte count.
if (SrcBytes.size() % 4)
return false;
// Avoid OOB by returning early on empty input.
if (SrcBytes.empty())
return true;
const UTF32 *Src = reinterpret_cast<const UTF32 *>(&*SrcBytes.begin());
const UTF32 *SrcEnd = reinterpret_cast<const UTF32 *>(&*SrcBytes.begin() + SrcBytes.size());
assert((uintptr_t)Src % sizeof(UTF32) == 0);
// Byteswap if necessary.
std::vector<UTF32> ByteSwapped;
if (Src[0] == UNI_UTF32_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (UTF32 &I : ByteSwapped)
I = wpi::ByteSwap_32(I);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
// Skip the BOM for conversion.
if (Src[0] == UNI_UTF32_BYTE_ORDER_MARK_NATIVE)
Src++;
// Just allocate enough space up front. We'll shrink it later. Allocate
// enough that we can fit a null terminator without reallocating.
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 =
ConvertUTF32toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
assert(CR != targetExhausted);
if (CR != conversionOK) {
Out.clear();
return false;
}
Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
Out.push_back(0);
Out.pop_back();
return true;
}
bool convertUTF32ToUTF8String(std::span<const UTF32> Src, std::string &Out) {
return convertUTF32ToUTF8String(
std::span<const char>(reinterpret_cast<const char *>(Src.data()),
Src.size() * sizeof(UTF32)),
Out);
}
bool convertUTF8ToUTF16String(std::string_view SrcUTF8,

View File

@@ -99,14 +99,30 @@ static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
// 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);
return std::clamp(NewCapacity, MinSize, MaxSize);
}
void *SmallVectorBase::replaceAllocation(void *NewElts, size_t TSize,
size_t NewCapacity,
size_t VSize) {
void *NewEltsReplace = wpi::safe_malloc(NewCapacity * TSize);
if (VSize)
memcpy(NewEltsReplace, NewElts, VSize * TSize);
free(NewElts);
return NewEltsReplace;
}
// Note: Moving this function into the header may cause performance regression.
void *SmallVectorBase::mallocForGrow(size_t MinSize, size_t TSize,
void *SmallVectorBase::mallocForGrow(void *FirstEl, size_t MinSize,
size_t TSize,
size_t &NewCapacity) {
NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
return wpi::safe_malloc(NewCapacity * TSize);
// Even if capacity is not 0 now, if the vector was originally created with
// capacity 0, it's possible for the malloc to return FirstEl.
void *NewElts = wpi::safe_malloc(NewCapacity * TSize);
if (NewElts == FirstEl)
NewElts = replaceAllocation(NewElts, TSize, NewCapacity);
return NewElts;
}
// Note: Moving this function into the header may cause performance regression.
@@ -115,13 +131,17 @@ void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize,
size_t NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
void *NewElts;
if (BeginX == FirstEl) {
NewElts = safe_malloc(NewCapacity * TSize);
NewElts = wpi::safe_malloc(NewCapacity * TSize);
if (NewElts == FirstEl)
NewElts = replaceAllocation(NewElts, TSize, NewCapacity);
// Copy the elements over. No need to run dtors on PODs.
memcpy(NewElts, this->BeginX, size() * TSize);
} else {
// If this wasn't grown from the inline copy, grow the allocated space.
NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
NewElts = wpi::safe_realloc(this->BeginX, NewCapacity * TSize);
if (NewElts == FirstEl)
NewElts = replaceAllocation(NewElts, TSize, NewCapacity, size());
}
this->BeginX = NewElts;

View File

@@ -18,7 +18,7 @@ using namespace wpi;
/// Returns the number of buckets to allocate to ensure that the DenseMap can
/// accommodate \p NumEntries without need to grow().
static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
static inline unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
// Ensure that "NumEntries * 4 < NumBuckets * 3"
if (NumEntries == 0)
return 0;
@@ -27,6 +27,21 @@ static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
return NextPowerOf2(NumEntries * 4 / 3 + 1);
}
static inline StringMapEntryBase **createTable(unsigned NewNumBuckets) {
auto **Table = static_cast<StringMapEntryBase **>(safe_calloc(
NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned)));
// Allocate one extra bucket, set it to look filled so the iterators stop at
// end.
Table[NewNumBuckets] = (StringMapEntryBase *)2;
return Table;
}
static inline unsigned *getHashTable(StringMapEntryBase **TheTable,
unsigned NumBuckets) {
return reinterpret_cast<unsigned *>(TheTable + NumBuckets + 1);
}
StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
ItemSize = itemSize;
@@ -54,15 +69,10 @@ void StringMapImpl::init(unsigned InitSize) {
NumItems = 0;
NumTombstones = 0;
TheTable = static_cast<StringMapEntryBase **>(safe_calloc(
NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned)));
TheTable = createTable(NewNumBuckets);
// 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;
}
/// LookupBucketFor - Look up the bucket that the specified string should end
@@ -71,14 +81,12 @@ void StringMapImpl::init(unsigned InitSize) {
/// case, the FullHashValue field of the bucket will be set to the hash value
/// of the string.
unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
unsigned HTSize = NumBuckets;
if (HTSize == 0) { // Hash table unallocated so far?
// Hash table unallocated so far?
if (NumBuckets == 0)
init(16);
HTSize = NumBuckets;
}
unsigned FullHashValue = djbHash(Name, 0);
unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned BucketNo = FullHashValue & (NumBuckets - 1);
unsigned *HashTable = getHashTable(TheTable, NumBuckets);
unsigned ProbeAmt = 1;
int FirstTombstone = -1;
@@ -117,7 +125,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) & (NumBuckets - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -129,12 +137,11 @@ unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
/// in the map, return the bucket number of the key. Otherwise return -1.
/// This does not modify the map.
int StringMapImpl::FindKey(std::string_view Key) const {
unsigned HTSize = NumBuckets;
if (HTSize == 0)
if (NumBuckets == 0)
return -1; // Really empty table?
unsigned FullHashValue = djbHash(Key, 0);
unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned BucketNo = FullHashValue & (NumBuckets - 1);
unsigned *HashTable = getHashTable(TheTable, NumBuckets);
unsigned ProbeAmt = 1;
while (true) {
@@ -161,7 +168,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) & (NumBuckets - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -198,8 +205,6 @@ StringMapEntryBase *StringMapImpl::RemoveKey(std::string_view Key) {
/// the appropriate mod-of-hashtable-size.
unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
unsigned NewSize;
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
// If the hash table is now more than 3/4 full, or if fewer than 1/8 of
// the buckets are empty (meaning that many are filled with tombstones),
// grow/rehash the table.
@@ -213,36 +218,25 @@ 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)));
unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
NewTableArray[NewSize] = (StringMapEntryBase *)2;
auto **NewTableArray = createTable(NewSize);
unsigned *NewHashArray = getHashTable(NewTableArray, NewSize);
unsigned *HashTable = getHashTable(TheTable, NumBuckets);
// 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.
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
// Fast case, bucket available.
// If the bucket is not available, probe for a spot.
unsigned FullHash = HashTable[I];
unsigned NewBucket = FullHash & (NewSize - 1);
if (!NewTableArray[NewBucket]) {
NewTableArray[FullHash & (NewSize - 1)] = Bucket;
NewHashArray[FullHash & (NewSize - 1)] = FullHash;
if (I == BucketNo)
NewBucketNo = NewBucket;
continue;
if (NewTableArray[NewBucket]) {
unsigned ProbeSize = 1;
do {
NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1);
} while (NewTableArray[NewBucket]);
}
// Otherwise probe for a spot.
unsigned ProbeSize = 1;
do {
NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1);
} while (NewTableArray[NewBucket]);
// Finally found a slot. Fill it in.
NewTableArray[NewBucket] = Bucket;
NewHashArray[NewBucket] = FullHash;

View File

@@ -83,6 +83,9 @@ inline bool RunningWindows8OrGreater() {
return GetWindowsOSVersion() >= wpi::VersionTuple(6, 2, 0, 0);
}
/// Determines if the program is running on Windows 11 or Windows Server 2022.
bool RunningWindows11OrGreater();
/// 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

View File

@@ -89,8 +89,15 @@ raw_ostream::~raw_ostream() {
}
size_t raw_ostream::preferred_buffer_size() const {
#ifdef _WIN32
// On Windows BUFSIZ is only 512 which results in more calls to write. This
// overhead can cause significant performance degradation. Therefore use a
// better default.
return (16 * 1024);
#else
// BUFSIZ is intended to be a reasonable default.
return BUFSIZ;
#endif
}
void raw_ostream::SetBuffered() {
@@ -237,10 +244,10 @@ void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
// Handle short strings specially, memcpy isn't very good at very short
// strings.
switch (Size) {
case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH;
case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH;
case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH;
case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH;
case 4: OutBufCur[3] = Ptr[3]; [[fallthrough]];
case 3: OutBufCur[2] = Ptr[2]; [[fallthrough]];
case 2: OutBufCur[1] = Ptr[1]; [[fallthrough]];
case 1: OutBufCur[0] = Ptr[0]; [[fallthrough]];
case 0: break;
default:
memcpy(OutBufCur, Ptr, Size);
@@ -256,7 +263,6 @@ void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) {
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,
@@ -266,12 +272,11 @@ static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C};
// Usually the indentation is small, handle it with a fastpath.
if (NumChars < array_lengthof(Chars))
if (NumChars < std::size(Chars))
return OS.write(Chars, NumChars);
while (NumChars) {
unsigned NumToWrite = std::min(NumChars,
(unsigned)array_lengthof(Chars)-1);
unsigned NumToWrite = std::min(NumChars, (unsigned)std::size(Chars) - 1);
OS.write(Chars, NumToWrite);
NumChars -= NumToWrite;
}
@@ -512,6 +517,14 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
)
continue;
#ifdef _WIN32
// Windows equivalents of SIGPIPE/EPIPE.
DWORD WinLastError = GetLastError();
if (WinLastError == ERROR_BROKEN_PIPE ||
(WinLastError == ERROR_NO_DATA && errno == EINVAL)) {
errno = EPIPE;
}
#endif
// Otherwise it's a non-recoverable error. Note it and quit.
error_detected(std::error_code(errno, std::generic_category()));
break;

View File

@@ -99,6 +99,28 @@ public:
void PrintStats() const {}
};
namespace detail {
template <typename Alloc> class AllocatorHolder : Alloc {
public:
AllocatorHolder() = default;
AllocatorHolder(const Alloc &A) : Alloc(A) {}
AllocatorHolder(Alloc &&A) : Alloc(static_cast<Alloc &&>(A)) {}
Alloc &getAllocator() { return *this; }
const Alloc &getAllocator() const { return *this; }
};
template <typename Alloc> class AllocatorHolder<Alloc &> {
Alloc &A;
public:
AllocatorHolder(Alloc &A) : A(A) {}
Alloc &getAllocator() { return A; }
const Alloc &getAllocator() const { return A; }
};
} // namespace detail
} // namespace wpi
#endif // WPIUTIL_WPI_ALLOCATORBASE_H

View File

@@ -0,0 +1,808 @@
//===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(),
// cast_if_present<X>(), and dyn_cast_if_present<X>() templates.
//
//===----------------------------------------------------------------------===//
#ifndef WPIUTIL_WPI_CASTING_H
#define WPIUTIL_WPI_CASTING_H
#include "wpi/Compiler.h"
#include "wpi/type_traits.h"
#include <cassert>
#include <memory>
#include <optional>
#include <type_traits>
namespace wpi {
//===----------------------------------------------------------------------===//
// simplify_type
//===----------------------------------------------------------------------===//
/// Define a template that can be specialized by smart pointers to reflect the
/// fact that they are automatically dereferenced, and are not involved with the
/// template selection process... the default implementation is a noop.
// TODO: rename this and/or replace it with other cast traits.
template <typename From> struct simplify_type {
using SimpleType = From; // The real type this represents...
// An accessor to get the real value...
static SimpleType &getSimplifiedValue(From &Val) { return Val; }
};
template <typename From> struct simplify_type<const From> {
using NonConstSimpleType = typename simplify_type<From>::SimpleType;
using SimpleType = typename add_const_past_pointer<NonConstSimpleType>::type;
using RetType =
typename add_lvalue_reference_if_not_pointer<SimpleType>::type;
static RetType getSimplifiedValue(const From &Val) {
return simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val));
}
};
// TODO: add this namespace once everyone is switched to using the new
// interface.
// namespace detail {
//===----------------------------------------------------------------------===//
// isa_impl
//===----------------------------------------------------------------------===//
// The core of the implementation of isa<X> is here; To and From should be
// the names of classes. This template can be specialized to customize the
// implementation of isa<> without rewriting it from scratch.
template <typename To, typename From, typename Enabler = void> struct isa_impl {
static inline bool doit(const From &Val) { return To::classof(&Val); }
};
// Always allow upcasts, and perform no dynamic check for them.
template <typename To, typename From>
struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> {
static inline bool doit(const From &) { return true; }
};
template <typename To, typename From> struct isa_impl_cl {
static inline bool doit(const From &Val) {
return isa_impl<To, From>::doit(Val);
}
};
template <typename To, typename From> struct isa_impl_cl<To, const From> {
static inline bool doit(const From &Val) {
return isa_impl<To, From>::doit(Val);
}
};
template <typename To, typename From>
struct isa_impl_cl<To, const std::unique_ptr<From>> {
static inline bool doit(const std::unique_ptr<From> &Val) {
assert(Val && "isa<> used on a null pointer");
return isa_impl_cl<To, From>::doit(*Val);
}
};
template <typename To, typename From> struct isa_impl_cl<To, From *> {
static inline bool doit(const From *Val) {
assert(Val && "isa<> used on a null pointer");
return isa_impl<To, From>::doit(*Val);
}
};
template <typename To, typename From> struct isa_impl_cl<To, From *const> {
static inline bool doit(const From *Val) {
assert(Val && "isa<> used on a null pointer");
return isa_impl<To, From>::doit(*Val);
}
};
template <typename To, typename From> struct isa_impl_cl<To, const From *> {
static inline bool doit(const From *Val) {
assert(Val && "isa<> used on a null pointer");
return isa_impl<To, From>::doit(*Val);
}
};
template <typename To, typename From>
struct isa_impl_cl<To, const From *const> {
static inline bool doit(const From *Val) {
assert(Val && "isa<> used on a null pointer");
return isa_impl<To, From>::doit(*Val);
}
};
template <typename To, typename From, typename SimpleFrom>
struct isa_impl_wrap {
// When From != SimplifiedType, we can simplify the type some more by using
// the simplify_type template.
static bool doit(const From &Val) {
return isa_impl_wrap<To, SimpleFrom,
typename simplify_type<SimpleFrom>::SimpleType>::
doit(simplify_type<const From>::getSimplifiedValue(Val));
}
};
template <typename To, typename FromTy>
struct isa_impl_wrap<To, FromTy, FromTy> {
// When From == SimpleType, we are as simple as we are going to get.
static bool doit(const FromTy &Val) {
return isa_impl_cl<To, FromTy>::doit(Val);
}
};
//===----------------------------------------------------------------------===//
// cast_retty + cast_retty_impl
//===----------------------------------------------------------------------===//
template <class To, class From> struct cast_retty;
// Calculate what type the 'cast' function should return, based on a requested
// type of To and a source type of From.
template <class To, class From> struct cast_retty_impl {
using ret_type = To &; // Normal case, return Ty&
};
template <class To, class From> struct cast_retty_impl<To, const From> {
using ret_type = const To &; // Normal case, return Ty&
};
template <class To, class From> struct cast_retty_impl<To, From *> {
using ret_type = To *; // Pointer arg case, return Ty*
};
template <class To, class From> struct cast_retty_impl<To, const From *> {
using ret_type = const To *; // Constant pointer arg case, return const Ty*
};
template <class To, class From> struct cast_retty_impl<To, const From *const> {
using ret_type = const To *; // Constant pointer arg case, return const Ty*
};
template <class To, class From>
struct cast_retty_impl<To, std::unique_ptr<From>> {
private:
using PointerType = typename cast_retty_impl<To, From *>::ret_type;
using ResultType = std::remove_pointer_t<PointerType>;
public:
using ret_type = std::unique_ptr<ResultType>;
};
template <class To, class From, class SimpleFrom> struct cast_retty_wrap {
// When the simplified type and the from type are not the same, use the type
// simplifier to reduce the type, then reuse cast_retty_impl to get the
// resultant type.
using ret_type = typename cast_retty<To, SimpleFrom>::ret_type;
};
template <class To, class FromTy> struct cast_retty_wrap<To, FromTy, FromTy> {
// When the simplified type is equal to the from type, use it directly.
using ret_type = typename cast_retty_impl<To, FromTy>::ret_type;
};
template <class To, class From> struct cast_retty {
using ret_type = typename cast_retty_wrap<
To, From, typename simplify_type<From>::SimpleType>::ret_type;
};
//===----------------------------------------------------------------------===//
// cast_convert_val
//===----------------------------------------------------------------------===//
// Ensure the non-simple values are converted using the simplify_type template
// that may be specialized by smart pointers...
//
template <class To, class From, class SimpleFrom> struct cast_convert_val {
// This is not a simple type, use the template to simplify it...
static typename cast_retty<To, From>::ret_type doit(const From &Val) {
return cast_convert_val<To, SimpleFrom,
typename simplify_type<SimpleFrom>::SimpleType>::
doit(simplify_type<From>::getSimplifiedValue(const_cast<From &>(Val)));
}
};
template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> {
// If it's a reference, switch to a pointer to do the cast and then deref it.
static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type>
*)&const_cast<FromTy &>(Val);
}
};
template <class To, class FromTy>
struct cast_convert_val<To, FromTy *, FromTy *> {
// If it's a pointer, we can use c-style casting directly.
static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) {
return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>(
Val);
}
};
//===----------------------------------------------------------------------===//
// is_simple_type
//===----------------------------------------------------------------------===//
template <class X> struct is_simple_type {
static const bool value =
std::is_same<X, typename simplify_type<X>::SimpleType>::value;
};
// } // namespace detail
//===----------------------------------------------------------------------===//
// CastIsPossible
//===----------------------------------------------------------------------===//
/// This struct provides a way to check if a given cast is possible. It provides
/// a static function called isPossible that is used to check if a cast can be
/// performed. It should be overridden like this:
///
/// template<> struct CastIsPossible<foo, bar> {
/// static inline bool isPossible(const bar &b) {
/// return bar.isFoo();
/// }
/// };
template <typename To, typename From, typename Enable = void>
struct CastIsPossible {
static inline bool isPossible(const From &f) {
return isa_impl_wrap<
To, const From,
typename simplify_type<const From>::SimpleType>::doit(f);
}
};
// Needed for optional unwrapping. This could be implemented with isa_impl, but
// we want to implement things in the new method and move old implementations
// over. In fact, some of the isa_impl templates should be moved over to
// CastIsPossible.
template <typename To, typename From>
struct CastIsPossible<To, std::optional<From>> {
static inline bool isPossible(const std::optional<From> &f) {
assert(f && "CastIsPossible::isPossible called on a nullopt!");
return isa_impl_wrap<
To, const From,
typename simplify_type<const From>::SimpleType>::doit(*f);
}
};
/// Upcasting (from derived to base) and casting from a type to itself should
/// always be possible.
template <typename To, typename From>
struct CastIsPossible<To, From,
std::enable_if_t<std::is_base_of<To, From>::value>> {
static inline bool isPossible(const From &f) { return true; }
};
//===----------------------------------------------------------------------===//
// Cast traits
//===----------------------------------------------------------------------===//
/// All of these cast traits are meant to be implementations for useful casts
/// that users may want to use that are outside the standard behavior. An
/// example of how to use a special cast called `CastTrait` is:
///
/// template<> struct CastInfo<foo, bar> : public CastTrait<foo, bar> {};
///
/// Essentially, if your use case falls directly into one of the use cases
/// supported by a given cast trait, simply inherit your special CastInfo
/// directly from one of these to avoid having to reimplement the boilerplate
/// `isPossible/castFailed/doCast/doCastIfPossible`. A cast trait can also
/// provide a subset of those functions.
/// This cast trait just provides castFailed for the specified `To` type to make
/// CastInfo specializations more declarative. In order to use this, the target
/// result type must be `To` and `To` must be constructible from `nullptr`.
template <typename To> struct NullableValueCastFailed {
static To castFailed() { return To(nullptr); }
};
/// This cast trait just provides the default implementation of doCastIfPossible
/// to make CastInfo specializations more declarative. The `Derived` template
/// parameter *must* be provided for forwarding castFailed and doCast.
template <typename To, typename From, typename Derived>
struct DefaultDoCastIfPossible {
static To doCastIfPossible(From f) {
if (!Derived::isPossible(f))
return Derived::castFailed();
return Derived::doCast(f);
}
};
namespace detail {
/// A helper to derive the type to use with `Self` for cast traits, when the
/// provided CRTP derived type is allowed to be void.
template <typename OptionalDerived, typename Default>
using SelfType = std::conditional_t<std::is_same<OptionalDerived, void>::value,
Default, OptionalDerived>;
} // namespace detail
/// This cast trait provides casting for the specific case of casting to a
/// value-typed object from a pointer-typed object. Note that `To` must be
/// nullable/constructible from a pointer to `From` to use this cast.
template <typename To, typename From, typename Derived = void>
struct ValueFromPointerCast
: public CastIsPossible<To, From *>,
public NullableValueCastFailed<To>,
public DefaultDoCastIfPossible<
To, From *,
detail::SelfType<Derived, ValueFromPointerCast<To, From>>> {
static inline To doCast(From *f) { return To(f); }
};
/// This cast trait provides std::unique_ptr casting. It has the semantics of
/// moving the contents of the input unique_ptr into the output unique_ptr
/// during the cast. It's also a good example of how to implement a move-only
/// cast.
template <typename To, typename From, typename Derived = void>
struct UniquePtrCast : public CastIsPossible<To, From *> {
using Self = detail::SelfType<Derived, UniquePtrCast<To, From>>;
using CastResultType = std::unique_ptr<
std::remove_reference_t<typename cast_retty<To, From>::ret_type>>;
static inline CastResultType doCast(std::unique_ptr<From> &&f) {
return CastResultType((typename CastResultType::element_type *)f.release());
}
static inline CastResultType castFailed() { return CastResultType(nullptr); }
static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
if (!Self::isPossible(f))
return castFailed();
return doCast(f);
}
};
/// This cast trait provides std::optional<T> casting. This means that if you
/// have a value type, you can cast it to another value type and have dyn_cast
/// return an std::optional<T>.
template <typename To, typename From, typename Derived = void>
struct OptionalValueCast
: public CastIsPossible<To, From>,
public DefaultDoCastIfPossible<
std::optional<To>, From,
detail::SelfType<Derived, OptionalValueCast<To, From>>> {
static inline std::optional<To> castFailed() { return std::optional<To>{}; }
static inline std::optional<To> doCast(const From &f) { return To(f); }
};
/// Provides a cast trait that strips `const` from types to make it easier to
/// implement a const-version of a non-const cast. It just removes boilerplate
/// and reduces the amount of code you as the user need to implement. You can
/// use it like this:
///
/// template<> struct CastInfo<foo, bar> {
/// ...verbose implementation...
/// };
///
/// template<> struct CastInfo<foo, const bar> : public
/// ConstStrippingForwardingCast<foo, const bar, CastInfo<foo, bar>> {};
///
template <typename To, typename From, typename ForwardTo>
struct ConstStrippingForwardingCast {
// Remove the pointer if it exists, then we can get rid of consts/volatiles.
using DecayedFrom = std::remove_cv_t<std::remove_pointer_t<From>>;
// Now if it's a pointer, add it back. Otherwise, we want a ref.
using NonConstFrom = std::conditional_t<std::is_pointer<From>::value,
DecayedFrom *, DecayedFrom &>;
static inline bool isPossible(const From &f) {
return ForwardTo::isPossible(const_cast<NonConstFrom>(f));
}
static inline decltype(auto) castFailed() { return ForwardTo::castFailed(); }
static inline decltype(auto) doCast(const From &f) {
return ForwardTo::doCast(const_cast<NonConstFrom>(f));
}
static inline decltype(auto) doCastIfPossible(const From &f) {
return ForwardTo::doCastIfPossible(const_cast<NonConstFrom>(f));
}
};
/// Provides a cast trait that uses a defined pointer to pointer cast as a base
/// for reference-to-reference casts. Note that it does not provide castFailed
/// and doCastIfPossible because a pointer-to-pointer cast would likely just
/// return `nullptr` which could cause nullptr dereference. You can use it like
/// this:
///
/// template <> struct CastInfo<foo, bar *> { ... verbose implementation... };
///
/// template <>
/// struct CastInfo<foo, bar>
/// : public ForwardToPointerCast<foo, bar, CastInfo<foo, bar *>> {};
///
template <typename To, typename From, typename ForwardTo>
struct ForwardToPointerCast {
static inline bool isPossible(const From &f) {
return ForwardTo::isPossible(&f);
}
static inline decltype(auto) doCast(const From &f) {
return *ForwardTo::doCast(&f);
}
};
//===----------------------------------------------------------------------===//
// CastInfo
//===----------------------------------------------------------------------===//
/// This struct provides a method for customizing the way a cast is performed.
/// It inherits from CastIsPossible, to support the case of declaring many
/// CastIsPossible specializations without having to specialize the full
/// CastInfo.
///
/// In order to specialize different behaviors, specify different functions in
/// your CastInfo specialization.
/// For isa<> customization, provide:
///
/// `static bool isPossible(const From &f)`
///
/// For cast<> customization, provide:
///
/// `static To doCast(const From &f)`
///
/// For dyn_cast<> and the *_if_present<> variants' customization, provide:
///
/// `static To castFailed()` and `static To doCastIfPossible(const From &f)`
///
/// Your specialization might look something like this:
///
/// template<> struct CastInfo<foo, bar> : public CastIsPossible<foo, bar> {
/// static inline foo doCast(const bar &b) {
/// return foo(const_cast<bar &>(b));
/// }
/// static inline foo castFailed() { return foo(); }
/// static inline foo doCastIfPossible(const bar &b) {
/// if (!CastInfo<foo, bar>::isPossible(b))
/// return castFailed();
/// return doCast(b);
/// }
/// };
// The default implementations of CastInfo don't use cast traits for now because
// we need to specify types all over the place due to the current expected
// casting behavior and the way cast_retty works. New use cases can and should
// take advantage of the cast traits whenever possible!
template <typename To, typename From, typename Enable = void>
struct CastInfo : public CastIsPossible<To, From> {
using Self = CastInfo<To, From, Enable>;
using CastReturnType = typename cast_retty<To, From>::ret_type;
static inline CastReturnType doCast(const From &f) {
return cast_convert_val<
To, From,
typename simplify_type<From>::SimpleType>::doit(const_cast<From &>(f));
}
// This assumes that you can construct the cast return type from `nullptr`.
// This is largely to support legacy use cases - if you don't want this
// behavior you should specialize CastInfo for your use case.
static inline CastReturnType castFailed() { return CastReturnType(nullptr); }
static inline CastReturnType doCastIfPossible(const From &f) {
if (!Self::isPossible(f))
return castFailed();
return doCast(f);
}
};
/// This struct provides an overload for CastInfo where From has simplify_type
/// defined. This simply forwards to the appropriate CastInfo with the
/// simplified type/value, so you don't have to implement both.
template <typename To, typename From>
struct CastInfo<To, From, std::enable_if_t<!is_simple_type<From>::value>> {
using Self = CastInfo<To, From>;
using SimpleFrom = typename simplify_type<From>::SimpleType;
using SimplifiedSelf = CastInfo<To, SimpleFrom>;
static inline bool isPossible(From &f) {
return SimplifiedSelf::isPossible(
simplify_type<From>::getSimplifiedValue(f));
}
static inline decltype(auto) doCast(From &f) {
return SimplifiedSelf::doCast(simplify_type<From>::getSimplifiedValue(f));
}
static inline decltype(auto) castFailed() {
return SimplifiedSelf::castFailed();
}
static inline decltype(auto) doCastIfPossible(From &f) {
return SimplifiedSelf::doCastIfPossible(
simplify_type<From>::getSimplifiedValue(f));
}
};
//===----------------------------------------------------------------------===//
// Pre-specialized CastInfo
//===----------------------------------------------------------------------===//
/// Provide a CastInfo specialized for std::unique_ptr.
template <typename To, typename From>
struct CastInfo<To, std::unique_ptr<From>> : public UniquePtrCast<To, From> {};
/// Provide a CastInfo specialized for std::optional<From>. It's assumed that if
/// the input is std::optional<From> that the output can be std::optional<To>.
/// If that's not the case, specialize CastInfo for your use case.
template <typename To, typename From>
struct CastInfo<To, std::optional<From>> : public OptionalValueCast<To, From> {
};
/// isa<X> - Return true if the parameter to the template is an instance of one
/// of the template type arguments. Used like this:
///
/// if (isa<Type>(myVal)) { ... }
/// if (isa<Type0, Type1, Type2>(myVal)) { ... }
template <typename To, typename From>
[[nodiscard]] inline bool isa(const From &Val) {
return CastInfo<To, const From>::isPossible(Val);
}
template <typename First, typename Second, typename... Rest, typename From>
[[nodiscard]] inline bool isa(const From &Val) {
return isa<First>(Val) || isa<Second, Rest...>(Val);
}
/// cast<X> - Return the argument parameter cast to the specified type. This
/// casting operator asserts that the type is correct, so it does not return
/// null on failure. It does not allow a null argument (use cast_if_present for
/// that). It is typically used like this:
///
/// cast<Instruction>(myVal)->getParent()
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) cast(const From &Val) {
assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
return CastInfo<To, const From>::doCast(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) cast(From &Val) {
assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
return CastInfo<To, From>::doCast(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) cast(From *Val) {
assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
return CastInfo<To, From *>::doCast(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) cast(std::unique_ptr<From> &&Val) {
assert(isa<To>(Val) && "cast<Ty>() argument of incompatible type!");
return CastInfo<To, std::unique_ptr<From>>::doCast(std::move(Val));
}
//===----------------------------------------------------------------------===//
// ValueIsPresent
//===----------------------------------------------------------------------===//
template <typename T>
constexpr bool IsNullable =
std::is_pointer_v<T> || std::is_constructible_v<T, std::nullptr_t>;
/// ValueIsPresent provides a way to check if a value is, well, present. For
/// pointers, this is the equivalent of checking against nullptr, for Optionals
/// this is the equivalent of checking hasValue(). It also provides a method for
/// unwrapping a value (think calling .value() on an optional).
// Generic values can't *not* be present.
template <typename T, typename Enable = void> struct ValueIsPresent {
using UnwrappedType = T;
static inline bool isPresent(const T &t) { return true; }
static inline decltype(auto) unwrapValue(T &t) { return t; }
};
// Optional provides its own way to check if something is present.
template <typename T> struct ValueIsPresent<std::optional<T>> {
using UnwrappedType = T;
static inline bool isPresent(const std::optional<T> &t) {
return t.has_value();
}
static inline decltype(auto) unwrapValue(std::optional<T> &t) { return *t; }
};
// If something is "nullable" then we just compare it to nullptr to see if it
// exists.
template <typename T>
struct ValueIsPresent<T, std::enable_if_t<IsNullable<T>>> {
using UnwrappedType = T;
static inline bool isPresent(const T &t) { return t != T(nullptr); }
static inline decltype(auto) unwrapValue(T &t) { return t; }
};
namespace detail {
// Convenience function we can use to check if a value is present. Because of
// simplify_type, we have to call it on the simplified type for now.
template <typename T> inline bool isPresent(const T &t) {
return ValueIsPresent<typename simplify_type<T>::SimpleType>::isPresent(
simplify_type<T>::getSimplifiedValue(const_cast<T &>(t)));
}
// Convenience function we can use to unwrap a value.
template <typename T> inline decltype(auto) unwrapValue(T &t) {
return ValueIsPresent<T>::unwrapValue(t);
}
} // namespace detail
/// dyn_cast<X> - Return the argument parameter cast to the specified type. This
/// casting operator returns null if the argument is of the wrong type, so it
/// can be used to test for a type as well as cast if successful. The value
/// passed in must be present, if not, use dyn_cast_if_present. This should be
/// used in the context of an if statement like this:
///
/// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) dyn_cast(const From &Val) {
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
return CastInfo<To, const From>::doCastIfPossible(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) dyn_cast(From &Val) {
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
return CastInfo<To, From>::doCastIfPossible(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) dyn_cast(From *Val) {
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
return CastInfo<To, From *>::doCastIfPossible(Val);
}
template <typename To, typename From>
[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
std::forward<std::unique_ptr<From> &&>(Val));
}
/// isa_and_present<X> - Functionally identical to isa, except that a null value
/// is accepted.
template <typename... X, class Y>
[[nodiscard]] inline bool isa_and_present(const Y &Val) {
if (!detail::isPresent(Val))
return false;
return isa<X...>(Val);
}
template <typename... X, class Y>
[[nodiscard]] inline bool isa_and_nonnull(const Y &Val) {
return isa_and_present<X...>(Val);
}
/// cast_if_present<X> - Functionally identical to cast, except that a null
/// value is accepted.
template <class X, class Y>
[[nodiscard]] inline auto cast_if_present(const Y &Val) {
if (!detail::isPresent(Val))
return CastInfo<X, const Y>::castFailed();
assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
return cast<X>(detail::unwrapValue(Val));
}
template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y &Val) {
if (!detail::isPresent(Val))
return CastInfo<X, Y>::castFailed();
assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
return cast<X>(detail::unwrapValue(Val));
}
template <class X, class Y> [[nodiscard]] inline auto cast_if_present(Y *Val) {
if (!detail::isPresent(Val))
return CastInfo<X, Y *>::castFailed();
assert(isa<X>(Val) && "cast_if_present<Ty>() argument of incompatible type!");
return cast<X>(detail::unwrapValue(Val));
}
template <class X, class Y>
[[nodiscard]] inline auto cast_if_present(std::unique_ptr<Y> &&Val) {
if (!detail::isPresent(Val))
return UniquePtrCast<X, Y>::castFailed();
return UniquePtrCast<X, Y>::doCast(std::move(Val));
}
// Provide a forwarding from cast_or_null to cast_if_present for current
// users. This is deprecated and will be removed in a future patch, use
// cast_if_present instead.
template <class X, class Y> auto cast_or_null(const Y &Val) {
return cast_if_present<X>(Val);
}
template <class X, class Y> auto cast_or_null(Y &Val) {
return cast_if_present<X>(Val);
}
template <class X, class Y> auto cast_or_null(Y *Val) {
return cast_if_present<X>(Val);
}
template <class X, class Y> auto cast_or_null(std::unique_ptr<Y> &&Val) {
return cast_if_present<X>(std::move(Val));
}
/// dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a
/// null (or none in the case of optionals) value is accepted.
template <class X, class Y> auto dyn_cast_if_present(const Y &Val) {
if (!detail::isPresent(Val))
return CastInfo<X, const Y>::castFailed();
return CastInfo<X, const Y>::doCastIfPossible(detail::unwrapValue(Val));
}
template <class X, class Y> auto dyn_cast_if_present(Y &Val) {
if (!detail::isPresent(Val))
return CastInfo<X, Y>::castFailed();
return CastInfo<X, Y>::doCastIfPossible(detail::unwrapValue(Val));
}
template <class X, class Y> auto dyn_cast_if_present(Y *Val) {
if (!detail::isPresent(Val))
return CastInfo<X, Y *>::castFailed();
return CastInfo<X, Y *>::doCastIfPossible(detail::unwrapValue(Val));
}
// Forwards to dyn_cast_if_present to avoid breaking current users. This is
// deprecated and will be removed in a future patch, use
// cast_if_present instead.
template <class X, class Y> auto dyn_cast_or_null(const Y &Val) {
return dyn_cast_if_present<X>(Val);
}
template <class X, class Y> auto dyn_cast_or_null(Y &Val) {
return dyn_cast_if_present<X>(Val);
}
template <class X, class Y> auto dyn_cast_or_null(Y *Val) {
return dyn_cast_if_present<X>(Val);
}
/// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
/// taking ownership of the input pointer iff isa<X>(Val) is true. If the
/// cast is successful, From refers to nullptr on exit and the casted value
/// is returned. If the cast is unsuccessful, the function returns nullptr
/// and From is unchanged.
template <class X, class Y>
[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
unique_dyn_cast(std::unique_ptr<Y> &Val) {
if (!isa<X>(Val))
return nullptr;
return cast<X>(std::move(Val));
}
template <class X, class Y>
[[nodiscard]] inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast<X, Y>(Val);
}
// unique_dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast,
// except that a null value is accepted.
template <class X, class Y>
[[nodiscard]] inline typename CastInfo<X, std::unique_ptr<Y>>::CastResultType
unique_dyn_cast_or_null(std::unique_ptr<Y> &Val) {
if (!Val)
return nullptr;
return unique_dyn_cast<X, Y>(Val);
}
template <class X, class Y>
[[nodiscard]] inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast_or_null<X, Y>(Val);
}
} // end namespace wpi
#endif // WPIUTIL_WPI_CASTING_H

View File

@@ -38,6 +38,10 @@
# define __has_builtin(x) 0
#endif
#ifndef __has_include
# define __has_include(x) 0
#endif
// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
#ifndef LLVM_HAS_CPP_ATTRIBUTE
@@ -101,26 +105,6 @@
#endif
#endif
/// Does the compiler support ref-qualifiers for *this?
///
/// 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.
/// FIXME: Remove LLVM_HAS_RVALUE_REFERENCE_THIS macro
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
/// Expands to '&' if ref-qualifiers for *this are supported.
///
/// This can be used to provide lvalue/rvalue overrides of member functions.
/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
#ifndef LLVM_LVALUE_FUNCTION
#if LLVM_HAS_RVALUE_REFERENCE_THIS
#define LLVM_LVALUE_FUNCTION &
#else
#define LLVM_LVALUE_FUNCTION
#endif
#endif
/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
/// into a shared library, then the class should be private to the library and
/// not accessible from outside it. Can also be used to mark variables and
@@ -130,8 +114,9 @@
/// 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) && !defined(__MINGW32__) && \
!defined(__CYGWIN__) && !defined(_WIN32)
#if __has_attribute(visibility) && \
(!(defined(_WIN32) || defined(__CYGWIN__)) || \
(defined(__MINGW32__) && defined(__clang__)))
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
@@ -159,23 +144,10 @@
#endif
#endif
/// LLVM_NODISCARD - Warn if a type or return value is discarded.
// Use the 'nodiscard' attribute in C++17 or newer mode.
#ifndef LLVM_NODISCARD
#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
#define LLVM_NODISCARD [[nodiscard]]
#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
#define LLVM_NODISCARD [[clang::warn_unused_result]]
// Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also
// warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518).
// Use the 'nodiscard' attribute in C++14 mode only with GCC.
// TODO: remove this workaround when PR33518 is resolved.
#elif defined(__GNUC__) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
#define LLVM_NODISCARD [[nodiscard]]
#if defined(__clang__)
#define LLVM_DEPRECATED(MSG, FIX) __attribute__((deprecated(MSG, FIX)))
#else
#define LLVM_NODISCARD
#endif
#define LLVM_DEPRECATED(MSG, FIX) [[deprecated(MSG)]]
#endif
// Indicate that a non-static, non-const C++ member function reinitializes
@@ -356,23 +328,18 @@
#endif
#endif
// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
// This macro will be removed.
// Use C++14's attribute instead: [[deprecated("message")]]
#ifndef LLVM_ATTRIBUTE_DEPRECATED
#define LLVM_ATTRIBUTE_DEPRECATED(decl, message) [[deprecated(message)]] decl
#endif
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
/// compiler to reach this point. Otherwise is not defined.
///
/// '#else' is intentionally left out so that other macro logic (e.g.,
/// LLVM_ASSUME_ALIGNED and wpi_unreachable()) can detect whether
/// LLVM_BUILTIN_UNREACHABLE has a definition.
#ifndef LLVM_BUILTIN_UNREACHABLE
#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
@@ -454,24 +421,6 @@
#endif
#endif
/// \macro LLVM_PTR_SIZE
/// A constant integer equivalent to the value of sizeof(void*).
/// Generally used in combination with alignas or when doing computation in the
/// preprocessor.
#ifndef LLVM_PTR_SIZE
#ifdef __SIZEOF_POINTER__
# define LLVM_PTR_SIZE __SIZEOF_POINTER__
#elif defined(_WIN64)
# define LLVM_PTR_SIZE 8
#elif defined(_WIN32)
# define LLVM_PTR_SIZE 4
#elif defined(_MSC_VER)
# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
#else
# define LLVM_PTR_SIZE sizeof(void *)
#endif
#endif
/// \macro LLVM_MEMORY_SANITIZER_BUILD
/// Whether LLVM itself is built with MemorySanitizer instrumentation.
#if __has_feature(memory_sanitizer)
@@ -489,13 +438,34 @@
/// Whether LLVM itself is built with AddressSanitizer instrumentation.
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
# define LLVM_ADDRESS_SANITIZER_BUILD 1
#if __has_include(<sanitizer/asan_interface.h>)
# include <sanitizer/asan_interface.h>
#else
// These declarations exist to support ASan with MSVC. If MSVC eventually ships
// asan_interface.h in their headers, then we can remove this.
#ifdef __cplusplus
extern "C" {
#endif
void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
#else
# define LLVM_ADDRESS_SANITIZER_BUILD 0
# define __asan_poison_memory_region(p, size)
# define __asan_unpoison_memory_region(p, size)
#endif
/// \macro LLVM_HWADDRESS_SANITIZER_BUILD
/// Whether LLVM itself is built with HWAddressSanitizer instrumentation.
#if __has_feature(hwaddress_sanitizer)
#define LLVM_HWADDRESS_SANITIZER_BUILD 1
#else
#define LLVM_HWADDRESS_SANITIZER_BUILD 0
#endif
/// \macro LLVM_THREAD_SANITIZER_BUILD
/// Whether LLVM itself is built with ThreadSanitizer instrumentation.
#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)

View File

@@ -6,25 +6,41 @@
*
*==------------------------------------------------------------------------==*/
/*
* Copyright 2001-2004 Unicode, Inc.
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in
* http://www.unicode.org/copyright.html.
*
* Disclaimer
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of the Unicode data files and any associated documentation
* (the "Data Files") or Unicode software and any associated documentation
* (the "Software") to deal in the Data Files or Software
* without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, and/or sell copies of
* the Data Files or Software, and to permit persons to whom the Data Files
* or Software are furnished to do so, provided that
* (a) this copyright and permission notice appear with all copies
* of the Data Files or Software,
* (b) this copyright and permission notice appear in associated
* documentation, and
* (c) there is clear notice in each modified Data File or in the Software
* as well as in the documentation associated with the Data File(s) or
* Software that the data or software has been modified.
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in these Data Files or Software without prior
* written authorization of the copyright holder.
*/
/* ---------------------------------------------------------------------
@@ -89,10 +105,9 @@
#ifndef WPIUTIL_WPI_CONVERTUTF_H
#define WPIUTIL_WPI_CONVERTUTF_H
#include <span>
#include <cstddef>
#include <string>
#include <span>
#include <string_view>
#include <system_error>
@@ -126,6 +141,9 @@ typedef bool Boolean; /* 0 or 1 */
#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF
#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE
#define UNI_UTF32_BYTE_ORDER_MARK_NATIVE 0x0000FEFF
#define UNI_UTF32_BYTE_ORDER_MARK_SWAPPED 0xFFFE0000
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
@@ -178,6 +196,8 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd);
unsigned getUTF8SequenceSize(const UTF8 *source, const UTF8 *sourceEnd);
unsigned getNumBytesForUTF8(UTF8 firstByte);
/*************************************************************************/
@@ -279,6 +299,24 @@ bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<ch
*/
bool convertUTF16ToUTF8String(std::span<const UTF16> Src, SmallVectorImpl<char> &Out);
/**
* Converts a stream of raw bytes assumed to be UTF32 into a UTF8 std::string.
*
* \param [in] SrcBytes A buffer of what is assumed to be UTF-32 encoded text.
* \param [out] Out Converted UTF-8 is stored here on success.
* \returns true on success
*/
bool convertUTF32ToUTF8String(std::span<const char> SrcBytes, std::string &Out);
/**
* Converts a UTF32 string into a UTF8 std::string.
*
* \param [in] Src A buffer of UTF-32 encoded text.
* \param [out] Out Converted UTF-8 is stored here on success.
* \returns true on success
*/
bool convertUTF32ToUTF8String(std::span<const UTF32> Src, std::string &Out);
/**
* Converts a UTF-8 string into a UTF-16 string with native endianness.
*

View File

@@ -95,9 +95,7 @@ public:
return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
}
LLVM_NODISCARD bool empty() const {
return getNumEntries() == 0;
}
[[nodiscard]] bool empty() const { return getNumEntries() == 0; }
unsigned size() const { return getNumEntries(); }
/// Grow the densemap so that it can contain at least \p NumEntries items
@@ -137,6 +135,7 @@ public:
}
}
assert(NumEntries == 0 && "Node count imbalance!");
(void)NumEntries;
}
setNumEntries(0);
setNumTombstones(0);
@@ -906,6 +905,8 @@ class SmallDenseMap
public:
explicit SmallDenseMap(unsigned NumInitBuckets = 0) {
if (NumInitBuckets > InlineBuckets)
NumInitBuckets = NextPowerOf2(NumInitBuckets - 1);
init(NumInitBuckets);
}
@@ -1196,8 +1197,7 @@ class DenseMapIterator : DebugEpochBase::HandleBase {
public:
using difference_type = ptrdiff_t;
using value_type =
typename std::conditional<IsConst, const Bucket, Bucket>::type;
using value_type = std::conditional_t<IsConst, const Bucket, Bucket>;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;

View File

@@ -18,7 +18,9 @@
#include <cstddef>
#include <cstdint>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
namespace wpi {
@@ -252,7 +254,7 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
template <unsigned I>
static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
using EltType = typename std::tuple_element<I, Tuple>::type;
using EltType = std::tuple_element_t<I, Tuple>;
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
return detail::combineHashValue(
DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
@@ -271,7 +273,7 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
template <unsigned I>
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
using EltType = typename std::tuple_element<I, Tuple>::type;
using EltType = std::tuple_element_t<I, Tuple>;
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
isEqualImpl<I + 1>(lhs, rhs, atEnd);
@@ -288,6 +290,37 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
}
};
// Provide DenseMapInfo for variants whose all alternatives have DenseMapInfo.
template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
using Variant = std::variant<Ts...>;
using FirstT = std::variant_alternative_t<0, Variant>;
static inline Variant getEmptyKey() {
return Variant(std::in_place_index<0>, DenseMapInfo<FirstT>::getEmptyKey());
}
static inline Variant getTombstoneKey() {
return Variant(std::in_place_index<0>,
DenseMapInfo<FirstT>::getTombstoneKey());
}
static unsigned getHashValue(const Variant &Val) {
return std::visit(
[&Val](auto &&Alternative) {
using T = std::decay_t<decltype(Alternative)>;
// Include index in hash to make sure same value as different
// alternatives don't collide.
return detail::combineHashValue(
DenseMapInfo<size_t>::getHashValue(Val.index()),
DenseMapInfo<T>::getHashValue(Alternative));
},
Val);
}
static bool isEqual(const Variant &LHS, const Variant &RHS) {
return LHS == RHS;
}
};
} // end namespace wpi
#endif // WPIUTIL_WPI_DENSEMAPINFO_H

View File

@@ -33,10 +33,10 @@ namespace wpi {
/// is still valid.
///
class DebugEpochBase {
uint64_t Epoch;
uint64_t Epoch = 0;
public:
DebugEpochBase() : Epoch(0) {}
DebugEpochBase() = default;
/// Calling incrementEpoch invalidates all handles pointing into the
/// calling instance.
@@ -55,11 +55,11 @@ public:
/// make an iterator-invalidating modification.
///
class HandleBase {
const uint64_t *EpochAddress;
uint64_t EpochAtCreation;
const uint64_t *EpochAddress = nullptr;
uint64_t EpochAtCreation = UINT64_MAX;
public:
HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
HandleBase() = default;
explicit HandleBase(const DebugEpochBase *Parent)
: EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}

View File

@@ -15,7 +15,6 @@
#include <cerrno>
#include <string>
#include <type_traits>
namespace wpi {
namespace sys {

View File

@@ -123,19 +123,34 @@ wpi_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
/// Marks that the current location is not supposed to be reachable.
/// In !NDEBUG builds, prints the message and location info to stderr.
/// In NDEBUG builds, becomes an optimizer hint that the current location
/// is not supposed to be reachable. On compilers that don't support
/// such hints, prints a reduced message instead and aborts the program.
/// In NDEBUG builds, if the platform does not support a builtin unreachable
/// then we call an internal LLVM runtime function. Otherwise the behavior is
/// controlled by the CMake flag
/// -DLLVM_UNREACHABLE_OPTIMIZE
/// * When "ON" (default) wpi_unreachable() becomes an optimizer hint
/// that the current location is not supposed to be reachable: the hint
/// turns such code path into undefined behavior. On compilers that don't
/// support such hints, prints a reduced message instead and aborts the
/// program.
/// * When "OFF", a builtin_trap is emitted instead of an
// optimizer hint or printing a reduced message.
///
/// Use this instead of assert(0). It conveys intent more clearly and
/// allows compilers to omit some unnecessary code.
/// Use this instead of assert(0). It conveys intent more clearly, suppresses
/// diagnostics for unreachable code paths, and allows compilers to omit
/// unnecessary code.
#ifndef NDEBUG
#define wpi_unreachable(msg) \
::wpi::wpi_unreachable_internal(msg, __FILE__, __LINE__)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
#elif !defined(LLVM_BUILTIN_UNREACHABLE)
#define wpi_unreachable(msg) ::wpi::wpi_unreachable_internal()
#elif LLVM_UNREACHABLE_OPTIMIZE
#define wpi_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
#else
#define wpi_unreachable(msg) ::wpi::wpi_unreachable_internal()
#define wpi_unreachable(msg) \
do { \
LLVM_BUILTIN_TRAP; \
LLVM_BUILTIN_UNREACHABLE; \
} while (false)
#endif
#endif

View File

@@ -72,7 +72,7 @@ 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<wpi::disjunction<
using EnableIfCallable = std::enable_if_t<std::disjunction<
std::is_void<Ret>,
std::is_same<decltype(std::declval<CallableT>()(std::declval<Params>()...)),
Ret>,
@@ -106,11 +106,11 @@ protected:
template <typename T> struct AdjustedParamTBase {
static_assert(!std::is_reference<T>::value,
"references should be handled by template specialization");
using type = typename std::conditional<
using type = std::conditional_t<
wpi::is_trivially_copy_constructible<T>::value &&
wpi::is_trivially_move_constructible<T>::value &&
IsSizeLessThanThresholdT<T>::value,
T, T &>::type;
T, T &>;
};
// This specialization ensures that 'AdjustedParam<V<T>&>' or
@@ -167,9 +167,8 @@ protected:
// provide four pointers worth of storage here.
// This is mutable as an inlined `const unique_function<void() const>` may
// still modify its own mutable members.
mutable
typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type
InlineStorage;
mutable std::aligned_storage_t<InlineStorageSize, alignof(void *)>
InlineStorage;
} StorageUnion;
// A compressed pointer to either our dispatching callback or our table of

View File

@@ -50,6 +50,7 @@
#include <algorithm>
#include <cassert>
#include <cstring>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
@@ -126,6 +127,8 @@ hash_code hash_value(const std::tuple<Ts...> &arg);
template <typename T>
hash_code hash_value(const std::basic_string<T> &arg);
/// Compute a hash_code for a standard string.
template <typename T> hash_code hash_value(const std::optional<T> &arg);
/// Override the execution seed with a fixed value.
///
@@ -655,24 +658,8 @@ hash_code hash_value(const std::pair<T, U> &arg) {
return hash_combine(arg.first, arg.second);
}
// Implementation details for the hash_value overload for std::tuple<...>(...).
namespace hashing {
namespace detail {
template <typename... Ts, std::size_t... Indices>
hash_code hash_value_tuple_helper(const std::tuple<Ts...> &arg,
std::index_sequence<Indices...>) {
return hash_combine(std::get<Indices>(arg)...);
}
} // namespace detail
} // namespace hashing
template <typename... Ts>
hash_code hash_value(const std::tuple<Ts...> &arg) {
// TODO: Use std::apply when LLVM starts using C++17.
return ::wpi::hashing::detail::hash_value_tuple_helper(
arg, typename std::index_sequence_for<Ts...>());
template <typename... Ts> hash_code hash_value(const std::tuple<Ts...> &arg) {
return std::apply([](const auto &...xs) { return hash_combine(xs...); }, arg);
}
// Declared and documented above, but defined here so that any of the hashing
@@ -682,6 +669,10 @@ hash_code hash_value(const std::basic_string<T> &arg) {
return hash_combine_range(arg.begin(), arg.end());
}
template <typename T> hash_code hash_value(const std::optional<T> &arg) {
return arg ? hash_combine(true, *arg) : hash_value(false);
}
template <> struct DenseMapInfo<hash_code, void> {
static inline hash_code getEmptyKey() { return hash_code(-1); }
static inline hash_code getTombstoneKey() { return hash_code(-2); }

View File

@@ -39,7 +39,7 @@ class MapVector {
VectorType Vector;
static_assert(
std::is_integral<typename MapType::mapped_type>::value,
std::is_integral_v<typename MapType::mapped_type>,
"The mapped_type of the specified Map must be an integral type");
public:
@@ -109,7 +109,7 @@ public:
// Returns a copy of the value. Only allowed if ValueT is copyable.
ValueT lookup(const KeyT &Key) const {
static_assert(std::is_copy_constructible<ValueT>::value,
static_assert(std::is_copy_constructible_v<ValueT>,
"Cannot call lookup() if ValueT is not copyable.");
typename MapType::const_iterator Pos = Map.find(Key);
return Pos == Map.end()? ValueT() : Vector[Pos->second].second;

View File

@@ -13,31 +13,16 @@
#ifndef WPIUTIL_WPI_MATHEXTRAS_H
#define WPIUTIL_WPI_MATHEXTRAS_H
#include "wpi/bit.h"
#include "wpi/Compiler.h"
#include <bit>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
#ifdef __ANDROID_NDK__
#include <android/api-level.h>
#endif
#ifdef _MSC_VER
// Declare these intrinsics manually rather including intrin.h. It's very
// expensive, and MathExtras.h is popular.
// #include <intrin.h>
extern "C" {
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
}
#endif
namespace wpi {
/// The behavior an operation has on an input of 0.
@@ -45,152 +30,31 @@ enum ZeroBehavior {
/// The returned value is undefined.
ZB_Undefined,
/// The returned value is numeric_limits<T>::max()
ZB_Max,
/// The returned value is numeric_limits<T>::digits
ZB_Width
ZB_Max
};
namespace detail {
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
static unsigned count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
if (Val & 0x1)
return 0;
// Bisection method.
unsigned ZeroBits = 0;
T Shift = std::numeric_limits<T>::digits >> 1;
T Mask = (std::numeric_limits<T>::max)() >> Shift;
while (Shift) {
if ((Val & Mask) == 0) {
Val >>= Shift;
ZeroBits |= Shift;
}
Shift >>= 1;
Mask >>= Shift;
}
return ZeroBits;
}
};
#if defined(__GNUC__) || defined(_MSC_VER)
template <typename T> struct TrailingZerosCounter<T, 4> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
return __builtin_ctz(Val);
#elif defined(_MSC_VER)
unsigned long Index;
_BitScanForward(&Index, Val);
return Index;
#endif
}
};
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct TrailingZerosCounter<T, 8> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
return __builtin_ctzll(Val);
#elif defined(_MSC_VER)
unsigned long Index;
_BitScanForward64(&Index, Val);
return Index;
#endif
}
};
#endif
#endif
} // namespace detail
/// Count number of 0's from the least significant bit to the most
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
/// Returns std::numeric_limits<T>::digits on an input of 0.
template <typename T> unsigned countTrailingZeros(T Val) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
return wpi::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
return std::countr_zero(Val);
}
namespace detail {
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
static unsigned count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
// Bisection method.
unsigned ZeroBits = 0;
for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
T Tmp = Val >> Shift;
if (Tmp)
Val = Tmp;
else
ZeroBits |= Shift;
}
return ZeroBits;
}
};
#if defined(__GNUC__) || defined(_MSC_VER)
template <typename T> struct LeadingZerosCounter<T, 4> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
#if __has_builtin(__builtin_clz) || defined(__GNUC__)
return __builtin_clz(Val);
#elif defined(_MSC_VER)
unsigned long Index;
_BitScanReverse(&Index, Val);
return Index ^ 31;
#endif
}
};
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct LeadingZerosCounter<T, 8> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
return __builtin_clzll(Val);
#elif defined(_MSC_VER)
unsigned long Index;
_BitScanReverse64(&Index, Val);
return Index ^ 63;
#endif
}
};
#endif
#endif
} // namespace detail
/// Count number of 0's from the most significant bit to the least
/// stopping at the first 1.
///
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
/// Returns std::numeric_limits<T>::digits on an input of 0.
template <typename T> unsigned countLeadingZeros(T Val) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
return wpi::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
return std::countl_zero(Val);
}
/// Get the index of the first set bit starting from the least
@@ -198,13 +62,12 @@ unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
///
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
/// \param ZB the behavior on an input of 0.
template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return (std::numeric_limits<T>::max)();
return countTrailingZeros(Val, ZB_Undefined);
return std::countr_zero(Val);
}
/// Create a bitmask with the N right-most bits set to 1, and all other
@@ -239,16 +102,14 @@ template <typename T> T maskLeadingZeros(unsigned N) {
///
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
/// \param ZB the behavior on an input of 0.
template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return (std::numeric_limits<T>::max)();
// Use ^ instead of - because both gcc and llvm can remove the associated ^
// in the __builtin_clz intrinsic on x86.
return countLeadingZeros(Val, ZB_Undefined) ^
(std::numeric_limits<T>::digits - 1);
return std::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
}
/// Macro compressed bit reversal table for 256 bits.
@@ -265,8 +126,24 @@ static const unsigned char BitReverseTable256[256] = {
};
/// Reverse the bits in \p Val.
template <typename T>
T reverseBits(T Val) {
template <typename T> T reverseBits(T Val) {
#if __has_builtin(__builtin_bitreverse8)
if constexpr (std::is_same_v<T, uint8_t>)
return __builtin_bitreverse8(Val);
#endif
#if __has_builtin(__builtin_bitreverse16)
if constexpr (std::is_same_v<T, uint16_t>)
return __builtin_bitreverse16(Val);
#endif
#if __has_builtin(__builtin_bitreverse32)
if constexpr (std::is_same_v<T, uint32_t>)
return __builtin_bitreverse32(Val);
#endif
#if __has_builtin(__builtin_bitreverse64)
if constexpr (std::is_same_v<T, uint64_t>)
return __builtin_bitreverse64(Val);
#endif
unsigned char in[sizeof(Val)];
unsigned char out[sizeof(Val)];
std::memcpy(in, &Val, sizeof(Val));
@@ -276,34 +153,6 @@ T reverseBits(T Val) {
return Val;
}
#if __has_builtin(__builtin_bitreverse8)
template<>
inline uint8_t reverseBits<uint8_t>(uint8_t Val) {
return __builtin_bitreverse8(Val);
}
#endif
#if __has_builtin(__builtin_bitreverse16)
template<>
inline uint16_t reverseBits<uint16_t>(uint16_t Val) {
return __builtin_bitreverse16(Val);
}
#endif
#if __has_builtin(__builtin_bitreverse32)
template<>
inline uint32_t reverseBits<uint32_t>(uint32_t Val) {
return __builtin_bitreverse32(Val);
}
#endif
#if __has_builtin(__builtin_bitreverse64)
template<>
inline uint64_t reverseBits<uint64_t>(uint64_t Val) {
return __builtin_bitreverse64(Val);
}
#endif
// NOTE: The following support functions use the _32/_64 extensions instead of
// type overloading so that signed and unsigned integers can be used without
// ambiguity.
@@ -325,17 +174,16 @@ constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
/// Checks if an integer fits into the given bit width.
template <unsigned N> constexpr inline bool isInt(int64_t x) {
return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
}
// Template specializations to get better code for common cases.
template <> constexpr inline bool isInt<8>(int64_t x) {
return static_cast<int8_t>(x) == x;
}
template <> constexpr inline bool isInt<16>(int64_t x) {
return static_cast<int16_t>(x) == x;
}
template <> constexpr inline bool isInt<32>(int64_t x) {
return static_cast<int32_t>(x) == x;
if constexpr (N == 8)
return static_cast<int8_t>(x) == x;
if constexpr (N == 16)
return static_cast<int16_t>(x) == x;
if constexpr (N == 32)
return static_cast<int32_t>(x) == x;
if constexpr (N < 64)
return -(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1));
(void)x; // MSVC v19.25 warns that x is unused.
return true;
}
/// Checks if a signed integer is an N bit number shifted left by S.
@@ -348,34 +196,20 @@ constexpr inline bool isShiftedInt(int64_t x) {
}
/// Checks if an unsigned integer fits into the given bit width.
///
/// This is written as two functions rather than as simply
///
/// return N >= 64 || X < (UINT64_C(1) << N);
///
/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
/// left too many places.
template <unsigned N>
constexpr inline std::enable_if_t<(N < 64), bool> isUInt(uint64_t X) {
template <unsigned N> constexpr inline bool isUInt(uint64_t x) {
static_assert(N > 0, "isUInt<0> doesn't make sense");
return X < (UINT64_C(1) << (N));
}
template <unsigned N>
constexpr inline std::enable_if_t<N >= 64, bool> isUInt(uint64_t) {
if constexpr (N == 8)
return static_cast<uint8_t>(x) == x;
if constexpr (N == 16)
return static_cast<uint16_t>(x) == x;
if constexpr (N == 32)
return static_cast<uint32_t>(x) == x;
if constexpr (N < 64)
return x < (UINT64_C(1) << (N));
(void)x; // MSVC v19.25 warns that x is unused.
return true;
}
// Template specializations to get better code for common cases.
template <> constexpr inline bool isUInt<8>(uint64_t x) {
return static_cast<uint8_t>(x) == x;
}
template <> constexpr inline bool isUInt<16>(uint64_t x) {
return static_cast<uint16_t>(x) == x;
}
template <> constexpr inline bool isUInt<32>(uint64_t x) {
return static_cast<uint32_t>(x) == x;
}
/// Checks if a unsigned integer is an N bit number shifted left by S.
template <unsigned N, unsigned S>
constexpr inline bool isShiftedUInt(uint64_t x) {
@@ -462,12 +296,12 @@ constexpr inline bool isShiftedMask_64(uint64_t Value) {
/// Return true if the argument is a power of two > 0.
/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
constexpr inline bool isPowerOf2_32(uint32_t Value) {
return Value && !(Value & (Value - 1));
return std::has_single_bit(Value);
}
/// Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr inline bool isPowerOf2_64(uint64_t Value) {
return Value && !(Value & (Value - 1));
return std::has_single_bit(Value);
}
/// Count the number of ones from the most significant bit to the first
@@ -476,14 +310,11 @@ constexpr inline bool isPowerOf2_64(uint64_t Value) {
/// Ex. countLeadingOnes(0xFF0FFF00) == 8.
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of all ones. Only ZB_Width and
/// ZB_Undefined are valid arguments.
template <typename T>
unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
/// Returns std::numeric_limits<T>::digits on an input of all ones.
template <typename T> unsigned countLeadingOnes(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
return countLeadingZeros<T>(~Value, ZB);
return std::countl_one<T>(Value);
}
/// Count the number of ones from the least significant bit to the first
@@ -492,56 +323,48 @@ unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
/// Ex. countTrailingOnes(0x00FF00FF) == 8.
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of all ones. Only ZB_Width and
/// ZB_Undefined are valid arguments.
template <typename T>
unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
/// Returns std::numeric_limits<T>::digits on an input of all ones.
template <typename T> unsigned countTrailingOnes(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
return countTrailingZeros<T>(~Value, ZB);
return std::countr_one<T>(Value);
}
namespace detail {
template <typename T, std::size_t SizeOfT> struct PopulationCounter {
static unsigned count(T Value) {
// Generic version, forward to 32 bits.
static_assert(SizeOfT <= 4, "Not implemented!");
#if defined(__GNUC__)
return __builtin_popcount(Value);
#else
uint32_t v = Value;
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
#endif
}
};
template <typename T> struct PopulationCounter<T, 8> {
static unsigned count(T Value) {
#if defined(__GNUC__)
return __builtin_popcountll(Value);
#else
uint64_t v = Value;
v = v - ((v >> 1) & 0x5555555555555555ULL);
v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56);
#endif
}
};
} // namespace detail
/// Count the number of set bits in a value.
/// Ex. countPopulation(0xF000F000) = 8
/// Returns 0 if the word is zero.
template <typename T>
inline unsigned countPopulation(T Value) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
return detail::PopulationCounter<T, sizeof(T)>::count(Value);
return (unsigned)std::popcount(Value);
}
/// Return true if the argument contains a non-empty sequence of ones with the
/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
/// If true, \p MaskIdx will specify the index of the lowest set bit and \p
/// MaskLen is updated to specify the length of the mask, else neither are
/// updated.
inline bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx,
unsigned &MaskLen) {
if (!isShiftedMask_32(Value))
return false;
MaskIdx = std::countr_zero(Value);
MaskLen = std::popcount(Value);
return true;
}
/// Return true if the argument contains a non-empty sequence of ones with the
/// remainder zero (64 bit version.) If true, \p MaskIdx will specify the index
/// of the lowest set bit and \p MaskLen is updated to specify the length of the
/// mask, else neither are updated.
inline bool isShiftedMask_64(uint64_t Value, unsigned &MaskIdx,
unsigned &MaskLen) {
if (!isShiftedMask_64(Value))
return false;
MaskIdx = std::countr_zero(Value);
MaskLen = std::popcount(Value);
return true;
}
/// Compile time Log2.
@@ -554,90 +377,58 @@ template <size_t kValue> constexpr inline size_t CTLog2() {
template <> constexpr inline size_t CTLog2<1>() { return 0; }
/// Return the log base 2 of the specified value.
inline double Log2(double Value) {
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
return __builtin_log(Value) / __builtin_log(2.0);
#else
return std::log2(Value);
#endif
}
/// Return the floor log base 2 of the specified value, -1 if the value is zero.
/// (32 bit edition.)
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
inline unsigned Log2_32(uint32_t Value) {
return static_cast<unsigned>(31 - countLeadingZeros(Value));
return static_cast<unsigned>(31 - std::countl_zero(Value));
}
/// Return the floor log base 2 of the specified value, -1 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64(uint64_t Value) {
return static_cast<unsigned>(63 - countLeadingZeros(Value));
return static_cast<unsigned>(63 - std::countl_zero(Value));
}
/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
/// (32 bit edition).
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
inline unsigned Log2_32_Ceil(uint32_t Value) {
return static_cast<unsigned>(32 - countLeadingZeros(Value - 1));
return static_cast<unsigned>(32 - std::countl_zero(Value - 1));
}
/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
/// (64 bit edition.)
inline unsigned Log2_64_Ceil(uint64_t Value) {
return static_cast<unsigned>(64 - countLeadingZeros(Value - 1));
}
/// Return the greatest common divisor of the values using Euclid's algorithm.
template <typename T>
inline T greatestCommonDivisor(T A, T B) {
while (B) {
T Tmp = B;
B = A % B;
A = Tmp;
}
return A;
}
inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
return greatestCommonDivisor<uint64_t>(A, B);
return static_cast<unsigned>(64 - std::countl_zero(Value - 1));
}
/// This function takes a 64-bit integer and returns the bit equivalent double.
inline double BitsToDouble(uint64_t Bits) {
double D;
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
memcpy(&D, &Bits, sizeof(Bits));
return D;
return wpi::bit_cast<double>(Bits);
}
/// This function takes a 32-bit integer and returns the bit equivalent float.
inline float BitsToFloat(uint32_t Bits) {
float F;
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
memcpy(&F, &Bits, sizeof(Bits));
return F;
return wpi::bit_cast<float>(Bits);
}
/// This function takes a double and returns the bit equivalent 64-bit integer.
/// Note that copying doubles around changes the bits of NaNs on some hosts,
/// notably x86, so this routine cannot be used if these bits are needed.
inline uint64_t DoubleToBits(double Double) {
uint64_t Bits;
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
memcpy(&Bits, &Double, sizeof(Double));
return Bits;
return wpi::bit_cast<uint64_t>(Double);
}
/// This function takes a float and returns the bit equivalent 32-bit integer.
/// Note that copying floats around changes the bits of NaNs on some hosts,
/// notably x86, so this routine cannot be used if these bits are needed.
inline uint32_t FloatToBits(float Float) {
uint32_t Bits;
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
memcpy(&Bits, &Float, sizeof(Float));
return Bits;
return wpi::bit_cast<uint32_t>(Float);
}
/// A and B are either alignments or offsets. Return the minimum alignment that
@@ -653,7 +444,7 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
/// Returns the next power of two (in 64-bits) that is strictly greater than A.
/// Returns zero on overflow.
inline uint64_t NextPowerOf2(uint64_t A) {
constexpr inline uint64_t NextPowerOf2(uint64_t A) {
A |= (A >> 1);
A |= (A >> 2);
A |= (A >> 4);
@@ -666,8 +457,7 @@ inline uint64_t NextPowerOf2(uint64_t A) {
/// Returns the power of two which is less than or equal to the given value.
/// Essentially, it is a floor operation across the domain of powers of two.
inline uint64_t PowerOf2Floor(uint64_t A) {
if (!A) return 0;
return 1ull << (63 - countLeadingZeros(A, ZB_Undefined));
return std::bit_floor(A);
}
/// Returns the power of two which is greater than or equal to the given value.
@@ -681,27 +471,40 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
/// Returns the next integer (mod 2**64) that is greater than or equal to
/// \p Value and is a multiple of \p Align. \p Align must be non-zero.
///
/// If non-zero \p Skew is specified, the return value will be a minimal
/// integer that is greater than or equal to \p Value and equal to
/// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
/// \p Align, its value is adjusted to '\p Skew mod \p Align'.
///
/// Examples:
/// \code
/// alignTo(5, 8) = 8
/// alignTo(17, 8) = 24
/// alignTo(~0LL, 8) = 0
/// alignTo(321, 255) = 510
/// \endcode
inline uint64_t alignTo(uint64_t Value, uint64_t Align) {
assert(Align != 0u && "Align can't be 0.");
return (Value + Align - 1) / Align * Align;
}
inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
assert(Align != 0 && (Align & (Align - 1)) == 0 &&
"Align must be a power of 2");
return (Value + Align - 1) & -Align;
}
/// If non-zero \p Skew is specified, the return value will be a minimal integer
/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
/// Skew mod \p A'. \p Align must be non-zero.
///
/// Examples:
/// \code
/// alignTo(5, 8, 7) = 7
/// alignTo(17, 8, 1) = 17
/// alignTo(~0LL, 8, 3) = 3
/// alignTo(321, 255, 42) = 552
/// \endcode
inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew) {
assert(Align != 0u && "Align can't be 0.");
Skew %= Align;
return (Value + Align - 1 - Skew) / Align * Align + Skew;
return alignTo(Value - Skew, Align) + Skew;
}
/// Returns the next integer (mod 2**64) that is greater than or equal to
@@ -785,6 +588,18 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
return Z;
}
/// Add multiple unsigned integers of type T. Clamp the result to the
/// maximum representable value of T on overflow.
template <class T, class... Ts>
std::enable_if_t<std::is_unsigned_v<T>, T> SaturatingAdd(T X, T Y, T Z,
Ts... Args) {
bool Overflowed = false;
T XY = SaturatingAdd(X, Y, &Overflowed);
if (Overflowed)
return SaturatingAdd((std::numeric_limits<T>::max)(), T(1), Args...);
return SaturatingAdd(XY, Z, Args...);
}
/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
@@ -852,7 +667,7 @@ extern const float huge_valf;
/// Add two signed integers, computing the two's complement truncated result,
/// returning true if overflow occured.
/// returning true if overflow occurred.
template <typename T>
std::enable_if_t<std::is_signed<T>::value, T> AddOverflow(T X, T Y, T &Result) {
#if __has_builtin(__builtin_add_overflow)

View File

@@ -61,19 +61,19 @@ public:
IntType getInt() const { return (IntType)Info::getInt(Value); }
void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
void setPointer(PointerTy PtrVal) & {
Value = Info::updatePointer(Value, PtrVal);
}
void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION {
void setInt(IntType IntVal) & {
Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal));
}
void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
void initWithPointer(PointerTy PtrVal) & {
Value = Info::updatePointer(0, PtrVal);
}
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION {
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) & {
Value = Info::updateInt(Info::updatePointer(0, PtrVal),
static_cast<intptr_t>(IntVal));
}
@@ -91,7 +91,7 @@ public:
void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
void setFromOpaqueValue(void *Val) LLVM_LVALUE_FUNCTION {
void setFromOpaqueValue(void *Val) & {
Value = reinterpret_cast<intptr_t>(Val);
}
@@ -128,7 +128,6 @@ public:
}
};
template <typename PointerT, unsigned IntBits, typename PtrTraits>
struct PointerIntPairInfo {
static_assert(PtrTraits::NumLowBitsAvailable <
@@ -228,6 +227,32 @@ struct PointerLikeTypeTraits<
PtrTraits::NumLowBitsAvailable - IntBits;
};
// Allow structured bindings on PointerIntPair.
template <std::size_t I, typename PointerTy, unsigned IntBits, typename IntType,
typename PtrTraits, typename Info>
decltype(auto)
get(const PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info> &Pair) {
static_assert(I < 2);
if constexpr (I == 0)
return Pair.getPointer();
else
return Pair.getInt();
}
} // end namespace wpi
namespace std {
template <typename PointerTy, unsigned IntBits, typename IntType,
typename PtrTraits, typename Info>
struct tuple_size<
wpi::PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>
: std::integral_constant<std::size_t, 2> {};
template <std::size_t I, typename PointerTy, unsigned IntBits, typename IntType,
typename PtrTraits, typename Info>
struct tuple_element<
I, wpi::PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>>
: std::conditional<I == 0, PointerTy, IntType> {};
} // namespace std
#endif // WPIUTIL_WPI_POINTERINTPAIR_H

View File

@@ -17,6 +17,7 @@
#include "wpi/DenseMapInfo.h"
#include "wpi/PointerIntPair.h"
#include "wpi/Casting.h"
#include "wpi/PointerLikeTypeTraits.h"
#include <algorithm>
#include <cassert>
@@ -132,6 +133,9 @@ namespace pointer_union_detail {
};
}
// This is a forward declaration of CastInfoPointerUnionImpl
// Refer to its definition below for further details
template <typename... PTs> struct CastInfoPointerUnionImpl;
/// A discriminated union of two or more pointer types, with the discriminator
/// in the low bit of the pointer.
///
@@ -167,6 +171,11 @@ class PointerUnion
using First = TypeAtIndex<0, PTs...>;
using Base = typename PointerUnion::PointerUnionMembers;
/// This is needed to give the CastInfo implementation below access
/// to protected members.
/// Refer to its definition for further details.
friend struct CastInfoPointerUnionImpl<PTs...>;
public:
PointerUnion() = default;
@@ -179,25 +188,24 @@ public:
explicit operator bool() const { return !isNull(); }
// FIXME: Replace the uses of is(), get() and dyn_cast() with
// isa<T>, cast<T> and the wpi::dyn_cast<T>
/// Test if the Union currently holds the type matching T.
template <typename T> bool is() const {
return this->Val.getInt() == FirstIndexOfType<T, PTs...>::value;
}
template <typename T> inline bool is() const { return isa<T>(*this); }
/// Returns the value of the specified pointer type.
///
/// If the specified pointer type is incorrect, assert.
template <typename T> T get() const {
assert(is<T>() && "Invalid accessor called");
return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer());
template <typename T> inline T get() const {
assert(isa<T>(*this) && "Invalid accessor called");
return cast<T>(*this);
}
/// Returns the current pointer if it is of the specified pointer type,
/// otherwise returns null.
template <typename T> T dyn_cast() const {
if (is<T>())
return get<T>();
return T();
template <typename T> inline T dyn_cast() const {
return wpi::dyn_cast_if_present<T>(*this);
}
/// If the union is set to the first pointer type get an address pointing to
@@ -250,6 +258,52 @@ bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
return lhs.getOpaqueValue() < rhs.getOpaqueValue();
}
/// We can't (at least, at this moment with C++14) declare CastInfo
/// as a friend of PointerUnion like this:
/// ```
/// template<typename To>
/// friend struct CastInfo<To, PointerUnion<PTs...>>;
/// ```
/// The compiler complains 'Partial specialization cannot be declared as a
/// friend'.
/// So we define this struct to be a bridge between CastInfo and
/// PointerUnion.
template <typename... PTs> struct CastInfoPointerUnionImpl {
using From = PointerUnion<PTs...>;
template <typename To> static inline bool isPossible(From &F) {
return F.Val.getInt() == FirstIndexOfType<To, PTs...>::value;
}
template <typename To> static To doCast(From &F) {
assert(isPossible<To>(F) && "cast to an incompatible type !");
return PointerLikeTypeTraits<To>::getFromVoidPointer(F.Val.getPointer());
}
};
// Specialization of CastInfo for PointerUnion
template <typename To, typename... PTs>
struct CastInfo<To, PointerUnion<PTs...>>
: public DefaultDoCastIfPossible<To, PointerUnion<PTs...>,
CastInfo<To, PointerUnion<PTs...>>> {
using From = PointerUnion<PTs...>;
using Impl = CastInfoPointerUnionImpl<PTs...>;
static inline bool isPossible(From &f) {
return Impl::template isPossible<To>(f);
}
static To doCast(From &f) { return Impl::template doCast<To>(f); }
static inline To castFailed() { return To(); }
};
template <typename To, typename... PTs>
struct CastInfo<To, const PointerUnion<PTs...>>
: public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>,
CastInfo<To, PointerUnion<PTs...>>> {
};
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
// # low bits available = min(PT1bits,PT2bits)-1.
template <typename ...PTs>

View File

@@ -17,53 +17,11 @@
#ifndef WPIUTIL_WPI_STLFORWARDCOMPAT_H
#define WPIUTIL_WPI_STLFORWARDCOMPAT_H
#include <optional>
#include <type_traits>
namespace wpi {
//===----------------------------------------------------------------------===//
// Features from C++17
//===----------------------------------------------------------------------===//
template <typename T>
struct negation // NOLINT(readability-identifier-naming)
: std::integral_constant<bool, !bool(T::value)> {};
template <typename...>
struct conjunction // NOLINT(readability-identifier-naming)
: std::true_type {};
template <typename B1> struct conjunction<B1> : B1 {};
template <typename B1, typename... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template <typename...>
struct disjunction // NOLINT(readability-identifier-naming)
: std::false_type {};
template <typename B1> struct disjunction<B1> : B1 {};
template <typename B1, typename... Bn>
struct disjunction<B1, Bn...>
: std::conditional<bool(B1::value), B1, disjunction<Bn...>>::type {};
struct in_place_t // NOLINT(readability-identifier-naming)
{
explicit in_place_t() = default;
};
/// \warning This must not be odr-used, as it cannot be made \c inline in C++14.
constexpr in_place_t in_place; // NOLINT(readability-identifier-naming)
template <typename T>
struct in_place_type_t // NOLINT(readability-identifier-naming)
{
explicit in_place_type_t() = default;
};
template <std::size_t I>
struct in_place_index_t // NOLINT(readability-identifier-naming)
{
explicit in_place_index_t() = default;
};
//===----------------------------------------------------------------------===//
// Features from C++20
//===----------------------------------------------------------------------===//
@@ -78,6 +36,30 @@ template <typename T>
using remove_cvref_t // NOLINT(readability-identifier-naming)
= typename wpi::remove_cvref<T>::type;
//===----------------------------------------------------------------------===//
// Features from C++23
//===----------------------------------------------------------------------===//
// TODO: Remove this in favor of std::optional<T>::transform once we switch to
// C++23.
template <typename T, typename Function>
auto transformOptional(const std::optional<T> &O, const Function &F)
-> std::optional<decltype(F(*O))> {
if (O)
return F(*O);
return std::nullopt;
}
// TODO: Remove this in favor of std::optional<T>::transform once we switch to
// C++23.
template <typename T, typename Function>
auto transformOptional(std::optional<T> &&O, const Function &F)
-> std::optional<decltype(F(*std::move(O)))> {
if (O)
return F(*std::move(O));
return std::nullopt;
}
} // namespace wpi
#endif // WPIUTIL_WPI_STLFORWARDCOMPAT_H

View File

@@ -89,7 +89,7 @@ public:
SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete;
LLVM_NODISCARD bool empty() const { return size() == 0; }
[[nodiscard]] bool empty() const { return size() == 0; }
size_type size() const { return NumNonEmpty - NumTombstones; }
void clear() {

View File

@@ -140,6 +140,7 @@ class SmallSet {
std::set<T, C> Set;
using VIterator = typename SmallVector<T, N>::const_iterator;
using SIterator = typename std::set<T, C>::const_iterator;
using mutable_iterator = typename SmallVector<T, N>::iterator;
// In small mode SmallPtrSet uses linear search for the elements, so it is
@@ -153,9 +154,7 @@ public:
SmallSet() = default;
LLVM_NODISCARD bool empty() const {
return Vector.empty() && Set.empty();
}
[[nodiscard]] bool empty() const { return Vector.empty() && Set.empty(); }
size_type size() const {
return isSmall() ? Vector.size() : Set.size();
@@ -172,22 +171,21 @@ public:
}
/// insert - Insert an element into the set if it isn't already there.
/// Returns true if the element is inserted (it was not in the set before).
/// The first value of the returned pair is unused and provided for
/// partial compatibility with the standard library self-associative container
/// concept.
// FIXME: Add iterators that abstract over the small and large form, and then
// return those here.
std::pair<std::nullopt_t, bool> insert(const T &V) {
if (!isSmall())
return std::make_pair(std::nullopt, Set.insert(V).second);
/// Returns a pair. The first value of it is an iterator to the inserted
/// element or the existing element in the set. The second value is true
/// if the element is inserted (it was not in the set before).
std::pair<const_iterator, bool> insert(const T &V) {
if (!isSmall()) {
auto [I, Inserted] = Set.insert(V);
return std::make_pair(const_iterator(I), Inserted);
}
VIterator I = vfind(V);
if (I != Vector.end()) // Don't reinsert if it already exists.
return std::make_pair(std::nullopt, false);
return std::make_pair(const_iterator(I), false);
if (Vector.size() < N) {
Vector.push_back(V);
return std::make_pair(std::nullopt, true);
return std::make_pair(const_iterator(std::prev(Vector.end())), true);
}
// Otherwise, grow from vector to set.
@@ -195,8 +193,7 @@ public:
Set.insert(Vector.back());
Vector.pop_back();
}
Set.insert(V);
return std::make_pair(std::nullopt, true);
return std::make_pair(const_iterator(Set.insert(V).first), true);
}
template <typename IterT>

View File

@@ -35,6 +35,7 @@
#include <limits>
#include <memory>
#include <new>
#include <span>
#include <type_traits>
#include <utility>
@@ -42,6 +43,11 @@ namespace wpi {
template <typename IteratorT> class iterator_range;
template <class Iterator>
using EnableIfConvertibleToInputIterator = std::enable_if_t<std::is_convertible<
typename std::iterator_traits<Iterator>::iterator_category,
std::input_iterator_tag>::value>;
/// This is all the stuff common to all SmallVectors.
///
/// The template parameter specifies the type which should be used to hold the
@@ -67,18 +73,32 @@ protected:
/// This is a helper for \a grow() that's out of line to reduce code
/// duplication. This function will report a fatal error if it can't grow at
/// least to \p MinSize.
void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity);
void *mallocForGrow(void *FirstEl, size_t MinSize, size_t TSize,
size_t &NewCapacity);
/// This is an implementation of the grow() method which only works
/// on POD-like data types and is out of line to reduce code duplication.
/// This function will report a fatal error if it cannot increase capacity.
void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
/// If vector was first created with capacity 0, getFirstEl() points to the
/// memory right after, an area unallocated. If a subsequent allocation,
/// that grows the vector, happens to return the same pointer as getFirstEl(),
/// get a new allocation, otherwise isSmall() will falsely return that no
/// allocation was done (true) and the memory will not be freed in the
/// destructor. If a VSize is given (vector size), also copy that many
/// elements to the new allocation - used if realloca fails to increase
/// space, and happens to allocate precisely at BeginX.
/// This is unlikely to be called often, but resolves a memory leak when the
/// situation does occur.
void *replaceAllocation(void *NewElts, size_t TSize, size_t NewCapacity,
size_t VSize = 0);
public:
size_t size() const { return Size; }
size_t capacity() const { return Capacity; }
LLVM_NODISCARD bool empty() const { return !Size; }
[[nodiscard]] bool empty() const { return !Size; }
protected:
/// Set the array size to \p N, which the current array must have enough
@@ -99,13 +119,14 @@ template <class T, typename = void> struct SmallVectorAlignmentAndSize {
};
/// This is the part of SmallVectorTemplateBase which does not depend on whether
/// the type T is a POD. The extra dummy template argument is used by ArrayRef
/// the type T is a POD. The extra dummy template argument is used by std::span
/// to avoid unnecessarily requiring T to be complete.
template <typename T, typename = void>
class SmallVectorTemplateCommon
: public SmallVectorBase {
using Base = SmallVectorBase;
protected:
/// Find the address of the first element. For this pointer math to be valid
/// with small-size of 0 for T with lots of alignment, it's important that
/// SmallVectorStorage is properly-aligned even for small-size of 0.
@@ -116,7 +137,6 @@ class SmallVectorTemplateCommon
}
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
protected:
SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}
void grow_pod(size_t MinSize, size_t TSize) {
@@ -331,8 +351,7 @@ protected:
/// constructing elements as needed.
template<typename It1, typename It2>
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
std::uninitialized_copy(std::make_move_iterator(I),
std::make_move_iterator(E), Dest);
std::uninitialized_move(I, E, Dest);
}
/// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
@@ -349,11 +368,7 @@ protected:
/// Create a new allocation big enough for \p MinSize and pass back its size
/// in \p NewCapacity. This is the first section of \a grow().
T *mallocForGrow(size_t MinSize, size_t &NewCapacity) {
return static_cast<T *>(
SmallVectorBase::mallocForGrow(
MinSize, sizeof(T), NewCapacity));
}
T *mallocForGrow(size_t MinSize, size_t &NewCapacity);
/// Move existing elements over to the new allocation \p NewElts, the middle
/// section of \a grow().
@@ -427,6 +442,14 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
takeAllocationForGrow(NewElts, NewCapacity);
}
template <typename T, bool TriviallyCopyable>
T *SmallVectorTemplateBase<T, TriviallyCopyable>::mallocForGrow(
size_t MinSize, size_t &NewCapacity) {
return static_cast<T *>(
SmallVectorBase::mallocForGrow(
this->getFirstEl(), MinSize, sizeof(T), NewCapacity));
}
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T, bool TriviallyCopyable>
void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow(
@@ -465,8 +488,7 @@ protected:
/// Either const T& or T, depending on whether it's cheap enough to take
/// parameters by value.
using ValueParamT =
typename std::conditional<TakesParamByValue, T, const T &>::type;
using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
@@ -494,8 +516,8 @@ protected:
template <typename T1, typename T2>
static void uninitialized_copy(
T1 *I, T1 *E, T2 *Dest,
std::enable_if_t<std::is_same<typename std::remove_const<T1>::type,
T2>::value> * = nullptr) {
std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>::value> * =
nullptr) {
// Use memcpy for PODs iterated by pointers (which includes SmallVector
// iterators): std::uninitialized_copy optimizes to memmove, but we can
// use memcpy here. Note that I and E are iterators and thus might be
@@ -654,7 +676,7 @@ public:
truncate(this->size() - NumItems);
}
LLVM_NODISCARD T pop_back_val() {
[[nodiscard]] T pop_back_val() {
T Result = ::std::move(this->back());
this->pop_back();
return Result;
@@ -663,11 +685,8 @@ public:
void swap(SmallVectorImpl &RHS);
/// Add the specified range to the end of the SmallVector.
template <typename in_iter,
typename = std::enable_if_t<std::is_convertible<
typename std::iterator_traits<in_iter>::iterator_category,
std::input_iterator_tag>::value>>
void append(in_iter in_start, in_iter in_end) {
template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
void append(ItTy in_start, ItTy in_end) {
this->assertSafeToAddRange(in_start, in_end);
size_type NumInputs = std::distance(in_start, in_end);
this->reserve(this->size() + NumInputs);
@@ -707,11 +726,8 @@ public:
// FIXME: Consider assigning over existing elements, rather than clearing &
// re-initializing them - for all assign(...) variants.
template <typename in_iter,
typename = std::enable_if_t<std::is_convertible<
typename std::iterator_traits<in_iter>::iterator_category,
std::input_iterator_tag>::value>>
void assign(in_iter in_start, in_iter in_end) {
template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
void assign(ItTy in_start, ItTy in_end) {
this->assertSafeToReferenceAfterClear(in_start, in_end);
clear();
append(in_start, in_end);
@@ -861,10 +877,7 @@ public:
return I;
}
template <typename ItTy,
typename = std::enable_if_t<std::is_convertible<
typename std::iterator_traits<ItTy>::iterator_category,
std::input_iterator_tag>::value>>
template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
iterator insert(iterator I, ItTy From, ItTy To) {
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
@@ -952,6 +965,9 @@ public:
return std::lexicographical_compare(this->begin(), this->end(),
RHS.begin(), RHS.end());
}
bool operator>(const SmallVectorImpl &RHS) const { return RHS < *this; }
bool operator<=(const SmallVectorImpl &RHS) const { return !(*this > RHS); }
bool operator>=(const SmallVectorImpl &RHS) const { return !(*this < RHS); }
};
template <typename T>
@@ -1197,10 +1213,7 @@ public:
this->assign(Size, Value);
}
template <typename ItTy,
typename = std::enable_if_t<std::is_convertible<
typename std::iterator_traits<ItTy>::iterator_category,
std::input_iterator_tag>::value>>
template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
this->append(S, E);
}
@@ -1212,7 +1225,13 @@ public:
}
SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
this->assign(IL);
this->append(IL);
}
template <typename U,
typename = std::enable_if_t<std::is_convertible<U, T>::value>>
explicit SmallVector(std::span<const U> A) : SmallVectorImpl<T>(N) {
this->append(A.begin(), A.end());
}
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
@@ -1271,8 +1290,8 @@ inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
template <typename RangeType>
using ValueTypeFromRangeType =
typename std::remove_const<typename std::remove_reference<
decltype(*std::begin(std::declval<RangeType &>()))>::type>::type;
std::remove_const_t<std::remove_reference_t<decltype(*std::begin(
std::declval<RangeType &>()))>>;
/// Given a range of type R, iterate the entire range and return a
/// SmallVector with elements of the vector. This is useful, for example,
@@ -1282,10 +1301,16 @@ 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) {
SmallVector<ValueTypeFromRangeType<R>> to_vector(R &&Range) {
return {std::begin(Range), std::end(Range)};
}
template <typename Out, unsigned Size, typename R>
SmallVector<Out, Size> to_vector_of(R &&Range) {
return {std::begin(Range), std::end(Range)};
}
template <typename Out, typename R> SmallVector<Out> to_vector_of(R &&Range) {
return {std::begin(Range), std::end(Range)};
}

View File

@@ -111,8 +111,9 @@ public:
/// funky memory allocation and hashing things to make it extremely efficient,
/// storing the string data *after* the value in the map.
template <typename ValueTy, typename AllocatorTy = MallocAllocator>
class StringMap : public StringMapImpl {
AllocatorTy Allocator;
class StringMap : public StringMapImpl,
private detail::AllocatorHolder<AllocatorTy> {
using AllocTy = detail::AllocatorHolder<AllocatorTy>;
public:
using MapEntryTy = StringMapEntry<ValueTy>;
@@ -123,12 +124,11 @@ public:
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
explicit StringMap(AllocatorTy A)
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {
}
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), AllocTy(A) {}
StringMap(unsigned InitialSize, AllocatorTy A)
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
Allocator(A) {}
AllocTy(A) {}
StringMap(std::initializer_list<std::pair<std::string_view, ValueTy>> List)
: StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
@@ -136,11 +136,11 @@ public:
}
StringMap(StringMap &&RHS)
: StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
: StringMapImpl(std::move(RHS)), AllocTy(std::move(RHS.getAllocator())) {}
StringMap(const StringMap &RHS)
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
Allocator(RHS.Allocator) {
AllocTy(RHS.getAllocator()) {
if (RHS.empty())
return;
@@ -159,8 +159,8 @@ public:
continue;
}
TheTable[I] = MapEntryTy::Create(
static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
TheTable[I] = MapEntryTy::create(
static_cast<MapEntryTy *>(Bucket)->getKey(), getAllocator(),
static_cast<MapEntryTy *>(Bucket)->getValue());
HashTable[I] = RHSHashTable[I];
}
@@ -175,7 +175,7 @@ public:
StringMap &operator=(StringMap RHS) {
StringMapImpl::swap(RHS);
std::swap(Allocator, RHS.Allocator);
std::swap(getAllocator(), RHS.getAllocator());
return *this;
}
@@ -187,15 +187,14 @@ public:
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy *>(Bucket)->Destroy(Allocator);
static_cast<MapEntryTy *>(Bucket)->Destroy(getAllocator());
}
}
}
free(TheTable);
}
AllocatorTy &getAllocator() { return Allocator; }
const AllocatorTy &getAllocator() const { return Allocator; }
using AllocTy::getAllocator;
using key_type = const char *;
using mapped_type = ValueTy;
@@ -331,7 +330,7 @@ public:
/// if and only if the insertion takes place, and the iterator component of
/// the pair points to the element with key equivalent to the key of the pair.
template <typename... ArgsTy>
std::pair<iterator, bool> try_emplace(std::string_view Key, ArgsTy &&... Args) {
std::pair<iterator, bool> try_emplace(std::string_view Key, ArgsTy &&...Args) {
unsigned BucketNo = LookupBucketFor(Key);
StringMapEntryBase *&Bucket = TheTable[BucketNo];
if (Bucket && Bucket != getTombstoneVal())
@@ -340,7 +339,8 @@ public:
if (Bucket == getTombstoneVal())
--NumTombstones;
Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
Bucket =
MapEntryTy::create(Key, getAllocator(), std::forward<ArgsTy>(Args)...);
++NumItems;
assert(NumItems + NumTombstones <= NumBuckets);
@@ -358,7 +358,7 @@ public:
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
StringMapEntryBase *&Bucket = TheTable[I];
if (Bucket && Bucket != getTombstoneVal()) {
static_cast<MapEntryTy *>(Bucket)->Destroy(Allocator);
static_cast<MapEntryTy *>(Bucket)->Destroy(getAllocator());
}
Bucket = nullptr;
}
@@ -374,7 +374,7 @@ public:
void erase(iterator I) {
MapEntryTy &V = *I;
remove(&V);
V.Destroy(Allocator);
V.Destroy(getAllocator());
}
bool erase(std::string_view Key) {

View File

@@ -77,7 +77,7 @@ public:
explicit StringMapEntryStorage(size_t keyLength)
: StringMapEntryBase(keyLength), second() {}
template <typename... InitTy>
StringMapEntryStorage(size_t keyLength, InitTy &&... initVals)
StringMapEntryStorage(size_t keyLength, InitTy &&...initVals)
: StringMapEntryBase(keyLength),
second(std::forward<InitTy>(initVals)...) {}
StringMapEntryStorage(StringMapEntryStorage &e) = delete;
@@ -88,9 +88,11 @@ public:
void setValue(const ValueTy &V) { second = V; }
};
template <> class StringMapEntryStorage<std::nullopt_t> : public StringMapEntryBase {
template <>
class StringMapEntryStorage<std::nullopt_t> : public StringMapEntryBase {
public:
explicit StringMapEntryStorage(size_t keyLength, std::nullopt_t = std::nullopt)
explicit StringMapEntryStorage(size_t keyLength,
std::nullopt_t = std::nullopt)
: StringMapEntryBase(keyLength) {}
StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
@@ -105,6 +107,8 @@ class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
public:
using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
using ValueType = ValueTy;
std::string_view getKey() const {
return std::string_view(getKeyData(), this->getKeyLength());
}
@@ -123,7 +127,7 @@ public:
/// Create a StringMapEntry for the specified key construct the value using
/// \p InitiVals.
template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(std::string_view key, AllocatorTy &allocator,
static StringMapEntry *create(std::string_view key, AllocatorTy &allocator,
InitTy &&... initVals) {
return new (StringMapEntryBase::allocateWithKey(
sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator))
@@ -148,6 +152,26 @@ public:
}
};
// Allow structured bindings on StringMapEntry.
template <std::size_t Index, typename ValueTy>
decltype(auto) get(const StringMapEntry<ValueTy> &E) {
static_assert(Index < 2);
if constexpr (Index == 0)
return E.first();
else
return E.second;
}
} // end namespace wpi
namespace std {
template <typename ValueTy>
struct tuple_size<wpi::StringMapEntry<ValueTy>>
: std::integral_constant<std::size_t, 2> {};
template <std::size_t I, typename ValueTy>
struct tuple_element<I, wpi::StringMapEntry<ValueTy>>
: std::conditional<I == 0, std::string_view, ValueTy> {};
} // namespace std
#endif // WPIUTIL_WPI_STRINGMAPENTRY_H

View File

@@ -14,12 +14,10 @@
#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
#define WPIUTIL_WPI_SWAPBYTEORDER_H
#include "wpi/bit.h"
#include <cstddef>
#include <cstdint>
#include <type_traits>
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <stdlib.h>
#endif
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
@@ -50,45 +48,13 @@ namespace wpi {
/// ByteSwap_16 - This function returns a byte-swapped representation of
/// the 16-bit argument.
inline uint16_t ByteSwap_16(uint16_t value) {
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
return _byteswap_ushort(value);
#else
uint16_t Hi = value << 8;
uint16_t Lo = value >> 8;
return Hi | Lo;
#endif
}
inline uint16_t ByteSwap_16(uint16_t value) { return wpi::byteswap(value); }
/// This function returns a byte-swapped representation of the 32-bit argument.
inline uint32_t ByteSwap_32(uint32_t value) {
#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap32(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(value);
#else
uint32_t Byte0 = value & 0x000000FF;
uint32_t Byte1 = value & 0x0000FF00;
uint32_t Byte2 = value & 0x00FF0000;
uint32_t Byte3 = value & 0xFF000000;
return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
#endif
}
inline uint32_t ByteSwap_32(uint32_t value) { return wpi::byteswap(value); }
/// This function returns a byte-swapped representation of the 64-bit argument.
inline uint64_t ByteSwap_64(uint64_t value) {
#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap64(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(value);
#else
uint64_t Hi = ByteSwap_32(uint32_t(value));
uint32_t Lo = ByteSwap_32(uint32_t(value >> 32));
return (Hi << 32) | Lo;
#endif
}
inline uint64_t ByteSwap_64(uint64_t value) { return wpi::byteswap(value); }
namespace sys {
@@ -100,33 +66,21 @@ constexpr bool IsBigEndianHost = false;
static const bool IsLittleEndianHost = !IsBigEndianHost;
inline unsigned char getSwappedBytes(unsigned char C) { return C; }
inline signed char getSwappedBytes(signed char C) { return C; }
inline char getSwappedBytes(char C) { return C; }
inline unsigned char getSwappedBytes(unsigned char C) { return wpi::byteswap(C); }
inline signed char getSwappedBytes( signed char C) { return wpi::byteswap(C); }
inline char getSwappedBytes( char C) { return wpi::byteswap(C); }
inline unsigned short getSwappedBytes(unsigned short C) { return ByteSwap_16(C); }
inline signed short getSwappedBytes( signed short C) { return ByteSwap_16(C); }
inline unsigned short getSwappedBytes(unsigned short C) { return wpi::byteswap(C); }
inline signed short getSwappedBytes( signed short C) { return wpi::byteswap(C); }
inline unsigned int getSwappedBytes(unsigned int C) { return ByteSwap_32(C); }
inline signed int getSwappedBytes( signed int C) { return ByteSwap_32(C); }
inline unsigned int getSwappedBytes(unsigned int C) { return wpi::byteswap(C); }
inline signed int getSwappedBytes( signed int C) { return wpi::byteswap(C); }
inline unsigned long getSwappedBytes(unsigned long C) {
// Handle LLP64 and LP64 platforms.
return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
: ByteSwap_64((uint64_t)C);
}
inline signed long getSwappedBytes(signed long C) {
// Handle LLP64 and LP64 platforms.
return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
: ByteSwap_64((uint64_t)C);
}
inline unsigned long getSwappedBytes(unsigned long C) { return wpi::byteswap(C); }
inline signed long getSwappedBytes( signed long C) { return wpi::byteswap(C); }
inline unsigned long long getSwappedBytes(unsigned long long C) {
return ByteSwap_64(C);
}
inline signed long long getSwappedBytes(signed long long C) {
return ByteSwap_64(C);
}
inline unsigned long long getSwappedBytes(unsigned long long C) { return wpi::byteswap(C); }
inline signed long long getSwappedBytes( signed long long C) { return wpi::byteswap(C); }
inline float getSwappedBytes(float C) {
union {
@@ -134,7 +88,7 @@ inline float getSwappedBytes(float C) {
float f;
} in, out;
in.f = C;
out.i = ByteSwap_32(in.i);
out.i = wpi::byteswap(in.i);
return out.f;
}
@@ -144,14 +98,14 @@ inline double getSwappedBytes(double C) {
double d;
} in, out;
in.d = C;
out.i = ByteSwap_64(in.i);
out.i = wpi::byteswap(in.i);
return out.d;
}
template <typename T>
inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
return static_cast<T>(
getSwappedBytes(static_cast<std::underlying_type_t<T>>(C)));
wpi::byteswap(static_cast<std::underlying_type_t<T>>(C)));
}
template<typename T>

View File

@@ -16,11 +16,14 @@
#include "wpi/DenseMapInfo.h"
#include "wpi/Hashing.h"
#include "wpi/Endian.h"
#include <optional>
#include <string>
#include <tuple>
namespace wpi {
template <typename HasherT, support::endianness Endianness>
class HashBuilderImpl;
class raw_ostream;
/// Represents a version number in the form major[.minor[.subminor[.build]]].
@@ -37,24 +40,25 @@ class VersionTuple {
unsigned HasBuild : 1;
public:
VersionTuple()
constexpr VersionTuple()
: Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false),
Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major)
explicit constexpr VersionTuple(unsigned Major)
: Major(Major), Minor(0), HasMinor(false), Subminor(0),
HasSubminor(false), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor)
explicit constexpr VersionTuple(unsigned Major, unsigned Minor)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(0),
HasSubminor(false), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
unsigned Subminor)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
HasSubminor(true), Build(0), HasBuild(false) {}
explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
unsigned Build)
explicit constexpr VersionTuple(unsigned Major, unsigned Minor,
unsigned Subminor, unsigned Build)
: Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor),
HasSubminor(true), Build(Build), HasBuild(true) {}
@@ -95,6 +99,12 @@ public:
return *this;
}
/// Return a version tuple that contains a different major version but
/// everything else is the same.
VersionTuple withMajorReplaced(unsigned NewMajor) const {
return VersionTuple(NewMajor, Minor, Subminor, Build);
}
/// Return a version tuple that contains only components that are non-zero.
VersionTuple normalize() const {
VersionTuple Result = *this;

View File

@@ -0,0 +1,99 @@
//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the C++20 <bit> header.
///
//===----------------------------------------------------------------------===//
#ifndef WPIUTIL_WPI_BIT_H
#define WPIUTIL_WPI_BIT_H
#include "wpi/Compiler.h"
#include <cstdint>
#include <limits>
#include <type_traits>
#if !__has_builtin(__builtin_bit_cast)
#include <cstring>
#endif
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <cstdlib> // for _byteswap_{ushort,ulong,uint64}
#endif
namespace wpi {
// This implementation of bit_cast is different from the C++20 one in two ways:
// - It isn't constexpr because that requires compiler support.
// - It requires trivially-constructible To, to avoid UB in the implementation.
template <
typename To, typename From,
typename = std::enable_if_t<sizeof(To) == sizeof(From)>,
typename = std::enable_if_t<std::is_trivially_constructible<To>::value>,
typename = std::enable_if_t<std::is_trivially_copyable<To>::value>,
typename = std::enable_if_t<std::is_trivially_copyable<From>::value>>
[[nodiscard]] inline To bit_cast(const From &from) noexcept {
#if __has_builtin(__builtin_bit_cast)
return __builtin_bit_cast(To, from);
#else
To to;
std::memcpy(&to, &from, sizeof(To));
return to;
#endif
}
/// Reverses the bytes in the given integer value V.
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
[[nodiscard]] constexpr T byteswap(T V) noexcept {
if constexpr (sizeof(T) == 1) {
return V;
} else if constexpr (sizeof(T) == 2) {
uint16_t UV = V;
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
return _byteswap_ushort(UV);
#else
uint16_t Hi = UV << 8;
uint16_t Lo = UV >> 8;
return Hi | Lo;
#endif
} else if constexpr (sizeof(T) == 4) {
uint32_t UV = V;
#if __has_builtin(__builtin_bswap32)
return __builtin_bswap32(UV);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(UV);
#else
uint32_t Byte0 = UV & 0x000000FF;
uint32_t Byte1 = UV & 0x0000FF00;
uint32_t Byte2 = UV & 0x00FF0000;
uint32_t Byte3 = UV & 0xFF000000;
return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
#endif
} else if constexpr (sizeof(T) == 8) {
uint64_t UV = V;
#if __has_builtin(__builtin_bswap64)
return __builtin_bswap64(UV);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(UV);
#else
uint64_t Hi = wpi::byteswap<uint32_t>(UV);
uint32_t Lo = wpi::byteswap<uint32_t>(UV >> 32);
return (Hi << 32) | Lo;
#endif
} else {
static_assert(!sizeof(T *), "Don't know how to handle the given type.");
return 0;
}
}
} // namespace wpi
#endif

View File

@@ -14,15 +14,14 @@
#define WPIUTIL_WPI_RAW_OSTREAM_H
#include "wpi/SmallVector.h"
#include <span>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
#include <span>
#include <string>
#if __cplusplus > 201402L
#include <string_view>
#endif
#include <system_error>
#include <type_traits>
#include <vector>
@@ -229,6 +228,20 @@ public:
return *this;
}
#if defined(__cpp_char8_t)
// When using `char8_t *` integers or pointers are written to the ostream
// instead of UTF-8 code as one might expect. This might lead to unexpected
// behavior, especially as `u8""` literals are of type `char8_t*` instead of
// type `char_t*` from C++20 onwards. Thus we disallow using them with
// raw_ostreams.
// If you have u8"" literals to stream, you can rewrite them as ordinary
// literals with escape sequences
// e.g. replace `u8"\u00a0"` by `"\xc2\xa0"`
// or use `reinterpret_cast`:
// e.g. replace `u8"\u00a0"` by `reinterpret_cast<const char *>(u8"\u00a0")`
raw_ostream &operator<<(const char8_t *Str) = delete;
#endif
raw_ostream &operator<<(const char *Str) {
// Inline fast path, particularly for constant strings where a sufficiently
// smart compiler will simplify strlen.
@@ -734,7 +747,7 @@ class buffer_ostream : public raw_svector_ostream {
raw_ostream &OS;
SmallVector<char, 0> Buffer;
virtual void anchor() override;
void anchor() override;
public:
buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {}
@@ -745,7 +758,7 @@ class buffer_unique_ostream : public raw_svector_ostream {
std::unique_ptr<raw_ostream> OS;
SmallVector<char, 0> Buffer;
virtual void anchor() override;
void anchor() override;
public:
buffer_unique_ostream(std::unique_ptr<raw_ostream> OS)

View File

@@ -98,7 +98,6 @@ using is_trivially_move_constructible = std::is_trivially_move_constructible<T>;
template <typename T>
using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>;
} // end namespace wpi
#endif // WPIUTIL_WPI_TYPE_TRAITS_H

View File

@@ -26,6 +26,18 @@ TEST(ConvertUTFTest, ConvertUTF16LittleEndianToUTF8String) {
EXPECT_EQ(Expected, std::string{Result});
}
TEST(ConvertUTFTest, ConvertUTF32LittleEndianToUTF8String) {
// Src is the look of disapproval.
alignas(UTF32) static const char Src[] =
"\xFF\xFE\x00\x00\xA0\x0C\x00\x00\x5F\x00\x00\x00\xA0\x0C\x00\x00";
std::span<const char> Ref(Src, sizeof(Src) - 1);
std::string Result;
bool Success = convertUTF32ToUTF8String(Ref, Result);
EXPECT_TRUE(Success);
std::string Expected("\xE0\xB2\xA0_\xE0\xB2\xA0");
EXPECT_EQ(Expected, Result);
}
TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
// Src is the look of disapproval.
alignas(UTF16) static const char Src[] = "\xfe\xff\x0c\xa0\x00_\x0c\xa0";
@@ -37,6 +49,18 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
EXPECT_EQ(Expected, std::string{Result});
}
TEST(ConvertUTFTest, ConvertUTF32BigEndianToUTF8String) {
// Src is the look of disapproval.
alignas(UTF32) static const char Src[] =
"\x00\x00\xFE\xFF\x00\x00\x0C\xA0\x00\x00\x00\x5F\x00\x00\x0C\xA0";
std::span<const char> Ref(Src, sizeof(Src) - 1);
std::string Result;
bool Success = convertUTF32ToUTF8String(Ref, Result);
EXPECT_TRUE(Success);
std::string Expected("\xE0\xB2\xA0_\xE0\xB2\xA0");
EXPECT_EQ(Expected, Result);
}
TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) {
// Src is the look of disapproval.
static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0";
@@ -58,7 +82,8 @@ TEST(ConvertUTFTest, OddLengthInput) {
TEST(ConvertUTFTest, Empty) {
SmallString<20> Result;
bool Success = convertUTF16ToUTF8String(std::span<const char>(), Result);
bool Success =
convertUTF16ToUTF8String(std::span<const char>(), Result);
EXPECT_TRUE(Success);
EXPECT_TRUE(std::string{Result}.empty());
}

View File

@@ -11,9 +11,13 @@
#endif
#include "wpi/DenseMap.h"
#include "wpi/DenseMapInfo.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <map>
#include <set>
#include <utility>
#include <variant>
using namespace wpi;
@@ -446,6 +450,7 @@ TEST(DenseMapCustomTest, InitFromIterator) {
std::vector<std::pair<int, CountCopyAndMove>> Values;
// The size is a random value greater than 64 (hardcoded DenseMap min init)
const int Count = 65;
Values.reserve(Count);
for (int i = 0; i < Count; i++)
Values.emplace_back(i, CountCopyAndMove());
@@ -586,6 +591,15 @@ TEST(DenseMapCustomTest, LargeSmallDenseMapCompaction) {
EXPECT_TRUE(map.find(0) == map.end());
}
TEST(DenseMapCustomTest, SmallDenseMapWithNumBucketsNonPowerOf2) {
// Is not power of 2.
const unsigned NumInitBuckets = 33;
// Power of 2 less then NumInitBuckets.
constexpr unsigned InlineBuckets = 4;
// Constructor should not trigger assert.
SmallDenseMap<int, int, InlineBuckets> map(NumInitBuckets);
}
TEST(DenseMapCustomTest, TryEmplaceTest) {
DenseMap<int, std::unique_ptr<int>> Map;
std::unique_ptr<int> P(new int(2));
@@ -648,7 +662,7 @@ struct B : public A {
namespace wpi {
template <typename T>
struct DenseMapInfo<T, std::enable_if_t<std::is_base_of<A, T>::value>> {
struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
static inline T getEmptyKey() { return {static_cast<int>(~0)}; }
static inline T getTombstoneKey() { return {static_cast<int>(~0U - 1)}; }
static unsigned getHashValue(const T &Val) { return Val.value; }
@@ -677,4 +691,18 @@ TEST(DenseMapCustomTest, SFINAEMapInfo) {
EXPECT_EQ(Map.find(Keys[1]), Map.end());
EXPECT_EQ(Map.find(Keys[2]), Map.end());
}
TEST(DenseMapCustomTest, VariantSupport) {
using variant = std::variant<int, int>;
DenseMap<variant, int> Map;
variant Keys[] = {
variant(std::in_place_index<0>, 1),
variant(std::in_place_index<1>, 1),
};
Map.try_emplace(Keys[0], 0);
Map.try_emplace(Keys[1], 1);
EXPECT_THAT(Map, testing::SizeIs(2));
EXPECT_NE(DenseMapInfo<variant>::getHashValue(Keys[0]),
DenseMapInfo<variant>::getHashValue(Keys[1]));
}
} // namespace

View File

@@ -175,6 +175,44 @@ TEST(MathExtras, reverseBits) {
EXPECT_EQ(0x5400000000000000ULL, reverseBits(NZ64));
}
TEST(MathExtras, isShiftedMask_32) {
EXPECT_FALSE(isShiftedMask_32(0x01010101));
EXPECT_TRUE(isShiftedMask_32(0xf0000000));
EXPECT_TRUE(isShiftedMask_32(0xffff0000));
EXPECT_TRUE(isShiftedMask_32(0xff << 1));
unsigned MaskIdx, MaskLen;
EXPECT_FALSE(isShiftedMask_32(0x01010101, MaskIdx, MaskLen));
EXPECT_TRUE(isShiftedMask_32(0xf0000000, MaskIdx, MaskLen));
EXPECT_EQ(28, (int)MaskIdx);
EXPECT_EQ(4, (int)MaskLen);
EXPECT_TRUE(isShiftedMask_32(0xffff0000, MaskIdx, MaskLen));
EXPECT_EQ(16, (int)MaskIdx);
EXPECT_EQ(16, (int)MaskLen);
EXPECT_TRUE(isShiftedMask_32(0xff << 1, MaskIdx, MaskLen));
EXPECT_EQ(1, (int)MaskIdx);
EXPECT_EQ(8, (int)MaskLen);
}
TEST(MathExtras, isShiftedMask_64) {
EXPECT_FALSE(isShiftedMask_64(0x0101010101010101ull));
EXPECT_TRUE(isShiftedMask_64(0xf000000000000000ull));
EXPECT_TRUE(isShiftedMask_64(0xffff000000000000ull));
EXPECT_TRUE(isShiftedMask_64(0xffull << 55));
unsigned MaskIdx, MaskLen;
EXPECT_FALSE(isShiftedMask_64(0x0101010101010101ull, MaskIdx, MaskLen));
EXPECT_TRUE(isShiftedMask_64(0xf000000000000000ull, MaskIdx, MaskLen));
EXPECT_EQ(60, (int)MaskIdx);
EXPECT_EQ(4, (int)MaskLen);
EXPECT_TRUE(isShiftedMask_64(0xffff000000000000ull, MaskIdx, MaskLen));
EXPECT_EQ(48, (int)MaskIdx);
EXPECT_EQ(16, (int)MaskLen);
EXPECT_TRUE(isShiftedMask_64(0xffull << 55, MaskIdx, MaskLen));
EXPECT_EQ(55, (int)MaskIdx);
EXPECT_EQ(8, (int)MaskLen);
}
TEST(MathExtras, isPowerOf2_32) {
EXPECT_FALSE(isPowerOf2_32(0));
EXPECT_TRUE(isPowerOf2_32(1 << 6));
@@ -271,9 +309,7 @@ TEST(MathExtras, alignTo) {
EXPECT_EQ(552u, alignTo(321, 255, 42));
}
template<typename T>
void SaturatingAddTestHelper()
{
template <typename T> void SaturatingAddTestHelper() {
const T Max = std::numeric_limits<T>::max();
bool ResultOverflowed;
@@ -296,6 +332,42 @@ void SaturatingAddTestHelper()
EXPECT_EQ(Max, SaturatingAdd(Max, Max));
EXPECT_EQ(Max, SaturatingAdd(Max, Max, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed);
EXPECT_EQ(T(6), SaturatingAdd(T(1), T(2), T(3)));
EXPECT_EQ(T(6), SaturatingAdd(T(1), T(2), T(3), &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(T(10), SaturatingAdd(T(1), T(2), T(3), T(4)));
EXPECT_EQ(T(10), SaturatingAdd(T(1), T(2), T(3), T(4), &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(Max, T(0), T(0)));
EXPECT_EQ(Max, SaturatingAdd(Max, T(0), T(0), &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(0), T(0), Max));
EXPECT_EQ(Max, SaturatingAdd(T(0), T(0), Max, &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(Max, T(0), T(1)));
EXPECT_EQ(Max, SaturatingAdd(Max, T(0), T(1), &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(0), T(1), Max));
EXPECT_EQ(Max, SaturatingAdd(T(0), T(1), Max, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 2), T(1)));
EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 2), T(1), &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(1), T(1), T(Max - 2)));
EXPECT_EQ(Max, SaturatingAdd(T(1), T(1), T(Max - 2), &ResultOverflowed));
EXPECT_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(Max, Max, Max));
EXPECT_EQ(Max, SaturatingAdd(Max, Max, Max, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed);
}
TEST(MathExtras, SaturatingAdd) {

View File

@@ -0,0 +1,15 @@
//===- llvm/unittest/ADT/MoveOnly.cpp - Optional unit tests ---------------===//
//
// 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 "MoveOnly.h"
using namespace wpi;
unsigned MoveOnly::MoveConstructions = 0;
unsigned MoveOnly::Destructions = 0;
unsigned MoveOnly::MoveAssignments = 0;

View File

@@ -0,0 +1,42 @@
//===- llvm/unittest/ADT/MoveOnly.h - Optional unit tests -----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UNITTESTS_ADT_MOVEONLY_H
#define LLVM_UNITTESTS_ADT_MOVEONLY_H
namespace wpi {
struct MoveOnly {
static unsigned MoveConstructions;
static unsigned Destructions;
static unsigned MoveAssignments;
int val;
explicit MoveOnly(int val) : val(val) {
}
MoveOnly(MoveOnly&& other) {
val = other.val;
++MoveConstructions;
}
MoveOnly &operator=(MoveOnly&& other) {
val = other.val;
++MoveAssignments;
return *this;
}
~MoveOnly() {
++Destructions;
}
static void ResetCounts() {
MoveConstructions = 0;
Destructions = 0;
MoveAssignments = 0;
}
};
} // end namespace wpi
#endif // LLVM_UNITTESTS_ADT_MOVEONLY_H

View File

@@ -62,7 +62,11 @@ TEST(PointerIntPairTest, GetSet) {
EXPECT_EQ(&s, Pair2.getPointer());
EXPECT_EQ(E::Case3, Pair2.getInt());
static_assert(std::is_trivially_copyable<PointerIntPair<S *, 2, E>>::value,
auto [Pointer2, Int2] = Pair2;
EXPECT_EQ(Pair2.getPointer(), Pointer2);
EXPECT_EQ(Pair2.getInt(), Int2);
static_assert(std::is_trivially_copyable_v<PointerIntPair<S *, 2, E>>,
"trivially copyable");
}
@@ -100,10 +104,9 @@ TEST(PointerIntPairTest, ManyUnusedBits) {
EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1,
(int)PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable);
static_assert(
std::is_trivially_copyable<
PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits>>::value,
"trivially copyable");
static_assert(std::is_trivially_copyable_v<
PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits>>,
"trivially copyable");
}
} // end anonymous namespace

View File

@@ -156,4 +156,137 @@ TEST_F(PointerUnionTest, GetAddrOfPtr1) {
EXPECT_TRUE((void *)n.getAddrOfPtr1() == (void *)&n);
}
TEST_F(PointerUnionTest, NewCastInfra) {
// test isa<>
EXPECT_TRUE(isa<float *>(a));
EXPECT_TRUE(isa<int *>(b));
EXPECT_TRUE(isa<int *>(c));
EXPECT_TRUE(isa<int *>(n));
EXPECT_TRUE(isa<int *>(i3));
EXPECT_TRUE(isa<float *>(f3));
EXPECT_TRUE(isa<long long *>(l3));
EXPECT_TRUE(isa<int *>(i4));
EXPECT_TRUE(isa<float *>(f4));
EXPECT_TRUE(isa<long long *>(l4));
EXPECT_TRUE(isa<double *>(d4));
EXPECT_TRUE(isa<int *>(i4null));
EXPECT_TRUE(isa<float *>(f4null));
EXPECT_TRUE(isa<long long *>(l4null));
EXPECT_TRUE(isa<double *>(d4null));
EXPECT_FALSE(isa<int *>(a));
EXPECT_FALSE(isa<float *>(b));
EXPECT_FALSE(isa<float *>(c));
EXPECT_FALSE(isa<float *>(n));
EXPECT_FALSE(isa<float *>(i3));
EXPECT_FALSE(isa<long long *>(i3));
EXPECT_FALSE(isa<int *>(f3));
EXPECT_FALSE(isa<long long *>(f3));
EXPECT_FALSE(isa<int *>(l3));
EXPECT_FALSE(isa<float *>(l3));
EXPECT_FALSE(isa<float *>(i4));
EXPECT_FALSE(isa<long long *>(i4));
EXPECT_FALSE(isa<double *>(i4));
EXPECT_FALSE(isa<int *>(f4));
EXPECT_FALSE(isa<long long *>(f4));
EXPECT_FALSE(isa<double *>(f4));
EXPECT_FALSE(isa<int *>(l4));
EXPECT_FALSE(isa<float *>(l4));
EXPECT_FALSE(isa<double *>(l4));
EXPECT_FALSE(isa<int *>(d4));
EXPECT_FALSE(isa<float *>(d4));
EXPECT_FALSE(isa<long long *>(d4));
EXPECT_FALSE(isa<float *>(i4null));
EXPECT_FALSE(isa<long long *>(i4null));
EXPECT_FALSE(isa<double *>(i4null));
EXPECT_FALSE(isa<int *>(f4null));
EXPECT_FALSE(isa<long long *>(f4null));
EXPECT_FALSE(isa<double *>(f4null));
EXPECT_FALSE(isa<int *>(l4null));
EXPECT_FALSE(isa<float *>(l4null));
EXPECT_FALSE(isa<double *>(l4null));
EXPECT_FALSE(isa<int *>(d4null));
EXPECT_FALSE(isa<float *>(d4null));
EXPECT_FALSE(isa<long long *>(d4null));
// test cast<>
EXPECT_EQ(cast<float *>(a), &f);
EXPECT_EQ(cast<int *>(b), &i);
EXPECT_EQ(cast<int *>(c), &i);
EXPECT_EQ(cast<int *>(i3), &i);
EXPECT_EQ(cast<float *>(f3), &f);
EXPECT_EQ(cast<long long *>(l3), &l);
EXPECT_EQ(cast<int *>(i4), &i);
EXPECT_EQ(cast<float *>(f4), &f);
EXPECT_EQ(cast<long long *>(l4), &l);
EXPECT_EQ(cast<double *>(d4), &d);
// test dyn_cast
EXPECT_EQ(dyn_cast<int *>(a), nullptr);
EXPECT_EQ(dyn_cast<float *>(a), &f);
EXPECT_EQ(dyn_cast<int *>(b), &i);
EXPECT_EQ(dyn_cast<float *>(b), nullptr);
EXPECT_EQ(dyn_cast<int *>(c), &i);
EXPECT_EQ(dyn_cast<float *>(c), nullptr);
EXPECT_EQ(dyn_cast_if_present<int *>(n), nullptr);
EXPECT_EQ(dyn_cast_if_present<float *>(n), nullptr);
EXPECT_EQ(dyn_cast<int *>(i3), &i);
EXPECT_EQ(dyn_cast<float *>(i3), nullptr);
EXPECT_EQ(dyn_cast<long long *>(i3), nullptr);
EXPECT_EQ(dyn_cast<int *>(f3), nullptr);
EXPECT_EQ(dyn_cast<float *>(f3), &f);
EXPECT_EQ(dyn_cast<long long *>(f3), nullptr);
EXPECT_EQ(dyn_cast<int *>(l3), nullptr);
EXPECT_EQ(dyn_cast<float *>(l3), nullptr);
EXPECT_EQ(dyn_cast<long long *>(l3), &l);
EXPECT_EQ(dyn_cast<int *>(i4), &i);
EXPECT_EQ(dyn_cast<float *>(i4), nullptr);
EXPECT_EQ(dyn_cast<long long *>(i4), nullptr);
EXPECT_EQ(dyn_cast<double *>(i4), nullptr);
EXPECT_EQ(dyn_cast<int *>(f4), nullptr);
EXPECT_EQ(dyn_cast<float *>(f4), &f);
EXPECT_EQ(dyn_cast<long long *>(f4), nullptr);
EXPECT_EQ(dyn_cast<double *>(f4), nullptr);
EXPECT_EQ(dyn_cast<int *>(l4), nullptr);
EXPECT_EQ(dyn_cast<float *>(l4), nullptr);
EXPECT_EQ(dyn_cast<long long *>(l4), &l);
EXPECT_EQ(dyn_cast<double *>(l4), nullptr);
EXPECT_EQ(dyn_cast<int *>(d4), nullptr);
EXPECT_EQ(dyn_cast<float *>(d4), nullptr);
EXPECT_EQ(dyn_cast<long long *>(d4), nullptr);
EXPECT_EQ(dyn_cast<double *>(d4), &d);
EXPECT_EQ(dyn_cast_if_present<int *>(i4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<float *>(i4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<long long *>(i4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<double *>(i4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<int *>(f4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<float *>(f4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<long long *>(f4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<double *>(f4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<int *>(l4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<float *>(l4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<long long *>(l4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<double *>(l4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<int *>(d4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<float *>(d4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<long long *>(d4null), nullptr);
EXPECT_EQ(dyn_cast_if_present<double *>(d4null), nullptr);
// test for const
const PU4 constd4(&d);
EXPECT_TRUE(isa<double *>(constd4));
EXPECT_FALSE(isa<int *>(constd4));
EXPECT_EQ(cast<double *>(constd4), &d);
EXPECT_EQ(dyn_cast<long long *>(constd4), nullptr);
auto *result1 = cast<double *>(constd4);
static_assert(std::is_same_v<double *, decltype(result1)>,
"type mismatch for cast with PointerUnion");
PointerUnion<int *, const double *> constd2(&d);
auto *result2 = cast<const double *>(constd2);
EXPECT_EQ(result2, &d);
static_assert(std::is_same_v<const double *, decltype(result2)>,
"type mismatch for cast with PointerUnion");
}
} // end anonymous namespace

View File

@@ -7,41 +7,11 @@
//===----------------------------------------------------------------------===//
#include "wpi/STLForwardCompat.h"
#include "MoveOnly.h"
#include "gtest/gtest.h"
namespace {
TEST(STLForwardCompatTest, NegationTest) {
EXPECT_TRUE((wpi::negation<std::false_type>::value));
EXPECT_FALSE((wpi::negation<std::true_type>::value));
}
struct incomplete_type;
TEST(STLForwardCompatTest, ConjunctionTest) {
EXPECT_TRUE((wpi::conjunction<>::value));
EXPECT_FALSE((wpi::conjunction<std::false_type>::value));
EXPECT_TRUE((wpi::conjunction<std::true_type>::value));
EXPECT_FALSE((wpi::conjunction<std::false_type, incomplete_type>::value));
EXPECT_FALSE((wpi::conjunction<std::false_type, std::true_type>::value));
EXPECT_FALSE((wpi::conjunction<std::true_type, std::false_type>::value));
EXPECT_TRUE((wpi::conjunction<std::true_type, std::true_type>::value));
EXPECT_TRUE((wpi::conjunction<std::true_type, std::true_type,
std::true_type>::value));
}
TEST(STLForwardCompatTest, DisjunctionTest) {
EXPECT_FALSE((wpi::disjunction<>::value));
EXPECT_FALSE((wpi::disjunction<std::false_type>::value));
EXPECT_TRUE((wpi::disjunction<std::true_type>::value));
EXPECT_TRUE((wpi::disjunction<std::true_type, incomplete_type>::value));
EXPECT_TRUE((wpi::disjunction<std::false_type, std::true_type>::value));
EXPECT_TRUE((wpi::disjunction<std::true_type, std::false_type>::value));
EXPECT_TRUE((wpi::disjunction<std::true_type, std::true_type>::value));
EXPECT_TRUE((wpi::disjunction<std::true_type, std::true_type,
std::true_type>::value));
}
template <typename T>
class STLForwardCompatRemoveCVRefTest : public ::testing::Test {};
@@ -75,4 +45,78 @@ TYPED_TEST(STLForwardCompatRemoveCVRefTest, RemoveCVRefT) {
wpi::remove_cvref_t<From>>::value));
}
TEST(TransformTest, TransformStd) {
std::optional<int> A;
std::optional<int> B = wpi::transformOptional(A, [&](int N) { return N + 1; });
EXPECT_FALSE(B.has_value());
A = 3;
std::optional<int> C = wpi::transformOptional(A, [&](int N) { return N + 1; });
EXPECT_TRUE(C.has_value());
EXPECT_EQ(4, *C);
}
TEST(TransformTest, MoveTransformStd) {
using wpi::MoveOnly;
std::optional<MoveOnly> A;
MoveOnly::ResetCounts();
std::optional<int> B = wpi::transformOptional(
std::move(A), [&](const MoveOnly &M) { return M.val + 2; });
EXPECT_FALSE(B.has_value());
EXPECT_EQ(0u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
EXPECT_EQ(0u, MoveOnly::Destructions);
A = MoveOnly(5);
MoveOnly::ResetCounts();
std::optional<int> C = wpi::transformOptional(
std::move(A), [&](const MoveOnly &M) { return M.val + 2; });
EXPECT_TRUE(C.has_value());
EXPECT_EQ(7, *C);
EXPECT_EQ(0u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
EXPECT_EQ(0u, MoveOnly::Destructions);
}
TEST(TransformTest, TransformLlvm) {
std::optional<int> A;
std::optional<int> B =
wpi::transformOptional(A, [&](int N) { return N + 1; });
EXPECT_FALSE(B.has_value());
A = 3;
std::optional<int> C =
wpi::transformOptional(A, [&](int N) { return N + 1; });
EXPECT_TRUE(C.has_value());
EXPECT_EQ(4, *C);
}
TEST(TransformTest, MoveTransformLlvm) {
using wpi::MoveOnly;
std::optional<MoveOnly> A;
MoveOnly::ResetCounts();
std::optional<int> B = wpi::transformOptional(
std::move(A), [&](const MoveOnly &M) { return M.val + 2; });
EXPECT_FALSE(B.has_value());
EXPECT_EQ(0u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
EXPECT_EQ(0u, MoveOnly::Destructions);
A = MoveOnly(5);
MoveOnly::ResetCounts();
std::optional<int> C = wpi::transformOptional(
std::move(A), [&](const MoveOnly &M) { return M.val + 2; });
EXPECT_TRUE(C.has_value());
EXPECT_EQ(7, *C);
EXPECT_EQ(0u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
EXPECT_EQ(0u, MoveOnly::Destructions);
}
} // namespace

View File

@@ -12,6 +12,7 @@
#include "wpi/SmallSet.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
using namespace wpi;
@@ -20,11 +21,17 @@ TEST(SmallSetTest, Insert) {
SmallSet<int, 4> s1;
for (int i = 0; i < 4; i++)
s1.insert(i);
for (int i = 0; i < 4; i++) {
auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, true);
}
for (int i = 0; i < 4; i++)
s1.insert(i);
for (int i = 0; i < 4; i++) {
auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, false);
}
EXPECT_EQ(4u, s1.size());
@@ -37,8 +44,17 @@ TEST(SmallSetTest, Insert) {
TEST(SmallSetTest, Grow) {
SmallSet<int, 4> s1;
for (int i = 0; i < 8; i++)
s1.insert(i);
for (int i = 0; i < 8; i++) {
auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, true);
}
for (int i = 0; i < 8; i++) {
auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, false);
}
EXPECT_EQ(8u, s1.size());

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,10 @@ using namespace wpi;
namespace {
static_assert(sizeof(StringMap<uint32_t>) <
sizeof(StringMap<uint32_t, MallocAllocator &>),
"Ensure empty base optimization happens with default allocator");
// Test fixture
class StringMapTest : public testing::Test {
protected:
@@ -22,7 +26,7 @@ protected:
static const char testKey[];
static const uint32_t testValue;
static const char* testKeyFirst;
static const char *testKeyFirst;
static size_t testKeyLength;
static const std::string testKeyStr;
@@ -39,7 +43,7 @@ protected:
EXPECT_EQ(0u, testMap.count(std::string_view(testKeyFirst, testKeyLength)));
EXPECT_EQ(0u, testMap.count(testKeyStr));
EXPECT_TRUE(testMap.find(testKey) == testMap.end());
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
testMap.end());
EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
}
@@ -62,7 +66,7 @@ protected:
EXPECT_EQ(1u, testMap.count(std::string_view(testKeyFirst, testKeyLength)));
EXPECT_EQ(1u, testMap.count(testKeyStr));
EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
testMap.begin());
EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
}
@@ -70,7 +74,7 @@ protected:
const char StringMapTest::testKey[] = "key";
const uint32_t StringMapTest::testValue = 1u;
const char* StringMapTest::testKeyFirst = testKey;
const char *StringMapTest::testKeyFirst = testKey;
size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
const std::string StringMapTest::testKeyStr(testKey);
@@ -85,13 +89,11 @@ struct CountCopyAndMove {
};
// Empty map tests.
TEST_F(StringMapTest, EmptyMapTest) {
assertEmptyMap();
}
TEST_F(StringMapTest, EmptyMapTest) { assertEmptyMap(); }
// Constant map tests.
TEST_F(StringMapTest, ConstEmptyMapTest) {
const StringMap<uint32_t>& constTestMap = testMap;
const StringMap<uint32_t> &constTestMap = testMap;
// Size tests
EXPECT_EQ(0u, constTestMap.size());
@@ -214,8 +216,8 @@ TEST_F(StringMapTest, IterationTest) {
}
// Iterate over all numbers and mark each one found.
for (StringMap<uint32_t>::iterator it = testMap.begin();
it != testMap.end(); ++it) {
for (StringMap<uint32_t>::iterator it = testMap.begin(); it != testMap.end();
++it) {
std::stringstream ss;
ss << "key_" << it->second;
ASSERT_STREQ(ss.str().c_str(), it->first().data());
@@ -232,7 +234,7 @@ TEST_F(StringMapTest, IterationTest) {
TEST_F(StringMapTest, StringMapEntryTest) {
MallocAllocator Allocator;
StringMap<uint32_t>::value_type *entry =
StringMap<uint32_t>::value_type::Create(
StringMap<uint32_t>::value_type::create(
std::string_view(testKeyFirst, testKeyLength), Allocator, 1u);
EXPECT_STREQ(testKey, entry->first().data());
EXPECT_EQ(1u, entry->second);
@@ -242,10 +244,8 @@ TEST_F(StringMapTest, StringMapEntryTest) {
// Test insert() method.
TEST_F(StringMapTest, InsertTest) {
SCOPED_TRACE("InsertTest");
testMap.insert(
StringMap<uint32_t>::value_type::Create(
std::string_view(testKeyFirst, testKeyLength),
testMap.getAllocator(), 1u));
testMap.insert(StringMap<uint32_t>::value_type::create(
std::string_view(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u));
assertSingleItemMap();
}
@@ -280,7 +280,7 @@ TEST_F(StringMapTest, InsertRehashingPairTest) {
EXPECT_EQ(0u, t.getNumBuckets());
StringMap<uint32_t>::iterator It =
t.insert(std::make_pair("abcdef", 42)).first;
t.insert(std::make_pair("abcdef", 42)).first;
EXPECT_EQ(16u, t.getNumBuckets());
EXPECT_EQ("abcdef", It->first());
EXPECT_EQ(42u, It->second);
@@ -338,13 +338,13 @@ TEST_F(StringMapTest, NonDefaultConstructable) {
struct Immovable {
Immovable() {}
Immovable(Immovable&&) = delete; // will disable the other special members
Immovable(Immovable &&) = delete; // will disable the other special members
};
struct MoveOnly {
int i;
MoveOnly(int i) : i(i) {}
MoveOnly(const Immovable&) : i(0) {}
MoveOnly(const Immovable &) : i(0) {}
MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
MoveOnly &operator=(MoveOnly &&RHS) {
i = RHS.i;
@@ -360,14 +360,14 @@ TEST_F(StringMapTest, MoveOnly) {
StringMap<MoveOnly> t;
t.insert(std::make_pair("Test", MoveOnly(42)));
std::string_view Key = "Test";
StringMapEntry<MoveOnly>::Create(Key, t.getAllocator(), MoveOnly(42))
StringMapEntry<MoveOnly>::create(Key, t.getAllocator(), MoveOnly(42))
->Destroy(t.getAllocator());
}
TEST_F(StringMapTest, CtorArg) {
std::string_view Key = "Test";
MallocAllocator Allocator;
StringMapEntry<MoveOnly>::Create(Key, Allocator, Immovable())
StringMapEntry<MoveOnly>::create(Key, Allocator, Immovable())
->Destroy(Allocator);
}
@@ -501,6 +501,16 @@ TEST_F(StringMapTest, MoveDtor) {
ASSERT_TRUE(B.empty());
}
TEST_F(StringMapTest, StructuredBindings) {
StringMap<int> A;
A["a"] = 42;
for (auto &[Key, Value] : A) {
EXPECT_EQ("a", Key);
EXPECT_EQ(42, Value);
}
}
namespace {
// Simple class that counts how many moves and copy happens when growing a map
struct CountCtorCopyAndMove {
@@ -570,7 +580,7 @@ struct NonMoveableNonCopyableType {
NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
};
}
} // namespace
// Test that we can "emplace" an element in the map without involving map/move
TEST(StringMapCustomTest, EmplaceTest) {