diff options
Diffstat (limited to 'unittests/ADT')
| -rw-r--r-- | unittests/ADT/APFloatTest.cpp | 7 | ||||
| -rw-r--r-- | unittests/ADT/APIntTest.cpp | 138 | ||||
| -rw-r--r-- | unittests/ADT/AnyTest.cpp | 175 | ||||
| -rw-r--r-- | unittests/ADT/ArrayRefTest.cpp | 8 | ||||
| -rw-r--r-- | unittests/ADT/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | unittests/ADT/DenseMapTest.cpp | 16 | ||||
| -rw-r--r-- | unittests/ADT/DenseSetTest.cpp | 2 | ||||
| -rw-r--r-- | unittests/ADT/FunctionExtrasTest.cpp | 228 | ||||
| -rw-r--r-- | unittests/ADT/IteratorTest.cpp | 63 | ||||
| -rw-r--r-- | unittests/ADT/MapVectorTest.cpp | 39 | ||||
| -rw-r--r-- | unittests/ADT/OptionalTest.cpp | 20 | ||||
| -rw-r--r-- | unittests/ADT/STLExtrasTest.cpp | 4 | ||||
| -rw-r--r-- | unittests/ADT/ScopeExitTest.cpp | 17 | ||||
| -rw-r--r-- | unittests/ADT/SmallPtrSetTest.cpp | 6 | ||||
| -rw-r--r-- | unittests/ADT/SmallSetTest.cpp | 149 | ||||
| -rw-r--r-- | unittests/ADT/SparseBitVectorTest.cpp | 2 | ||||
| -rw-r--r-- | unittests/ADT/StatisticTest.cpp | 160 | ||||
| -rw-r--r-- | unittests/ADT/StringExtrasTest.cpp | 25 | ||||
| -rw-r--r-- | unittests/ADT/StringMapTest.cpp | 44 | ||||
| -rw-r--r-- | unittests/ADT/StringRefTest.cpp | 23 | ||||
| -rw-r--r-- | unittests/ADT/StringSwitchTest.cpp | 6 | ||||
| -rw-r--r-- | unittests/ADT/TripleTest.cpp | 47 |
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&<>"'", 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()); |
