mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-03 03:01:44 +00:00
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
@@ -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 *)>
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 @@
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -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 {
|
||||
436
upstream_utils/llvm_patches/0030-Use-C-20-bit-header.patch
Normal file
436
upstream_utils/llvm_patches/0030-Use-C-20-bit-header.patch
Normal 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.
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
808
wpiutil/src/main/native/thirdparty/llvm/include/wpi/Casting.h
vendored
Normal file
808
wpiutil/src/main/native/thirdparty/llvm/include/wpi/Casting.h
vendored
Normal 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
|
||||
@@ -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__)
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <cerrno>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace wpi {
|
||||
namespace sys {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)};
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
99
wpiutil/src/main/native/thirdparty/llvm/include/wpi/bit.h
vendored
Normal file
99
wpiutil/src/main/native/thirdparty/llvm/include/wpi/bit.h
vendored
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
15
wpiutil/src/test/native/cpp/llvm/MoveOnly.cpp
Normal file
15
wpiutil/src/test/native/cpp/llvm/MoveOnly.cpp
Normal 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;
|
||||
42
wpiutil/src/test/native/cpp/llvm/MoveOnly.h
Normal file
42
wpiutil/src/test/native/cpp/llvm/MoveOnly.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user