Importing rustc-1.45.2
Change-Id: Idd187dd729f3089d9529753a17db5fbb40bacdeb
diff --git a/src/llvm-project/llvm/unittests/Support/AlignOfTest.cpp b/src/llvm-project/llvm/unittests/Support/AlignOfTest.cpp
index 94c6f5a..d8cabde 100644
--- a/src/llvm-project/llvm/unittests/Support/AlignOfTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/AlignOfTest.cpp
@@ -38,10 +38,10 @@
#endif
// Define some fixed alignment types to use in these tests.
-struct LLVM_ALIGNAS(1) A1 {};
-struct LLVM_ALIGNAS(2) A2 {};
-struct LLVM_ALIGNAS(4) A4 {};
-struct LLVM_ALIGNAS(8) A8 {};
+struct alignas(1) A1 {};
+struct alignas(2) A2 {};
+struct alignas(4) A4 {};
+struct alignas(8) A8 {};
struct S1 {};
struct S2 { char a; };
@@ -233,16 +233,5 @@
#ifndef _MSC_VER
EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion<V8>));
#endif
-
- EXPECT_EQ(1u, (alignof(AlignedCharArray<1, 1>)));
- EXPECT_EQ(2u, (alignof(AlignedCharArray<2, 1>)));
- EXPECT_EQ(4u, (alignof(AlignedCharArray<4, 1>)));
- EXPECT_EQ(8u, (alignof(AlignedCharArray<8, 1>)));
- EXPECT_EQ(16u, (alignof(AlignedCharArray<16, 1>)));
-
- EXPECT_EQ(1u, sizeof(AlignedCharArray<1, 1>));
- EXPECT_EQ(7u, sizeof(AlignedCharArray<1, 7>));
- EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>));
- EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>));
}
} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/AlignmentTest.cpp b/src/llvm-project/llvm/unittests/Support/AlignmentTest.cpp
new file mode 100644
index 0000000..cbd0856
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Support/AlignmentTest.cpp
@@ -0,0 +1,396 @@
+//=== - llvm/unittest/Support/Alignment.cpp - Alignment utility 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 "llvm/Support/Alignment.h"
+#include "gtest/gtest.h"
+
+#include <vector>
+
+#ifdef _MSC_VER
+// Disable warnings about potential divide by 0.
+#pragma warning(push)
+#pragma warning(disable : 4723)
+#endif
+
+using namespace llvm;
+
+namespace {
+
+TEST(AlignmentTest, AlignOfConstant) {
+ EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t)));
+ EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t)));
+ EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t)));
+ EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t)));
+}
+
+TEST(AlignmentTest, AlignConstant) {
+ EXPECT_EQ(Align::Constant<1>(), Align(1));
+ EXPECT_EQ(Align::Constant<2>(), Align(2));
+ EXPECT_EQ(Align::Constant<4>(), Align(4));
+ EXPECT_EQ(Align::Constant<8>(), Align(8));
+ EXPECT_EQ(Align::Constant<16>(), Align(16));
+ EXPECT_EQ(Align::Constant<32>(), Align(32));
+ EXPECT_EQ(Align::Constant<64>(), Align(64));
+}
+
+TEST(AlignmentTest, AlignConstexprConstant) {
+ constexpr Align kConstantAlign = Align::Of<uint64_t>();
+ EXPECT_EQ(Align(alignof(uint64_t)), kConstantAlign);
+}
+
+std::vector<uint64_t> getValidAlignments() {
+ std::vector<uint64_t> Out;
+ for (size_t Shift = 0; Shift < 64; ++Shift)
+ Out.push_back(1ULL << Shift);
+ return Out;
+}
+
+TEST(AlignmentTest, AlignDefaultCTor) {
+ EXPECT_EQ(Align().value(), 1ULL);
+ EXPECT_EQ(Align::None().value(), 1ULL);
+}
+
+TEST(AlignmentTest, MaybeAlignDefaultCTor) {
+ EXPECT_FALSE(MaybeAlign().hasValue());
+}
+
+TEST(AlignmentTest, ValidCTors) {
+ for (uint64_t Value : getValidAlignments()) {
+ EXPECT_EQ(Align(Value).value(), Value);
+ EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
+ }
+}
+
+TEST(AlignmentTest, CheckMaybeAlignHasValue) {
+ EXPECT_TRUE(MaybeAlign(1));
+ EXPECT_TRUE(MaybeAlign(1).hasValue());
+ EXPECT_FALSE(MaybeAlign(0));
+ EXPECT_FALSE(MaybeAlign(0).hasValue());
+ EXPECT_FALSE(MaybeAlign());
+ EXPECT_FALSE(MaybeAlign().hasValue());
+}
+
+TEST(AlignmentTest, Division) {
+ for (uint64_t Value : getValidAlignments()) {
+ if (Value > 1) {
+ EXPECT_EQ(Align(Value) / 2, Value / 2);
+ EXPECT_EQ(MaybeAlign(Value) / 2, Value / 2);
+ }
+ }
+ EXPECT_EQ(MaybeAlign(0) / 2, MaybeAlign(0));
+}
+
+TEST(AlignmentTest, AlignTo) {
+ struct {
+ uint64_t alignment;
+ uint64_t offset;
+ uint64_t rounded;
+ const void *forgedAddr() const {
+ // A value of any integral or enumeration type can be converted to a
+ // pointer type.
+ return reinterpret_cast<const void *>(offset);
+ }
+ } kTests[] = {
+ // MaybeAlign
+ {0, 0, 0},
+ {0, 1, 1},
+ {0, 5, 5},
+ // MaybeAlign / Align
+ {1, 0, 0},
+ {1, 1, 1},
+ {1, 5, 5},
+ {2, 0, 0},
+ {2, 1, 2},
+ {2, 2, 2},
+ {2, 7, 8},
+ {2, 16, 16},
+ {4, 0, 0},
+ {4, 1, 4},
+ {4, 4, 4},
+ {4, 6, 8},
+ };
+ for (const auto &T : kTests) {
+ MaybeAlign A(T.alignment);
+ // Test MaybeAlign
+ EXPECT_EQ(alignTo(T.offset, A), T.rounded);
+ // Test Align
+ if (A) {
+ EXPECT_EQ(alignTo(T.offset, A.getValue()), T.rounded);
+ EXPECT_EQ(alignAddr(T.forgedAddr(), A.getValue()), T.rounded);
+ }
+ }
+}
+
+TEST(AlignmentTest, Log2) {
+ for (uint64_t Value : getValidAlignments()) {
+ EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
+ EXPECT_EQ(Log2(MaybeAlign(Value)), Log2_64(Value));
+ }
+}
+
+TEST(AlignmentTest, MinAlign) {
+ struct {
+ uint64_t A;
+ uint64_t B;
+ uint64_t MinAlign;
+ } kTests[] = {
+ // MaybeAlign
+ {0, 0, 0},
+ {0, 8, 8},
+ {2, 0, 2},
+ // MaybeAlign / Align
+ {1, 2, 1},
+ {8, 4, 4},
+ };
+ for (const auto &T : kTests) {
+ EXPECT_EQ(commonAlignment(MaybeAlign(T.A), MaybeAlign(T.B)), T.MinAlign);
+ EXPECT_EQ(MinAlign(T.A, T.B), T.MinAlign);
+ if (T.A) {
+ EXPECT_EQ(commonAlignment(Align(T.A), MaybeAlign(T.B)), T.MinAlign);
+ }
+ if (T.B) {
+ EXPECT_EQ(commonAlignment(MaybeAlign(T.A), Align(T.B)), T.MinAlign);
+ }
+ if (T.A && T.B) {
+ EXPECT_EQ(commonAlignment(Align(T.A), Align(T.B)), T.MinAlign);
+ }
+ }
+}
+
+TEST(AlignmentTest, Encode_Decode) {
+ for (uint64_t Value : getValidAlignments()) {
+ {
+ Align Actual(Value);
+ Align Expected = decodeMaybeAlign(encode(Actual)).getValue();
+ EXPECT_EQ(Expected, Actual);
+ }
+ {
+ MaybeAlign Actual(Value);
+ MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
+ EXPECT_EQ(Expected, Actual);
+ }
+ }
+ MaybeAlign Actual(0);
+ MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
+ EXPECT_EQ(Expected, Actual);
+}
+
+TEST(AlignmentTest, isAligned_isAddrAligned) {
+ struct {
+ uint64_t alignment;
+ uint64_t offset;
+ bool isAligned;
+ const void *forgedAddr() const {
+ // A value of any integral or enumeration type can be converted to a
+ // pointer type.
+ return reinterpret_cast<const void *>(offset);
+ }
+ } kTests[] = {
+ {1, 0, true}, {1, 1, true}, {1, 5, true}, {2, 0, true},
+ {2, 1, false}, {2, 2, true}, {2, 7, false}, {2, 16, true},
+ {4, 0, true}, {4, 1, false}, {4, 4, true}, {4, 6, false},
+ };
+ for (const auto &T : kTests) {
+ MaybeAlign A(T.alignment);
+ // Test MaybeAlign
+ EXPECT_EQ(isAligned(A, T.offset), T.isAligned);
+ // Test Align
+ if (A) {
+ EXPECT_EQ(isAligned(A.getValue(), T.offset), T.isAligned);
+ EXPECT_EQ(isAddrAligned(A.getValue(), T.forgedAddr()), T.isAligned);
+ }
+ }
+}
+
+TEST(AlignmentTest, offsetToAlignment) {
+ struct {
+ uint64_t alignment;
+ uint64_t offset;
+ uint64_t alignedOffset;
+ const void *forgedAddr() const {
+ // A value of any integral or enumeration type can be converted to a
+ // pointer type.
+ return reinterpret_cast<const void *>(offset);
+ }
+ } kTests[] = {
+ {1, 0, 0}, {1, 1, 0}, {1, 5, 0}, {2, 0, 0}, {2, 1, 1}, {2, 2, 0},
+ {2, 7, 1}, {2, 16, 0}, {4, 0, 0}, {4, 1, 3}, {4, 4, 0}, {4, 6, 2},
+ };
+ for (const auto &T : kTests) {
+ const Align A(T.alignment);
+ EXPECT_EQ(offsetToAlignment(T.offset, A), T.alignedOffset);
+ EXPECT_EQ(offsetToAlignedAddr(T.forgedAddr(), A), T.alignedOffset);
+ }
+}
+
+TEST(AlignmentTest, AlignComparisons) {
+ std::vector<uint64_t> ValidAlignments = getValidAlignments();
+ std::sort(ValidAlignments.begin(), ValidAlignments.end());
+ for (size_t I = 1; I < ValidAlignments.size(); ++I) {
+ assert(I >= 1);
+ const Align A(ValidAlignments[I - 1]);
+ const Align B(ValidAlignments[I]);
+ EXPECT_EQ(A, A);
+ EXPECT_NE(A, B);
+ EXPECT_LT(A, B);
+ EXPECT_GT(B, A);
+ EXPECT_LE(A, B);
+ EXPECT_GE(B, A);
+ EXPECT_LE(A, A);
+ EXPECT_GE(A, A);
+
+ EXPECT_EQ(A, A.value());
+ EXPECT_NE(A, B.value());
+ EXPECT_LT(A, B.value());
+ EXPECT_GT(B, A.value());
+ EXPECT_LE(A, B.value());
+ EXPECT_GE(B, A.value());
+ EXPECT_LE(A, A.value());
+ EXPECT_GE(A, A.value());
+
+ EXPECT_EQ(std::max(A, B), B);
+ EXPECT_EQ(std::min(A, B), A);
+
+ const MaybeAlign MA(ValidAlignments[I - 1]);
+ const MaybeAlign MB(ValidAlignments[I]);
+ EXPECT_EQ(MA, MA);
+ EXPECT_NE(MA, MB);
+ EXPECT_LT(MA, MB);
+ EXPECT_GT(MB, MA);
+ EXPECT_LE(MA, MB);
+ EXPECT_GE(MB, MA);
+ EXPECT_LE(MA, MA);
+ EXPECT_GE(MA, MA);
+
+ EXPECT_EQ(MA, MA ? (*MA).value() : 0);
+ EXPECT_NE(MA, MB ? (*MB).value() : 0);
+ EXPECT_LT(MA, MB ? (*MB).value() : 0);
+ EXPECT_GT(MB, MA ? (*MA).value() : 0);
+ EXPECT_LE(MA, MB ? (*MB).value() : 0);
+ EXPECT_GE(MB, MA ? (*MA).value() : 0);
+ EXPECT_LE(MA, MA ? (*MA).value() : 0);
+ EXPECT_GE(MA, MA ? (*MA).value() : 0);
+
+ EXPECT_EQ(std::max(A, B), B);
+ EXPECT_EQ(std::min(A, B), A);
+ }
+}
+
+TEST(AlignmentTest, Max) {
+ // We introduce std::max here to test ADL.
+ using std::max;
+
+ // Uses llvm::max.
+ EXPECT_EQ(max(MaybeAlign(), Align(2)), Align(2));
+ EXPECT_EQ(max(Align(2), MaybeAlign()), Align(2));
+
+ EXPECT_EQ(max(MaybeAlign(1), Align(2)), Align(2));
+ EXPECT_EQ(max(Align(2), MaybeAlign(1)), Align(2));
+
+ EXPECT_EQ(max(MaybeAlign(2), Align(2)), Align(2));
+ EXPECT_EQ(max(Align(2), MaybeAlign(2)), Align(2));
+
+ EXPECT_EQ(max(MaybeAlign(4), Align(2)), Align(4));
+ EXPECT_EQ(max(Align(2), MaybeAlign(4)), Align(4));
+
+ // Uses std::max.
+ EXPECT_EQ(max(Align(2), Align(4)), Align(4));
+ EXPECT_EQ(max(MaybeAlign(2), MaybeAlign(4)), MaybeAlign(4));
+ EXPECT_EQ(max(MaybeAlign(), MaybeAlign()), MaybeAlign());
+}
+
+TEST(AlignmentTest, AssumeAligned) {
+ EXPECT_EQ(assumeAligned(0), Align(1));
+ EXPECT_EQ(assumeAligned(0), Align());
+ EXPECT_EQ(assumeAligned(1), Align(1));
+ EXPECT_EQ(assumeAligned(1), Align());
+}
+
+// Death tests reply on assert which is disabled in release mode.
+#ifndef NDEBUG
+
+// We use a subset of valid alignments for DEATH_TESTs as they are particularly
+// slow.
+std::vector<uint64_t> getValidAlignmentsForDeathTest() {
+ return {1, 1ULL << 31, 1ULL << 63};
+}
+
+std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }
+
+TEST(AlignmentDeathTest, Log2) {
+ EXPECT_DEATH(Log2(MaybeAlign(0)), ".* should be defined");
+}
+
+TEST(AlignmentDeathTest, CantConvertUnsetMaybe) {
+ EXPECT_DEATH((MaybeAlign(0).getValue()), ".*");
+}
+
+TEST(AlignmentDeathTest, Division) {
+ EXPECT_DEATH(Align(1) / 2, "Can't halve byte alignment");
+ EXPECT_DEATH(MaybeAlign(1) / 2, "Can't halve byte alignment");
+
+ EXPECT_DEATH(Align(8) / 0, "Divisor must be positive and a power of 2");
+ EXPECT_DEATH(Align(8) / 3, "Divisor must be positive and a power of 2");
+}
+
+TEST(AlignmentDeathTest, InvalidCTors) {
+ EXPECT_DEATH((Align(0)), "Value must not be 0");
+ for (uint64_t Value : getNonPowerOfTwo()) {
+ EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
+ EXPECT_DEATH((MaybeAlign(Value)),
+ "Alignment is neither 0 nor a power of 2");
+ }
+}
+
+TEST(AlignmentDeathTest, ComparisonsWithZero) {
+ for (uint64_t Value : getValidAlignmentsForDeathTest()) {
+ EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
+ }
+}
+
+TEST(AlignmentDeathTest, CompareMaybeAlignToZero) {
+ for (uint64_t Value : getValidAlignmentsForDeathTest()) {
+ // MaybeAlign is allowed to be == or != 0
+ (void)(MaybeAlign(Value) == 0);
+ (void)(MaybeAlign(Value) != 0);
+ EXPECT_DEATH((void)(MaybeAlign(Value) >= 0), ".* should be defined");
+ EXPECT_DEATH((void)(MaybeAlign(Value) <= 0), ".* should be defined");
+ EXPECT_DEATH((void)(MaybeAlign(Value) > 0), ".* should be defined");
+ EXPECT_DEATH((void)(MaybeAlign(Value) < 0), ".* should be defined");
+ }
+}
+
+TEST(AlignmentDeathTest, CompareAlignToUndefMaybeAlign) {
+ for (uint64_t Value : getValidAlignmentsForDeathTest()) {
+ EXPECT_DEATH((void)(Align(Value) == MaybeAlign(0)), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) != MaybeAlign(0)), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) >= MaybeAlign(0)), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) <= MaybeAlign(0)), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) > MaybeAlign(0)), ".* should be defined");
+ EXPECT_DEATH((void)(Align(Value) < MaybeAlign(0)), ".* should be defined");
+ }
+}
+
+TEST(AlignmentDeathTest, AlignAddr) {
+ const void *const unaligned_high_ptr =
+ reinterpret_cast<const void *>(std::numeric_limits<uintptr_t>::max() - 1);
+ EXPECT_DEATH(alignAddr(unaligned_high_ptr, Align(16)), "Overflow");
+}
+
+#endif // NDEBUG
+
+} // end anonymous namespace
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/src/llvm-project/llvm/unittests/Support/AllocatorTest.cpp b/src/llvm-project/llvm/unittests/Support/AllocatorTest.cpp
index a0223ea..8a07ddd 100644
--- a/src/llvm-project/llvm/unittests/Support/AllocatorTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/AllocatorTest.cpp
@@ -145,8 +145,8 @@
void *Allocate(size_t Size, size_t /*Alignment*/) {
// Allocate space for the alignment, the slab, and a void* that goes right
// before the slab.
- size_t Alignment = 4096;
- void *MemBase = safe_malloc(Size + Alignment - 1 + sizeof(void*));
+ Align Alignment(4096);
+ void *MemBase = safe_malloc(Size + Alignment.value() - 1 + sizeof(void *));
// Find the slab start.
void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment);
diff --git a/src/llvm-project/llvm/unittests/Support/BinaryStreamTest.cpp b/src/llvm-project/llvm/unittests/Support/BinaryStreamTest.cpp
index 5291a31..6d6ecc4 100644
--- a/src/llvm-project/llvm/unittests/Support/BinaryStreamTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/BinaryStreamTest.cpp
@@ -144,8 +144,8 @@
for (uint32_t I = 0; I < NumEndians; ++I) {
auto InByteStream =
- llvm::make_unique<BinaryByteStream>(InputData, Endians[I]);
- auto InBrokenStream = llvm::make_unique<BrokenStream>(
+ std::make_unique<BinaryByteStream>(InputData, Endians[I]);
+ auto InBrokenStream = std::make_unique<BrokenStream>(
BrokenInputData, Endians[I], Align);
Streams[I * 2].Input = std::move(InByteStream);
@@ -159,8 +159,8 @@
for (uint32_t I = 0; I < NumEndians; ++I) {
Streams[I * 2].Output =
- llvm::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
- Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
+ std::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
+ Streams[I * 2 + 1].Output = std::make_unique<BrokenStream>(
BrokenOutputData, Endians[I], Align);
}
}
@@ -168,8 +168,8 @@
void initializeOutputFromInput(uint32_t Align) {
for (uint32_t I = 0; I < NumEndians; ++I) {
Streams[I * 2].Output =
- llvm::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
- Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
+ std::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
+ Streams[I * 2 + 1].Output = std::make_unique<BrokenStream>(
BrokenInputData, Endians[I], Align);
}
}
@@ -177,8 +177,8 @@
void initializeInputFromOutput(uint32_t Align) {
for (uint32_t I = 0; I < NumEndians; ++I) {
Streams[I * 2].Input =
- llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]);
- Streams[I * 2 + 1].Input = llvm::make_unique<BrokenStream>(
+ std::make_unique<BinaryByteStream>(OutputData, Endians[I]);
+ Streams[I * 2 + 1].Input = std::make_unique<BrokenStream>(
BrokenOutputData, Endians[I], Align);
}
}
diff --git a/src/llvm-project/llvm/unittests/Support/CMakeLists.txt b/src/llvm-project/llvm/unittests/Support/CMakeLists.txt
index da2b501..1618915 100644
--- a/src/llvm-project/llvm/unittests/Support/CMakeLists.txt
+++ b/src/llvm-project/llvm/unittests/Support/CMakeLists.txt
@@ -3,6 +3,7 @@
)
add_llvm_unittest(SupportTests
+ AlignmentTest.cpp
AlignOfTest.cpp
AllocatorTest.cpp
AnnotationsTest.cpp
@@ -30,7 +31,9 @@
ErrorOrTest.cpp
ErrorTest.cpp
FileCheckTest.cpp
+ FileCollectorTest.cpp
FileOutputBufferTest.cpp
+ FileUtilitiesTest.cpp
FormatVariadicTest.cpp
GlobPatternTest.cpp
Host.cpp
diff --git a/src/llvm-project/llvm/unittests/Support/CRCTest.cpp b/src/llvm-project/llvm/unittests/Support/CRCTest.cpp
index 71afb0a..32d2cf7 100644
--- a/src/llvm-project/llvm/unittests/Support/CRCTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/CRCTest.cpp
@@ -11,19 +11,54 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/CRC.h"
+#include "llvm/ADT/StringExtras.h"
#include "gtest/gtest.h"
+#include <stdlib.h>
using namespace llvm;
namespace {
TEST(CRCTest, CRC32) {
- EXPECT_EQ(0x414FA339U,
- llvm::crc32(
- 0, StringRef("The quick brown fox jumps over the lazy dog")));
+ EXPECT_EQ(0x414FA339U, llvm::crc32(arrayRefFromStringRef(
+ "The quick brown fox jumps over the lazy dog")));
+
// CRC-32/ISO-HDLC test vector
// http://reveng.sourceforge.net/crc-catalogue/17plus.htm#crc.cat.crc-32c
- EXPECT_EQ(0xCBF43926U, llvm::crc32(0, StringRef("123456789")));
+ EXPECT_EQ(0xCBF43926U, llvm::crc32(arrayRefFromStringRef("123456789")));
+
+ // Check the CRC-32 of each byte value, exercising all of CRCTable.
+ for (int i = 0; i < 256; i++) {
+ // Compute CRCTable[i] using Hacker's Delight (2nd ed.) Figure 14-7.
+ uint32_t crc = i;
+ for (int j = 7; j >= 0; j--) {
+ uint32_t mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+
+ // CRCTable[i] is the CRC-32 of i without the initial and final bit flips.
+ uint8_t byte = i;
+ EXPECT_EQ(crc, ~llvm::crc32(0xFFFFFFFFU, byte));
+ }
+
+ EXPECT_EQ(0x00000000U, llvm::crc32(arrayRefFromStringRef("")));
}
+#if (SIZE_MAX > UINT32_MAX) && defined(EXPENSIVE_CHECKS)
+TEST(CRCTest, LargeCRC32) {
+ // Check that crc32 can handle inputs with sizes larger than 32 bits.
+ size_t TestSize = (size_t)UINT32_MAX + 42;
+ uint8_t *TestData = (uint8_t*)calloc(TestSize, 1);
+ if (!TestData)
+ return;
+
+ // Test expectation generated with:
+ // $ truncate --size=`echo 2^32-1+42 | bc` /tmp/foo
+ // $ crc32 /tmp/foo
+ EXPECT_EQ(0xE46F28FBU, llvm::crc32(makeArrayRef(TestData, TestSize)));
+
+ free(TestData);
+}
+#endif
+
} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/Casting.cpp b/src/llvm-project/llvm/unittests/Support/Casting.cpp
index bcdaca9..a196fc2 100644
--- a/src/llvm-project/llvm/unittests/Support/Casting.cpp
+++ b/src/llvm-project/llvm/unittests/Support/Casting.cpp
@@ -193,12 +193,12 @@
EXPECT_NE(F5, null_foo);
}
-std::unique_ptr<derived> newd() { return llvm::make_unique<derived>(); }
-std::unique_ptr<base> newb() { return llvm::make_unique<derived>(); }
+std::unique_ptr<derived> newd() { return std::make_unique<derived>(); }
+std::unique_ptr<base> newb() { return std::make_unique<derived>(); }
TEST(CastingTest, unique_dyn_cast) {
derived *OrigD = nullptr;
- auto D = llvm::make_unique<derived>();
+ auto D = std::make_unique<derived>();
OrigD = D.get();
// Converting from D to itself is valid, it should return a new unique_ptr
diff --git a/src/llvm-project/llvm/unittests/Support/CommandLineTest.cpp b/src/llvm-project/llvm/unittests/Support/CommandLineTest.cpp
index 1a1c8a4..a435200 100644
--- a/src/llvm-project/llvm/unittests/Support/CommandLineTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/CommandLineTest.cpp
@@ -9,23 +9,33 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <fstream>
#include <stdlib.h>
#include <string>
+#include <tuple>
using namespace llvm;
namespace {
+MATCHER(StringEquality, "Checks if two char* are equal as strings") {
+ return std::string(std::get<0>(arg)) == std::string(std::get<1>(arg));
+}
+
class TempEnvVar {
public:
TempEnvVar(const char *name, const char *value)
@@ -61,7 +71,7 @@
~StackOption() override { this->removeArgument(); }
template <class DT> StackOption<T> &operator=(const DT &V) {
- this->setValue(V);
+ Base::operator=(V);
return *this;
}
};
@@ -778,119 +788,99 @@
}
TEST(CommandLineTest, ResponseFiles) {
- llvm::SmallString<128> TestDir;
- std::error_code EC =
- llvm::sys::fs::createUniqueDirectory("unittest", TestDir);
- EXPECT_TRUE(!EC);
+ vfs::InMemoryFileSystem FS;
+#ifdef _WIN32
+ const char *TestRoot = "C:\\";
+#else
+ const char *TestRoot = "/";
+#endif
+ FS.setCurrentWorkingDirectory(TestRoot);
// Create included response file of first level.
- llvm::SmallString<128> IncludedFileName;
- llvm::sys::path::append(IncludedFileName, TestDir, "resp1");
- std::ofstream IncludedFile(IncludedFileName.c_str());
- EXPECT_TRUE(IncludedFile.is_open());
- IncludedFile << "-option_1 -option_2\n"
- "@incdir/resp2\n"
- "-option_3=abcd\n"
- "@incdir/resp3\n"
- "-option_4=efjk\n";
- IncludedFile.close();
+ llvm::StringRef IncludedFileName = "resp1";
+ FS.addFile(IncludedFileName, 0,
+ llvm::MemoryBuffer::getMemBuffer("-option_1 -option_2\n"
+ "@incdir/resp2\n"
+ "-option_3=abcd\n"
+ "@incdir/resp3\n"
+ "-option_4=efjk\n"));
// Directory for included file.
- llvm::SmallString<128> IncDir;
- llvm::sys::path::append(IncDir, TestDir, "incdir");
- EC = llvm::sys::fs::create_directory(IncDir);
- EXPECT_TRUE(!EC);
+ llvm::StringRef IncDir = "incdir";
// Create included response file of second level.
llvm::SmallString<128> IncludedFileName2;
llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
- std::ofstream IncludedFile2(IncludedFileName2.c_str());
- EXPECT_TRUE(IncludedFile2.is_open());
- IncludedFile2 << "-option_21 -option_22\n";
- IncludedFile2 << "-option_23=abcd\n";
- IncludedFile2.close();
+ FS.addFile(IncludedFileName2, 0,
+ MemoryBuffer::getMemBuffer("-option_21 -option_22\n"
+ "-option_23=abcd\n"));
// Create second included response file of second level.
llvm::SmallString<128> IncludedFileName3;
llvm::sys::path::append(IncludedFileName3, IncDir, "resp3");
- std::ofstream IncludedFile3(IncludedFileName3.c_str());
- EXPECT_TRUE(IncludedFile3.is_open());
- IncludedFile3 << "-option_31 -option_32\n";
- IncludedFile3 << "-option_33=abcd\n";
- IncludedFile3.close();
+ FS.addFile(IncludedFileName3, 0,
+ MemoryBuffer::getMemBuffer("-option_31 -option_32\n"
+ "-option_33=abcd\n"));
// Prepare 'file' with reference to response file.
SmallString<128> IncRef;
IncRef.append(1, '@');
- IncRef.append(IncludedFileName.c_str());
- llvm::SmallVector<const char *, 4> Argv =
- { "test/test", "-flag_1", IncRef.c_str(), "-flag_2" };
+ IncRef.append(IncludedFileName);
+ llvm::SmallVector<const char *, 4> Argv = {"test/test", "-flag_1",
+ IncRef.c_str(), "-flag_2"};
// Expand response files.
llvm::BumpPtrAllocator A;
llvm::StringSaver Saver(A);
- bool Res = llvm::cl::ExpandResponseFiles(
- Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true);
- EXPECT_TRUE(Res);
- EXPECT_EQ(Argv.size(), 13U);
- EXPECT_STREQ(Argv[0], "test/test");
- EXPECT_STREQ(Argv[1], "-flag_1");
- EXPECT_STREQ(Argv[2], "-option_1");
- EXPECT_STREQ(Argv[3], "-option_2");
- EXPECT_STREQ(Argv[4], "-option_21");
- EXPECT_STREQ(Argv[5], "-option_22");
- EXPECT_STREQ(Argv[6], "-option_23=abcd");
- EXPECT_STREQ(Argv[7], "-option_3=abcd");
- EXPECT_STREQ(Argv[8], "-option_31");
- EXPECT_STREQ(Argv[9], "-option_32");
- EXPECT_STREQ(Argv[10], "-option_33=abcd");
- EXPECT_STREQ(Argv[11], "-option_4=efjk");
- EXPECT_STREQ(Argv[12], "-flag_2");
-
- llvm::sys::fs::remove(IncludedFileName3);
- llvm::sys::fs::remove(IncludedFileName2);
- llvm::sys::fs::remove(IncDir);
- llvm::sys::fs::remove(IncludedFileName);
- llvm::sys::fs::remove(TestDir);
+ ASSERT_TRUE(llvm::cl::ExpandResponseFiles(
+ Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true, FS,
+ /*CurrentDir=*/StringRef(TestRoot)));
+ EXPECT_THAT(Argv, testing::Pointwise(
+ StringEquality(),
+ {"test/test", "-flag_1", "-option_1", "-option_2",
+ "-option_21", "-option_22", "-option_23=abcd",
+ "-option_3=abcd", "-option_31", "-option_32",
+ "-option_33=abcd", "-option_4=efjk", "-flag_2"}));
}
TEST(CommandLineTest, RecursiveResponseFiles) {
- SmallString<128> TestDir;
- std::error_code EC = sys::fs::createUniqueDirectory("unittest", TestDir);
- EXPECT_TRUE(!EC);
+ vfs::InMemoryFileSystem FS;
+#ifdef _WIN32
+ const char *TestRoot = "C:\\";
+#else
+ const char *TestRoot = "/";
+#endif
+ FS.setCurrentWorkingDirectory(TestRoot);
- SmallString<128> SelfFilePath;
- sys::path::append(SelfFilePath, TestDir, "self.rsp");
- std::string SelfFileRef = std::string("@") + SelfFilePath.c_str();
+ StringRef SelfFilePath = "self.rsp";
+ std::string SelfFileRef = ("@" + SelfFilePath).str();
- SmallString<128> NestedFilePath;
- sys::path::append(NestedFilePath, TestDir, "nested.rsp");
- std::string NestedFileRef = std::string("@") + NestedFilePath.c_str();
+ StringRef NestedFilePath = "nested.rsp";
+ std::string NestedFileRef = ("@" + NestedFilePath).str();
- SmallString<128> FlagFilePath;
- sys::path::append(FlagFilePath, TestDir, "flag.rsp");
- std::string FlagFileRef = std::string("@") + FlagFilePath.c_str();
+ StringRef FlagFilePath = "flag.rsp";
+ std::string FlagFileRef = ("@" + FlagFilePath).str();
- std::ofstream SelfFile(SelfFilePath.str());
- EXPECT_TRUE(SelfFile.is_open());
+ std::string SelfFileContents;
+ raw_string_ostream SelfFile(SelfFileContents);
SelfFile << "-option_1\n";
SelfFile << FlagFileRef << "\n";
SelfFile << NestedFileRef << "\n";
SelfFile << SelfFileRef << "\n";
- SelfFile.close();
+ FS.addFile(SelfFilePath, 0, MemoryBuffer::getMemBuffer(SelfFile.str()));
- std::ofstream NestedFile(NestedFilePath.str());
- EXPECT_TRUE(NestedFile.is_open());
+ std::string NestedFileContents;
+ raw_string_ostream NestedFile(NestedFileContents);
NestedFile << "-option_2\n";
NestedFile << FlagFileRef << "\n";
NestedFile << SelfFileRef << "\n";
NestedFile << NestedFileRef << "\n";
- NestedFile.close();
+ FS.addFile(NestedFilePath, 0, MemoryBuffer::getMemBuffer(NestedFile.str()));
- std::ofstream FlagFile(FlagFilePath.str());
- EXPECT_TRUE(FlagFile.is_open());
+ std::string FlagFileContents;
+ raw_string_ostream FlagFile(FlagFileContents);
FlagFile << "-option_x\n";
- FlagFile.close();
+ FS.addFile(FlagFilePath, 0, MemoryBuffer::getMemBuffer(FlagFile.str()));
// Ensure:
// Recursive expansion terminates
@@ -905,47 +895,48 @@
#else
cl::TokenizerCallback Tokenizer = cl::TokenizeGNUCommandLine;
#endif
- bool Res = cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false);
- EXPECT_FALSE(Res);
+ ASSERT_FALSE(
+ cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, FS,
+ /*CurrentDir=*/llvm::StringRef(TestRoot)));
- EXPECT_EQ(Argv.size(), 9U);
- EXPECT_STREQ(Argv[0], "test/test");
- EXPECT_STREQ(Argv[1], "-option_1");
- EXPECT_STREQ(Argv[2], "-option_x");
- EXPECT_STREQ(Argv[3], "-option_2");
- EXPECT_STREQ(Argv[4], "-option_x");
- EXPECT_STREQ(Argv[5], SelfFileRef.c_str());
- EXPECT_STREQ(Argv[6], NestedFileRef.c_str());
- EXPECT_STREQ(Argv[7], SelfFileRef.c_str());
- EXPECT_STREQ(Argv[8], "-option_3");
+ EXPECT_THAT(Argv,
+ testing::Pointwise(StringEquality(),
+ {"test/test", "-option_1", "-option_x",
+ "-option_2", "-option_x", SelfFileRef.c_str(),
+ NestedFileRef.c_str(), SelfFileRef.c_str(),
+ "-option_3"}));
}
TEST(CommandLineTest, ResponseFilesAtArguments) {
- SmallString<128> TestDir;
- std::error_code EC = sys::fs::createUniqueDirectory("unittest", TestDir);
- EXPECT_TRUE(!EC);
+ vfs::InMemoryFileSystem FS;
+#ifdef _WIN32
+ const char *TestRoot = "C:\\";
+#else
+ const char *TestRoot = "/";
+#endif
+ FS.setCurrentWorkingDirectory(TestRoot);
- SmallString<128> ResponseFilePath;
- sys::path::append(ResponseFilePath, TestDir, "test.rsp");
+ StringRef ResponseFilePath = "test.rsp";
- std::ofstream ResponseFile(ResponseFilePath.c_str());
- EXPECT_TRUE(ResponseFile.is_open());
+ std::string ResponseFileContents;
+ raw_string_ostream ResponseFile(ResponseFileContents);
ResponseFile << "-foo" << "\n";
ResponseFile << "-bar" << "\n";
- ResponseFile.close();
+ FS.addFile(ResponseFilePath, 0,
+ MemoryBuffer::getMemBuffer(ResponseFile.str()));
// Ensure we expand rsp files after lots of non-rsp arguments starting with @.
constexpr size_t NON_RSP_AT_ARGS = 64;
SmallVector<const char *, 4> Argv = {"test/test"};
Argv.append(NON_RSP_AT_ARGS, "@non_rsp_at_arg");
- std::string ResponseFileRef = std::string("@") + ResponseFilePath.c_str();
+ std::string ResponseFileRef = ("@" + ResponseFilePath).str();
Argv.push_back(ResponseFileRef.c_str());
BumpPtrAllocator A;
StringSaver Saver(A);
- bool Res = cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
- false, false);
- EXPECT_FALSE(Res);
+ ASSERT_FALSE(cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
+ false, false, FS,
+ /*CurrentDir=*/StringRef(TestRoot)));
// ASSERT instead of EXPECT to prevent potential out-of-bounds access.
ASSERT_EQ(Argv.size(), 1 + NON_RSP_AT_ARGS + 2);
@@ -957,6 +948,34 @@
EXPECT_STREQ(Argv[i++], "-bar");
}
+TEST(CommandLineTest, ResponseFileRelativePath) {
+ vfs::InMemoryFileSystem FS;
+#ifdef _WIN32
+ const char *TestRoot = "C:\\";
+#else
+ const char *TestRoot = "//net";
+#endif
+ FS.setCurrentWorkingDirectory(TestRoot);
+
+ StringRef OuterFile = "dir/outer.rsp";
+ StringRef OuterFileContents = "@inner.rsp";
+ FS.addFile(OuterFile, 0, MemoryBuffer::getMemBuffer(OuterFileContents));
+
+ StringRef InnerFile = "dir/inner.rsp";
+ StringRef InnerFileContents = "-flag";
+ FS.addFile(InnerFile, 0, MemoryBuffer::getMemBuffer(InnerFileContents));
+
+ SmallVector<const char *, 2> Argv = {"test/test", "@dir/outer.rsp"};
+
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
+ ASSERT_TRUE(cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
+ false, true, FS,
+ /*CurrentDir=*/StringRef(TestRoot)));
+ EXPECT_THAT(Argv,
+ testing::Pointwise(StringEquality(), {"test/test", "-flag"}));
+}
+
TEST(CommandLineTest, SetDefautValue) {
cl::ResetCommandLineParser();
@@ -1653,4 +1672,124 @@
EXPECT_TRUE(Errs.empty()); Errs.clear();
cl::ResetAllOptionOccurrences();
}
-} // anonymous namespace
+
+TEST(CommandLineTest, OptionErrorMessage) {
+ // When there is an error, we expect some error message like:
+ // prog: for the -a option: [...]
+ //
+ // Test whether the "for the -a option"-part is correctly formatted.
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> OptA("a", cl::desc("Some option"));
+ StackOption<bool> OptLong("long", cl::desc("Some long option"));
+
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
+ OptA.error("custom error", OS);
+ OS.flush();
+ EXPECT_FALSE(Errs.find("for the -a option:") == std::string::npos);
+ Errs.clear();
+
+ OptLong.error("custom error", OS);
+ OS.flush();
+ EXPECT_FALSE(Errs.find("for the --long option:") == std::string::npos);
+ Errs.clear();
+
+ cl::ResetAllOptionOccurrences();
+}
+
+TEST(CommandLineTest, OptionErrorMessageSuggest) {
+ // When there is an error, and the edit-distance is not very large,
+ // we expect some error message like:
+ // prog: did you mean '--option'?
+ //
+ // Test whether this message is well-formatted.
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
+
+ const char *args[] = {"prog", "--aluminum"};
+
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
+ EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
+ OS.flush();
+ EXPECT_FALSE(Errs.find("prog: Did you mean '--aluminium'?\n") ==
+ std::string::npos);
+ Errs.clear();
+
+ cl::ResetAllOptionOccurrences();
+}
+
+TEST(CommandLineTest, Callback) {
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> OptA("a", cl::desc("option a"));
+ StackOption<bool> OptB(
+ "b", cl::desc("option b -- This option turns on option a"),
+ cl::callback([&](const bool &) { OptA = true; }));
+ StackOption<bool> OptC(
+ "c", cl::desc("option c -- This option turns on options a and b"),
+ cl::callback([&](const bool &) { OptB = true; }));
+ StackOption<std::string, cl::list<std::string>> List(
+ "list",
+ cl::desc("option list -- This option turns on options a, b, and c when "
+ "'foo' is included in list"),
+ cl::CommaSeparated,
+ cl::callback([&](const std::string &Str) {
+ if (Str == "foo")
+ OptC = true;
+ }));
+
+ const char *args1[] = {"prog", "-a"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1));
+ EXPECT_TRUE(OptA);
+ EXPECT_FALSE(OptB);
+ EXPECT_FALSE(OptC);
+ EXPECT_TRUE(List.size() == 0);
+ cl::ResetAllOptionOccurrences();
+
+ const char *args2[] = {"prog", "-b"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args2));
+ EXPECT_TRUE(OptA);
+ EXPECT_TRUE(OptB);
+ EXPECT_FALSE(OptC);
+ EXPECT_TRUE(List.size() == 0);
+ cl::ResetAllOptionOccurrences();
+
+ const char *args3[] = {"prog", "-c"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args3));
+ EXPECT_TRUE(OptA);
+ EXPECT_TRUE(OptB);
+ EXPECT_TRUE(OptC);
+ EXPECT_TRUE(List.size() == 0);
+ cl::ResetAllOptionOccurrences();
+
+ const char *args4[] = {"prog", "--list=foo,bar"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args4));
+ EXPECT_TRUE(OptA);
+ EXPECT_TRUE(OptB);
+ EXPECT_TRUE(OptC);
+ EXPECT_TRUE(List.size() == 2);
+ cl::ResetAllOptionOccurrences();
+
+ const char *args5[] = {"prog", "--list=bar"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args5));
+ EXPECT_FALSE(OptA);
+ EXPECT_FALSE(OptB);
+ EXPECT_FALSE(OptC);
+ EXPECT_TRUE(List.size() == 1);
+
+ cl::ResetAllOptionOccurrences();
+}
+
+enum Enum { Val1, Val2 };
+static cl::bits<Enum> ExampleBits(
+ cl::desc("An example cl::bits to ensure it compiles"),
+ cl::values(
+ clEnumValN(Val1, "bits-val1", "The Val1 value"),
+ clEnumValN(Val1, "bits-val2", "The Val2 value")));
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/CrashRecoveryTest.cpp b/src/llvm-project/llvm/unittests/Support/CrashRecoveryTest.cpp
index d863dd0..798ed20 100644
--- a/src/llvm-project/llvm/unittests/Support/CrashRecoveryTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/CrashRecoveryTest.cpp
@@ -8,6 +8,8 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Signals.h"
#include "gtest/gtest.h"
#ifdef _WIN32
@@ -23,6 +25,7 @@
static void nullDeref() { *(volatile int *)0x10 = 0; }
static void incrementGlobal() { ++GlobalInt; }
static void llvmTrap() { LLVM_BUILTIN_TRAP; }
+static void incrementGlobalWithParam(void *) { ++GlobalInt; }
TEST(CrashRecoveryTest, Basic) {
llvm::CrashRecoveryContext::Enable();
@@ -58,6 +61,33 @@
EXPECT_FALSE(CRC.RunSafely(nullDeref));
} // run cleanups
EXPECT_EQ(1, GlobalInt);
+ llvm::CrashRecoveryContext::Disable();
+}
+
+TEST(CrashRecoveryTest, DumpStackCleanup) {
+ SmallString<128> Filename;
+ std::error_code EC = sys::fs::createTemporaryFile("crash", "test", Filename);
+ EXPECT_FALSE(EC);
+ sys::RemoveFileOnSignal(Filename);
+ llvm::sys::AddSignalHandler(incrementGlobalWithParam, nullptr);
+ GlobalInt = 0;
+ llvm::CrashRecoveryContext::Enable();
+ {
+ CrashRecoveryContext CRC;
+ CRC.DumpStackAndCleanupOnFailure = true;
+ EXPECT_TRUE(CRC.RunSafely(noop));
+ }
+ EXPECT_TRUE(sys::fs::exists(Filename));
+ EXPECT_EQ(GlobalInt, 0);
+ {
+ CrashRecoveryContext CRC;
+ CRC.DumpStackAndCleanupOnFailure = true;
+ EXPECT_FALSE(CRC.RunSafely(nullDeref));
+ EXPECT_NE(CRC.RetCode, 0);
+ }
+ EXPECT_FALSE(sys::fs::exists(Filename));
+ EXPECT_EQ(GlobalInt, 1);
+ llvm::CrashRecoveryContext::Disable();
}
#ifdef _WIN32
diff --git a/src/llvm-project/llvm/unittests/Support/DataExtractorTest.cpp b/src/llvm-project/llvm/unittests/Support/DataExtractorTest.cpp
index 9726a74..cdb8bfd 100644
--- a/src/llvm-project/llvm/unittests/Support/DataExtractorTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/DataExtractorTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/DataExtractor.h"
+#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -24,7 +25,7 @@
TEST(DataExtractorTest, UnsignedNumbers) {
DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
- uint32_t offset = 0;
+ uint64_t offset = 0;
EXPECT_EQ(0x80U, DE.getU8(&offset));
EXPECT_EQ(1U, offset);
@@ -72,7 +73,7 @@
TEST(DataExtractorTest, SignedNumbers) {
DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
- uint32_t offset = 0;
+ uint64_t offset = 0;
EXPECT_EQ(-128, DE.getSigned(&offset, 1));
EXPECT_EQ(1U, offset);
@@ -89,7 +90,7 @@
TEST(DataExtractorTest, Strings) {
DataExtractor DE(StringRef(stringData, sizeof(stringData)-1), false, 8);
- uint32_t offset = 0;
+ uint64_t offset = 0;
EXPECT_EQ(stringData, DE.getCStr(&offset));
EXPECT_EQ(11U, offset);
@@ -99,7 +100,7 @@
TEST(DataExtractorTest, LEB128) {
DataExtractor DE(StringRef(leb128data, sizeof(leb128data)-1), false, 8);
- uint32_t offset = 0;
+ uint64_t offset = 0;
EXPECT_EQ(9382ULL, DE.getULEB128(&offset));
EXPECT_EQ(2U, offset);
@@ -118,7 +119,7 @@
TEST(DataExtractorTest, LEB128_error) {
DataExtractor DE(StringRef("\x81"), false, 8);
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
EXPECT_EQ(0U, DE.getULEB128(&Offset));
EXPECT_EQ(0U, Offset);
@@ -126,4 +127,155 @@
EXPECT_EQ(0U, DE.getSLEB128(&Offset));
EXPECT_EQ(0U, Offset);
}
+
+TEST(DataExtractorTest, Cursor_tell) {
+ DataExtractor DE(StringRef("AB"), false, 8);
+ DataExtractor::Cursor C(0);
+ // A successful read operation advances the cursor
+ EXPECT_EQ('A', DE.getU8(C));
+ EXPECT_EQ(1u, C.tell());
+
+ // An unsuccessful one doesn't.
+ EXPECT_EQ(0u, DE.getU16(C));
+ EXPECT_EQ(1u, C.tell());
+
+ // And neither do any subsequent operations.
+ EXPECT_EQ(0, DE.getU8(C));
+ EXPECT_EQ(1u, C.tell());
+
+ consumeError(C.takeError());
+}
+
+TEST(DataExtractorTest, Cursor_takeError) {
+ DataExtractor DE(StringRef("AB"), false, 8);
+ DataExtractor::Cursor C(0);
+ // Initially, the cursor is in the "success" state.
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+
+ // It remains "success" after a successful read.
+ EXPECT_EQ('A', DE.getU8(C));
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+
+ // An unsuccessful read sets the error state.
+ EXPECT_EQ(0u, DE.getU32(C));
+ EXPECT_THAT_ERROR(C.takeError(), Failed());
+
+ // Once set the error sticks until explicitly cleared.
+ EXPECT_EQ(0u, DE.getU32(C));
+ EXPECT_EQ(0, DE.getU8(C));
+ EXPECT_THAT_ERROR(C.takeError(), Failed());
+
+ // At which point reads can be succeed again.
+ EXPECT_EQ('B', DE.getU8(C));
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+}
+
+TEST(DataExtractorTest, Cursor_chaining) {
+ DataExtractor DE(StringRef("ABCD"), false, 8);
+ DataExtractor::Cursor C(0);
+
+ // Multiple reads can be chained without trigerring any assertions.
+ EXPECT_EQ('A', DE.getU8(C));
+ EXPECT_EQ('B', DE.getU8(C));
+ EXPECT_EQ('C', DE.getU8(C));
+ EXPECT_EQ('D', DE.getU8(C));
+ // And the error checked at the end.
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+}
+
+#if defined(GTEST_HAS_DEATH_TEST) && defined(_DEBUG)
+TEST(DataExtractorDeathTest, Cursor) {
+ DataExtractor DE(StringRef("AB"), false, 8);
+
+ // Even an unused cursor must be checked for errors:
+ EXPECT_DEATH(DataExtractor::Cursor(0),
+ "Success values must still be checked prior to being destroyed");
+
+ {
+ auto C = std::make_unique<DataExtractor::Cursor>(0);
+ EXPECT_EQ(0u, DE.getU32(*C));
+ // It must also be checked after an unsuccessful operation.
+ // destruction.
+ EXPECT_DEATH(C.reset(), "unexpected end of data");
+ EXPECT_THAT_ERROR(C->takeError(), Failed());
+ }
+ {
+ auto C = std::make_unique<DataExtractor::Cursor>(0);
+ EXPECT_EQ('A', DE.getU8(*C));
+ // Same goes for a successful one.
+ EXPECT_DEATH(
+ C.reset(),
+ "Success values must still be checked prior to being destroyed");
+ EXPECT_THAT_ERROR(C->takeError(), Succeeded());
+ }
+ {
+ auto C = std::make_unique<DataExtractor::Cursor>(0);
+ EXPECT_EQ('A', DE.getU8(*C));
+ EXPECT_EQ(0u, DE.getU32(*C));
+ // Even if a successful operation is followed by an unsuccessful one.
+ EXPECT_DEATH(C.reset(), "unexpected end of data");
+ EXPECT_THAT_ERROR(C->takeError(), Failed());
+ }
+ {
+ auto C = std::make_unique<DataExtractor::Cursor>(0);
+ EXPECT_EQ(0u, DE.getU32(*C));
+ EXPECT_EQ(0, DE.getU8(*C));
+ // Even if an unsuccessful operation is followed by one that would normally
+ // succeed.
+ EXPECT_DEATH(C.reset(), "unexpected end of data");
+ EXPECT_THAT_ERROR(C->takeError(), Failed());
+ }
+}
+#endif
+
+TEST(DataExtractorTest, getU8_vector) {
+ DataExtractor DE(StringRef("AB"), false, 8);
+ DataExtractor::Cursor C(0);
+ SmallVector<uint8_t, 2> S;
+
+ DE.getU8(C, S, 4);
+ EXPECT_THAT_ERROR(C.takeError(), Failed());
+ EXPECT_EQ("", toStringRef(S));
+
+ DE.getU8(C, S, 2);
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+ EXPECT_EQ("AB", toStringRef(S));
+}
+
+TEST(DataExtractorTest, skip) {
+ DataExtractor DE(StringRef("AB"), false, 8);
+ DataExtractor::Cursor C(0);
+
+ DE.skip(C, 4);
+ EXPECT_THAT_ERROR(C.takeError(), Failed());
+ EXPECT_EQ(0u, C.tell());
+
+ DE.skip(C, 2);
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+ EXPECT_EQ(2u, C.tell());
+}
+
+TEST(DataExtractorTest, eof) {
+ DataExtractor DE(StringRef("A"), false, 8);
+ DataExtractor::Cursor C(0);
+
+ EXPECT_FALSE(DE.eof(C));
+
+ EXPECT_EQ(0, DE.getU16(C));
+ EXPECT_FALSE(DE.eof(C));
+ EXPECT_THAT_ERROR(C.takeError(), Failed());
+
+ EXPECT_EQ('A', DE.getU8(C));
+ EXPECT_TRUE(DE.eof(C));
+ EXPECT_THAT_ERROR(C.takeError(), Succeeded());
+}
+
+TEST(DataExtractorTest, size) {
+ uint8_t Data[] = {'A', 'B', 'C', 'D'};
+ DataExtractor DE1(StringRef(reinterpret_cast<char *>(Data), sizeof(Data)),
+ false, 8);
+ EXPECT_EQ(DE1.size(), sizeof(Data));
+ DataExtractor DE2(ArrayRef<uint8_t>(Data), false, 8);
+ EXPECT_EQ(DE2.size(), sizeof(Data));
+}
}
diff --git a/src/llvm-project/llvm/unittests/Support/ErrorTest.cpp b/src/llvm-project/llvm/unittests/Support/ErrorTest.cpp
index c4a9f3e..2cac94d 100644
--- a/src/llvm-project/llvm/unittests/Support/ErrorTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/ErrorTest.cpp
@@ -390,7 +390,8 @@
};
EXPECT_DEATH(FailToHandle(),
- "Failure value returned from cantFail wrapped call")
+ "Failure value returned from cantFail wrapped call\n"
+ "CustomError \\{7\\}")
<< "Unhandled Error in handleAllErrors call did not cause an "
"abort()";
}
@@ -409,7 +410,8 @@
};
EXPECT_DEATH(ReturnErrorFromHandler(),
- "Failure value returned from cantFail wrapped call")
+ "Failure value returned from cantFail wrapped call\n"
+ "CustomError \\{7\\}")
<< " Error returned from handler in handleAllErrors call did not "
"cause abort()";
}
@@ -510,11 +512,12 @@
// Test that cantFail results in a crash if you pass it a failure value.
#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
TEST(Error, CantFailDeath) {
- EXPECT_DEATH(
- cantFail(make_error<StringError>("foo", inconvertibleErrorCode()),
- "Cantfail call failed"),
- "Cantfail call failed")
- << "cantFail(Error) did not cause an abort for failure value";
+ EXPECT_DEATH(cantFail(make_error<StringError>("Original error message",
+ inconvertibleErrorCode()),
+ "Cantfail call failed"),
+ "Cantfail call failed\n"
+ "Original error message")
+ << "cantFail(Error) did not cause an abort for failure value";
EXPECT_DEATH(
{
diff --git a/src/llvm-project/llvm/unittests/Support/FileCheckTest.cpp b/src/llvm-project/llvm/unittests/Support/FileCheckTest.cpp
index 2275d72..8ca0af7 100644
--- a/src/llvm-project/llvm/unittests/Support/FileCheckTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/FileCheckTest.cpp
@@ -7,25 +7,27 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/FileCheck.h"
+#include "../lib/Support/FileCheckImpl.h"
#include "gtest/gtest.h"
#include <unordered_set>
using namespace llvm;
+
namespace {
class FileCheckTest : public ::testing::Test {};
TEST_F(FileCheckTest, Literal) {
// Eval returns the literal's value.
- FileCheckExpressionLiteral Ten(10);
+ ExpressionLiteral Ten(10);
Expected<uint64_t> Value = Ten.eval();
- EXPECT_TRUE(bool(Value));
+ ASSERT_TRUE(bool(Value));
EXPECT_EQ(10U, *Value);
// Max value can be correctly represented.
- FileCheckExpressionLiteral Max(std::numeric_limits<uint64_t>::max());
+ ExpressionLiteral Max(std::numeric_limits<uint64_t>::max());
Value = Max.eval();
- EXPECT_TRUE(bool(Value));
+ ASSERT_TRUE(bool(Value));
EXPECT_EQ(std::numeric_limits<uint64_t>::max(), *Value);
}
@@ -43,91 +45,91 @@
static void
expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
Error Err) {
- handleAllErrors(std::move(Err), [&](const FileCheckUndefVarError &E) {
+ handleAllErrors(std::move(Err), [&](const UndefVarError &E) {
ExpectedUndefVarNames.erase(E.getVarName());
});
EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
}
+// Return whether Err contains any UndefVarError whose associated name is not
+// ExpectedUndefVarName.
static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) {
expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err));
}
+uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
+
TEST_F(FileCheckTest, NumericVariable) {
// Undefined variable: getValue and eval fail, error returned by eval holds
- // the name of the undefined variable and setValue does not trigger assert.
- FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
+ // the name of the undefined variable.
+ NumericVariable FooVar("FOO", 1);
EXPECT_EQ("FOO", FooVar.getName());
- FileCheckNumericVariableUse FooVarUse =
- FileCheckNumericVariableUse("FOO", &FooVar);
+ NumericVariableUse FooVarUse("FOO", &FooVar);
EXPECT_FALSE(FooVar.getValue());
Expected<uint64_t> EvalResult = FooVarUse.eval();
- EXPECT_FALSE(EvalResult);
+ ASSERT_FALSE(EvalResult);
expectUndefError("FOO", EvalResult.takeError());
+
FooVar.setValue(42);
// Defined variable: getValue and eval return value set.
Optional<uint64_t> Value = FooVar.getValue();
- EXPECT_TRUE(bool(Value));
+ ASSERT_TRUE(bool(Value));
EXPECT_EQ(42U, *Value);
EvalResult = FooVarUse.eval();
- EXPECT_TRUE(bool(EvalResult));
+ ASSERT_TRUE(bool(EvalResult));
EXPECT_EQ(42U, *EvalResult);
// Clearing variable: getValue and eval fail. Error returned by eval holds
// the name of the cleared variable.
FooVar.clearValue();
- Value = FooVar.getValue();
- EXPECT_FALSE(Value);
+ EXPECT_FALSE(FooVar.getValue());
EvalResult = FooVarUse.eval();
- EXPECT_FALSE(EvalResult);
+ ASSERT_FALSE(EvalResult);
expectUndefError("FOO", EvalResult.takeError());
}
-uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
-
TEST_F(FileCheckTest, Binop) {
- FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO");
+ NumericVariable FooVar("FOO", 1);
FooVar.setValue(42);
- std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
- llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
- FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR");
+ std::unique_ptr<NumericVariableUse> FooVarUse =
+ std::make_unique<NumericVariableUse>("FOO", &FooVar);
+ NumericVariable BarVar("BAR", 2);
BarVar.setValue(18);
- std::unique_ptr<FileCheckNumericVariableUse> BarVarUse =
- llvm::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar);
- FileCheckASTBinop Binop =
- FileCheckASTBinop(doAdd, std::move(FooVarUse), std::move(BarVarUse));
+ std::unique_ptr<NumericVariableUse> BarVarUse =
+ std::make_unique<NumericVariableUse>("BAR", &BarVar);
+ BinaryOperation Binop(doAdd, std::move(FooVarUse), std::move(BarVarUse));
// Defined variable: eval returns right value.
Expected<uint64_t> Value = Binop.eval();
- EXPECT_TRUE(bool(Value));
+ ASSERT_TRUE(bool(Value));
EXPECT_EQ(60U, *Value);
// 1 undefined variable: eval fails, error contains name of undefined
// variable.
FooVar.clearValue();
Value = Binop.eval();
- EXPECT_FALSE(Value);
+ ASSERT_FALSE(Value);
expectUndefError("FOO", Value.takeError());
// 2 undefined variables: eval fails, error contains names of all undefined
// variables.
BarVar.clearValue();
Value = Binop.eval();
- EXPECT_FALSE(Value);
+ ASSERT_FALSE(Value);
expectUndefErrors({"FOO", "BAR"}, Value.takeError());
}
TEST_F(FileCheckTest, ValidVarNameStart) {
- EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('a'));
- EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('G'));
- EXPECT_TRUE(FileCheckPattern::isValidVarNameStart('_'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('2'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('$'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('@'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('+'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart('-'));
- EXPECT_FALSE(FileCheckPattern::isValidVarNameStart(':'));
+ EXPECT_TRUE(Pattern::isValidVarNameStart('a'));
+ EXPECT_TRUE(Pattern::isValidVarNameStart('G'));
+ EXPECT_TRUE(Pattern::isValidVarNameStart('_'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart('2'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart('$'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart('@'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart('+'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart('-'));
+ EXPECT_FALSE(Pattern::isValidVarNameStart(':'));
}
static StringRef bufferize(SourceMgr &SM, StringRef Str) {
@@ -142,66 +144,66 @@
SourceMgr SM;
StringRef OrigVarName = bufferize(SM, "GoodVar42");
StringRef VarName = OrigVarName;
- Expected<FileCheckPattern::VariableProperties> ParsedVarResult =
- FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ Expected<Pattern::VariableProperties> ParsedVarResult =
+ Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
EXPECT_TRUE(VarName.empty());
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
EXPECT_TRUE(VarName.empty());
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
EXPECT_TRUE(VarName.empty());
EXPECT_TRUE(ParsedVarResult->IsPseudo);
VarName = bufferize(SM, "42BadVar");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
VarName = bufferize(SM, "$@");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
EXPECT_TRUE(errorToBool(ParsedVarResult.takeError()));
VarName = OrigVarName = bufferize(SM, "B@dVar");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(VarName, OrigVarName.substr(1));
EXPECT_EQ(ParsedVarResult->Name, "B");
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = OrigVarName = bufferize(SM, "B$dVar");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(VarName, OrigVarName.substr(1));
EXPECT_EQ(ParsedVarResult->Name, "B");
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = bufferize(SM, "BadVar+");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(VarName, "+");
EXPECT_EQ(ParsedVarResult->Name, "BadVar");
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = bufferize(SM, "BadVar-");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(VarName, "-");
EXPECT_EQ(ParsedVarResult->Name, "BadVar");
EXPECT_FALSE(ParsedVarResult->IsPseudo);
VarName = bufferize(SM, "BadVar:");
- ParsedVarResult = FileCheckPattern::parseVariable(VarName, SM);
- EXPECT_TRUE(bool(ParsedVarResult));
+ ParsedVarResult = Pattern::parseVariable(VarName, SM);
+ ASSERT_TRUE(bool(ParsedVarResult));
EXPECT_EQ(VarName, ":");
EXPECT_EQ(ParsedVarResult->Name, "BadVar");
EXPECT_FALSE(ParsedVarResult->IsPseudo);
@@ -213,14 +215,15 @@
SourceMgr SM;
FileCheckRequest Req;
FileCheckPatternContext Context;
- FileCheckPattern P =
- FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
+ Pattern P{Check::CheckPlain, &Context, LineNumber++};
public:
PatternTester() {
std::vector<std::string> GlobalDefines;
GlobalDefines.emplace_back(std::string("#FOO=42"));
GlobalDefines.emplace_back(std::string("BAR=BAZ"));
+ // An ASSERT_FALSE would make more sense but cannot be used in a
+ // constructor.
EXPECT_FALSE(
errorToBool(Context.defineCmdlineVariables(GlobalDefines, SM)));
Context.createLineVariable();
@@ -233,22 +236,16 @@
}
void initNextPattern() {
- P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
- }
-
- bool parseNumVarDefExpect(StringRef Expr) {
- StringRef ExprBufferRef = bufferize(SM, Expr);
- return errorToBool(FileCheckPattern::parseNumericVariableDefinition(
- ExprBufferRef, &Context, LineNumber, SM)
- .takeError());
+ P = Pattern(Check::CheckPlain, &Context, LineNumber++);
}
bool parseSubstExpect(StringRef Expr) {
StringRef ExprBufferRef = bufferize(SM, Expr);
- Optional<FileCheckNumericVariable *> DefinedNumericVariable;
- return errorToBool(P.parseNumericSubstitutionBlock(
- ExprBufferRef, DefinedNumericVariable, false, SM)
- .takeError());
+ Optional<NumericVariable *> DefinedNumericVariable;
+ return errorToBool(
+ P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
+ false, LineNumber - 1, &Context, SM)
+ .takeError());
}
bool parsePatternExpect(StringRef Pattern) {
@@ -263,19 +260,6 @@
}
};
-TEST_F(FileCheckTest, ParseNumericVariableDefinition) {
- PatternTester Tester;
-
- // Invalid definition of pseudo.
- EXPECT_TRUE(Tester.parseNumVarDefExpect("@LINE"));
-
- // Conflict with pattern variable.
- EXPECT_TRUE(Tester.parseNumVarDefExpect("BAR"));
-
- // Defined variable.
- EXPECT_FALSE(Tester.parseNumVarDefExpect("FOO"));
-}
-
TEST_F(FileCheckTest, ParseExpr) {
PatternTester Tester;
@@ -286,17 +270,18 @@
EXPECT_TRUE(Tester.parseSubstExpect("@FOO:"));
EXPECT_TRUE(Tester.parseSubstExpect("@LINE:"));
+ // Conflict with pattern variable.
+ EXPECT_TRUE(Tester.parseSubstExpect("BAR:"));
+
// Garbage after name of variable being defined.
EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:"));
- // Variable defined to numeric expression.
- EXPECT_TRUE(Tester.parseSubstExpect("VAR1: FOO"));
-
// Acceptable variable definition.
EXPECT_FALSE(Tester.parseSubstExpect("VAR1:"));
EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:"));
EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :"));
EXPECT_FALSE(Tester.parseSubstExpect("VAR3: "));
+ EXPECT_FALSE(Tester.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
// Numeric expression.
@@ -309,10 +294,22 @@
EXPECT_FALSE(Tester.parseSubstExpect("FOO"));
EXPECT_FALSE(Tester.parseSubstExpect("UNDEF"));
- // Use variable defined on same line.
- EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]"));
+ // Valid empty expression.
+ EXPECT_FALSE(Tester.parseSubstExpect(""));
+
+ // Invalid use of variable defined on the same line from expression. Note
+ // that the same pattern object is used for the parsePatternExpect and
+ // parseSubstExpect since no initNextPattern is called, thus appearing as
+ // being on the same line from the pattern's point of view.
+ ASSERT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR"));
+ // Invalid use of variable defined on same line from input. As above, the
+ // absence of a call to initNextPattern makes it appear to be on the same
+ // line from the pattern's point of view.
+ ASSERT_FALSE(Tester.parsePatternExpect("[[#LINE2VAR:]]"));
+ EXPECT_TRUE(Tester.parseSubstExpect("LINE2VAR"));
+
// Unsupported operator.
EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2"));
@@ -323,6 +320,8 @@
EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5"));
EXPECT_FALSE(Tester.parseSubstExpect("FOO+4"));
Tester.initNextPattern();
+ EXPECT_FALSE(Tester.parseSubstExpect("FOOBAR"));
+ EXPECT_FALSE(Tester.parseSubstExpect("LINE1VAR"));
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+FOO]]"));
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+3-FOO]]"));
}
@@ -353,7 +352,6 @@
EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]"));
EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]"));
EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]"));
- EXPECT_TRUE(Tester.parsePatternExpect("[[#YUP:@LINE]]"));
// Valid numeric expressions and numeric variable definition.
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]"));
@@ -364,9 +362,16 @@
TEST_F(FileCheckTest, Match) {
PatternTester Tester;
+ // Check matching an empty expression only matches a number.
+ Tester.parsePatternExpect("[[#]]");
+ EXPECT_TRUE(Tester.matchExpect("FAIL"));
+ EXPECT_FALSE(Tester.matchExpect("18"));
+
// Check matching a definition only matches a number.
+ Tester.initNextPattern();
Tester.parsePatternExpect("[[#NUMVAR:]]");
EXPECT_TRUE(Tester.matchExpect("FAIL"));
+ EXPECT_TRUE(Tester.matchExpect(""));
EXPECT_FALSE(Tester.matchExpect("18"));
// Check matching the variable defined matches the correct number only
@@ -380,16 +385,16 @@
// the correct value for @LINE.
Tester.initNextPattern();
EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
- // Ok, @LINE is 4 now.
- EXPECT_FALSE(Tester.matchExpect("4"));
+ // Ok, @LINE is 5 now.
+ EXPECT_FALSE(Tester.matchExpect("5"));
Tester.initNextPattern();
- // @LINE is now 5, match with substitution failure.
+ // @LINE is now 6, match with substitution failure.
EXPECT_FALSE(Tester.parsePatternExpect("[[#UNKNOWN]]"));
EXPECT_TRUE(Tester.matchExpect("FOO"));
Tester.initNextPattern();
- // Check that @LINE is 6 as expected.
+ // Check that @LINE is 7 as expected.
EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
- EXPECT_FALSE(Tester.matchExpect("6"));
+ EXPECT_FALSE(Tester.matchExpect("7"));
}
TEST_F(FileCheckTest, Substitution) {
@@ -401,53 +406,50 @@
// Substitution of an undefined string variable fails and error holds that
// variable's name.
- FileCheckStringSubstitution StringSubstitution =
- FileCheckStringSubstitution(&Context, "VAR404", 42);
+ StringSubstitution StringSubstitution(&Context, "VAR404", 42);
Expected<std::string> SubstValue = StringSubstitution.getResult();
- EXPECT_FALSE(bool(SubstValue));
+ ASSERT_FALSE(bool(SubstValue));
expectUndefError("VAR404", SubstValue.takeError());
// Substitutions of defined pseudo and non-pseudo numeric variables return
// the right value.
- FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE");
+ NumericVariable LineVar("@LINE", 1);
+ NumericVariable NVar("N", 1);
LineVar.setValue(42);
- FileCheckNumericVariable NVar = FileCheckNumericVariable("N");
NVar.setValue(10);
- auto LineVarUse =
- llvm::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar);
- auto NVarUse = llvm::make_unique<FileCheckNumericVariableUse>("N", &NVar);
- FileCheckNumericSubstitution SubstitutionLine = FileCheckNumericSubstitution(
- &Context, "@LINE", std::move(LineVarUse), 12);
- FileCheckNumericSubstitution SubstitutionN =
- FileCheckNumericSubstitution(&Context, "N", std::move(NVarUse), 30);
+ auto LineVarUse = std::make_unique<NumericVariableUse>("@LINE", &LineVar);
+ auto NVarUse = std::make_unique<NumericVariableUse>("N", &NVar);
+ NumericSubstitution SubstitutionLine(&Context, "@LINE", std::move(LineVarUse),
+ 12);
+ NumericSubstitution SubstitutionN(&Context, "N", std::move(NVarUse), 30);
SubstValue = SubstitutionLine.getResult();
- EXPECT_TRUE(bool(SubstValue));
+ ASSERT_TRUE(bool(SubstValue));
EXPECT_EQ("42", *SubstValue);
SubstValue = SubstitutionN.getResult();
- EXPECT_TRUE(bool(SubstValue));
+ ASSERT_TRUE(bool(SubstValue));
EXPECT_EQ("10", *SubstValue);
// Substitution of an undefined numeric variable fails, error holds name of
// undefined variable.
LineVar.clearValue();
SubstValue = SubstitutionLine.getResult();
- EXPECT_FALSE(bool(SubstValue));
+ ASSERT_FALSE(bool(SubstValue));
expectUndefError("@LINE", SubstValue.takeError());
NVar.clearValue();
SubstValue = SubstitutionN.getResult();
- EXPECT_FALSE(bool(SubstValue));
+ ASSERT_FALSE(bool(SubstValue));
expectUndefError("N", SubstValue.takeError());
// Substitution of a defined string variable returns the right value.
- FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context, 1);
- StringSubstitution = FileCheckStringSubstitution(&Context, "FOO", 42);
+ Pattern P(Check::CheckPlain, &Context, 1);
+ StringSubstitution = llvm::StringSubstitution(&Context, "FOO", 42);
SubstValue = StringSubstitution.getResult();
- EXPECT_TRUE(bool(SubstValue));
+ ASSERT_TRUE(bool(SubstValue));
EXPECT_EQ("BAR", *SubstValue);
}
TEST_F(FileCheckTest, FileCheckContext) {
- FileCheckPatternContext Cxt = FileCheckPatternContext();
+ FileCheckPatternContext Cxt;
std::vector<std::string> GlobalDefines;
SourceMgr SM;
@@ -493,31 +495,46 @@
// Define local variables from command-line.
GlobalDefines.clear();
+ // Clear local variables to remove dummy numeric variable x that
+ // parseNumericSubstitutionBlock would have created and stored in
+ // GlobalNumericVariableTable.
+ Cxt.clearLocalVars();
GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
GlobalDefines.emplace_back(std::string("EmptyVar="));
- GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
- EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
+ GlobalDefines.emplace_back(std::string("#LocalNumVar1=18"));
+ GlobalDefines.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
+ ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
// Check defined variables are present and undefined is absent.
StringRef LocalVarStr = "LocalVar";
- StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar");
+ StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
+ StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
StringRef EmptyVarStr = "EmptyVar";
StringRef UnknownVarStr = "UnknownVar";
Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
- FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1);
- Optional<FileCheckNumericVariable *> DefinedNumericVariable;
- Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionAST =
- P.parseNumericSubstitutionBlock(LocalNumVarRef, DefinedNumericVariable,
- /*IsLegacyLineExpr=*/false, SM);
- EXPECT_TRUE(bool(LocalVar));
+ Pattern P(Check::CheckPlain, &Cxt, 1);
+ Optional<NumericVariable *> DefinedNumericVariable;
+ Expected<std::unique_ptr<ExpressionAST>> ExpressionASTPointer =
+ P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
+ /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/1, &Cxt, SM);
+ ASSERT_TRUE(bool(LocalVar));
EXPECT_EQ(*LocalVar, "FOO");
Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
- EXPECT_TRUE(bool(ExpressionAST));
- Expected<uint64_t> ExpressionVal = (*ExpressionAST)->eval();
- EXPECT_TRUE(bool(ExpressionVal));
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ Expected<uint64_t> ExpressionVal = (*ExpressionASTPointer)->eval();
+ ASSERT_TRUE(bool(ExpressionVal));
EXPECT_EQ(*ExpressionVal, 18U);
- EXPECT_TRUE(bool(EmptyVar));
+ ExpressionASTPointer =
+ P.parseNumericSubstitutionBlock(LocalNumVar2Ref, DefinedNumericVariable,
+ /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/1, &Cxt, SM);
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ ExpressionVal = (*ExpressionASTPointer)->eval();
+ ASSERT_TRUE(bool(ExpressionVal));
+ EXPECT_EQ(*ExpressionVal, 20U);
+ ASSERT_TRUE(bool(EmptyVar));
EXPECT_EQ(*EmptyVar, "");
EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
@@ -529,12 +546,19 @@
// local variables, if it was created before. This is important because local
// variable clearing due to --enable-var-scope happens after numeric
// expressions are linked to the numeric variables they use.
- EXPECT_TRUE(errorToBool((*ExpressionAST)->eval().takeError()));
- P = FileCheckPattern(Check::CheckPlain, &Cxt, 2);
- ExpressionAST = P.parseNumericSubstitutionBlock(
- LocalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
- EXPECT_TRUE(bool(ExpressionAST));
- ExpressionVal = (*ExpressionAST)->eval();
+ EXPECT_TRUE(errorToBool((*ExpressionASTPointer)->eval().takeError()));
+ P = Pattern(Check::CheckPlain, &Cxt, 2);
+ ExpressionASTPointer = P.parseNumericSubstitutionBlock(
+ LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/2, &Cxt, SM);
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ ExpressionVal = (*ExpressionASTPointer)->eval();
+ EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
+ ExpressionASTPointer = P.parseNumericSubstitutionBlock(
+ LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/2, &Cxt, SM);
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ ExpressionVal = (*ExpressionASTPointer)->eval();
EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
EXPECT_TRUE(errorToBool(EmptyVar.takeError()));
@@ -545,29 +569,31 @@
// Redefine global variables and check variables are defined again.
GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));
GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36"));
- EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
+ ASSERT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
StringRef GlobalVarStr = "$GlobalVar";
StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
- EXPECT_TRUE(bool(GlobalVar));
+ ASSERT_TRUE(bool(GlobalVar));
EXPECT_EQ(*GlobalVar, "BAR");
- P = FileCheckPattern(Check::CheckPlain, &Cxt, 3);
- ExpressionAST = P.parseNumericSubstitutionBlock(
- GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
- EXPECT_TRUE(bool(ExpressionAST));
- ExpressionVal = (*ExpressionAST)->eval();
- EXPECT_TRUE(bool(ExpressionVal));
+ P = Pattern(Check::CheckPlain, &Cxt, 3);
+ ExpressionASTPointer = P.parseNumericSubstitutionBlock(
+ GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/3, &Cxt, SM);
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ ExpressionVal = (*ExpressionASTPointer)->eval();
+ ASSERT_TRUE(bool(ExpressionVal));
EXPECT_EQ(*ExpressionVal, 36U);
// Clear local variables and check global variables remain defined.
Cxt.clearLocalVars();
EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
- P = FileCheckPattern(Check::CheckPlain, &Cxt, 4);
- ExpressionAST = P.parseNumericSubstitutionBlock(
- GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
- EXPECT_TRUE(bool(ExpressionAST));
- ExpressionVal = (*ExpressionAST)->eval();
- EXPECT_TRUE(bool(ExpressionVal));
+ P = Pattern(Check::CheckPlain, &Cxt, 4);
+ ExpressionASTPointer = P.parseNumericSubstitutionBlock(
+ GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/4, &Cxt, SM);
+ ASSERT_TRUE(bool(ExpressionASTPointer));
+ ExpressionVal = (*ExpressionASTPointer)->eval();
+ ASSERT_TRUE(bool(ExpressionVal));
EXPECT_EQ(*ExpressionVal, 36U);
}
} // namespace
diff --git a/src/llvm-project/llvm/unittests/Support/FileCollectorTest.cpp b/src/llvm-project/llvm/unittests/Support/FileCollectorTest.cpp
new file mode 100644
index 0000000..c6aeedd
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Support/FileCollectorTest.cpp
@@ -0,0 +1,299 @@
+//===-- FileCollectorTest.cpp -----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "llvm/Support/FileCollector.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace llvm;
+
+namespace llvm {
+namespace vfs {
+inline bool operator==(const llvm::vfs::YAMLVFSEntry &LHS,
+ const llvm::vfs::YAMLVFSEntry &RHS) {
+ return LHS.VPath == RHS.VPath && LHS.RPath == RHS.RPath;
+}
+} // namespace vfs
+} // namespace llvm
+
+namespace {
+class TestingFileCollector : public FileCollector {
+public:
+ using FileCollector::FileCollector;
+ using FileCollector::Root;
+ using FileCollector::Seen;
+ using FileCollector::SymlinkMap;
+ using FileCollector::VFSWriter;
+
+ bool hasSeen(StringRef fs) {
+ return Seen.find(fs) != Seen.end();
+ }
+};
+
+struct ScopedDir {
+ SmallString<128> Path;
+ ScopedDir(const Twine &Name, bool Unique = false) {
+ std::error_code EC;
+ if (Unique) {
+ EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
+ } else {
+ Path = Name.str();
+ EC = llvm::sys::fs::create_directory(Twine(Path));
+ }
+ if (EC)
+ Path = "";
+ EXPECT_FALSE(EC);
+ // Ensure the path is the real path so tests can use it to compare against
+ // realpath output.
+ SmallString<128> RealPath;
+ if (!llvm::sys::fs::real_path(Path, RealPath))
+ Path.swap(RealPath);
+ }
+ ~ScopedDir() {
+ if (Path != "") {
+ EXPECT_FALSE(llvm::sys::fs::remove_directories(Path.str()));
+ }
+ }
+ operator StringRef() { return Path.str(); }
+};
+
+struct ScopedLink {
+ SmallString<128> Path;
+ ScopedLink(const Twine &To, const Twine &From) {
+ Path = From.str();
+ std::error_code EC = sys::fs::create_link(To, From);
+ if (EC)
+ Path = "";
+ EXPECT_FALSE(EC);
+ }
+ ~ScopedLink() {
+ if (Path != "") {
+ EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
+ }
+ }
+ operator StringRef() { return Path.str(); }
+};
+
+struct ScopedFile {
+ SmallString<128> Path;
+ ScopedFile(const Twine &Name) {
+ std::error_code EC;
+ EC = llvm::sys::fs::createUniqueFile(Name, Path);
+ if (EC)
+ Path = "";
+ EXPECT_FALSE(EC);
+ }
+ ~ScopedFile() {
+ if (Path != "") {
+ EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
+ }
+ }
+ operator StringRef() { return Path.str(); }
+};
+} // end anonymous namespace
+
+TEST(FileCollectorTest, addFile) {
+ ScopedDir root("add_file_root", true);
+ std::string root_fs = root.Path.str();
+ TestingFileCollector FileCollector(root_fs, root_fs);
+
+ FileCollector.addFile("/path/to/a");
+ FileCollector.addFile("/path/to/b");
+ FileCollector.addFile("/path/to/c");
+
+ // Make sure the root is correct.
+ EXPECT_EQ(FileCollector.Root, root_fs);
+
+ // Make sure we've seen all the added files.
+ EXPECT_TRUE(FileCollector.hasSeen("/path/to/a"));
+ EXPECT_TRUE(FileCollector.hasSeen("/path/to/b"));
+ EXPECT_TRUE(FileCollector.hasSeen("/path/to/c"));
+
+ // Make sure we've only seen the added files.
+ EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));
+}
+
+TEST(FileCollectorTest, copyFiles) {
+ ScopedDir file_root("file_root", true);
+ ScopedFile a(file_root + "/aaa");
+ ScopedFile b(file_root + "/bbb");
+ ScopedFile c(file_root + "/ccc");
+
+ // Create file collector and add files.
+ ScopedDir root("copy_files_root", true);
+ std::string root_fs = root.Path.str();
+ TestingFileCollector FileCollector(root_fs, root_fs);
+ FileCollector.addFile(a.Path);
+ FileCollector.addFile(b.Path);
+ FileCollector.addFile(c.Path);
+
+ // Make sure we can copy the files.
+ std::error_code ec = FileCollector.copyFiles(true);
+ EXPECT_FALSE(ec);
+
+ // Now add a bogus file and make sure we error out.
+ FileCollector.addFile("/some/bogus/file");
+ ec = FileCollector.copyFiles(true);
+ EXPECT_TRUE(ec);
+
+ // However, if stop_on_error is true the copy should still succeed.
+ ec = FileCollector.copyFiles(false);
+ EXPECT_FALSE(ec);
+}
+
+TEST(FileCollectorTest, recordAndConstructDirectory) {
+ ScopedDir file_root("dir_root", true);
+ ScopedDir subdir(file_root + "/subdir");
+ ScopedDir subdir2(file_root + "/subdir2");
+ ScopedFile a(subdir2 + "/a");
+
+ // Create file collector and add files.
+ ScopedDir root("copy_files_root", true);
+ std::string root_fs = root.Path.str();
+ TestingFileCollector FileCollector(root_fs, root_fs);
+ FileCollector.addFile(a.Path);
+
+ // The empty directory isn't seen until we add it.
+ EXPECT_TRUE(FileCollector.hasSeen(a.Path));
+ EXPECT_FALSE(FileCollector.hasSeen(subdir.Path));
+
+ FileCollector.addFile(subdir.Path);
+ EXPECT_TRUE(FileCollector.hasSeen(subdir.Path));
+
+ // Make sure we can construct the directory.
+ std::error_code ec = FileCollector.copyFiles(true);
+ EXPECT_FALSE(ec);
+ bool IsDirectory = false;
+ llvm::SmallString<128> SubdirInRoot = root.Path;
+ llvm::sys::path::append(SubdirInRoot,
+ llvm::sys::path::relative_path(subdir.Path));
+ ec = sys::fs::is_directory(SubdirInRoot, IsDirectory);
+ EXPECT_FALSE(ec);
+ ASSERT_TRUE(IsDirectory);
+}
+
+TEST(FileCollectorTest, recordVFSAccesses) {
+ ScopedDir file_root("dir_root", true);
+ ScopedDir subdir(file_root + "/subdir");
+ ScopedDir subdir2(file_root + "/subdir2");
+ ScopedFile a(subdir2 + "/a");
+ ScopedFile b(file_root + "/b");
+ ScopedDir subdir3(file_root + "/subdir3");
+ ScopedFile subdir3a(subdir3 + "/aa");
+ ScopedDir subdir3b(subdir3 + "/subdirb");
+ {
+ ScopedFile subdir3fileremoved(subdir3 + "/removed");
+ }
+
+ // Create file collector and add files.
+ ScopedDir root("copy_files_root", true);
+ std::string root_fs = root.Path.str();
+ auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
+ auto VFS =
+ FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
+ VFS->status(a.Path);
+ EXPECT_TRUE(Collector->hasSeen(a.Path));
+
+ VFS->openFileForRead(b.Path);
+ EXPECT_TRUE(Collector->hasSeen(b.Path));
+
+ VFS->status(subdir.Path);
+ EXPECT_TRUE(Collector->hasSeen(subdir.Path));
+
+#ifndef _WIN32
+ std::error_code EC;
+ auto It = VFS->dir_begin(subdir3.Path, EC);
+ EXPECT_FALSE(EC);
+ EXPECT_TRUE(Collector->hasSeen(subdir3.Path));
+ EXPECT_TRUE(Collector->hasSeen(subdir3a.Path));
+ EXPECT_TRUE(Collector->hasSeen(subdir3b.Path));
+ std::string RemovedFileName = (Twine(subdir3.Path) + "/removed").str();
+ EXPECT_FALSE(Collector->hasSeen(RemovedFileName));
+#endif
+}
+
+#ifndef _WIN32
+TEST(FileCollectorTest, Symlinks) {
+ // Root where the original files live.
+ ScopedDir file_root("file_root", true);
+
+ // Create some files in the file root.
+ ScopedFile a(file_root + "/aaa");
+ ScopedFile b(file_root + "/bbb");
+ ScopedFile c(file_root + "/ccc");
+
+ // Create a directory foo with file ddd.
+ ScopedDir foo(file_root + "/foo");
+ ScopedFile d(foo + "/ddd");
+
+ // Create a file eee in the foo's parent directory.
+ ScopedFile e(foo + "/../eee");
+
+ // Create a symlink bar pointing to foo.
+ ScopedLink symlink(file_root + "/foo", file_root + "/bar");
+
+ // Root where files are copied to.
+ ScopedDir reproducer_root("reproducer_root", true);
+ std::string root_fs = reproducer_root.Path.str();
+ TestingFileCollector FileCollector(root_fs, root_fs);
+
+ // Add all the files to the collector.
+ FileCollector.addFile(a.Path);
+ FileCollector.addFile(b.Path);
+ FileCollector.addFile(c.Path);
+ FileCollector.addFile(d.Path);
+ FileCollector.addFile(e.Path);
+ FileCollector.addFile(file_root + "/bar/ddd");
+
+ auto mapping = FileCollector.VFSWriter.getMappings();
+
+ {
+ // Make sure the common case works.
+ std::string vpath = (file_root + "/aaa").str();
+ std::string rpath = (reproducer_root.Path + file_root.Path + "/aaa").str();
+ printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
+ EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
+ }
+
+ {
+ // Make sure the virtual path points to the real source path.
+ std::string vpath = (file_root + "/bar/ddd").str();
+ std::string rpath =
+ (reproducer_root.Path + file_root.Path + "/foo/ddd").str();
+ printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
+ EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
+ }
+
+ {
+ // Make sure that .. is removed from the source path.
+ std::string vpath = (file_root + "/eee").str();
+ std::string rpath = (reproducer_root.Path + file_root.Path + "/eee").str();
+ printf("%s -> %s\n", vpath.c_str(), rpath.c_str());
+ EXPECT_THAT(mapping, testing::Contains(vfs::YAMLVFSEntry(vpath, rpath)));
+ }
+}
+
+TEST(FileCollectorTest, recordVFSSymlinkAccesses) {
+ ScopedDir file_root("dir_root", true);
+ ScopedFile a(file_root + "/a");
+ ScopedLink symlink(file_root + "/a", file_root + "/b");
+
+ // Create file collector and add files.
+ ScopedDir root("copy_files_root", true);
+ std::string root_fs = root.Path.str();
+ auto Collector = std::make_shared<TestingFileCollector>(root_fs, root_fs);
+ auto VFS =
+ FileCollector::createCollectorVFS(vfs::getRealFileSystem(), Collector);
+ SmallString<256> Output;
+ VFS->getRealPath(symlink.Path, Output);
+ EXPECT_TRUE(Collector->hasSeen(a.Path));
+ EXPECT_TRUE(Collector->hasSeen(symlink.Path));
+}
+#endif
diff --git a/src/llvm-project/llvm/unittests/Support/FileOutputBufferTest.cpp b/src/llvm-project/llvm/unittests/Support/FileOutputBufferTest.cpp
index 8afc212..6b6196f 100644
--- a/src/llvm-project/llvm/unittests/Support/FileOutputBufferTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/FileOutputBufferTest.cpp
@@ -118,6 +118,28 @@
EXPECT_TRUE(IsExecutable);
ASSERT_NO_ERROR(fs::remove(File4.str()));
+ // TEST 5: In-memory buffer works as expected.
+ SmallString<128> File5(TestDirectory);
+ File5.append("/file5");
+ {
+ Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(File5, 8000, FileOutputBuffer::F_no_mmap);
+ ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
+ std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
+ // Start buffer with special header.
+ memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
+ // Write to end of buffer to verify it is writable.
+ memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Commit buffer.
+ ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
+ }
+
+ // Verify file is correct size.
+ uint64_t File5Size;
+ ASSERT_NO_ERROR(fs::file_size(Twine(File5), File5Size));
+ ASSERT_EQ(File5Size, 8000ULL);
+ ASSERT_NO_ERROR(fs::remove(File5.str()));
// Clean up.
ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
}
diff --git a/src/llvm-project/llvm/unittests/Support/FileUtilitiesTest.cpp b/src/llvm-project/llvm/unittests/Support/FileUtilitiesTest.cpp
new file mode 100644
index 0000000..2bf9dc5
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/Support/FileUtilitiesTest.cpp
@@ -0,0 +1,52 @@
+//===- llvm/unittest/Support/FileUtilitiesTest.cpp - 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 "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "gtest/gtest.h"
+#include <fstream>
+
+using namespace llvm;
+using namespace llvm::sys;
+
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+
+namespace {
+TEST(writeFileAtomicallyTest, Test) {
+ // Create unique temporary directory for these tests
+ SmallString<128> RootTestDirectory;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("writeFileAtomicallyTest", RootTestDirectory));
+
+ SmallString<128> FinalTestfilePath(RootTestDirectory);
+ sys::path::append(FinalTestfilePath, "foo.txt");
+ const std::string TempUniqTestFileModel = FinalTestfilePath.str().str() + "-%%%%%%%%";
+ const std::string TestfileContent = "fooFOOfoo";
+
+ llvm::Error Err = llvm::writeFileAtomically(TempUniqTestFileModel, FinalTestfilePath, TestfileContent);
+ ASSERT_FALSE(static_cast<bool>(Err));
+
+ std::ifstream FinalFileStream(FinalTestfilePath.str());
+ std::string FinalFileContent;
+ FinalFileStream >> FinalFileContent;
+ ASSERT_EQ(FinalFileContent, TestfileContent);
+}
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/GlobPatternTest.cpp b/src/llvm-project/llvm/unittests/Support/GlobPatternTest.cpp
index 113b20e..17d60b2 100644
--- a/src/llvm-project/llvm/unittests/Support/GlobPatternTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/GlobPatternTest.cpp
@@ -14,57 +14,115 @@
class GlobPatternTest : public ::testing::Test {};
-TEST_F(GlobPatternTest, Basics) {
+TEST_F(GlobPatternTest, Empty) {
Expected<GlobPattern> Pat1 = GlobPattern::create("");
EXPECT_TRUE((bool)Pat1);
EXPECT_TRUE(Pat1->match(""));
EXPECT_FALSE(Pat1->match("a"));
+}
- Expected<GlobPattern> Pat2 = GlobPattern::create("ab*c*def");
+TEST_F(GlobPatternTest, Glob) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("ab*c*def");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("abcdef"));
+ EXPECT_TRUE(Pat1->match("abxcxdef"));
+ EXPECT_FALSE(Pat1->match(""));
+ EXPECT_FALSE(Pat1->match("xabcdef"));
+ EXPECT_FALSE(Pat1->match("abcdefx"));
+}
+
+TEST_F(GlobPatternTest, Wildcard) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("a??c");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("axxc"));
+ EXPECT_FALSE(Pat1->match("axxx"));
+ EXPECT_FALSE(Pat1->match(""));
+}
+
+TEST_F(GlobPatternTest, Escape) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("\\*");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("*"));
+ EXPECT_FALSE(Pat1->match("\\*"));
+ EXPECT_FALSE(Pat1->match("a"));
+
+ Expected<GlobPattern> Pat2 = GlobPattern::create("a?\\?c");
EXPECT_TRUE((bool)Pat2);
- EXPECT_TRUE(Pat2->match("abcdef"));
- EXPECT_TRUE(Pat2->match("abxcxdef"));
+ EXPECT_TRUE(Pat2->match("ax?c"));
+ EXPECT_FALSE(Pat2->match("axxc"));
EXPECT_FALSE(Pat2->match(""));
- EXPECT_FALSE(Pat2->match("xabcdef"));
- EXPECT_FALSE(Pat2->match("abcdefx"));
+}
- Expected<GlobPattern> Pat3 = GlobPattern::create("a??c");
- EXPECT_TRUE((bool)Pat3);
- EXPECT_TRUE(Pat3->match("axxc"));
- EXPECT_FALSE(Pat3->match("axxx"));
- EXPECT_FALSE(Pat3->match(""));
+TEST_F(GlobPatternTest, BasicCharacterClass) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("[abc-fy-z]");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("a"));
+ EXPECT_TRUE(Pat1->match("b"));
+ EXPECT_TRUE(Pat1->match("c"));
+ EXPECT_TRUE(Pat1->match("d"));
+ EXPECT_TRUE(Pat1->match("e"));
+ EXPECT_TRUE(Pat1->match("f"));
+ EXPECT_TRUE(Pat1->match("y"));
+ EXPECT_TRUE(Pat1->match("z"));
+ EXPECT_FALSE(Pat1->match("g"));
+ EXPECT_FALSE(Pat1->match(""));
+}
- Expected<GlobPattern> Pat4 = GlobPattern::create("[abc-fy-z]");
- EXPECT_TRUE((bool)Pat4);
- EXPECT_TRUE(Pat4->match("a"));
- EXPECT_TRUE(Pat4->match("b"));
- EXPECT_TRUE(Pat4->match("c"));
- EXPECT_TRUE(Pat4->match("d"));
- EXPECT_TRUE(Pat4->match("e"));
- EXPECT_TRUE(Pat4->match("f"));
- EXPECT_TRUE(Pat4->match("y"));
- EXPECT_TRUE(Pat4->match("z"));
- EXPECT_FALSE(Pat4->match("g"));
- EXPECT_FALSE(Pat4->match(""));
+TEST_F(GlobPatternTest, NegatedCharacterClass) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("[^abc-fy-z]");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("g"));
+ EXPECT_FALSE(Pat1->match("a"));
+ EXPECT_FALSE(Pat1->match("b"));
+ EXPECT_FALSE(Pat1->match("c"));
+ EXPECT_FALSE(Pat1->match("d"));
+ EXPECT_FALSE(Pat1->match("e"));
+ EXPECT_FALSE(Pat1->match("f"));
+ EXPECT_FALSE(Pat1->match("y"));
+ EXPECT_FALSE(Pat1->match("z"));
+ EXPECT_FALSE(Pat1->match(""));
- Expected<GlobPattern> Pat5 = GlobPattern::create("[^abc-fy-z]");
- EXPECT_TRUE((bool)Pat5);
- EXPECT_TRUE(Pat5->match("g"));
- EXPECT_FALSE(Pat5->match("a"));
- EXPECT_FALSE(Pat5->match("b"));
- EXPECT_FALSE(Pat5->match("c"));
- EXPECT_FALSE(Pat5->match("d"));
- EXPECT_FALSE(Pat5->match("e"));
- EXPECT_FALSE(Pat5->match("f"));
- EXPECT_FALSE(Pat5->match("y"));
- EXPECT_FALSE(Pat5->match("z"));
- EXPECT_FALSE(Pat5->match(""));
+ Expected<GlobPattern> Pat2 = GlobPattern::create("[!abc-fy-z]");
+ EXPECT_TRUE((bool)Pat2);
+ EXPECT_TRUE(Pat2->match("g"));
+ EXPECT_FALSE(Pat2->match("a"));
+ EXPECT_FALSE(Pat2->match("b"));
+ EXPECT_FALSE(Pat2->match("c"));
+ EXPECT_FALSE(Pat2->match("d"));
+ EXPECT_FALSE(Pat2->match("e"));
+ EXPECT_FALSE(Pat2->match("f"));
+ EXPECT_FALSE(Pat2->match("y"));
+ EXPECT_FALSE(Pat2->match("z"));
+ EXPECT_FALSE(Pat2->match(""));
+}
+
+TEST_F(GlobPatternTest, BracketFrontOfCharacterClass) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("[]a]x");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("]x"));
+ EXPECT_TRUE(Pat1->match("ax"));
+ EXPECT_FALSE(Pat1->match("a]x"));
+ EXPECT_FALSE(Pat1->match(""));
+}
+
+TEST_F(GlobPatternTest, SpecialCharsInCharacterClass) {
+ Expected<GlobPattern> Pat1 = GlobPattern::create("[*?^]");
+ EXPECT_TRUE((bool)Pat1);
+ EXPECT_TRUE(Pat1->match("*"));
+ EXPECT_TRUE(Pat1->match("?"));
+ EXPECT_TRUE(Pat1->match("^"));
+ EXPECT_FALSE(Pat1->match("*?^"));
+ EXPECT_FALSE(Pat1->match(""));
}
TEST_F(GlobPatternTest, Invalid) {
Expected<GlobPattern> Pat1 = GlobPattern::create("[");
EXPECT_FALSE((bool)Pat1);
handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {});
+
+ Expected<GlobPattern> Pat2 = GlobPattern::create("[]");
+ EXPECT_FALSE((bool)Pat2);
+ handleAllErrors(Pat2.takeError(), [&](ErrorInfoBase &EIB) {});
}
TEST_F(GlobPatternTest, ExtSym) {
diff --git a/src/llvm-project/llvm/unittests/Support/Host.cpp b/src/llvm-project/llvm/unittests/Support/Host.cpp
index ec9dd95..2c17a50 100644
--- a/src/llvm-project/llvm/unittests/Support/Host.cpp
+++ b/src/llvm-project/llvm/unittests/Support/Host.cpp
@@ -147,7 +147,7 @@
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
-CPU part : 0xd03
+CPU part : 0xd05
processor : 1
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
@@ -159,17 +159,17 @@
EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
"CPU variant : 0xc\n"
"CPU part : 0xafe"),
- "exynos-m1");
- // Verify Exynos M1.
+ "exynos-m3");
+ // Verify Exynos M3.
EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
"CPU variant : 0x1\n"
- "CPU part : 0x001"),
- "exynos-m1");
- // Verify Exynos M2.
+ "CPU part : 0x002"),
+ "exynos-m3");
+ // Verify Exynos M4.
EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
- "CPU variant : 0x4\n"
- "CPU part : 0x001"),
- "exynos-m2");
+ "CPU variant : 0x1\n"
+ "CPU part : 0x003"),
+ "exynos-m4");
const std::string ThunderX2T99ProcCpuInfo = R"(
processor : 0
@@ -273,7 +273,7 @@
Size = ::lseek(FD, 0, SEEK_END);
ASSERT_NE(-1, Size);
::lseek(FD, 0, SEEK_SET);
- Buffer = llvm::make_unique<char[]>(Size);
+ Buffer = std::make_unique<char[]>(Size);
ASSERT_EQ(::read(FD, Buffer.get(), Size), Size);
::close(FD);
diff --git a/src/llvm-project/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp b/src/llvm-project/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp
index 9143289..b20cdcf 100644
--- a/src/llvm-project/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp
@@ -249,6 +249,19 @@
{"_Z1fRA1_i"}, {"_Z1fRA_f"},
}
},
+
+ // Unmangled names can be remapped as complete encodings.
+ {
+ {
+ {FragmentKind::Encoding, "3foo", "3bar"},
+ },
+ {
+ // foo == bar
+ {"foo", "bar"},
+ // void f<foo>() == void f<bar>()
+ {"_Z1fIL_Z3fooEEvv", "_Z1fIL_Z3barEEvv"},
+ }
+ },
};
}
@@ -343,7 +356,7 @@
EquivalenceError::InvalidSecondMangling);
EXPECT_EQ(Canonicalizer.canonicalize("_Z3fooE"),
llvm::ItaniumManglingCanonicalizer::Key());
- EXPECT_EQ(Canonicalizer.canonicalize("foo"),
+ EXPECT_EQ(Canonicalizer.canonicalize("_Zfoo"),
llvm::ItaniumManglingCanonicalizer::Key());
// A reference to a template parameter ('T_' etc) cannot appear in a <name>,
diff --git a/src/llvm-project/llvm/unittests/Support/JSONTest.cpp b/src/llvm-project/llvm/unittests/Support/JSONTest.cpp
index 14c11b1..93efcf2 100644
--- a/src/llvm-project/llvm/unittests/Support/JSONTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/JSONTest.cpp
@@ -71,7 +71,7 @@
}
TEST(JSONTest, Escaping) {
- std::string test = {
+ std::string Test = {
0, // Strings may contain nulls.
'\b', '\f', // Have mnemonics, but we escape numerically.
'\r', '\n', '\t', // Escaped with mnemonics.
@@ -80,17 +80,17 @@
'\xce', '\x94', // Non-ASCII UTF-8 is not escaped.
};
- std::string teststring = R"("\u0000\u0008\u000c\r\n\tS\"\\)"
+ std::string TestString = R"("\u0000\u0008\u000c\r\n\tS\"\\)"
"\x7f\xCE\x94\"";
- EXPECT_EQ(teststring, s(test));
+ EXPECT_EQ(TestString, s(Test));
EXPECT_EQ(R"({"object keys are\nescaped":true})",
s(Object{{"object keys are\nescaped", true}}));
}
TEST(JSONTest, PrettyPrinting) {
- const char str[] = R"({
+ const char Str[] = R"({
"empty_array": [],
"empty_object": {},
"full_array": [
@@ -106,7 +106,7 @@
}
})";
- EXPECT_EQ(str, sp(Object{
+ EXPECT_EQ(Str, sp(Object{
{"empty_object", Object{}},
{"empty_array", {}},
{"full_array", {1, nullptr}},
@@ -120,6 +120,33 @@
}));
}
+TEST(JSONTest, Array) {
+ Array A{1, 2};
+ A.emplace_back(3);
+ A.emplace(++A.begin(), 0);
+ A.push_back(4);
+ A.insert(++++A.begin(), 99);
+
+ EXPECT_EQ(A.size(), 6u);
+ EXPECT_EQ(R"([1,0,99,2,3,4])", s(std::move(A)));
+}
+
+TEST(JSONTest, Object) {
+ Object O{{"a", 1}, {"b", 2}, {"c", 3}};
+ EXPECT_TRUE(O.try_emplace("d", 4).second);
+ EXPECT_FALSE(O.try_emplace("a", 4).second);
+
+ auto D = O.find("d");
+ EXPECT_FALSE(D == O.end());
+ auto E = O.find("e");
+ EXPECT_TRUE(E == O.end());
+
+ O.erase("b");
+ O.erase(D);
+ EXPECT_EQ(O.size(), 2u);
+ EXPECT_EQ(R"({"a":1,"c":3})", s(std::move(O)));
+}
+
TEST(JSONTest, Parse) {
auto Compare = [](llvm::StringRef S, Value Expected) {
if (auto E = parse(S)) {
diff --git a/src/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp b/src/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp
index c2b3b12..372521d 100644
--- a/src/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp
@@ -127,4 +127,18 @@
TestAddSubExhaustive(false);
}
+TEST(KnownBitsTest, GetMinMaxVal) {
+ unsigned Bits = 4;
+ ForeachKnownBits(Bits, [&](const KnownBits &Known) {
+ APInt Min = APInt::getMaxValue(Bits);
+ APInt Max = APInt::getMinValue(Bits);
+ ForeachNumInKnownBits(Known, [&](const APInt &N) {
+ Min = APIntOps::umin(Min, N);
+ Max = APIntOps::umax(Max, N);
+ });
+ EXPECT_EQ(Min, Known.getMinValue());
+ EXPECT_EQ(Max, Known.getMaxValue());
+ });
+}
+
} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/MathExtrasTest.cpp b/src/llvm-project/llvm/unittests/Support/MathExtrasTest.cpp
index de87714..e910d83 100644
--- a/src/llvm-project/llvm/unittests/Support/MathExtrasTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/MathExtrasTest.cpp
@@ -203,6 +203,25 @@
EXPECT_EQ(4U, PowerOf2Floor(7U));
}
+TEST(MathExtras, CTLog2) {
+ EXPECT_EQ(CTLog2<1ULL << 0>(), 0U);
+ EXPECT_EQ(CTLog2<1ULL << 1>(), 1U);
+ EXPECT_EQ(CTLog2<1ULL << 2>(), 2U);
+ EXPECT_EQ(CTLog2<1ULL << 3>(), 3U);
+ EXPECT_EQ(CTLog2<1ULL << 4>(), 4U);
+ EXPECT_EQ(CTLog2<1ULL << 5>(), 5U);
+ EXPECT_EQ(CTLog2<1ULL << 6>(), 6U);
+ EXPECT_EQ(CTLog2<1ULL << 7>(), 7U);
+ EXPECT_EQ(CTLog2<1ULL << 8>(), 8U);
+ EXPECT_EQ(CTLog2<1ULL << 9>(), 9U);
+ EXPECT_EQ(CTLog2<1ULL << 10>(), 10U);
+ EXPECT_EQ(CTLog2<1ULL << 11>(), 11U);
+ EXPECT_EQ(CTLog2<1ULL << 12>(), 12U);
+ EXPECT_EQ(CTLog2<1ULL << 13>(), 13U);
+ EXPECT_EQ(CTLog2<1ULL << 14>(), 14U);
+ EXPECT_EQ(CTLog2<1ULL << 15>(), 15U);
+}
+
TEST(MathExtras, ByteSwap_32) {
EXPECT_EQ(0x44332211u, ByteSwap_32(0x11223344));
EXPECT_EQ(0xDDCCBBAAu, ByteSwap_32(0xAABBCCDD));
@@ -468,4 +487,131 @@
EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15)));
}
+template <typename T>
+class OverflowTest : public ::testing::Test { };
+
+using OverflowTestTypes = ::testing::Types<signed char, short, int, long,
+ long long>;
+
+TYPED_TEST_CASE(OverflowTest, OverflowTestTypes);
+
+TYPED_TEST(OverflowTest, AddNoOverflow) {
+ TypeParam Result;
+ EXPECT_FALSE(AddOverflow<TypeParam>(1, 2, Result));
+ EXPECT_EQ(Result, TypeParam(3));
+}
+
+TYPED_TEST(OverflowTest, AddOverflowToNegative) {
+ TypeParam Result;
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ EXPECT_TRUE(AddOverflow<TypeParam>(MaxValue, MaxValue, Result));
+ EXPECT_EQ(Result, TypeParam(-2));
+}
+
+TYPED_TEST(OverflowTest, AddOverflowToMin) {
+ TypeParam Result;
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ EXPECT_TRUE(AddOverflow<TypeParam>(MaxValue, TypeParam(1), Result));
+ EXPECT_EQ(Result, std::numeric_limits<TypeParam>::min());
+}
+
+TYPED_TEST(OverflowTest, AddOverflowToZero) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(AddOverflow<TypeParam>(MinValue, MinValue, Result));
+ EXPECT_EQ(Result, TypeParam(0));
+}
+
+TYPED_TEST(OverflowTest, AddOverflowToMax) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(AddOverflow<TypeParam>(MinValue, TypeParam(-1), Result));
+ EXPECT_EQ(Result, std::numeric_limits<TypeParam>::max());
+}
+
+TYPED_TEST(OverflowTest, SubNoOverflow) {
+ TypeParam Result;
+ EXPECT_FALSE(SubOverflow<TypeParam>(1, 2, Result));
+ EXPECT_EQ(Result, TypeParam(-1));
+}
+
+TYPED_TEST(OverflowTest, SubOverflowToMax) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(SubOverflow<TypeParam>(0, MinValue, Result));
+ EXPECT_EQ(Result, MinValue);
+}
+
+TYPED_TEST(OverflowTest, SubOverflowToMin) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(SubOverflow<TypeParam>(0, MinValue, Result));
+ EXPECT_EQ(Result, MinValue);
+}
+
+TYPED_TEST(OverflowTest, SubOverflowToNegative) {
+ TypeParam Result;
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(SubOverflow<TypeParam>(MaxValue, MinValue, Result));
+ EXPECT_EQ(Result, TypeParam(-1));
+}
+
+TYPED_TEST(OverflowTest, SubOverflowToPositive) {
+ TypeParam Result;
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(SubOverflow<TypeParam>(MinValue, MaxValue, Result));
+ EXPECT_EQ(Result, TypeParam(1));
+}
+
+TYPED_TEST(OverflowTest, MulNoOverflow) {
+ TypeParam Result;
+ EXPECT_FALSE(MulOverflow<TypeParam>(1, 2, Result));
+ EXPECT_EQ(Result, 2);
+ EXPECT_FALSE(MulOverflow<TypeParam>(-1, 3, Result));
+ EXPECT_EQ(Result, -3);
+ EXPECT_FALSE(MulOverflow<TypeParam>(4, -2, Result));
+ EXPECT_EQ(Result, -8);
+ EXPECT_FALSE(MulOverflow<TypeParam>(-6, -5, Result));
+ EXPECT_EQ(Result, 30);
+}
+
+TYPED_TEST(OverflowTest, MulNoOverflowToMax) {
+ TypeParam Result;
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_FALSE(MulOverflow<TypeParam>(MinValue + 1, -1, Result));
+ EXPECT_EQ(Result, MaxValue);
+}
+
+TYPED_TEST(OverflowTest, MulOverflowToMin) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ EXPECT_TRUE(MulOverflow<TypeParam>(MinValue, -1, Result));
+ EXPECT_EQ(Result, MinValue);
+}
+
+TYPED_TEST(OverflowTest, MulOverflowMax) {
+ TypeParam Result;
+ auto MinValue = std::numeric_limits<TypeParam>::min();
+ auto MaxValue = std::numeric_limits<TypeParam>::max();
+ EXPECT_TRUE(MulOverflow<TypeParam>(MinValue, MinValue, Result));
+ EXPECT_EQ(Result, 0);
+ EXPECT_TRUE(MulOverflow<TypeParam>(MaxValue, MaxValue, Result));
+ EXPECT_EQ(Result, 1);
+}
+
+TYPED_TEST(OverflowTest, MulResultZero) {
+ TypeParam Result;
+ EXPECT_FALSE(MulOverflow<TypeParam>(4, 0, Result));
+ EXPECT_EQ(Result, TypeParam(0));
+ EXPECT_FALSE(MulOverflow<TypeParam>(-5, 0, Result));
+ EXPECT_EQ(Result, TypeParam(0));
+ EXPECT_FALSE(MulOverflow<TypeParam>(0, 5, Result));
+ EXPECT_EQ(Result, TypeParam(0));
+ EXPECT_FALSE(MulOverflow<TypeParam>(0, -5, Result));
+ EXPECT_EQ(Result, TypeParam(0));
+}
+
} // namespace
diff --git a/src/llvm-project/llvm/unittests/Support/MemoryBufferTest.cpp b/src/llvm-project/llvm/unittests/Support/MemoryBufferTest.cpp
index 2f96643..1b72aad 100644
--- a/src/llvm-project/llvm/unittests/Support/MemoryBufferTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/MemoryBufferTest.cpp
@@ -11,14 +11,43 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
+#if LLVM_ENABLE_THREADS
+#include <thread>
+#endif
+#if LLVM_ON_UNIX
+#include <unistd.h>
+#endif
+#if _WIN32
+#include <windows.h>
+#endif
using namespace llvm;
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+
+#define ASSERT_ERROR(x) \
+ if (!x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return a failure error code.\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ }
+
namespace {
class MemoryBufferTest : public testing::Test {
@@ -65,6 +94,37 @@
EXPECT_EQ("this is some data", data);
}
+TEST_F(MemoryBufferTest, getOpenFile) {
+ int FD;
+ SmallString<64> TestPath;
+ ASSERT_EQ(sys::fs::createTemporaryFile("MemoryBufferTest_getOpenFile", "temp",
+ FD, TestPath),
+ std::error_code());
+
+ FileRemover Cleanup(TestPath);
+ raw_fd_ostream OF(FD, /*shouldClose*/ true);
+ OF << "12345678";
+ OF.close();
+
+ {
+ Expected<sys::fs::file_t> File = sys::fs::openNativeFileForRead(TestPath);
+ ASSERT_THAT_EXPECTED(File, Succeeded());
+ auto OnExit =
+ make_scope_exit([&] { ASSERT_NO_ERROR(sys::fs::closeFile(*File)); });
+ ErrorOr<OwningBuffer> MB = MemoryBuffer::getOpenFile(*File, TestPath, 6);
+ ASSERT_NO_ERROR(MB.getError());
+ EXPECT_EQ("123456", MB.get()->getBuffer());
+ }
+ {
+ Expected<sys::fs::file_t> File = sys::fs::openNativeFileForWrite(
+ TestPath, sys::fs::CD_OpenExisting, sys::fs::OF_None);
+ ASSERT_THAT_EXPECTED(File, Succeeded());
+ auto OnExit =
+ make_scope_exit([&] { ASSERT_NO_ERROR(sys::fs::closeFile(*File)); });
+ ASSERT_ERROR(MemoryBuffer::getOpenFile(*File, TestPath, 6).getError());
+ }
+}
+
TEST_F(MemoryBufferTest, NullTerminator4K) {
// Test that a file with size that is a multiple of the page size can be null
// terminated correctly by MemoryBuffer.
@@ -101,6 +161,38 @@
EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart());
}
+#if LLVM_ENABLE_THREADS
+TEST_F(MemoryBufferTest, createFromPipe) {
+ sys::fs::file_t pipes[2];
+#if LLVM_ON_UNIX
+ ASSERT_EQ(::pipe(pipes), 0) << strerror(errno);
+#else
+ ASSERT_TRUE(::CreatePipe(&pipes[0], &pipes[1], nullptr, 0))
+ << ::GetLastError();
+#endif
+ auto ReadCloser = make_scope_exit([&] { sys::fs::closeFile(pipes[0]); });
+ std::thread Writer([&] {
+ auto WriteCloser = make_scope_exit([&] { sys::fs::closeFile(pipes[1]); });
+ for (unsigned i = 0; i < 5; ++i) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+#if LLVM_ON_UNIX
+ ASSERT_EQ(::write(pipes[1], "foo", 3), 3) << strerror(errno);
+#else
+ DWORD Written;
+ ASSERT_TRUE(::WriteFile(pipes[1], "foo", 3, &Written, nullptr))
+ << ::GetLastError();
+ ASSERT_EQ(Written, 3u);
+#endif
+ }
+ });
+ ErrorOr<OwningBuffer> MB =
+ MemoryBuffer::getOpenFile(pipes[0], "pipe", /*FileSize*/ -1);
+ Writer.join();
+ ASSERT_NO_ERROR(MB.getError());
+ EXPECT_EQ(MB.get()->getBuffer(), "foofoofoofoofoo");
+}
+#endif
+
TEST_F(MemoryBufferTest, make_new) {
// 0-sized buffer
OwningBuffer Zero(WritableMemoryBuffer::getNewUninitMemBuffer(0));
diff --git a/src/llvm-project/llvm/unittests/Support/Path.cpp b/src/llvm-project/llvm/unittests/Support/Path.cpp
index ccd72d7..b143ea6 100644
--- a/src/llvm-project/llvm/unittests/Support/Path.cpp
+++ b/src/llvm-project/llvm/unittests/Support/Path.cpp
@@ -8,6 +8,7 @@
#include "llvm/Support/Path.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Magic.h"
@@ -20,8 +21,9 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
+#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#ifdef _WIN32
#include "llvm/ADT/ArrayRef.h"
@@ -185,10 +187,19 @@
path::native(*i, temp_store);
}
- SmallString<32> Relative("foo.cpp");
- sys::fs::make_absolute("/root", Relative);
- Relative[5] = '/'; // Fix up windows paths.
- ASSERT_EQ("/root/foo.cpp", Relative);
+ {
+ SmallString<32> Relative("foo.cpp");
+ sys::fs::make_absolute("/root", Relative);
+ Relative[5] = '/'; // Fix up windows paths.
+ ASSERT_EQ("/root/foo.cpp", Relative);
+ }
+
+ {
+ SmallString<32> Relative("foo.cpp");
+ sys::fs::make_absolute("//root", Relative);
+ Relative[6] = '/'; // Fix up windows paths.
+ ASSERT_EQ("//root/foo.cpp", Relative);
+ }
}
TEST(Support, FilenameParent) {
@@ -1021,7 +1032,7 @@
path::append(FilePathname, "test");
{
- raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text);
+ raw_fd_ostream File(FilePathname, EC, sys::fs::OF_Text);
ASSERT_NO_ERROR(EC);
File << '\n';
}
@@ -1032,7 +1043,7 @@
}
{
- raw_fd_ostream File(FilePathname, EC, sys::fs::F_None);
+ raw_fd_ostream File(FilePathname, EC, sys::fs::OF_None);
ASSERT_NO_ERROR(EC);
File << '\n';
}
@@ -1219,7 +1230,9 @@
TEST(Support, ReplacePathPrefix) {
SmallString<64> Path1("/foo");
SmallString<64> Path2("/old/foo");
+ SmallString<64> Path3("/oldnew/foo");
SmallString<64> OldPrefix("/old");
+ SmallString<64> OldPrefixSep("/old/");
SmallString<64> NewPrefix("/new");
SmallString<64> NewPrefix2("/longernew");
SmallString<64> EmptyPrefix("");
@@ -1239,6 +1252,39 @@
Path = Path2;
path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
EXPECT_EQ(Path, "/foo");
+ Path = Path2;
+ path::replace_path_prefix(Path, OldPrefix, EmptyPrefix, path::Style::native,
+ true);
+ EXPECT_EQ(Path, "foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix, path::Style::native,
+ false);
+ EXPECT_EQ(Path, "/newnew/foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix, path::Style::native,
+ true);
+ EXPECT_EQ(Path, "/oldnew/foo");
+ Path = Path3;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, path::Style::native,
+ true);
+ EXPECT_EQ(Path, "/oldnew/foo");
+ Path = Path1;
+ path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/foo");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new");
+ Path = OldPrefixSep;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, path::Style::native,
+ false);
+ EXPECT_EQ(Path, "/old");
+ Path = OldPrefix;
+ path::replace_path_prefix(Path, OldPrefixSep, NewPrefix, path::Style::native,
+ true);
+ EXPECT_EQ(Path, "/new");
}
TEST_F(FileSystemTest, OpenFileForRead) {
@@ -1418,7 +1464,7 @@
fs::CD_OpenExisting};
// Write some data and re-open it with every possible disposition (this is a
- // hack that shouldn't work, but is left for compatibility. F_Append
+ // hack that shouldn't work, but is left for compatibility. OF_Append
// overrides
// the specified disposition.
for (fs::CreationDisposition Disp : Disps) {
@@ -1504,6 +1550,49 @@
verifyWrite(FD, "Buzz", true);
}
+TEST_F(FileSystemTest, readNativeFile) {
+ createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "01234");
+ FileRemover Cleanup(NonExistantFile);
+ const auto &Read = [&](size_t ToRead) -> Expected<std::string> {
+ std::string Buf(ToRead, '?');
+ Expected<fs::file_t> FD = fs::openNativeFileForRead(NonExistantFile);
+ if (!FD)
+ return FD.takeError();
+ auto Close = make_scope_exit([&] { fs::closeFile(*FD); });
+ if (Expected<size_t> BytesRead = fs::readNativeFile(
+ *FD, makeMutableArrayRef(&*Buf.begin(), Buf.size())))
+ return Buf.substr(0, *BytesRead);
+ else
+ return BytesRead.takeError();
+ };
+ EXPECT_THAT_EXPECTED(Read(5), HasValue("01234"));
+ EXPECT_THAT_EXPECTED(Read(3), HasValue("012"));
+ EXPECT_THAT_EXPECTED(Read(6), HasValue("01234"));
+}
+
+TEST_F(FileSystemTest, readNativeFileSlice) {
+ createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "01234");
+ FileRemover Cleanup(NonExistantFile);
+ Expected<fs::file_t> FD = fs::openNativeFileForRead(NonExistantFile);
+ ASSERT_THAT_EXPECTED(FD, Succeeded());
+ auto Close = make_scope_exit([&] { fs::closeFile(*FD); });
+ const auto &Read = [&](size_t Offset,
+ size_t ToRead) -> Expected<std::string> {
+ std::string Buf(ToRead, '?');
+ if (Expected<size_t> BytesRead = fs::readNativeFileSlice(
+ *FD, makeMutableArrayRef(&*Buf.begin(), Buf.size()), Offset))
+ return Buf.substr(0, *BytesRead);
+ else
+ return BytesRead.takeError();
+ };
+ EXPECT_THAT_EXPECTED(Read(0, 5), HasValue("01234"));
+ EXPECT_THAT_EXPECTED(Read(0, 3), HasValue("012"));
+ EXPECT_THAT_EXPECTED(Read(2, 3), HasValue("234"));
+ EXPECT_THAT_EXPECTED(Read(0, 6), HasValue("01234"));
+ EXPECT_THAT_EXPECTED(Read(2, 6), HasValue("234"));
+ EXPECT_THAT_EXPECTED(Read(5, 5), HasValue(""));
+}
+
TEST_F(FileSystemTest, is_local) {
bool TestDirectoryIsLocal;
ASSERT_NO_ERROR(fs::is_local(TestDirectory, TestDirectoryIsLocal));
diff --git a/src/llvm-project/llvm/unittests/Support/ProcessTest.cpp b/src/llvm-project/llvm/unittests/Support/ProcessTest.cpp
index dbfaf8e..83be3a9 100644
--- a/src/llvm-project/llvm/unittests/Support/ProcessTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/ProcessTest.cpp
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/Process.h"
#include "gtest/gtest.h"
@@ -61,4 +64,39 @@
}
#endif
+class PageSizeTest : public testing::Test {
+ Triple Host;
+
+protected:
+ PageSizeTest() : Host(Triple::normalize(sys::getProcessTriple())) {}
+
+ bool isSupported() const {
+ // For now just on X86-64 and Aarch64. This can be expanded in the future.
+ return (Host.getArch() == Triple::x86_64 ||
+ Host.getArch() == Triple::aarch64) &&
+ Host.getOS() == Triple::Linux;
+ }
+
+ bool pageSizeAsExpected(unsigned PageSize) const {
+ switch (Host.getArch()) {
+ case Triple::x86_64:
+ return PageSize == 4096;
+ case Triple::aarch64:
+ // supported granule sizes are 4k, 16k and 64k
+ return PageSize == 4096 || PageSize == 16384 || PageSize == 65536;
+ default:
+ llvm_unreachable("unexpected arch!");
+ }
+ }
+};
+
+TEST_F(PageSizeTest, PageSize) {
+ if (!isSupported())
+ return;
+
+ llvm::Expected<unsigned> Result = llvm::sys::Process::getPageSize();
+ ASSERT_FALSE(!Result);
+ ASSERT_TRUE(pageSizeAsExpected(*Result));
+}
+
} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/Support/ReverseIterationTest.cpp b/src/llvm-project/llvm/unittests/Support/ReverseIterationTest.cpp
index 05804e6..6573682 100644
--- a/src/llvm-project/llvm/unittests/Support/ReverseIterationTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/ReverseIterationTest.cpp
@@ -45,7 +45,7 @@
int IterKeys[] = { 2, 4, 1, 3 };
// Check that the DenseMap is iterated in the expected order.
- for (const auto &Tuple : zip(Map, IterKeys))
+ for (auto Tuple : zip(Map, IterKeys))
ASSERT_EQ(std::get<0>(Tuple).first, std::get<1>(Tuple));
// Check operator++ (post-increment).
@@ -99,7 +99,7 @@
std::reverse(&Keys[0], &Keys[4]);
// Check that the DenseMap is iterated in the expected order.
- for (const auto &Tuple : zip(Map, Keys))
+ for (auto Tuple : zip(Map, Keys))
ASSERT_EQ(std::get<0>(Tuple).second, std::get<1>(Tuple)->value);
// Check operator++ (post-increment).
diff --git a/src/llvm-project/llvm/unittests/Support/SpecialCaseListTest.cpp b/src/llvm-project/llvm/unittests/Support/SpecialCaseListTest.cpp
index 2245588..de1f058 100644
--- a/src/llvm-project/llvm/unittests/Support/SpecialCaseListTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -9,6 +9,7 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -161,7 +162,8 @@
EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced",
Error);
std::vector<std::string> Files(1, "unexisting");
- EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error));
+ EXPECT_EQ(nullptr,
+ SpecialCaseList::create(Files, *vfs::getRealFileSystem(), Error));
EXPECT_EQ(0U, Error.find("can't open file 'unexisting':"));
}
@@ -177,7 +179,7 @@
"src:ban=init\n"));
Files.push_back(makeSpecialCaseListFile("src:baz\n"
"src:*fog*\n"));
- auto SCL = SpecialCaseList::createOrDie(Files);
+ auto SCL = SpecialCaseList::createOrDie(Files, *vfs::getRealFileSystem());
EXPECT_TRUE(SCL->inSection("", "src", "bar"));
EXPECT_TRUE(SCL->inSection("", "src", "baz"));
EXPECT_FALSE(SCL->inSection("", "src", "ban"));
diff --git a/src/llvm-project/llvm/unittests/Support/TargetParserTest.cpp b/src/llvm-project/llvm/unittests/Support/TargetParserTest.cpp
index 04ee379..32d0924 100644
--- a/src/llvm-project/llvm/unittests/Support/TargetParserTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/TargetParserTest.cpp
@@ -44,7 +44,6 @@
pass &= ((ExtKind ^ ARM::AEK_NONE) == ExpectedFlags);
else
pass &= (ExtKind == ExpectedFlags);
-
pass &= ARM::getCPUAttr(AK).equals(CPUAttr);
return pass;
@@ -257,21 +256,17 @@
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_FP16 |
ARM::AEK_RAS | ARM::AEK_DOTPROD,
"8.2-A"));
+ EXPECT_TRUE(testARMCPU("neoverse-n1", "armv8.2-a", "crypto-neon-fp-armv8",
+ ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
+ ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_FP16 |
+ ARM::AEK_RAS | ARM::AEK_DOTPROD,
+ "8.2-A"));
EXPECT_TRUE(testARMCPU("cyclone", "armv8-a", "crypto-neon-fp-armv8",
ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
"8-A"));
- EXPECT_TRUE(testARMCPU("exynos-m1", "armv8-a", "crypto-neon-fp-armv8",
- ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
- ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
- ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
- "8-A"));
- EXPECT_TRUE(testARMCPU("exynos-m2", "armv8-a", "crypto-neon-fp-armv8",
- ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
- ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
- ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,
- "8-A"));
EXPECT_TRUE(testARMCPU("exynos-m3", "armv8-a", "crypto-neon-fp-armv8",
ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |
ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
@@ -304,7 +299,7 @@
"7-S"));
}
-static constexpr unsigned NumARMCPUArchs = 86;
+static constexpr unsigned NumARMCPUArchs = 85;
TEST(TargetParserTest, testARMCPUArchList) {
SmallVector<StringRef, NumARMCPUArchs> List;
@@ -327,10 +322,11 @@
bool testARMArch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,
unsigned ArchAttr) {
ARM::ArchKind AK = ARM::parseArch(Arch);
- return (AK!= ARM::ArchKind::INVALID) &
- ARM::getDefaultCPU(Arch).equals(DefaultCPU) &
- ARM::getSubArch(AK).equals(SubArch) &
- (ARM::getArchAttr(AK) == ArchAttr);
+ bool Result = (AK != ARM::ArchKind::INVALID);
+ Result &= ARM::getDefaultCPU(Arch).equals(DefaultCPU);
+ Result &= ARM::getSubArch(AK).equals(SubArch);
+ Result &= (ARM::getArchAttr(AK) == ArchAttr);
+ return Result;
}
TEST(TargetParserTest, testARMArch) {
@@ -782,6 +778,20 @@
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD, "8-A"));
EXPECT_TRUE(testAArch64CPU(
+ "cortex-a65", "armv8.2-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP | AArch64::AEK_FP16 | AArch64::AEK_LSE |
+ AArch64::AEK_RAS | AArch64::AEK_RCPC | AArch64::AEK_RDM |
+ AArch64::AEK_SIMD | AArch64::AEK_SSBS,
+ "8.2-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "cortex-a65ae", "armv8.2-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP | AArch64::AEK_FP16 | AArch64::AEK_LSE |
+ AArch64::AEK_RAS | AArch64::AEK_RCPC | AArch64::AEK_RDM |
+ AArch64::AEK_SIMD | AArch64::AEK_SSBS,
+ "8.2-A"));
+ EXPECT_TRUE(testAArch64CPU(
"cortex-a72", "armv8-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD, "8-A"));
@@ -811,13 +821,50 @@
"cyclone", "armv8-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD, "8-A"));
EXPECT_TRUE(testAArch64CPU(
- "exynos-m1", "armv8-a", "crypto-neon-fp-armv8",
- AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
- AArch64::AEK_SIMD, "8-A"));
+ "apple-a7", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD, "8-A"));
EXPECT_TRUE(testAArch64CPU(
- "exynos-m2", "armv8-a", "crypto-neon-fp-armv8",
+ "apple-a8", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD, "8-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "apple-a9", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD, "8-A"));
+ EXPECT_TRUE(testAArch64CPU("apple-a10", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO |
+ AArch64::AEK_FP | AArch64::AEK_RDM |
+ AArch64::AEK_SIMD,
+ "8-A"));
+ EXPECT_TRUE(testAArch64CPU("apple-a11", "armv8.2-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO |
+ AArch64::AEK_FP | AArch64::AEK_LSE |
+ AArch64::AEK_RAS | AArch64::AEK_RDM |
+ AArch64::AEK_SIMD,
+ "8.2-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "apple-a12", "armv8.3-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
- AArch64::AEK_SIMD, "8-A"));
+ AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RAS |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_FP16,
+ "8.3-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "apple-a13", "armv8.4-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RAS |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP16 | AArch64::AEK_FP16FML,
+ "8.4-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "apple-s4", "armv8.3-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RAS |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_FP16,
+ "8.3-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "apple-s5", "armv8.3-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_RAS |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_FP16,
+ "8.3-A"));
EXPECT_TRUE(testAArch64CPU(
"exynos-m3", "armv8-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
@@ -843,6 +890,20 @@
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD, "8-A"));
EXPECT_TRUE(testAArch64CPU(
+ "neoverse-e1", "armv8.2-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP | AArch64::AEK_FP16 | AArch64::AEK_LSE |
+ AArch64::AEK_RAS | AArch64::AEK_RCPC | AArch64::AEK_RDM |
+ AArch64::AEK_SIMD | AArch64::AEK_SSBS,
+ "8.2-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "neoverse-n1", "armv8.2-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP | AArch64::AEK_FP16 | AArch64::AEK_LSE |
+ AArch64::AEK_PROFILE | AArch64::AEK_RAS | AArch64::AEK_RCPC |
+ AArch64::AEK_RDM | AArch64::AEK_SIMD | AArch64::AEK_SSBS,
+ "8.2-A"));
+ EXPECT_TRUE(testAArch64CPU(
"thunderx2t99", "armv8.1-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_LSE |
AArch64::AEK_RDM | AArch64::AEK_FP | AArch64::AEK_SIMD, "8.1-A"));
@@ -875,7 +936,7 @@
"8.2-A"));
}
-static constexpr unsigned NumAArch64CPUArchs = 24;
+static constexpr unsigned NumAArch64CPUArchs = 35;
TEST(TargetParserTest, testAArch64CPUArchList) {
SmallVector<StringRef, NumAArch64CPUArchs> List;
@@ -936,10 +997,6 @@
AArch64::ArchKind::INVALID, "ras"));
EXPECT_FALSE(testAArch64Extension("cyclone",
AArch64::ArchKind::INVALID, "ras"));
- EXPECT_FALSE(testAArch64Extension("exynos-m1",
- AArch64::ArchKind::INVALID, "ras"));
- EXPECT_FALSE(testAArch64Extension("exynos-m2",
- AArch64::ArchKind::INVALID, "ras"));
EXPECT_FALSE(testAArch64Extension("exynos-m3",
AArch64::ArchKind::INVALID, "ras"));
EXPECT_TRUE(testAArch64Extension("exynos-m4",
@@ -1120,6 +1177,7 @@
{"rcpc", "norcpc", "+rcpc", "-rcpc" },
{"rng", "norng", "+rand", "-rand"},
{"memtag", "nomemtag", "+mte", "-mte"},
+ {"tme", "notme", "+tme", "-tme"},
{"ssbs", "nossbs", "+ssbs", "-ssbs"},
{"sb", "nosb", "+sb", "-sb"},
{"predres", "nopredres", "+predres", "-predres"}
diff --git a/src/llvm-project/llvm/unittests/Support/ThreadPool.cpp b/src/llvm-project/llvm/unittests/Support/ThreadPool.cpp
index 4755b52..a16adbb 100644
--- a/src/llvm-project/llvm/unittests/Support/ThreadPool.cpp
+++ b/src/llvm-project/llvm/unittests/Support/ThreadPool.cpp
@@ -71,8 +71,7 @@
std::condition_variable WaitMainThread;
std::mutex WaitMainThreadMutex;
- bool MainThreadReady;
-
+ bool MainThreadReady = false;
};
#define CHECK_UNSUPPORTED() \
diff --git a/src/llvm-project/llvm/unittests/Support/Threading.cpp b/src/llvm-project/llvm/unittests/Support/Threading.cpp
index 01f1c51..183c9aa 100644
--- a/src/llvm-project/llvm/unittests/Support/Threading.cpp
+++ b/src/llvm-project/llvm/unittests/Support/Threading.cpp
@@ -10,6 +10,9 @@
#include "llvm/Support/thread.h"
#include "gtest/gtest.h"
+#include <atomic>
+#include <condition_variable>
+
using namespace llvm;
namespace {
@@ -21,4 +24,57 @@
ASSERT_LE(Num, thread::hardware_concurrency());
}
+#if LLVM_ENABLE_THREADS
+
+class Notification {
+public:
+ void notify() {
+ {
+ std::lock_guard<std::mutex> Lock(M);
+ Notified = true;
+ // Broadcast with the lock held, so it's safe to destroy the Notification
+ // after wait() returns.
+ CV.notify_all();
+ }
+ }
+
+ bool wait() {
+ std::unique_lock<std::mutex> Lock(M);
+ using steady_clock = std::chrono::steady_clock;
+ auto Deadline = steady_clock::now() +
+ std::chrono::duration_cast<steady_clock::duration>(
+ std::chrono::duration<double>(5));
+ return CV.wait_until(Lock, Deadline, [this] { return Notified; });
+ }
+
+private:
+ bool Notified = false;
+ mutable std::condition_variable CV;
+ mutable std::mutex M;
+};
+
+TEST(Threading, RunOnThreadSyncAsync) {
+ Notification ThreadStarted, ThreadAdvanced, ThreadFinished;
+
+ auto ThreadFunc = [&] {
+ ThreadStarted.notify();
+ ASSERT_TRUE(ThreadAdvanced.wait());
+ ThreadFinished.notify();
+ };
+
+ llvm::llvm_execute_on_thread_async(ThreadFunc);
+ ASSERT_TRUE(ThreadStarted.wait());
+ ThreadAdvanced.notify();
+ ASSERT_TRUE(ThreadFinished.wait());
+}
+
+TEST(Threading, RunOnThreadSync) {
+ std::atomic_bool Executed(false);
+ llvm::llvm_execute_on_thread(
+ [](void *Arg) { *static_cast<std::atomic_bool *>(Arg) = true; },
+ &Executed);
+ ASSERT_EQ(Executed, true);
+}
+#endif
+
} // end anon namespace
diff --git a/src/llvm-project/llvm/unittests/Support/TrailingObjectsTest.cpp b/src/llvm-project/llvm/unittests/Support/TrailingObjectsTest.cpp
index 967f6f6..e2656b2 100644
--- a/src/llvm-project/llvm/unittests/Support/TrailingObjectsTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/TrailingObjectsTest.cpp
@@ -232,7 +232,7 @@
EXPECT_EQ(C->getTrailingObjects<char>(), reinterpret_cast<char *>(C + 1));
EXPECT_EQ(C->getTrailingObjects<long>(),
reinterpret_cast<long *>(llvm::alignAddr(
- reinterpret_cast<char *>(C + 1) + 1, alignof(long))));
+ reinterpret_cast<char *>(C + 1) + 1, Align::Of<long>())));
}
}
diff --git a/src/llvm-project/llvm/unittests/Support/TrigramIndexTest.cpp b/src/llvm-project/llvm/unittests/Support/TrigramIndexTest.cpp
index 9b10daa..42b3fcd 100644
--- a/src/llvm-project/llvm/unittests/Support/TrigramIndexTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/TrigramIndexTest.cpp
@@ -22,7 +22,7 @@
std::unique_ptr<TrigramIndex> makeTrigramIndex(
std::vector<std::string> Rules) {
std::unique_ptr<TrigramIndex> TI =
- make_unique<TrigramIndex>();
+ std::make_unique<TrigramIndex>();
for (auto &Rule : Rules)
TI->insert(Rule);
return TI;
diff --git a/src/llvm-project/llvm/unittests/Support/VirtualFileSystemTest.cpp b/src/llvm-project/llvm/unittests/Support/VirtualFileSystemTest.cpp
index a867bc5..d61652b 100644
--- a/src/llvm-project/llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -41,7 +41,9 @@
class DummyFileSystem : public vfs::FileSystem {
int FSID; // used to produce UniqueIDs
int FileID; // used to produce UniqueIDs
+ std::string WorkingDirectory;
std::map<std::string, vfs::Status> FilesAndDirs;
+ typedef std::map<std::string, vfs::Status>::const_iterator const_iterator;
static int getNextFSID() {
static int Count = 0;
@@ -52,8 +54,7 @@
DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
ErrorOr<vfs::Status> status(const Twine &Path) override {
- std::map<std::string, vfs::Status>::iterator I =
- FilesAndDirs.find(Path.str());
+ auto I = findEntry(Path);
if (I == FilesAndDirs.end())
return make_error_code(llvm::errc::no_such_file_or_directory);
return I->second;
@@ -66,15 +67,16 @@
return S.getError();
}
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
- return std::string();
+ return WorkingDirectory;
}
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ WorkingDirectory = Path.str();
return std::error_code();
}
// Map any symlink to "/symlink".
std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const override {
- auto I = FilesAndDirs.find(Path.str());
+ auto I = findEntry(Path);
if (I == FilesAndDirs.end())
return make_error_code(llvm::errc::no_such_file_or_directory);
if (I->second.isSymlink()) {
@@ -136,6 +138,15 @@
FilesAndDirs[Path] = Status;
}
+ const_iterator findEntry(const Twine &Path) const {
+ SmallString<128> P;
+ Path.toVector(P);
+ std::error_code EC = makeAbsolute(P);
+ assert(!EC);
+ (void)EC;
+ return FilesAndDirs.find(P.str());
+ }
+
void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
vfs::Status S(Path, UniqueID(FSID, FileID++),
std::chrono::system_clock::now(), 0, 0, 1024,
@@ -158,6 +169,12 @@
}
};
+class ErrorDummyFileSystem : public DummyFileSystem {
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ return llvm::errc::no_such_file_or_directory;
+ }
+};
+
/// Replace back-slashes by front-slashes.
std::string getPosixPath(std::string S) {
SmallString<128> Result;
@@ -1994,3 +2011,181 @@
EXPECT_EQ(FS->getRealPath("/non_existing", RealPath),
errc::no_such_file_or_directory);
}
+
+TEST_F(VFSFromYAMLTest, WorkingDirectory) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addDirectory("//root/");
+ Lower->addDirectory("//root/foo");
+ Lower->addRegularFile("//root/foo/a");
+ Lower->addRegularFile("//root/foo/b");
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+ "{ 'use-external-names': false,\n"
+ " 'roots': [\n"
+ "{\n"
+ " 'type': 'directory',\n"
+ " 'name': '//root/bar',\n"
+ " 'contents': [ {\n"
+ " 'type': 'file',\n"
+ " 'name': 'a',\n"
+ " 'external-contents': '//root/foo/a'\n"
+ " }\n"
+ " ]\n"
+ "}\n"
+ "]\n"
+ "}",
+ Lower);
+ ASSERT_TRUE(FS.get() != nullptr);
+ std::error_code EC = FS->setCurrentWorkingDirectory("//root/bar");
+ ASSERT_FALSE(EC);
+
+ llvm::ErrorOr<std::string> WorkingDir = FS->getCurrentWorkingDirectory();
+ ASSERT_TRUE(WorkingDir);
+ EXPECT_EQ(*WorkingDir, "//root/bar");
+
+ llvm::ErrorOr<vfs::Status> Status = FS->status("./a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->isStatusKnown());
+ EXPECT_FALSE(Status->isDirectory());
+ EXPECT_TRUE(Status->isRegularFile());
+ EXPECT_FALSE(Status->isSymlink());
+ EXPECT_FALSE(Status->isOther());
+ EXPECT_TRUE(Status->exists());
+
+ EC = FS->setCurrentWorkingDirectory("bogus");
+ ASSERT_TRUE(EC);
+ WorkingDir = FS->getCurrentWorkingDirectory();
+ ASSERT_TRUE(WorkingDir);
+ EXPECT_EQ(*WorkingDir, "//root/bar");
+
+ EC = FS->setCurrentWorkingDirectory("//root/");
+ ASSERT_FALSE(EC);
+ WorkingDir = FS->getCurrentWorkingDirectory();
+ ASSERT_TRUE(WorkingDir);
+ EXPECT_EQ(*WorkingDir, "//root/");
+
+ EC = FS->setCurrentWorkingDirectory("bar");
+ ASSERT_FALSE(EC);
+ WorkingDir = FS->getCurrentWorkingDirectory();
+ ASSERT_TRUE(WorkingDir);
+ EXPECT_EQ(*WorkingDir, "//root/bar");
+}
+
+TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthrough) {
+ IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+ Lower->addDirectory("//root/");
+ Lower->addDirectory("//root/foo");
+ Lower->addRegularFile("//root/foo/a");
+ Lower->addRegularFile("//root/foo/b");
+ Lower->addRegularFile("//root/c");
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+ "{ 'use-external-names': false,\n"
+ " 'roots': [\n"
+ "{\n"
+ " 'type': 'directory',\n"
+ " 'name': '//root/bar',\n"
+ " 'contents': [ {\n"
+ " 'type': 'file',\n"
+ " 'name': 'a',\n"
+ " 'external-contents': '//root/foo/a'\n"
+ " }\n"
+ " ]\n"
+ "},\n"
+ "{\n"
+ " 'type': 'directory',\n"
+ " 'name': '//root/bar/baz',\n"
+ " 'contents': [ {\n"
+ " 'type': 'file',\n"
+ " 'name': 'a',\n"
+ " 'external-contents': '//root/foo/a'\n"
+ " }\n"
+ " ]\n"
+ "}\n"
+ "]\n"
+ "}",
+ Lower);
+ ASSERT_TRUE(FS.get() != nullptr);
+ std::error_code EC = FS->setCurrentWorkingDirectory("//root/");
+ ASSERT_FALSE(EC);
+ ASSERT_TRUE(FS.get() != nullptr);
+
+ llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ Status = FS->status("foo/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ EC = FS->setCurrentWorkingDirectory("//root/bar");
+ ASSERT_FALSE(EC);
+
+ Status = FS->status("./a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ Status = FS->status("./b");
+ ASSERT_TRUE(Status.getError());
+
+ Status = FS->status("./c");
+ ASSERT_TRUE(Status.getError());
+
+ EC = FS->setCurrentWorkingDirectory("//root/");
+ ASSERT_FALSE(EC);
+
+ Status = FS->status("c");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ Status = FS->status("./bar/baz/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ EC = FS->setCurrentWorkingDirectory("//root/bar");
+ ASSERT_FALSE(EC);
+
+ Status = FS->status("./baz/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+#if !defined(_WIN32)
+ Status = FS->status("../bar/baz/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+#endif
+}
+
+TEST_F(VFSFromYAMLTest, WorkingDirectoryFallthroughInvalid) {
+ IntrusiveRefCntPtr<ErrorDummyFileSystem> Lower(new ErrorDummyFileSystem());
+ Lower->addDirectory("//root/");
+ Lower->addDirectory("//root/foo");
+ Lower->addRegularFile("//root/foo/a");
+ Lower->addRegularFile("//root/foo/b");
+ Lower->addRegularFile("//root/c");
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+ "{ 'use-external-names': false,\n"
+ " 'roots': [\n"
+ "{\n"
+ " 'type': 'directory',\n"
+ " 'name': '//root/bar',\n"
+ " 'contents': [ {\n"
+ " 'type': 'file',\n"
+ " 'name': 'a',\n"
+ " 'external-contents': '//root/foo/a'\n"
+ " }\n"
+ " ]\n"
+ "}\n"
+ "]\n"
+ "}",
+ Lower);
+ ASSERT_TRUE(FS.get() != nullptr);
+ std::error_code EC = FS->setCurrentWorkingDirectory("//root/");
+ ASSERT_FALSE(EC);
+ ASSERT_TRUE(FS.get() != nullptr);
+
+ llvm::ErrorOr<vfs::Status> Status = FS->status("bar/a");
+ ASSERT_FALSE(Status.getError());
+ EXPECT_TRUE(Status->exists());
+
+ Status = FS->status("foo/a");
+ ASSERT_TRUE(Status.getError());
+}
diff --git a/src/llvm-project/llvm/unittests/Support/YAMLIOTest.cpp b/src/llvm-project/llvm/unittests/Support/YAMLIOTest.cpp
index e02f68f..df111e7 100644
--- a/src/llvm-project/llvm/unittests/Support/YAMLIOTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/YAMLIOTest.cpp
@@ -2189,7 +2189,6 @@
//
// Test error handling reading built-in Hex8 type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
std::vector<Hex8> seq;
Input yin("---\n"
@@ -2200,15 +2199,26 @@
/*Ctxt=*/nullptr,
suppressErrorMessages);
yin >> seq;
-
EXPECT_TRUE(!!yin.error());
+
+ std::vector<Hex8> seq2;
+ Input yin2("---\n"
+ "[ 0x12, 0xFE, 0x123 ]\n"
+ "...\n",
+ /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin2 >> seq2;
+ EXPECT_TRUE(!!yin2.error());
+
+ EXPECT_TRUE(seq.size() == 3);
+ EXPECT_TRUE(seq.size() == seq2.size());
+ for (size_t i = 0; i < seq.size(); ++i)
+ EXPECT_TRUE(seq[i] == seq2[i]);
}
//
// Test error handling reading built-in Hex16 type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
std::vector<Hex16> seq;
Input yin("---\n"
@@ -2219,14 +2229,25 @@
/*Ctxt=*/nullptr,
suppressErrorMessages);
yin >> seq;
-
EXPECT_TRUE(!!yin.error());
+
+ std::vector<Hex16> seq2;
+ Input yin2("---\n"
+ "[ 0x0012, 0xFEFF, 0x12345 ]\n"
+ "...\n",
+ /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin2 >> seq2;
+ EXPECT_TRUE(!!yin2.error());
+
+ EXPECT_TRUE(seq.size() == 3);
+ EXPECT_TRUE(seq.size() == seq2.size());
+ for (size_t i = 0; i < seq.size(); ++i)
+ EXPECT_TRUE(seq[i] == seq2[i]);
}
//
// Test error handling reading built-in Hex32 type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
std::vector<Hex32> seq;
Input yin("---\n"
@@ -2239,12 +2260,24 @@
yin >> seq;
EXPECT_TRUE(!!yin.error());
+
+ std::vector<Hex32> seq2;
+ Input yin2("---\n"
+ "[ 0x0012, 0xFEFF0000, 0x1234556789 ]\n"
+ "...\n",
+ /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin2 >> seq2;
+ EXPECT_TRUE(!!yin2.error());
+
+ EXPECT_TRUE(seq.size() == 3);
+ EXPECT_TRUE(seq.size() == seq2.size());
+ for (size_t i = 0; i < seq.size(); ++i)
+ EXPECT_TRUE(seq[i] == seq2[i]);
}
//
// Test error handling reading built-in Hex64 type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
std::vector<Hex64> seq;
Input yin("---\n"
@@ -2255,8 +2288,20 @@
/*Ctxt=*/nullptr,
suppressErrorMessages);
yin >> seq;
-
EXPECT_TRUE(!!yin.error());
+
+ std::vector<Hex64> seq2;
+ Input yin2("---\n"
+ "[ 0x0012, 0xFFEEDDCCBBAA9988, 0x12345567890ABCDEF0 ]\n"
+ "...\n",
+ /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin2 >> seq2;
+ EXPECT_TRUE(!!yin2.error());
+
+ EXPECT_TRUE(seq.size() == 3);
+ EXPECT_TRUE(seq.size() == seq2.size());
+ for (size_t i = 0; i < seq.size(); ++i)
+ EXPECT_TRUE(seq[i] == seq2[i]);
}
TEST(YAMLIO, TestMalformedMapFailsGracefully) {
@@ -2841,19 +2886,19 @@
static Scalar &getAsScalar(std::unique_ptr<Poly> &N) {
if (!N || !isa<Scalar>(*N))
- N = llvm::make_unique<Scalar>();
+ N = std::make_unique<Scalar>();
return *cast<Scalar>(N.get());
}
static Seq &getAsSequence(std::unique_ptr<Poly> &N) {
if (!N || !isa<Seq>(*N))
- N = llvm::make_unique<Seq>();
+ N = std::make_unique<Seq>();
return *cast<Seq>(N.get());
}
static Map &getAsMap(std::unique_ptr<Poly> &N) {
if (!N || !isa<Map>(*N))
- N = llvm::make_unique<Map>();
+ N = std::make_unique<Map>();
return *cast<Map>(N.get());
}
};
@@ -2932,7 +2977,7 @@
TEST(YAMLIO, TestReadWritePolymorphicScalar) {
std::string intermediate;
- std::unique_ptr<Poly> node = llvm::make_unique<Scalar>(true);
+ std::unique_ptr<Poly> node = std::make_unique<Scalar>(true);
llvm::raw_string_ostream ostr(intermediate);
Output yout(ostr);
@@ -2946,9 +2991,9 @@
TEST(YAMLIO, TestReadWritePolymorphicSeq) {
std::string intermediate;
{
- auto seq = llvm::make_unique<Seq>();
- seq->push_back(llvm::make_unique<Scalar>(true));
- seq->push_back(llvm::make_unique<Scalar>(1.0));
+ auto seq = std::make_unique<Seq>();
+ seq->push_back(std::make_unique<Scalar>(true));
+ seq->push_back(std::make_unique<Scalar>(1.0));
auto node = llvm::unique_dyn_cast<Poly>(seq);
llvm::raw_string_ostream ostr(intermediate);
@@ -2978,9 +3023,9 @@
TEST(YAMLIO, TestReadWritePolymorphicMap) {
std::string intermediate;
{
- auto map = llvm::make_unique<Map>();
- (*map)["foo"] = llvm::make_unique<Scalar>(false);
- (*map)["bar"] = llvm::make_unique<Scalar>(2.0);
+ auto map = std::make_unique<Map>();
+ (*map)["foo"] = std::make_unique<Scalar>(false);
+ (*map)["bar"] = std::make_unique<Scalar>(2.0);
std::unique_ptr<Poly> node = llvm::unique_dyn_cast<Poly>(map);
llvm::raw_string_ostream ostr(intermediate);
@@ -3005,3 +3050,55 @@
EXPECT_EQ(bar->DoubleValue, 2.0);
}
}
+
+TEST(YAMLIO, TestAnchorMapError) {
+ Input yin("& & &: ");
+ yin.setCurrentDocument();
+ EXPECT_TRUE(yin.error());
+}
+
+TEST(YAMLIO, TestFlowSequenceTokenErrors) {
+ Input yin(",");
+ EXPECT_FALSE(yin.setCurrentDocument());
+ EXPECT_TRUE(yin.error());
+
+ Input yin2("]");
+ EXPECT_FALSE(yin2.setCurrentDocument());
+ EXPECT_TRUE(yin2.error());
+
+ Input yin3("}");
+ EXPECT_FALSE(yin3.setCurrentDocument());
+ EXPECT_TRUE(yin3.error());
+}
+
+TEST(YAMLIO, TestDirectiveMappingNoValue) {
+ Input yin("%YAML\n{5:");
+ EXPECT_FALSE(yin.setCurrentDocument());
+ EXPECT_TRUE(yin.error());
+
+ Input yin2("%TAG\n'\x98!< :\n");
+ yin2.setCurrentDocument();
+ EXPECT_TRUE(yin2.error());
+}
+
+TEST(YAMLIO, TestUnescapeInfiniteLoop) {
+ Input yin("\"\\u\\^#\\\\\"");
+ yin.setCurrentDocument();
+ EXPECT_TRUE(yin.error());
+}
+
+TEST(YAMLIO, TestScannerUnexpectedCharacter) {
+ Input yin("!<$\x9F.");
+ EXPECT_FALSE(yin.setCurrentDocument());
+ EXPECT_TRUE(yin.error());
+}
+
+TEST(YAMLIO, TestUnknownDirective) {
+ Input yin("%");
+ EXPECT_FALSE(yin.setCurrentDocument());
+ EXPECT_TRUE(yin.error());
+
+ Input yin2("%)");
+ EXPECT_FALSE(yin2.setCurrentDocument());
+ EXPECT_TRUE(yin2.error());
+}
diff --git a/src/llvm-project/llvm/unittests/Support/YAMLParserTest.cpp b/src/llvm-project/llvm/unittests/Support/YAMLParserTest.cpp
index 06d4b0e..938a6ab 100644
--- a/src/llvm-project/llvm/unittests/Support/YAMLParserTest.cpp
+++ b/src/llvm-project/llvm/unittests/Support/YAMLParserTest.cpp
@@ -331,4 +331,15 @@
EXPECT_TRUE(End == AnotherEnd);
}
+TEST(YAMLParser, FlowSequenceTokensOutsideFlowSequence) {
+ auto FlowSequenceStrs = {",", "]", "}"};
+ SourceMgr SM;
+
+ for (auto &Str : FlowSequenceStrs) {
+ yaml::Stream Stream(Str, SM);
+ yaml::Document &Doc = *Stream.begin();
+ EXPECT_FALSE(Doc.skip());
+ }
+}
+
} // end namespace llvm
diff --git a/src/llvm-project/llvm/unittests/Support/raw_ostream_test.cpp b/src/llvm-project/llvm/unittests/Support/raw_ostream_test.cpp
index 4ce4917..0e56464 100644
--- a/src/llvm-project/llvm/unittests/Support/raw_ostream_test.cpp
+++ b/src/llvm-project/llvm/unittests/Support/raw_ostream_test.cpp
@@ -18,8 +18,7 @@
template<typename T> std::string printToString(const T &Value) {
std::string res;
- llvm::raw_string_ostream(res) << Value;
- return res;
+ return (llvm::raw_string_ostream(res) << Value).str();
}
/// printToString - Print the given value to a stream which only has \arg
@@ -47,6 +46,10 @@
return res;
}
+struct X {};
+
+raw_ostream &operator<<(raw_ostream &OS, const X &) { return OS << 'X'; }
+
TEST(raw_ostreamTest, Types_Buffered) {
// Char
EXPECT_EQ("c", printToString('c'));
@@ -76,6 +79,9 @@
// Min and max.
EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX));
EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN));
+
+ // X, checking free operator<<().
+ EXPECT_EQ("X", printToString(X{}));
}
TEST(raw_ostreamTest, Types_Unbuffered) {
@@ -107,6 +113,9 @@
// Min and max.
EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX));
EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN));
+
+ // X, checking free operator<<().
+ EXPECT_EQ("X", printToString(X{}));
}
TEST(raw_ostreamTest, BufferEdge) {
@@ -339,7 +348,7 @@
TEST(raw_fd_ostreamTest, multiple_raw_fd_ostream_to_stdout) {
std::error_code EC;
- { raw_fd_ostream("-", EC, sys::fs::OpenFlags::F_None); }
- { raw_fd_ostream("-", EC, sys::fs::OpenFlags::F_None); }
+ { raw_fd_ostream("-", EC, sys::fs::OpenFlags::OF_None); }
+ { raw_fd_ostream("-", EC, sys::fs::OpenFlags::OF_None); }
}
}
diff --git a/src/llvm-project/llvm/unittests/Support/raw_sha1_ostream_test.cpp b/src/llvm-project/llvm/unittests/Support/raw_sha1_ostream_test.cpp
index be03536..3238d0d 100644
--- a/src/llvm-project/llvm/unittests/Support/raw_sha1_ostream_test.cpp
+++ b/src/llvm-project/llvm/unittests/Support/raw_sha1_ostream_test.cpp
@@ -43,6 +43,22 @@
ASSERT_EQ("2EF7BDE608CE5404E97D5F042F95F89F1C232871", Hash);
}
+TEST(sha1_hash_test, Update) {
+ SHA1 sha1;
+ std::string Input = "123456789012345678901234567890";
+ ASSERT_EQ(Input.size(), 30UL);
+ // 3 short updates.
+ sha1.update(Input);
+ sha1.update(Input);
+ sha1.update(Input);
+ // Long update that gets into the optimized loop with prefix/suffix.
+ sha1.update(Input + Input + Input + Input);
+ // 18 bytes buffered now.
+
+ std::string Hash = toHex(sha1.final());
+ ASSERT_EQ("3E4A614101AD84985AB0FE54DC12A6D71551E5AE", Hash);
+}
+
// Check that getting the intermediate hash in the middle of the stream does
// not invalidate the final result.
TEST(raw_sha1_ostreamTest, Intermediate) {