summaryrefslogtreecommitdiff
path: root/unittests/ADT
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ADT')
-rw-r--r--unittests/ADT/APFloatTest.cpp7
-rw-r--r--unittests/ADT/APIntTest.cpp138
-rw-r--r--unittests/ADT/AnyTest.cpp175
-rw-r--r--unittests/ADT/ArrayRefTest.cpp8
-rw-r--r--unittests/ADT/CMakeLists.txt10
-rw-r--r--unittests/ADT/DenseMapTest.cpp16
-rw-r--r--unittests/ADT/DenseSetTest.cpp2
-rw-r--r--unittests/ADT/FunctionExtrasTest.cpp228
-rw-r--r--unittests/ADT/IteratorTest.cpp63
-rw-r--r--unittests/ADT/MapVectorTest.cpp39
-rw-r--r--unittests/ADT/OptionalTest.cpp20
-rw-r--r--unittests/ADT/STLExtrasTest.cpp4
-rw-r--r--unittests/ADT/ScopeExitTest.cpp17
-rw-r--r--unittests/ADT/SmallPtrSetTest.cpp6
-rw-r--r--unittests/ADT/SmallSetTest.cpp149
-rw-r--r--unittests/ADT/SparseBitVectorTest.cpp2
-rw-r--r--unittests/ADT/StatisticTest.cpp160
-rw-r--r--unittests/ADT/StringExtrasTest.cpp25
-rw-r--r--unittests/ADT/StringMapTest.cpp44
-rw-r--r--unittests/ADT/StringRefTest.cpp23
-rw-r--r--unittests/ADT/StringSwitchTest.cpp6
-rw-r--r--unittests/ADT/TripleTest.cpp47
22 files changed, 1138 insertions, 51 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp
index 8b88c123b197..1212b45fb575 100644
--- a/unittests/ADT/APFloatTest.cpp
+++ b/unittests/ADT/APFloatTest.cpp
@@ -983,6 +983,13 @@ TEST(APFloatTest, toString) {
ASSERT_EQ("8.73183400000000010e+02", convertToString(873.1834, 0, 0, false));
ASSERT_EQ("1.79769313486231570e+308",
convertToString(1.7976931348623157E+308, 0, 0, false));
+
+ {
+ SmallString<64> Str;
+ APFloat UnnormalZero(APFloat::x87DoubleExtended(), APInt(80, {0, 1}));
+ UnnormalZero.toString(Str);
+ ASSERT_EQ("NaN", Str);
+ }
}
TEST(APFloatTest, toInteger) {
diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp
index 05fad386064c..48f91195e446 100644
--- a/unittests/ADT/APIntTest.cpp
+++ b/unittests/ADT/APIntTest.cpp
@@ -1060,6 +1060,38 @@ TEST(APIntTest, divremuint) {
APInt{1024, 1});
}
+TEST(APIntTest, divrem_simple) {
+ // Test simple cases.
+ APInt A(65, 2), B(65, 2);
+ APInt Q, R;
+
+ // X / X
+ APInt::sdivrem(A, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 1));
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(A, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 1));
+ EXPECT_EQ(R, APInt(65, 0));
+
+ // 0 / X
+ APInt O(65, 0);
+ APInt::sdivrem(O, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 0));
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(O, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 0));
+ EXPECT_EQ(R, APInt(65, 0));
+
+ // X / 1
+ APInt I(65, 1);
+ APInt::sdivrem(A, I, Q, R);
+ EXPECT_EQ(Q, A);
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(A, I, Q, R);
+ EXPECT_EQ(Q, A);
+ EXPECT_EQ(R, APInt(65, 0));
+}
+
TEST(APIntTest, fromString) {
EXPECT_EQ(APInt(32, 0), APInt(32, "0", 2));
EXPECT_EQ(APInt(32, 1), APInt(32, "1", 2));
@@ -1659,6 +1691,38 @@ TEST(APIntTest, isShiftedMask) {
}
}
+// Test that self-move works, but only when we're using MSVC.
+#if defined(_MSC_VER)
+#if defined(__clang__)
+// Disable the pragma warning from versions of Clang without -Wself-move
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+// Disable the warning that triggers on exactly what is being tested.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+TEST(APIntTest, SelfMoveAssignment) {
+ APInt X(32, 0xdeadbeef);
+ X = std::move(X);
+ EXPECT_EQ(32u, X.getBitWidth());
+ EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue());
+
+ uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL};
+ APInt Y(128, Bits);
+ Y = std::move(Y);
+ EXPECT_EQ(128u, Y.getBitWidth());
+ EXPECT_EQ(~0ULL, Y.getLimitedValue());
+ const uint64_t *Raw = Y.getRawData();
+ EXPECT_EQ(2u, Y.getNumWords());
+ EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]);
+ EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]);
+}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#pragma clang diagnostic pop
+#endif
+#endif // _MSC_VER
+
TEST(APIntTest, reverseBits) {
EXPECT_EQ(1, APInt(1, 1).reverseBits());
EXPECT_EQ(0, APInt(1, 0).reverseBits());
@@ -1768,6 +1832,13 @@ TEST(APIntTest, extractBits) {
i257.extractBits(128, 1).getSExtValue());
EXPECT_EQ(static_cast<int64_t>(0xFFFFFFFFFF80007Full),
i257.extractBits(129, 1).getSExtValue());
+
+ EXPECT_EQ(APInt(48, 0),
+ APInt(144, "281474976710655", 10).extractBits(48, 48));
+ EXPECT_EQ(APInt(48, 0x0000ffffffffffffull),
+ APInt(144, "281474976710655", 10).extractBits(48, 0));
+ EXPECT_EQ(APInt(48, 0x00007fffffffffffull),
+ APInt(144, "281474976710655", 10).extractBits(48, 1));
}
TEST(APIntTest, getLowBitsSet) {
@@ -2219,4 +2290,71 @@ TEST(APIntTest, multiply) {
EXPECT_EQ(64U, i96.countTrailingZeros());
}
+TEST(APIntTest, RoundingUDiv) {
+ for (uint64_t Ai = 1; Ai <= 255; Ai++) {
+ APInt A(8, Ai);
+ APInt Zero(8, 0);
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::UP));
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::DOWN));
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::TOWARD_ZERO));
+
+ for (uint64_t Bi = 1; Bi <= 255; Bi++) {
+ APInt B(8, Bi);
+ {
+ APInt Quo = APIntOps::RoundingUDiv(A, B, APInt::Rounding::UP);
+ auto Prod = Quo.zext(16) * B.zext(16);
+ EXPECT_TRUE(Prod.uge(Ai));
+ if (Prod.ugt(Ai)) {
+ EXPECT_TRUE(((Quo - 1).zext(16) * B.zext(16)).ult(Ai));
+ }
+ }
+ {
+ APInt Quo = A.udiv(B);
+ EXPECT_EQ(Quo, APIntOps::RoundingUDiv(A, B, APInt::Rounding::TOWARD_ZERO));
+ EXPECT_EQ(Quo, APIntOps::RoundingUDiv(A, B, APInt::Rounding::DOWN));
+ }
+ }
+ }
+}
+
+TEST(APIntTest, RoundingSDiv) {
+ for (int64_t Ai = -128; Ai <= 127; Ai++) {
+ APInt A(8, Ai);
+
+ if (Ai != 0) {
+ APInt Zero(8, 0);
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::UP));
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::DOWN));
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::TOWARD_ZERO));
+ }
+
+ for (uint64_t Bi = -128; Bi <= 127; Bi++) {
+ if (Bi == 0)
+ continue;
+
+ APInt B(8, Bi);
+ {
+ APInt Quo = APIntOps::RoundingSDiv(A, B, APInt::Rounding::UP);
+ auto Prod = Quo.sext(16) * B.sext(16);
+ EXPECT_TRUE(Prod.uge(A));
+ if (Prod.ugt(A)) {
+ EXPECT_TRUE(((Quo - 1).sext(16) * B.sext(16)).ult(A));
+ }
+ }
+ {
+ APInt Quo = APIntOps::RoundingSDiv(A, B, APInt::Rounding::DOWN);
+ auto Prod = Quo.sext(16) * B.sext(16);
+ EXPECT_TRUE(Prod.ule(A));
+ if (Prod.ult(A)) {
+ EXPECT_TRUE(((Quo + 1).sext(16) * B.sext(16)).ugt(A));
+ }
+ }
+ {
+ APInt Quo = A.sdiv(B);
+ EXPECT_EQ(Quo, APIntOps::RoundingSDiv(A, B, APInt::Rounding::TOWARD_ZERO));
+ }
+ }
+ }
+}
+
} // end anonymous namespace
diff --git a/unittests/ADT/AnyTest.cpp b/unittests/ADT/AnyTest.cpp
new file mode 100644
index 000000000000..658f6b6ce3b7
--- /dev/null
+++ b/unittests/ADT/AnyTest.cpp
@@ -0,0 +1,175 @@
+//===- llvm/unittest/Support/AnyTest.cpp - Any tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Any.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+namespace {
+
+// Make sure we can construct, copy-construct, move-construct, and assign Any's.
+TEST(AnyTest, ConstructionAndAssignment) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{8};
+ llvm::Any D{"hello"};
+ llvm::Any E{3.7};
+
+ // An empty Any is not anything.
+ EXPECT_FALSE(A.hasValue());
+ EXPECT_FALSE(any_isa<int>(A));
+
+ // An int is an int but not something else.
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_TRUE(any_isa<int>(B));
+ EXPECT_FALSE(any_isa<float>(B));
+
+ EXPECT_TRUE(C.hasValue());
+ EXPECT_TRUE(any_isa<int>(C));
+
+ // A const char * is a const char * but not an int.
+ EXPECT_TRUE(D.hasValue());
+ EXPECT_TRUE(any_isa<const char *>(D));
+ EXPECT_FALSE(any_isa<int>(D));
+
+ // A double is a double but not a float.
+ EXPECT_TRUE(E.hasValue());
+ EXPECT_TRUE(any_isa<double>(E));
+ EXPECT_FALSE(any_isa<float>(E));
+
+ // After copy constructing from an int, the new item and old item are both
+ // ints.
+ llvm::Any F(B);
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_TRUE(F.hasValue());
+ EXPECT_TRUE(any_isa<int>(F));
+ EXPECT_TRUE(any_isa<int>(B));
+
+ // After move constructing from an int, the new item is an int and the old one
+ // isn't.
+ llvm::Any G(std::move(C));
+ EXPECT_FALSE(C.hasValue());
+ EXPECT_TRUE(G.hasValue());
+ EXPECT_TRUE(any_isa<int>(G));
+ EXPECT_FALSE(any_isa<int>(C));
+
+ // After copy-assigning from an int, the new item and old item are both ints.
+ A = F;
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_TRUE(F.hasValue());
+ EXPECT_TRUE(any_isa<int>(A));
+ EXPECT_TRUE(any_isa<int>(F));
+
+ // After move-assigning from an int, the new item and old item are both ints.
+ B = std::move(G);
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_FALSE(G.hasValue());
+ EXPECT_TRUE(any_isa<int>(B));
+ EXPECT_FALSE(any_isa<int>(G));
+}
+
+TEST(AnyTest, GoodAnyCast) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{8};
+ llvm::Any D{"hello"};
+ llvm::Any E{'x'};
+
+ // Check each value twice to make sure it isn't damaged by the cast.
+ EXPECT_EQ(7, llvm::any_cast<int>(B));
+ EXPECT_EQ(7, llvm::any_cast<int>(B));
+
+ EXPECT_STREQ("hello", llvm::any_cast<const char *>(D));
+ EXPECT_STREQ("hello", llvm::any_cast<const char *>(D));
+
+ EXPECT_EQ('x', llvm::any_cast<char>(E));
+ EXPECT_EQ('x', llvm::any_cast<char>(E));
+
+ llvm::Any F(B);
+ EXPECT_EQ(7, llvm::any_cast<int>(F));
+ EXPECT_EQ(7, llvm::any_cast<int>(F));
+
+ llvm::Any G(std::move(C));
+ EXPECT_EQ(8, llvm::any_cast<int>(G));
+ EXPECT_EQ(8, llvm::any_cast<int>(G));
+
+ A = F;
+ EXPECT_EQ(7, llvm::any_cast<int>(A));
+ EXPECT_EQ(7, llvm::any_cast<int>(A));
+
+ E = std::move(G);
+ EXPECT_EQ(8, llvm::any_cast<int>(E));
+ EXPECT_EQ(8, llvm::any_cast<int>(E));
+
+ // Make sure we can any_cast from an rvalue and that it's properly destroyed
+ // in the process.
+ EXPECT_EQ(8, llvm::any_cast<int>(std::move(E)));
+ EXPECT_TRUE(E.hasValue());
+
+ // Make sure moving from pointers gives back pointers, and that we can modify
+ // the underlying value through those pointers.
+ EXPECT_EQ(7, *llvm::any_cast<int>(&A));
+ int *N = llvm::any_cast<int>(&A);
+ *N = 42;
+ EXPECT_EQ(42, llvm::any_cast<int>(A));
+
+ // Make sure that we can any_cast to a reference and this is considered a good
+ // cast, resulting in an lvalue which can be modified.
+ llvm::any_cast<int &>(A) = 43;
+ EXPECT_EQ(43, llvm::any_cast<int>(A));
+}
+
+TEST(AnyTest, CopiesAndMoves) {
+ struct TestType {
+ TestType() = default;
+ TestType(const TestType &Other)
+ : Copies(Other.Copies + 1), Moves(Other.Moves) {}
+ TestType(TestType &&Other) : Copies(Other.Copies), Moves(Other.Moves + 1) {}
+ int Copies = 0;
+ int Moves = 0;
+ };
+
+ // One move to get TestType into the Any, and one move on the cast.
+ TestType T1 = llvm::any_cast<TestType>(Any{TestType()});
+ EXPECT_EQ(0, T1.Copies);
+ EXPECT_EQ(2, T1.Moves);
+
+ // One move to get TestType into the Any, and one copy on the cast.
+ Any A{TestType()};
+ TestType T2 = llvm::any_cast<TestType>(A);
+ EXPECT_EQ(1, T2.Copies);
+ EXPECT_EQ(1, T2.Moves);
+
+ // One move to get TestType into the Any, and one move on the cast.
+ TestType T3 = llvm::any_cast<TestType>(std::move(A));
+ EXPECT_EQ(0, T3.Copies);
+ EXPECT_EQ(2, T3.Moves);
+}
+
+TEST(AnyTest, BadAnyCast) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{"hello"};
+ llvm::Any D{'x'};
+
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
+ EXPECT_DEATH(llvm::any_cast<int>(A), "");
+
+ EXPECT_DEATH(llvm::any_cast<float>(B), "");
+ EXPECT_DEATH(llvm::any_cast<int *>(B), "");
+
+ EXPECT_DEATH(llvm::any_cast<std::string>(C), "");
+
+ EXPECT_DEATH(llvm::any_cast<unsigned char>(D), "");
+#endif
+}
+
+} // anonymous namespace
diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp
index 4694ff112cb5..e01d212f218b 100644
--- a/unittests/ADT/ArrayRefTest.cpp
+++ b/unittests/ADT/ArrayRefTest.cpp
@@ -39,16 +39,16 @@ static_assert(
// std::is_assignable and actually writing such an assignment.
#if !defined(_MSC_VER)
static_assert(
- !std::is_assignable<ArrayRef<int *>, int *>::value,
+ !std::is_assignable<ArrayRef<int *>&, int *>::value,
"Assigning from single prvalue element");
static_assert(
- !std::is_assignable<ArrayRef<int *>, int * &&>::value,
+ !std::is_assignable<ArrayRef<int *>&, int * &&>::value,
"Assigning from single xvalue element");
static_assert(
- std::is_assignable<ArrayRef<int *>, int * &>::value,
+ std::is_assignable<ArrayRef<int *>&, int * &>::value,
"Assigning from single lvalue element");
static_assert(
- !std::is_assignable<ArrayRef<int *>, std::initializer_list<int *>>::value,
+ !std::is_assignable<ArrayRef<int *>&, std::initializer_list<int *>>::value,
"Assigning from an initializer list");
#endif
diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt
index c0d511000f61..19657da8bcee 100644
--- a/unittests/ADT/CMakeLists.txt
+++ b/unittests/ADT/CMakeLists.txt
@@ -2,7 +2,8 @@ set(LLVM_LINK_COMPONENTS
Support
)
-set(ADTSources
+add_llvm_unittest(ADTTests
+ AnyTest.cpp
APFloatTest.cpp
APIntTest.cpp
APSIntTest.cpp
@@ -18,6 +19,7 @@ set(ADTSources
DepthFirstIteratorTest.cpp
EquivalenceClassesTest.cpp
FoldingSet.cpp
+ FunctionExtrasTest.cpp
FunctionRefTest.cpp
HashingTest.cpp
IListBaseTest.cpp
@@ -51,11 +53,13 @@ set(ADTSources
SetVectorTest.cpp
SimpleIListTest.cpp
SmallPtrSetTest.cpp
+ SmallSetTest.cpp
SmallStringTest.cpp
SmallVectorTest.cpp
SparseBitVectorTest.cpp
SparseMultiSetTest.cpp
SparseSetTest.cpp
+ StatisticTest.cpp
StringExtrasTest.cpp
StringMapTest.cpp
StringRefTest.cpp
@@ -64,10 +68,6 @@ set(ADTSources
TripleTest.cpp
TwineTest.cpp
VariadicFunctionTest.cpp
- )
-
-add_llvm_unittest(ADTTests
- ${ADTSources}
)
add_dependencies(ADTTests intrinsics_gen)
diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp
index cb5ba6875eaa..87f22f6f403e 100644
--- a/unittests/ADT/DenseMapTest.cpp
+++ b/unittests/ADT/DenseMapTest.cpp
@@ -30,7 +30,7 @@ uint32_t *getTestValue(int i, uint32_t **) {
return &dummy_arr1[i];
}
-/// \brief A test class that tries to check that construction and destruction
+/// A test class that tries to check that construction and destruction
/// occur correctly.
class CtorTester {
static std::set<CtorTester *> Constructed;
@@ -247,7 +247,7 @@ TYPED_TEST(DenseMapTest, AssignmentTest) {
EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
// test self-assignment.
- copyMap = copyMap;
+ copyMap = static_cast<TypeParam &>(copyMap);
EXPECT_EQ(1u, copyMap.size());
EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
}
@@ -262,7 +262,7 @@ TYPED_TEST(DenseMapTest, AssignmentTestNotSmall) {
EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
// test self-assignment.
- copyMap = copyMap;
+ copyMap = static_cast<TypeParam &>(copyMap);
EXPECT_EQ(5u, copyMap.size());
for (int Key = 0; Key < 5; ++Key)
EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
@@ -384,7 +384,7 @@ TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
EXPECT_EQ(MemorySize, Map.getMemorySize());
// Check that move was called the expected number of times
EXPECT_EQ(ExpectedMaxInitialEntries, CountCopyAndMove::Move);
- // Check that no copy occured
+ // Check that no copy occurred
EXPECT_EQ(0, CountCopyAndMove::Copy);
// Adding one extra element should grow the map
@@ -397,7 +397,7 @@ TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
// Check that move was called the expected number of times
// This relies on move-construction elision, and cannot be reliably tested.
// EXPECT_EQ(ExpectedMaxInitialEntries + 2, CountCopyAndMove::Move);
- // Check that no copy occured
+ // Check that no copy occurred
EXPECT_EQ(0, CountCopyAndMove::Copy);
}
@@ -422,7 +422,7 @@ TEST(DenseMapCustomTest, InitialSizeTest) {
EXPECT_EQ(MemorySize, Map.getMemorySize());
// Check that move was called the expected number of times
EXPECT_EQ(Size, CountCopyAndMove::Move);
- // Check that no copy occured
+ // Check that no copy occurred
EXPECT_EQ(0, CountCopyAndMove::Copy);
}
}
@@ -438,7 +438,7 @@ TEST(DenseMapCustomTest, InitFromIterator) {
CountCopyAndMove::Move = 0;
CountCopyAndMove::Copy = 0;
DenseMap<int, CountCopyAndMove> Map(Values.begin(), Values.end());
- // Check that no move occured
+ // Check that no move occurred
EXPECT_EQ(0, CountCopyAndMove::Move);
// Check that copy was called the expected number of times
EXPECT_EQ(Count, CountCopyAndMove::Copy);
@@ -466,7 +466,7 @@ TEST(DenseMapCustomTest, ReserveTest) {
EXPECT_EQ(MemorySize, Map.getMemorySize());
// Check that move was called the expected number of times
EXPECT_EQ(Size, CountCopyAndMove::Move);
- // Check that no copy occured
+ // Check that no copy occurred
EXPECT_EQ(0, CountCopyAndMove::Copy);
}
}
diff --git a/unittests/ADT/DenseSetTest.cpp b/unittests/ADT/DenseSetTest.cpp
index a09537a3e990..03738e46be4a 100644
--- a/unittests/ADT/DenseSetTest.cpp
+++ b/unittests/ADT/DenseSetTest.cpp
@@ -181,7 +181,7 @@ TEST(DenseSetCustomTest, ReserveTest) {
EXPECT_EQ(MemorySize, Set.getMemorySize());
// Check that move was called the expected number of times
EXPECT_EQ(Size, CountCopyAndMove::Move);
- // Check that no copy occured
+ // Check that no copy occurred
EXPECT_EQ(0, CountCopyAndMove::Copy);
}
}
diff --git a/unittests/ADT/FunctionExtrasTest.cpp b/unittests/ADT/FunctionExtrasTest.cpp
new file mode 100644
index 000000000000..d85962e0f773
--- /dev/null
+++ b/unittests/ADT/FunctionExtrasTest.cpp
@@ -0,0 +1,228 @@
+//===- FunctionExtrasTest.cpp - Unit tests for function type erasure ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "gtest/gtest.h"
+
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+TEST(UniqueFunctionTest, Basic) {
+ unique_function<int(int, int)> Sum = [](int A, int B) { return A + B; };
+ EXPECT_EQ(Sum(1, 2), 3);
+
+ unique_function<int(int, int)> Sum2 = std::move(Sum);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ unique_function<int(int, int)> Sum3 = [](int A, int B) { return A + B; };
+ Sum2 = std::move(Sum3);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ Sum2 = unique_function<int(int, int)>([](int A, int B) { return A + B; });
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ // Explicit self-move test.
+ *&Sum2 = std::move(Sum2);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ Sum2 = unique_function<int(int, int)>();
+ EXPECT_FALSE(Sum2);
+
+ // Make sure we can forward through l-value reference parameters.
+ unique_function<void(int &)> Inc = [](int &X) { ++X; };
+ int X = 42;
+ Inc(X);
+ EXPECT_EQ(X, 43);
+
+ // Make sure we can forward through r-value reference parameters with
+ // move-only types.
+ unique_function<int(std::unique_ptr<int> &&)> ReadAndDeallocByRef =
+ [](std::unique_ptr<int> &&Ptr) {
+ int V = *Ptr;
+ Ptr.reset();
+ return V;
+ };
+ std::unique_ptr<int> Ptr{new int(13)};
+ EXPECT_EQ(ReadAndDeallocByRef(std::move(Ptr)), 13);
+ EXPECT_FALSE((bool)Ptr);
+
+ // Make sure we can pass a move-only temporary as opposed to a local variable.
+ EXPECT_EQ(ReadAndDeallocByRef(std::unique_ptr<int>(new int(42))), 42);
+
+ // Make sure we can pass a move-only type by-value.
+ unique_function<int(std::unique_ptr<int>)> ReadAndDeallocByVal =
+ [](std::unique_ptr<int> Ptr) {
+ int V = *Ptr;
+ Ptr.reset();
+ return V;
+ };
+ Ptr.reset(new int(13));
+ EXPECT_EQ(ReadAndDeallocByVal(std::move(Ptr)), 13);
+ EXPECT_FALSE((bool)Ptr);
+
+ EXPECT_EQ(ReadAndDeallocByVal(std::unique_ptr<int>(new int(42))), 42);
+}
+
+TEST(UniqueFunctionTest, Captures) {
+ long A = 1, B = 2, C = 3, D = 4, E = 5;
+
+ unique_function<long()> Tmp;
+
+ unique_function<long()> C1 = [A]() { return A; };
+ EXPECT_EQ(C1(), 1);
+ Tmp = std::move(C1);
+ EXPECT_EQ(Tmp(), 1);
+
+ unique_function<long()> C2 = [A, B]() { return A + B; };
+ EXPECT_EQ(C2(), 3);
+ Tmp = std::move(C2);
+ EXPECT_EQ(Tmp(), 3);
+
+ unique_function<long()> C3 = [A, B, C]() { return A + B + C; };
+ EXPECT_EQ(C3(), 6);
+ Tmp = std::move(C3);
+ EXPECT_EQ(Tmp(), 6);
+
+ unique_function<long()> C4 = [A, B, C, D]() { return A + B + C + D; };
+ EXPECT_EQ(C4(), 10);
+ Tmp = std::move(C4);
+ EXPECT_EQ(Tmp(), 10);
+
+ unique_function<long()> C5 = [A, B, C, D, E]() { return A + B + C + D + E; };
+ EXPECT_EQ(C5(), 15);
+ Tmp = std::move(C5);
+ EXPECT_EQ(Tmp(), 15);
+}
+
+TEST(UniqueFunctionTest, MoveOnly) {
+ struct SmallCallable {
+ std::unique_ptr<int> A{new int(1)};
+
+ int operator()(int B) { return *A + B; }
+ };
+ unique_function<int(int)> Small = SmallCallable();
+ EXPECT_EQ(Small(2), 3);
+ unique_function<int(int)> Small2 = std::move(Small);
+ EXPECT_EQ(Small2(2), 3);
+
+ struct LargeCallable {
+ std::unique_ptr<int> A{new int(1)};
+ std::unique_ptr<int> B{new int(2)};
+ std::unique_ptr<int> C{new int(3)};
+ std::unique_ptr<int> D{new int(4)};
+ std::unique_ptr<int> E{new int(5)};
+
+ int operator()() { return *A + *B + *C + *D + *E; }
+ };
+ unique_function<int()> Large = LargeCallable();
+ EXPECT_EQ(Large(), 15);
+ unique_function<int()> Large2 = std::move(Large);
+ EXPECT_EQ(Large2(), 15);
+}
+
+TEST(UniqueFunctionTest, CountForwardingCopies) {
+ struct CopyCounter {
+ int &CopyCount;
+
+ CopyCounter(int &CopyCount) : CopyCount(CopyCount) {}
+ CopyCounter(const CopyCounter &Arg) : CopyCount(Arg.CopyCount) {
+ ++CopyCount;
+ }
+ };
+
+ unique_function<void(CopyCounter)> ByValF = [](CopyCounter) {};
+ int CopyCount = 0;
+ ByValF(CopyCounter(CopyCount));
+ EXPECT_EQ(1, CopyCount);
+
+ CopyCount = 0;
+ {
+ CopyCounter Counter{CopyCount};
+ ByValF(Counter);
+ }
+ EXPECT_EQ(2, CopyCount);
+
+ // Check that we don't generate a copy at all when we can bind a reference all
+ // the way down, even if that reference could *in theory* allow copies.
+ unique_function<void(const CopyCounter &)> ByRefF = [](const CopyCounter &) {
+ };
+ CopyCount = 0;
+ ByRefF(CopyCounter(CopyCount));
+ EXPECT_EQ(0, CopyCount);
+
+ CopyCount = 0;
+ {
+ CopyCounter Counter{CopyCount};
+ ByRefF(Counter);
+ }
+ EXPECT_EQ(0, CopyCount);
+
+ // If we use a reference, we can make a stronger guarantee that *no* copy
+ // occurs.
+ struct Uncopyable {
+ Uncopyable() = default;
+ Uncopyable(const Uncopyable &) = delete;
+ };
+ unique_function<void(const Uncopyable &)> UncopyableF =
+ [](const Uncopyable &) {};
+ UncopyableF(Uncopyable());
+ Uncopyable X;
+ UncopyableF(X);
+}
+
+TEST(UniqueFunctionTest, CountForwardingMoves) {
+ struct MoveCounter {
+ int &MoveCount;
+
+ MoveCounter(int &MoveCount) : MoveCount(MoveCount) {}
+ MoveCounter(MoveCounter &&Arg) : MoveCount(Arg.MoveCount) { ++MoveCount; }
+ };
+
+ unique_function<void(MoveCounter)> ByValF = [](MoveCounter) {};
+ int MoveCount = 0;
+ ByValF(MoveCounter(MoveCount));
+ EXPECT_EQ(1, MoveCount);
+
+ MoveCount = 0;
+ {
+ MoveCounter Counter{MoveCount};
+ ByValF(std::move(Counter));
+ }
+ EXPECT_EQ(2, MoveCount);
+
+ // Check that when we use an r-value reference we get no spurious copies.
+ unique_function<void(MoveCounter &&)> ByRefF = [](MoveCounter &&) {};
+ MoveCount = 0;
+ ByRefF(MoveCounter(MoveCount));
+ EXPECT_EQ(0, MoveCount);
+
+ MoveCount = 0;
+ {
+ MoveCounter Counter{MoveCount};
+ ByRefF(std::move(Counter));
+ }
+ EXPECT_EQ(0, MoveCount);
+
+ // If we use an r-value reference we can in fact make a stronger guarantee
+ // with an unmovable type.
+ struct Unmovable {
+ Unmovable() = default;
+ Unmovable(Unmovable &&) = delete;
+ };
+ unique_function<void(const Unmovable &)> UnmovableF = [](const Unmovable &) {
+ };
+ UnmovableF(Unmovable());
+ Unmovable X;
+ UnmovableF(X);
+}
+
+} // anonymous namespace
diff --git a/unittests/ADT/IteratorTest.cpp b/unittests/ADT/IteratorTest.cpp
index c95ce8061847..50c3b01bbc74 100644
--- a/unittests/ADT/IteratorTest.cpp
+++ b/unittests/ADT/IteratorTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "gtest/gtest.h"
@@ -127,6 +128,20 @@ TEST(PointeeIteratorTest, Range) {
EXPECT_EQ(A[I++], II);
}
+TEST(PointeeIteratorTest, PointeeType) {
+ struct S {
+ int X;
+ bool operator==(const S &RHS) const { return X == RHS.X; };
+ };
+ S A[] = {S{0}, S{1}};
+ SmallVector<S *, 2> V{&A[0], &A[1]};
+
+ pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
+ for (int j = 0; j < 2; ++j, ++I) {
+ EXPECT_EQ(*V[j], *I);
+ }
+}
+
TEST(FilterIteratorTest, Lambda) {
auto IsOdd = [](int N) { return N % 2 == 1; };
int A[] = {0, 1, 2, 3, 4, 5, 6};
@@ -196,6 +211,33 @@ TEST(FilterIteratorTest, InputIterator) {
EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
}
+TEST(FilterIteratorTest, ReverseFilterRange) {
+ auto IsOdd = [](int N) { return N % 2 == 1; };
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+
+ // Check basic reversal.
+ auto Range = reverse(make_filter_range(A, IsOdd));
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
+
+ // Check that the reverse of the reverse is the original.
+ auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
+ SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
+
+ // Check empty ranges.
+ auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
+ SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
+ EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
+
+ // Check that we don't skip the first element, provided it isn't filtered
+ // away.
+ auto IsEven = [](int N) { return N % 2 == 0; };
+ auto Range4 = reverse(make_filter_range(A, IsEven));
+ SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
+ EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
+}
+
TEST(PointerIterator, Basic) {
int A[] = {1, 2, 3, 4};
pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
@@ -337,4 +379,25 @@ TEST(ZipIteratorTest, Reverse) {
EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
}
+TEST(RangeTest, Distance) {
+ std::vector<int> v1;
+ std::vector<int> v2{1, 2, 3};
+
+ EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
+ EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
+}
+
+TEST(IteratorRangeTest, DropBegin) {
+ SmallVector<int, 5> vec{0, 1, 2, 3, 4};
+
+ for (int n = 0; n < 5; ++n) {
+ int i = n;
+ for (auto &v : drop_begin(vec, n)) {
+ EXPECT_EQ(v, i);
+ i += 1;
+ }
+ EXPECT_EQ(i, 5);
+ }
+}
+
} // anonymous namespace
diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp
index bd6602b030f6..16e9b5a74f42 100644
--- a/unittests/ADT/MapVectorTest.cpp
+++ b/unittests/ADT/MapVectorTest.cpp
@@ -157,6 +157,45 @@ TEST(MapVectorTest, NonCopyable) {
ASSERT_EQ(*MV.find(2)->second, 2);
}
+template <class IntType> struct MapVectorMappedTypeTest : ::testing::Test {
+ using int_type = IntType;
+};
+
+using MapIntTypes = ::testing::Types<int, long, long long, unsigned,
+ unsigned long, unsigned long long>;
+TYPED_TEST_CASE(MapVectorMappedTypeTest, MapIntTypes);
+
+TYPED_TEST(MapVectorMappedTypeTest, DifferentDenseMap) {
+ // Test that using a map with a mapped type other than 'unsigned' compiles
+ // and works.
+ using IntType = typename TestFixture::int_type;
+ using MapVectorType = MapVector<int, int, DenseMap<int, IntType>>;
+
+ MapVectorType MV;
+ std::pair<typename MapVectorType::iterator, bool> R;
+
+ R = MV.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ const std::pair<int, int> Elem(1, 3);
+ R = MV.insert(Elem);
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_FALSE(R.second);
+
+ int& value = MV[4];
+ EXPECT_EQ(value, 0);
+ value = 5;
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 5);
+}
+
TEST(SmallMapVectorSmallTest, insert_pop) {
SmallMapVector<int, int, 32> MV;
std::pair<SmallMapVector<int, int, 32>::iterator, bool> R;
diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp
index 46d4fe0780c3..2e09c5340fa3 100644
--- a/unittests/ADT/OptionalTest.cpp
+++ b/unittests/ADT/OptionalTest.cpp
@@ -268,12 +268,12 @@ TEST_F(OptionalTest, MoveOnlyMoveConstruction) {
Optional<MoveOnly> A(MoveOnly(3));
MoveOnly::ResetCounts();
Optional<MoveOnly> B(std::move(A));
- EXPECT_FALSE((bool)A);
+ EXPECT_TRUE((bool)A);
EXPECT_TRUE((bool)B);
EXPECT_EQ(3, B->val);
EXPECT_EQ(1u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
- EXPECT_EQ(1u, MoveOnly::Destructions);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
}
TEST_F(OptionalTest, MoveOnlyAssignment) {
@@ -292,12 +292,12 @@ TEST_F(OptionalTest, MoveOnlyInitializingAssignment) {
Optional<MoveOnly> B;
MoveOnly::ResetCounts();
B = std::move(A);
- EXPECT_FALSE((bool)A);
+ EXPECT_TRUE((bool)A);
EXPECT_TRUE((bool)B);
EXPECT_EQ(3, B->val);
EXPECT_EQ(1u, MoveOnly::MoveConstructions);
EXPECT_EQ(0u, MoveOnly::MoveAssignments);
- EXPECT_EQ(1u, MoveOnly::Destructions);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
}
TEST_F(OptionalTest, MoveOnlyNullingAssignment) {
@@ -317,12 +317,12 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) {
Optional<MoveOnly> B(MoveOnly(4));
MoveOnly::ResetCounts();
B = std::move(A);
- EXPECT_FALSE((bool)A);
+ EXPECT_TRUE((bool)A);
EXPECT_TRUE((bool)B);
EXPECT_EQ(3, B->val);
EXPECT_EQ(0u, MoveOnly::MoveConstructions);
EXPECT_EQ(1u, MoveOnly::MoveAssignments);
- EXPECT_EQ(1u, MoveOnly::Destructions);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
}
struct Immovable {
@@ -518,5 +518,13 @@ TEST_F(OptionalTest, OperatorGreaterEqual) {
CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
}
+#if __has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)
+static_assert(std::is_trivially_copyable<Optional<int>>::value,
+ "Should be trivially copyable");
+static_assert(
+ !std::is_trivially_copyable<Optional<NonDefaultConstructible>>::value,
+ "Shouldn't be trivially copyable");
+#endif
+
} // end anonymous namespace
diff --git a/unittests/ADT/STLExtrasTest.cpp b/unittests/ADT/STLExtrasTest.cpp
index 89e876eb4de9..d744a3cd521a 100644
--- a/unittests/ADT/STLExtrasTest.cpp
+++ b/unittests/ADT/STLExtrasTest.cpp
@@ -302,8 +302,8 @@ TEST(STLExtrasTest, PartitionAdaptor) {
ASSERT_EQ(V.begin() + 4, I);
// Sort the two halves as partition may have messed with the order.
- std::sort(V.begin(), I);
- std::sort(I, V.end());
+ llvm::sort(V.begin(), I);
+ llvm::sort(I, V.end());
EXPECT_EQ(2, V[0]);
EXPECT_EQ(4, V[1]);
diff --git a/unittests/ADT/ScopeExitTest.cpp b/unittests/ADT/ScopeExitTest.cpp
index 301942c30bbc..ab11dff8ce48 100644
--- a/unittests/ADT/ScopeExitTest.cpp
+++ b/unittests/ADT/ScopeExitTest.cpp
@@ -29,4 +29,21 @@ TEST(ScopeExitTest, Basic) {
EXPECT_TRUE(Called);
}
+TEST(ScopeExitTest, Release) {
+ int Count = 0;
+ auto Increment = [&] { ++Count; };
+ {
+ auto G = make_scope_exit(Increment);
+ auto H = std::move(G);
+ auto I = std::move(G);
+ EXPECT_EQ(0, Count);
+ }
+ EXPECT_EQ(1, Count);
+ {
+ auto G = make_scope_exit(Increment);
+ G.release();
+ }
+ EXPECT_EQ(1, Count);
+}
+
} // end anonymous namespace
diff --git a/unittests/ADT/SmallPtrSetTest.cpp b/unittests/ADT/SmallPtrSetTest.cpp
index 0070d1cbae1b..76f9cf7fb9af 100644
--- a/unittests/ADT/SmallPtrSetTest.cpp
+++ b/unittests/ADT/SmallPtrSetTest.cpp
@@ -28,7 +28,7 @@ TEST(SmallPtrSetTest, Assignment) {
(s2 = s1).insert(&buf[2]);
// Self assign as well.
- (s2 = s2).insert(&buf[3]);
+ (s2 = static_cast<SmallPtrSet<int *, 4> &>(s2)).insert(&buf[3]);
s1 = s2;
EXPECT_EQ(4U, s1.size());
@@ -56,7 +56,7 @@ TEST(SmallPtrSetTest, GrowthTest) {
SmallPtrSet<int *, 4> s;
typedef SmallPtrSet<int *, 4>::iterator iter;
-
+
s.insert(&buf[0]);
s.insert(&buf[1]);
s.insert(&buf[2]);
@@ -299,7 +299,7 @@ TEST(SmallPtrSetTest, dereferenceAndIterate) {
// Sort. We should hit the first element just once and the final element N
// times.
- std::sort(std::begin(Found), std::end(Found));
+ llvm::sort(std::begin(Found), std::end(Found));
for (auto F = std::begin(Found), E = std::end(Found); F != E; ++F)
EXPECT_EQ(F - Found + 1, *F);
}
diff --git a/unittests/ADT/SmallSetTest.cpp b/unittests/ADT/SmallSetTest.cpp
new file mode 100644
index 000000000000..d78a72b38f8b
--- /dev/null
+++ b/unittests/ADT/SmallSetTest.cpp
@@ -0,0 +1,149 @@
+//===- llvm/unittest/ADT/SmallSetTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SmallSet unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallSet.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+TEST(SmallSetTest, Insert) {
+
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 4; i++)
+ s1.insert(i);
+
+ for (int i = 0; i < 4; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(4u, s1.size());
+
+ for (int i = 0; i < 4; i++)
+ EXPECT_EQ(1u, s1.count(i));
+
+ EXPECT_EQ(0u, s1.count(4));
+}
+
+TEST(SmallSetTest, Grow) {
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 8; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(8u, s1.size());
+
+ for (int i = 0; i < 8; i++)
+ EXPECT_EQ(1u, s1.count(i));
+
+ EXPECT_EQ(0u, s1.count(8));
+}
+
+TEST(SmallSetTest, Erase) {
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 8; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(8u, s1.size());
+
+ // Remove elements one by one and check if all other elements are still there.
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(1u, s1.count(i));
+ EXPECT_TRUE(s1.erase(i));
+ EXPECT_EQ(0u, s1.count(i));
+ EXPECT_EQ(8u - i - 1, s1.size());
+ for (int j = i + 1; j < 8; j++)
+ EXPECT_EQ(1u, s1.count(j));
+ }
+
+ EXPECT_EQ(0u, s1.count(8));
+}
+
+TEST(SmallSetTest, IteratorInt) {
+ SmallSet<int, 4> s1;
+
+ // Test the 'small' case.
+ for (int i = 0; i < 3; i++)
+ s1.insert(i);
+
+ std::vector<int> V(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ for (int i = 0; i < 3; i++)
+ EXPECT_EQ(i, V[i]);
+
+ // Test the 'big' case by adding a few more elements to switch to std::set
+ // internally.
+ for (int i = 3; i < 6; i++)
+ s1.insert(i);
+
+ V.assign(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ for (int i = 0; i < 6; i++)
+ EXPECT_EQ(i, V[i]);
+}
+
+TEST(SmallSetTest, IteratorString) {
+ // Test SmallSetIterator for SmallSet with a type with non-trivial
+ // ctors/dtors.
+ SmallSet<std::string, 2> s1;
+
+ s1.insert("str 1");
+ s1.insert("str 2");
+ s1.insert("str 1");
+
+ std::vector<std::string> V(s1.begin(), s1.end());
+ std::sort(V.begin(), V.end());
+ EXPECT_EQ(2u, s1.size());
+ EXPECT_EQ("str 1", V[0]);
+ EXPECT_EQ("str 2", V[1]);
+
+ s1.insert("str 4");
+ s1.insert("str 0");
+ s1.insert("str 4");
+
+ V.assign(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ EXPECT_EQ(4u, s1.size());
+ EXPECT_EQ("str 0", V[0]);
+ EXPECT_EQ("str 1", V[1]);
+ EXPECT_EQ("str 2", V[2]);
+ EXPECT_EQ("str 4", V[3]);
+}
+
+TEST(SmallSetTest, IteratorIncMoveCopy) {
+ // Test SmallSetIterator for SmallSet with a type with non-trivial
+ // ctors/dtors.
+ SmallSet<std::string, 2> s1;
+
+ s1.insert("str 1");
+ s1.insert("str 2");
+
+ auto Iter = s1.begin();
+ EXPECT_EQ("str 1", *Iter);
+ ++Iter;
+ EXPECT_EQ("str 2", *Iter);
+
+ s1.insert("str 4");
+ s1.insert("str 0");
+ auto Iter2 = s1.begin();
+ Iter = std::move(Iter2);
+ EXPECT_EQ("str 0", *Iter);
+
+ auto Iter3 = s1.end();
+ Iter3 = Iter2;
+ EXPECT_EQ(Iter3, Iter2);
+}
diff --git a/unittests/ADT/SparseBitVectorTest.cpp b/unittests/ADT/SparseBitVectorTest.cpp
index 6cd4de35bca7..9d6f4f1665d5 100644
--- a/unittests/ADT/SparseBitVectorTest.cpp
+++ b/unittests/ADT/SparseBitVectorTest.cpp
@@ -68,7 +68,7 @@ TEST(SparseBitVectorTest, SelfAssignment) {
Vec.set(23);
Vec.set(234);
- Vec = Vec;
+ Vec = static_cast<SparseBitVector<> &>(Vec);
EXPECT_TRUE(Vec.test(23));
EXPECT_TRUE(Vec.test(234));
diff --git a/unittests/ADT/StatisticTest.cpp b/unittests/ADT/StatisticTest.cpp
new file mode 100644
index 000000000000..17a5c7fc204a
--- /dev/null
+++ b/unittests/ADT/StatisticTest.cpp
@@ -0,0 +1,160 @@
+//===- llvm/unittest/ADT/StatisticTest.cpp - Statistic unit tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+using OptionalStatistic = Optional<std::pair<StringRef, unsigned>>;
+
+namespace {
+#define DEBUG_TYPE "unittest"
+STATISTIC(Counter, "Counts things");
+STATISTIC(Counter2, "Counts other things");
+
+#if LLVM_ENABLE_STATS
+static void
+extractCounters(const std::vector<std::pair<StringRef, unsigned>> &Range,
+ OptionalStatistic &S1, OptionalStatistic &S2) {
+ for (const auto &S : Range) {
+ if (S.first == "Counter")
+ S1 = S;
+ if (S.first == "Counter2")
+ S2 = S;
+ }
+}
+#endif
+
+TEST(StatisticTest, Count) {
+ EnableStatistics();
+
+ Counter = 0;
+ EXPECT_EQ(Counter, 0u);
+ Counter++;
+ Counter++;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+}
+
+TEST(StatisticTest, Assign) {
+ EnableStatistics();
+
+ Counter = 2;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+}
+
+TEST(StatisticTest, API) {
+ EnableStatistics();
+
+ Counter = 0;
+ EXPECT_EQ(Counter, 0u);
+ Counter++;
+ Counter++;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+
+#if LLVM_ENABLE_STATS
+ {
+ const auto Range1 = GetStatistics();
+ EXPECT_NE(Range1.begin(), Range1.end());
+ EXPECT_EQ(Range1.begin() + 1, Range1.end());
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range1, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), false);
+ }
+
+ // Counter2 will be registered when it's first touched.
+ Counter2++;
+
+ {
+ const auto Range = GetStatistics();
+ EXPECT_NE(Range.begin(), Range.end());
+ EXPECT_EQ(Range.begin() + 2, Range.end());
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), true);
+
+ EXPECT_EQ(S1->first, "Counter");
+ EXPECT_EQ(S1->second, 2u);
+
+ EXPECT_EQ(S2->first, "Counter2");
+ EXPECT_EQ(S2->second, 1u);
+ }
+#else
+ Counter2++;
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin(), Range.end());
+#endif
+
+#if LLVM_ENABLE_STATS
+ // Check that resetting the statistics works correctly.
+ // It should empty the list and zero the counters.
+ ResetStatistics();
+ {
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin(), Range.end());
+ EXPECT_EQ(Counter, 0u);
+ EXPECT_EQ(Counter2, 0u);
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+ EXPECT_EQ(S1.hasValue(), false);
+ EXPECT_EQ(S2.hasValue(), false);
+ }
+
+ // Now check that they successfully re-register and count.
+ Counter++;
+ Counter2++;
+
+ {
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin() + 2, Range.end());
+ EXPECT_EQ(Counter, 1u);
+ EXPECT_EQ(Counter2, 1u);
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), true);
+
+ EXPECT_EQ(S1->first, "Counter");
+ EXPECT_EQ(S1->second, 1u);
+
+ EXPECT_EQ(S2->first, "Counter2");
+ EXPECT_EQ(S2->second, 1u);
+ }
+#else
+ // No need to test the output ResetStatistics(), there's nothing to reset so
+ // we can't tell if it failed anyway.
+ ResetStatistics();
+#endif
+}
+
+} // end anonymous namespace
diff --git a/unittests/ADT/StringExtrasTest.cpp b/unittests/ADT/StringExtrasTest.cpp
index 7bcdaf62fe5a..1df200553a61 100644
--- a/unittests/ADT/StringExtrasTest.cpp
+++ b/unittests/ADT/StringExtrasTest.cpp
@@ -13,6 +13,17 @@
using namespace llvm;
+TEST(StringExtrasTest, isPrint) {
+ EXPECT_FALSE(isPrint('\0'));
+ EXPECT_FALSE(isPrint('\t'));
+ EXPECT_TRUE(isPrint('0'));
+ EXPECT_TRUE(isPrint('a'));
+ EXPECT_TRUE(isPrint('A'));
+ EXPECT_TRUE(isPrint(' '));
+ EXPECT_TRUE(isPrint('~'));
+ EXPECT_TRUE(isPrint('?'));
+}
+
TEST(StringExtrasTest, Join) {
std::vector<std::string> Items;
EXPECT_EQ("", join(Items.begin(), Items.end(), " <sep> "));
@@ -92,3 +103,17 @@ TEST(StringExtrasTest, printLowerCase) {
printLowerCase("ABCdefg01234.,&!~`'}\"", OS);
EXPECT_EQ("abcdefg01234.,&!~`'}\"", OS.str());
}
+
+TEST(StringExtrasTest, printEscapedString) {
+ std::string str;
+ raw_string_ostream OS(str);
+ printEscapedString("ABCdef123&<>\\\"'\t", OS);
+ EXPECT_EQ("ABCdef123&<>\\5C\\22'\\09", OS.str());
+}
+
+TEST(StringExtrasTest, printHTMLEscaped) {
+ std::string str;
+ raw_string_ostream OS(str);
+ printHTMLEscaped("ABCdef123&<>\"'", OS);
+ EXPECT_EQ("ABCdef123&amp;&lt;&gt;&quot;&apos;", OS.str());
+}
diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp
index b5c63695ff35..1f5c4f031642 100644
--- a/unittests/ADT/StringMapTest.cpp
+++ b/unittests/ADT/StringMapTest.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/DataTypes.h"
#include "gtest/gtest.h"
+#include <limits>
#include <tuple>
using namespace llvm;
@@ -278,7 +279,7 @@ TEST_F(StringMapTest, IterMapKeys) {
Map["D"] = 3;
auto Keys = to_vector<4>(Map.keys());
- std::sort(Keys.begin(), Keys.end());
+ llvm::sort(Keys.begin(), Keys.end());
SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
EXPECT_EQ(Expected, Keys);
@@ -292,7 +293,7 @@ TEST_F(StringMapTest, IterSetKeys) {
Set.insert("D");
auto Keys = to_vector<4>(Set.keys());
- std::sort(Keys.begin(), Keys.end());
+ llvm::sort(Keys.begin(), Keys.end());
SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
EXPECT_EQ(Expected, Keys);
@@ -492,4 +493,43 @@ TEST(StringMapCustomTest, EmplaceTest) {
EXPECT_EQ(42, Map["abcd"].Data);
}
+// Test that StringMapEntryBase can handle size_t wide sizes.
+TEST(StringMapCustomTest, StringMapEntryBaseSize) {
+ size_t LargeValue;
+
+ // Test that the entry can represent max-unsigned.
+ if (sizeof(size_t) <= sizeof(unsigned))
+ LargeValue = std::numeric_limits<unsigned>::max();
+ else
+ LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
+ StringMapEntryBase LargeBase(LargeValue);
+ EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
+
+ // Test that the entry can hold at least max size_t.
+ LargeValue = std::numeric_limits<size_t>::max();
+ StringMapEntryBase LargerBase(LargeValue);
+ LargeValue = std::numeric_limits<size_t>::max();
+ EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
+}
+
+// Test that StringMapEntry can handle size_t wide sizes.
+TEST(StringMapCustomTest, StringMapEntrySize) {
+ size_t LargeValue;
+
+ // Test that the entry can represent max-unsigned.
+ if (sizeof(size_t) <= sizeof(unsigned))
+ LargeValue = std::numeric_limits<unsigned>::max();
+ else
+ LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
+ StringMapEntry<int> LargeEntry(LargeValue);
+ StringRef Key = LargeEntry.getKey();
+ EXPECT_EQ(LargeValue, Key.size());
+
+ // Test that the entry can hold at least max size_t.
+ LargeValue = std::numeric_limits<size_t>::max();
+ StringMapEntry<int> LargerEntry(LargeValue);
+ Key = LargerEntry.getKey();
+ EXPECT_EQ(LargeValue, Key.size());
+}
+
} // end anonymous namespace
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index 0e0b5957f025..4087d6c99a93 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -40,22 +40,22 @@ std::ostream &operator<<(std::ostream &OS,
// std::is_assignable and actually writing such an assignment.
#if !defined(_MSC_VER)
static_assert(
- !std::is_assignable<StringRef, std::string>::value,
+ !std::is_assignable<StringRef&, std::string>::value,
"Assigning from prvalue std::string");
static_assert(
- !std::is_assignable<StringRef, std::string &&>::value,
+ !std::is_assignable<StringRef&, std::string &&>::value,
"Assigning from xvalue std::string");
static_assert(
- std::is_assignable<StringRef, std::string &>::value,
+ std::is_assignable<StringRef&, std::string &>::value,
"Assigning from lvalue std::string");
static_assert(
- std::is_assignable<StringRef, const char *>::value,
+ std::is_assignable<StringRef&, const char *>::value,
"Assigning from prvalue C string");
static_assert(
- std::is_assignable<StringRef, const char * &&>::value,
+ std::is_assignable<StringRef&, const char * &&>::value,
"Assigning from xvalue C string");
static_assert(
- std::is_assignable<StringRef, const char * &>::value,
+ std::is_assignable<StringRef&, const char * &>::value,
"Assigning from lvalue C string");
#endif
@@ -181,6 +181,17 @@ TEST(StringRefTest, Split) {
Str.rsplit('l'));
EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
Str.rsplit('o'));
+
+ EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("o")),
+ Str.rsplit("ll"));
+ EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
+ Str.rsplit("h"));
+ EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
+ Str.rsplit("o"));
+ EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
+ Str.rsplit("::"));
+ EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")),
+ Str.rsplit("l"));
}
TEST(StringRefTest, Split2) {
diff --git a/unittests/ADT/StringSwitchTest.cpp b/unittests/ADT/StringSwitchTest.cpp
index 1a51629ca574..62d3a319e7a4 100644
--- a/unittests/ADT/StringSwitchTest.cpp
+++ b/unittests/ADT/StringSwitchTest.cpp
@@ -158,7 +158,8 @@ TEST(StringSwitchTest, Cases) {
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
- .Cases("wind\0ws", "win32", "winnt", OSType::Windows)
+ .Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
.Cases("linux", "unix", "*nix", "posix", OSType::Linux)
.Default(OSType::Unknown);
};
@@ -184,7 +185,8 @@ TEST(StringSwitchTest, CasesLower) {
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
- .CasesLower("wind\0ws", "win32", "winnt", OSType::Windows)
+ .CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
.CasesLower("linux", "unix", "*nix", "posix", OSType::Linux)
.Default(OSType::Unknown);
};
diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp
index ed4a88067b15..b6b470d34e2b 100644
--- a/unittests/ADT/TripleTest.cpp
+++ b/unittests/ADT/TripleTest.cpp
@@ -117,12 +117,29 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::CNK, T.getOS());
EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+ T = Triple("ppc-bgp-linux");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("ppc32-bgp-linux");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
T = Triple("powerpc64-bgq-linux");
EXPECT_EQ(Triple::ppc64, T.getArch());
EXPECT_EQ(Triple::BGQ, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+ T = Triple("ppc64-bgq-linux");
+ EXPECT_EQ(Triple::ppc64, T.getArch());
+ EXPECT_EQ(Triple::BGQ, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+
T = Triple("powerpc-ibm-aix");
EXPECT_EQ(Triple::ppc, T.getArch());
EXPECT_EQ(Triple::IBM, T.getVendor());
@@ -266,12 +283,6 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::AMDHSA, T.getOS());
EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
- T = Triple("amdgcn-amd-amdhsa-opencl");
- EXPECT_EQ(Triple::amdgcn, T.getArch());
- EXPECT_EQ(Triple::AMD, T.getVendor());
- EXPECT_EQ(Triple::AMDHSA, T.getOS());
- EXPECT_EQ(Triple::OpenCL, T.getEnvironment());
-
T = Triple("amdgcn-amd-amdpal");
EXPECT_EQ(Triple::amdgcn, T.getArch());
EXPECT_EQ(Triple::AMD, T.getVendor());
@@ -350,6 +361,18 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ T = Triple("arm-oe-linux-gnueabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::OpenEmbedded, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
+
+ T = Triple("aarch64-oe-linux");
+ EXPECT_EQ(Triple::aarch64, T.getArch());
+ EXPECT_EQ(Triple::OpenEmbedded, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
T = Triple("huh");
EXPECT_EQ(Triple::UnknownArch, T.getArch());
}
@@ -523,9 +546,6 @@ TEST(TripleTest, MutateName) {
EXPECT_EQ(Triple::PC, T.getVendor());
EXPECT_EQ(Triple::Darwin, T.getOS());
EXPECT_EQ("i386-pc-darwin", T.getTriple());
-
- T.setEnvironmentName("amdopencl");
- EXPECT_EQ(Triple::AMDOpenCL, T.getEnvironment());
}
TEST(TripleTest, BitWidthPredicates) {
@@ -1027,8 +1047,13 @@ TEST(TripleTest, FileFormat) {
EXPECT_EQ(Triple::ELF, Triple("i686-pc-windows-msvc-elf").getObjectFormat());
EXPECT_EQ(Triple::ELF, Triple("i686-pc-cygwin-elf").getObjectFormat());
- EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-unknown-wasm").getObjectFormat());
- EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-unknown-wasm").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-unknown").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-unknown").getObjectFormat());
+
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm32-unknown-unknown-wasm").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm64-unknown-unknown-wasm").getObjectFormat());
Triple MSVCNormalized(Triple::normalize("i686-pc-windows-msvc-elf"));
EXPECT_EQ(Triple::ELF, MSVCNormalized.getObjectFormat());