diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /unittests | |
parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) |
Notes
Diffstat (limited to 'unittests')
126 files changed, 8416 insertions, 1940 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index e57c8d4b931f..8f298cdfedb3 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -1173,11 +1173,11 @@ TEST(APFloatTest, exactInverse) { EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(8.5070592e+37f))); // Large float, inverse is a denormal. - EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(0)); + EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(nullptr)); // Zero - EXPECT_FALSE(APFloat(0.0).getExactInverse(0)); + EXPECT_FALSE(APFloat(0.0).getExactInverse(nullptr)); // Denormalized float - EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(0)); + EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(nullptr)); } TEST(APFloatTest, roundToIntegral) { @@ -1844,10 +1844,10 @@ TEST(APFloatTest, subtract) { { PInf, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity }, - { PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity }, @@ -1861,10 +1861,10 @@ TEST(APFloatTest, subtract) { { MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity }, - { MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity }, @@ -1878,10 +1878,10 @@ TEST(APFloatTest, subtract) { { PZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { PZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, - { PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, @@ -1895,10 +1895,10 @@ TEST(APFloatTest, subtract) { { MZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MZero, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero }, { MZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, - { MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, @@ -1946,10 +1946,10 @@ TEST(APFloatTest, subtract) { { PNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PNormalValue, PZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PNormalValue, MZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, - { PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { PNormalValue, MNormalValue, "0x1p+1", APFloat::opOK, APFloat::fcNormal }, @@ -1963,10 +1963,10 @@ TEST(APFloatTest, subtract) { { MNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MNormalValue, PZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MNormalValue, MZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, - { MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MNormalValue, PNormalValue, "-0x1p+1", APFloat::opOK, APFloat::fcNormal }, { MNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero }, @@ -1980,10 +1980,10 @@ TEST(APFloatTest, subtract) { { PLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PLargestValue, PZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { PLargestValue, MZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, - { PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { PLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, @@ -1997,10 +1997,10 @@ TEST(APFloatTest, subtract) { { MLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MLargestValue, PZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { MLargestValue, MZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, - { MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { MLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, @@ -2014,10 +2014,10 @@ TEST(APFloatTest, subtract) { { PSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PSmallestValue, PZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal }, { PSmallestValue, MZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal }, - { PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, @@ -2031,10 +2031,10 @@ TEST(APFloatTest, subtract) { { MSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MSmallestValue, PZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal }, { MSmallestValue, MZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal }, - { MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, @@ -2048,10 +2048,10 @@ TEST(APFloatTest, subtract) { { PSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PSmallestNormalized, PZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal }, { PSmallestNormalized, MZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal }, - { PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { PSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { PSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { PSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { PSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, @@ -2065,10 +2065,10 @@ TEST(APFloatTest, subtract) { { MSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MSmallestNormalized, PZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal }, { MSmallestNormalized, MZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal }, - { MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, + { MSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN }, #if 0 // See Note 1. - { MSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, + { MSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN }, #endif { MSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 3c0dfe144044..19c47ab13bf9 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -597,4 +597,85 @@ TEST(APIntTest, tcDecrement) { EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0); } } + +TEST(APIntTest, arrayAccess) { + // Single word check. + uint64_t E1 = 0x2CA7F46BF6569915ULL; + APInt A1(64, E1); + for (unsigned i = 0, e = 64; i < e; ++i) { + EXPECT_EQ(bool(E1 & (1ULL << i)), + A1[i]); + } + + // Multiword check. + integerPart E2[4] = { + 0xEB6EB136591CBA21ULL, + 0x7B9358BD6A33F10AULL, + 0x7E7FFA5EADD8846ULL, + 0x305F341CA00B613DULL + }; + APInt A2(integerPartWidth*4, ArrayRef<integerPart>(E2, 4)); + for (unsigned i = 0; i < 4; ++i) { + for (unsigned j = 0; j < integerPartWidth; ++j) { + EXPECT_EQ(bool(E2[i] & (1ULL << j)), + A2[i*integerPartWidth + j]); + } + } +} + +TEST(APIntTest, LargeAPIntConstruction) { + // Check that we can properly construct very large APInt. It is very + // unlikely that people will ever do this, but it is a legal input, + // so we should not crash on it. + APInt A9(UINT32_MAX, 0); + EXPECT_FALSE(A9.getBoolValue()); +} + +TEST(APIntTest, nearestLogBase2) { + // Single word check. + + // Test round up. + uint64_t I1 = 0x1800001; + APInt A1(64, I1); + EXPECT_EQ(A1.nearestLogBase2(), A1.ceilLogBase2()); + + // Test round down. + uint64_t I2 = 0x1000011; + APInt A2(64, I2); + EXPECT_EQ(A2.nearestLogBase2(), A2.logBase2()); + + // Test ties round up. + uint64_t I3 = 0x1800000; + APInt A3(64, I3); + EXPECT_EQ(A3.nearestLogBase2(), A3.ceilLogBase2()); + + // Multiple word check. + + // Test round up. + integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; + APInt A4(integerPartWidth*4, ArrayRef<integerPart>(I4, 4)); + EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); + + // Test round down. + integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; + APInt A5(integerPartWidth*4, ArrayRef<integerPart>(I5, 4)); + EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2()); + + // Test ties round up. + uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18}; + APInt A6(integerPartWidth*4, ArrayRef<integerPart>(I6, 4)); + EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2()); + + // Test BitWidth == 1 special cases. + APInt A7(1, 1); + EXPECT_EQ(A7.nearestLogBase2(), 0ULL); + APInt A8(1, 0); + EXPECT_EQ(A8.nearestLogBase2(), UINT32_MAX); + + // Test the zero case when we have a bit width large enough such + // that the bit width is larger than UINT32_MAX-1. + APInt A9(UINT32_MAX, 0); + EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX); +} + } diff --git a/unittests/ADT/APSIntTest.cpp b/unittests/ADT/APSIntTest.cpp new file mode 100644 index 000000000000..eef9c8a90af9 --- /dev/null +++ b/unittests/ADT/APSIntTest.cpp @@ -0,0 +1,44 @@ +//===- llvm/unittest/ADT/APSIntTest.cpp - APSInt 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/APSInt.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(APSIntTest, MoveTest) { + APSInt A(32, true); + EXPECT_TRUE(A.isUnsigned()); + + APSInt B(128, false); + A = B; + EXPECT_FALSE(A.isUnsigned()); + + APSInt C(B); + EXPECT_FALSE(C.isUnsigned()); + + APInt Wide(256, 0); + const uint64_t *Bits = Wide.getRawData(); + APSInt D(std::move(Wide)); + EXPECT_TRUE(D.isUnsigned()); + EXPECT_EQ(Bits, D.getRawData()); // Verify that "Wide" was really moved. + + A = APSInt(64, true); + EXPECT_TRUE(A.isUnsigned()); + + Wide = APInt(128, 1); + Bits = Wide.getRawData(); + A = std::move(Wide); + EXPECT_TRUE(A.isUnsigned()); + EXPECT_EQ(Bits, A.getRawData()); // Verify that "Wide" was really moved. +} + +} diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp new file mode 100644 index 000000000000..293afc6ea37d --- /dev/null +++ b/unittests/ADT/ArrayRefTest.cpp @@ -0,0 +1,40 @@ +//===- llvm/unittest/ADT/ArrayRefTest.cpp - ArrayRef 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/ArrayRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace llvm { + +TEST(ArrayRefTest, AllocatorCopy) { + BumpPtrAllocator Alloc; + static const uint16_t Words1[] = { 1, 4, 200, 37 }; + ArrayRef<uint16_t> Array1 = makeArrayRef(Words1, 4); + static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 }; + ArrayRef<uint16_t> Array2 = makeArrayRef(Words2, 5); + ArrayRef<uint16_t> Array1c = Array1.copy(Alloc); + ArrayRef<uint16_t> Array2c = Array2.copy(Alloc);; + EXPECT_TRUE(Array1.equals(Array1c)); + EXPECT_NE(Array1.data(), Array1c.data()); + EXPECT_TRUE(Array2.equals(Array2c)); + EXPECT_NE(Array2.data(), Array2c.data()); +} + +TEST(ArrayRefTest, DropBack) { + static const int TheNumbers[] = {4, 8, 15, 16, 23, 42}; + ArrayRef<int> AR1(TheNumbers); + ArrayRef<int> AR2(TheNumbers, AR1.size() - 1); + EXPECT_TRUE(AR1.drop_back().equals(AR2)); +} + + +} // end anonymous namespace diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp index d7cde891fb56..3deaff0fe356 100644 --- a/unittests/ADT/BitVectorTest.cpp +++ b/unittests/ADT/BitVectorTest.cpp @@ -356,6 +356,12 @@ TYPED_TEST(BitVectorTest, RangeOps) { EXPECT_TRUE( E.test(1)); EXPECT_TRUE( E.test(32)); EXPECT_FALSE(E.test(33)); + + TypeParam BufferOverrun; + unsigned size = sizeof(unsigned long) * 8; + BufferOverrun.resize(size); + BufferOverrun.reset(0, size); + BufferOverrun.set(0, size); } TYPED_TEST(BitVectorTest, CompoundTestReset) { diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 8ad303a9e1b3..0f214f3d0c80 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS set(ADTSources APFloatTest.cpp APIntTest.cpp + APSIntTest.cpp + ArrayRefTest.cpp BitVectorTest.cpp DAGDeltaAlgorithmTest.cpp DeltaAlgorithmTest.cpp @@ -18,9 +20,11 @@ set(ADTSources IntEqClassesTest.cpp IntervalMapTest.cpp IntrusiveRefCntPtrTest.cpp + MakeUniqueTest.cpp MapVectorTest.cpp OptionalTest.cpp PackedVectorTest.cpp + PointerIntPairTest.cpp PointerUnionTest.cpp SCCIteratorTest.cpp SmallPtrSetTest.cpp @@ -35,18 +39,8 @@ set(ADTSources TripleTest.cpp TwineTest.cpp VariadicFunctionTest.cpp - polymorphic_ptr_test.cpp ) -# They cannot be compiled on MSVC9 due to its bug. -if(MSVC AND MSVC_VERSION LESS 1600) - set(LLVM_OPTIONAL_SOURCES - DenseMapTest.cpp - SmallVectorTest.cpp - ) - list(REMOVE_ITEM ADTSources ${LLVM_OPTIONAL_SOURCES}) -endif() - add_llvm_unittest(ADTTests ${ADTSources} ) diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index 15eb6988f669..75a910a24cab 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -92,9 +92,9 @@ protected: }; template <typename T> -typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = 0; +typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = nullptr; template <typename T> -typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = 0; +typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = nullptr; // Register these types for testing. typedef ::testing::Types<DenseMap<uint32_t, uint32_t>, @@ -119,7 +119,7 @@ TYPED_TEST(DenseMapTest, EmptyIntMapTest) { // Lookup tests EXPECT_FALSE(this->Map.count(this->getKey())); EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end()); -#ifndef _MSC_VER +#if !defined(_MSC_VER) || defined(__clang__) EXPECT_EQ(typename TypeParam::mapped_type(), this->Map.lookup(this->getKey())); #else @@ -209,6 +209,34 @@ TYPED_TEST(DenseMapTest, CopyConstructorTest) { EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); } +// Test copy constructor method where SmallDenseMap isn't small. +TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) { + for (int Key = 0; Key < 5; ++Key) + this->Map[this->getKey(Key)] = this->getValue(Key); + TypeParam copyMap(this->Map); + + EXPECT_EQ(5u, copyMap.size()); + for (int Key = 0; Key < 5; ++Key) + EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]); +} + +// Test copying from a default-constructed map. +TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) { + TypeParam copyMap(this->Map); + + EXPECT_TRUE(copyMap.empty()); +} + +// Test copying from an empty map where SmallDenseMap isn't small. +TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) { + for (int Key = 0; Key < 5; ++Key) + this->Map[this->getKey(Key)] = this->getValue(Key); + this->Map.clear(); + TypeParam copyMap(this->Map); + + EXPECT_TRUE(copyMap.empty()); +} + // Test assignment operator method TYPED_TEST(DenseMapTest, AssignmentTest) { this->Map[this->getKey()] = this->getValue(); @@ -317,7 +345,7 @@ TEST(DenseMapCustomTest, FindAsTest) { EXPECT_EQ(3u, map.size()); // Normal lookup tests - EXPECT_EQ(1, map.count(1)); + EXPECT_EQ(1u, map.count(1)); EXPECT_EQ(1u, map.find(0)->second); EXPECT_EQ(2u, map.find(1)->second); EXPECT_EQ(3u, map.find(2)->second); diff --git a/unittests/ADT/DenseSetTest.cpp b/unittests/ADT/DenseSetTest.cpp index ada5f6db83af..154c5892d5fd 100644 --- a/unittests/ADT/DenseSetTest.cpp +++ b/unittests/ADT/DenseSetTest.cpp @@ -24,7 +24,7 @@ TEST_F(DenseSetTest, DoubleEntrySetTest) { set.insert(0); set.insert(1); // Original failure was an infinite loop in this call: - EXPECT_EQ(0, set.count(2)); + EXPECT_EQ(0u, set.count(2)); } } diff --git a/unittests/ADT/HashingTest.cpp b/unittests/ADT/HashingTest.cpp index 1b3d0617a5e3..acaa83cddddd 100644 --- a/unittests/ADT/HashingTest.cpp +++ b/unittests/ADT/HashingTest.cpp @@ -41,7 +41,7 @@ struct NonPOD { namespace hashing { namespace detail { -template <> struct is_hashable_data<LargeTestInteger> : true_type {}; +template <> struct is_hashable_data<LargeTestInteger> : std::true_type {}; } // namespace detail } // namespace hashing @@ -58,7 +58,7 @@ enum TestEnumeration { TEST(HashingTest, HashValueBasicTest) { int x = 42, y = 43, c = 'x'; - void *p = 0; + void *p = nullptr; uint64_t i = 71; const unsigned ci = 71; volatile int vi = 71; diff --git a/unittests/ADT/ImmutableMapTest.cpp b/unittests/ADT/ImmutableMapTest.cpp index 774581ca4eeb..6a99884bfbb3 100644 --- a/unittests/ADT/ImmutableMapTest.cpp +++ b/unittests/ADT/ImmutableMapTest.cpp @@ -36,8 +36,8 @@ TEST(ImmutableMapTest, MultiElemIntMapTest) { EXPECT_TRUE(S.isEmpty()); EXPECT_FALSE(S2.isEmpty()); - EXPECT_EQ(0, S.lookup(3)); - EXPECT_EQ(0, S.lookup(9)); + EXPECT_EQ(nullptr, S.lookup(3)); + EXPECT_EQ(nullptr, S.lookup(9)); EXPECT_EQ(10, *S2.lookup(3)); EXPECT_EQ(11, *S2.lookup(4)); diff --git a/unittests/ADT/MakeUniqueTest.cpp b/unittests/ADT/MakeUniqueTest.cpp new file mode 100644 index 000000000000..3b4938a2ef36 --- /dev/null +++ b/unittests/ADT/MakeUniqueTest.cpp @@ -0,0 +1,76 @@ +//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique 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/STLExtras.h" +#include "gtest/gtest.h" +#include <tuple> +using namespace llvm; + +namespace { + +TEST(MakeUniqueTest, SingleObject) { + auto p0 = make_unique<int>(); + EXPECT_TRUE((bool)p0); + EXPECT_EQ(0, *p0); + + auto p1 = make_unique<int>(5); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(5, *p1); + + auto p2 = make_unique<std::tuple<int, int>>(0, 1); + EXPECT_TRUE((bool)p2); + EXPECT_EQ(std::make_tuple(0, 1), *p2); + + auto p3 = make_unique<std::tuple<int, int, int>>(0, 1, 2); + EXPECT_TRUE((bool)p3); + EXPECT_EQ(std::make_tuple(0, 1, 2), *p3); + + auto p4 = make_unique<std::tuple<int, int, int, int>>(0, 1, 2, 3); + EXPECT_TRUE((bool)p4); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3), *p4); + + auto p5 = make_unique<std::tuple<int, int, int, int, int>>(0, 1, 2, 3, 4); + EXPECT_TRUE((bool)p5); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4), *p5); + + auto p6 = + make_unique<std::tuple<int, int, int, int, int, int>>(0, 1, 2, 3, 4, 5); + EXPECT_TRUE((bool)p6); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5), *p6); + + auto p7 = make_unique<std::tuple<int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6); + EXPECT_TRUE((bool)p7); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6), *p7); + + auto p8 = make_unique<std::tuple<int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7); + EXPECT_TRUE((bool)p8); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7), *p8); + + auto p9 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8); + EXPECT_TRUE((bool)p9); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8), *p9); + + auto p10 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + EXPECT_TRUE((bool)p10); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), *p10); +} + +TEST(MakeUniqueTest, Array) { + auto p1 = make_unique<int[]>(2); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(0, p1[0]); + EXPECT_EQ(0, p1[1]); +} +} diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp index 11178bc15e84..92f0dc41910b 100644 --- a/unittests/ADT/MapVectorTest.cpp +++ b/unittests/ADT/MapVectorTest.cpp @@ -53,3 +53,39 @@ TEST(MapVectorTest, insert_pop) { EXPECT_EQ(MV[1], 2); EXPECT_EQ(MV[4], 7); } + +TEST(MapVectorTest, erase) { + MapVector<int, int> MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); +} + +TEST(MapVectorTest, remove_if) { + MapVector<int, int> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 21e38475d309..2da408c15e0b 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,7 +169,6 @@ TEST_F(OptionalTest, NullCopyConstructionTest) { EXPECT_EQ(0u, NonDefaultConstructible::Destructions); } -#if LLVM_HAS_RVALUE_REFERENCES struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -278,7 +277,6 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { EXPECT_EQ(1u, MoveOnly::MoveAssignments); EXPECT_EQ(1u, MoveOnly::Destructions); } -#endif } // end anonymous namespace diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp new file mode 100644 index 000000000000..296d47590d78 --- /dev/null +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -0,0 +1,76 @@ +//===- llvm/unittest/ADT/PointerIntPairTest.cpp - Unit tests --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/PointerIntPair.h" +#include <limits> +using namespace llvm; + +namespace { + +// Test fixture +class PointerIntPairTest : public testing::Test { +}; + +TEST_F(PointerIntPairTest, GetSet) { + PointerIntPair<PointerIntPairTest *, 2> Pair(this, 1U); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(1U, Pair.getInt()); + + Pair.setInt(2); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(2U, Pair.getInt()); + + Pair.setPointer(nullptr); + EXPECT_EQ(nullptr, Pair.getPointer()); + EXPECT_EQ(2U, Pair.getInt()); + + Pair.setPointerAndInt(this, 3U); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(3U, Pair.getInt()); +} + +TEST_F(PointerIntPairTest, DefaultInitialize) { + PointerIntPair<PointerIntPairTest *, 2> Pair; + EXPECT_EQ(nullptr, Pair.getPointer()); + EXPECT_EQ(0U, Pair.getInt()); +} + +#if !(defined(_MSC_VER) && _MSC_VER==1700) +TEST_F(PointerIntPairTest, ManyUnusedBits) { + // In real code this would be a word-sized integer limited to 31 bits. + struct Fixnum31 { + uintptr_t Value; + }; + class FixnumPointerTraits { + public: + static inline void *getAsVoidPointer(Fixnum31 Num) { + return reinterpret_cast<void *>(Num.Value << NumLowBitsAvailable); + } + static inline Fixnum31 getFromVoidPointer(void *P) { + // In real code this would assert that the value is in range. + return { reinterpret_cast<uintptr_t>(P) >> NumLowBitsAvailable }; + } + enum { NumLowBitsAvailable = std::numeric_limits<uintptr_t>::digits - 31 }; + }; + + PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits> pair; + EXPECT_EQ((uintptr_t)0, pair.getPointer().Value); + EXPECT_FALSE(pair.getInt()); + + pair.setPointerAndInt({ 0x7FFFFFFF }, true ); + EXPECT_EQ((uintptr_t)0x7FFFFFFF, pair.getPointer().Value); + EXPECT_TRUE(pair.getInt()); + + EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1, + PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable); +} +#endif + +} // end anonymous namespace diff --git a/unittests/ADT/PointerUnionTest.cpp b/unittests/ADT/PointerUnionTest.cpp index 7eb718112d69..a592784ae095 100644 --- a/unittests/ADT/PointerUnionTest.cpp +++ b/unittests/ADT/PointerUnionTest.cpp @@ -13,22 +13,24 @@ using namespace llvm; namespace { -typedef PointerUnion<int*, float*> PU; +typedef PointerUnion<int *, float *> PU; -// Test fixture -class PointerUnionTest : public testing::Test { -}; +struct PointerUnionTest : public testing::Test { + float f; + int i; -float f = 3.14f; -int i = 42; + PU a, b, c, n; -const PU a(&f); -const PU b(&i); -const PU n; + PointerUnionTest() : f(3.14f), i(42), a(&f), b(&i), c(&i), n() {} +}; TEST_F(PointerUnionTest, Comparison) { + EXPECT_TRUE(a == a); + EXPECT_FALSE(a != a); EXPECT_TRUE(a != b); EXPECT_FALSE(a == b); + EXPECT_TRUE(b == c); + EXPECT_FALSE(b != c); EXPECT_TRUE(b != n); EXPECT_FALSE(b == n); } @@ -44,21 +46,27 @@ TEST_F(PointerUnionTest, Null) { EXPECT_TRUE((bool)a); EXPECT_TRUE((bool)b); EXPECT_FALSE(n); + + EXPECT_NE(n, b); + EXPECT_EQ(b, c); + b = nullptr; + EXPECT_EQ(n, b); + EXPECT_NE(b, c); } TEST_F(PointerUnionTest, Is) { - EXPECT_FALSE(a.is<int*>()); - EXPECT_TRUE(a.is<float*>()); - EXPECT_TRUE(b.is<int*>()); - EXPECT_FALSE(b.is<float*>()); - EXPECT_TRUE(n.is<int*>()); - EXPECT_FALSE(n.is<float*>()); + EXPECT_FALSE(a.is<int *>()); + EXPECT_TRUE(a.is<float *>()); + EXPECT_TRUE(b.is<int *>()); + EXPECT_FALSE(b.is<float *>()); + EXPECT_TRUE(n.is<int *>()); + EXPECT_FALSE(n.is<float *>()); } TEST_F(PointerUnionTest, Get) { - EXPECT_EQ(a.get<float*>(), &f); - EXPECT_EQ(b.get<int*>(), &i); - EXPECT_EQ(n.get<int*>(), (int*)0); + EXPECT_EQ(a.get<float *>(), &f); + EXPECT_EQ(b.get<int *>(), &i); + EXPECT_EQ(n.get<int *>(), (int *)nullptr); } } // end anonymous namespace diff --git a/unittests/ADT/SCCIteratorTest.cpp b/unittests/ADT/SCCIteratorTest.cpp index 92b4b317cfbd..3f1ba1c5843f 100644 --- a/unittests/ADT/SCCIteratorTest.cpp +++ b/unittests/ADT/SCCIteratorTest.cpp @@ -213,7 +213,7 @@ public: // Return a pointer to it. return FirstNode + i; assert(false && "Dereferencing end iterator!"); - return 0; // Avoid compiler warning. + return nullptr; // Avoid compiler warning. } }; @@ -277,7 +277,7 @@ TEST(SCCIteratorTest, AllSmallGraphs) { GT::NodeSubset NodesInSomeSCC; for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) { - std::vector<GT::NodeType*> &SCC = *I; + const std::vector<GT::NodeType *> &SCC = *I; // Get the nodes in this SCC as a NodeSubset rather than a vector. GT::NodeSubset NodesInThisSCC; diff --git a/unittests/ADT/SmallPtrSetTest.cpp b/unittests/ADT/SmallPtrSetTest.cpp index f85d7c941ebd..fdd1cbb60040 100644 --- a/unittests/ADT/SmallPtrSetTest.cpp +++ b/unittests/ADT/SmallPtrSetTest.cpp @@ -16,7 +16,30 @@ using namespace llvm; -// SmallPtrSet swapping test. +TEST(SmallPtrSetTest, Assignment) { + int buf[8]; + for (int i = 0; i < 8; ++i) + buf[i] = 0; + + SmallPtrSet<int *, 4> s1; + s1.insert(&buf[0]); + s1.insert(&buf[1]); + + SmallPtrSet<int *, 4> s2; + (s2 = s1).insert(&buf[2]); + + // Self assign as well. + (s2 = s2).insert(&buf[3]); + + s1 = s2; + EXPECT_EQ(4U, s1.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); +} + TEST(SmallPtrSetTest, GrowthTest) { int i; int buf[8]; @@ -71,6 +94,68 @@ TEST(SmallPtrSetTest, GrowthTest) { EXPECT_EQ(1,buf[i]); } +TEST(SmallPtrSetTest, CopyAndMoveTest) { + int buf[8]; + for (int i = 0; i < 8; ++i) + buf[i] = 0; + + SmallPtrSet<int *, 4> s1; + s1.insert(&buf[0]); + s1.insert(&buf[1]); + s1.insert(&buf[2]); + s1.insert(&buf[3]); + EXPECT_EQ(4U, s1.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); + + SmallPtrSet<int *, 4> s2(s1); + EXPECT_EQ(4U, s2.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s2.count(&buf[i])); + else + EXPECT_FALSE(s2.count(&buf[i])); + + s1 = s2; + EXPECT_EQ(4U, s1.size()); + EXPECT_EQ(4U, s2.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); + + SmallPtrSet<int *, 4> s3(std::move(s1)); + EXPECT_EQ(4U, s3.size()); + EXPECT_TRUE(s1.empty()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s3.count(&buf[i])); + else + EXPECT_FALSE(s3.count(&buf[i])); + + // Move assign into the moved-from object. Also test move of a non-small + // container. + s3.insert(&buf[4]); + s3.insert(&buf[5]); + s3.insert(&buf[6]); + s3.insert(&buf[7]); + s1 = std::move(s3); + EXPECT_EQ(8U, s1.size()); + EXPECT_TRUE(s3.empty()); + for (int i = 0; i < 8; ++i) + EXPECT_TRUE(s1.count(&buf[i])); + + // Copy assign into a moved-from object. + s3 = s1; + EXPECT_EQ(8U, s3.size()); + EXPECT_EQ(8U, s1.size()); + for (int i = 0; i < 8; ++i) + EXPECT_TRUE(s3.count(&buf[i])); +} TEST(SmallPtrSetTest, SwapTest) { int buf[10]; diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp index 90c7982699a7..95bf33e5bfba 100644 --- a/unittests/ADT/SmallVectorTest.cpp +++ b/unittests/ADT/SmallVectorTest.cpp @@ -26,32 +26,56 @@ namespace { class Constructable { private: static int numConstructorCalls; + static int numMoveConstructorCalls; + static int numCopyConstructorCalls; static int numDestructorCalls; static int numAssignmentCalls; + static int numMoveAssignmentCalls; + static int numCopyAssignmentCalls; + bool constructed; int value; public: - Constructable() : value(0) { + Constructable() : constructed(true), value(0) { ++numConstructorCalls; } - Constructable(int val) : value(val) { + Constructable(int val) : constructed(true), value(val) { ++numConstructorCalls; } - Constructable(const Constructable & src) { + Constructable(const Constructable & src) : constructed(true) { value = src.value; ++numConstructorCalls; + ++numCopyConstructorCalls; + } + + Constructable(Constructable && src) : constructed(true) { + value = src.value; + ++numConstructorCalls; + ++numMoveConstructorCalls; } ~Constructable() { + EXPECT_TRUE(constructed); ++numDestructorCalls; + constructed = false; } Constructable & operator=(const Constructable & src) { + EXPECT_TRUE(constructed); value = src.value; ++numAssignmentCalls; + ++numCopyAssignmentCalls; + return *this; + } + + Constructable & operator=(Constructable && src) { + EXPECT_TRUE(constructed); + value = src.value; + ++numAssignmentCalls; + ++numMoveAssignmentCalls; return *this; } @@ -61,18 +85,42 @@ public: static void reset() { numConstructorCalls = 0; + numMoveConstructorCalls = 0; + numCopyConstructorCalls = 0; numDestructorCalls = 0; numAssignmentCalls = 0; + numMoveAssignmentCalls = 0; + numCopyAssignmentCalls = 0; } static int getNumConstructorCalls() { return numConstructorCalls; } + static int getNumMoveConstructorCalls() { + return numMoveConstructorCalls; + } + + static int getNumCopyConstructorCalls() { + return numCopyConstructorCalls; + } + static int getNumDestructorCalls() { return numDestructorCalls; } + static int getNumAssignmentCalls() { + return numAssignmentCalls; + } + + static int getNumMoveAssignmentCalls() { + return numMoveAssignmentCalls; + } + + static int getNumCopyAssignmentCalls() { + return numCopyAssignmentCalls; + } + friend bool operator==(const Constructable & c0, const Constructable & c1) { return c0.getValue() == c1.getValue(); } @@ -84,8 +132,26 @@ public: }; int Constructable::numConstructorCalls; +int Constructable::numCopyConstructorCalls; +int Constructable::numMoveConstructorCalls; int Constructable::numDestructorCalls; int Constructable::numAssignmentCalls; +int Constructable::numCopyAssignmentCalls; +int Constructable::numMoveAssignmentCalls; + +struct NonCopyable { + NonCopyable() {} + NonCopyable(NonCopyable &&) {} + NonCopyable &operator=(NonCopyable &&) { return *this; } +private: + NonCopyable(const NonCopyable &) LLVM_DELETED_FUNCTION; + NonCopyable &operator=(const NonCopyable &) LLVM_DELETED_FUNCTION; +}; + +LLVM_ATTRIBUTE_USED void CompileTest() { + SmallVector<NonCopyable, 0> V; + V.resize(42); +} // Test fixture class template <typename VectorT> @@ -132,7 +198,8 @@ protected: typedef ::testing::Types<SmallVector<Constructable, 0>, SmallVector<Constructable, 1>, SmallVector<Constructable, 2>, - SmallVector<Constructable, 4> + SmallVector<Constructable, 4>, + SmallVector<Constructable, 5> > SmallVectorTestTypes; TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes); @@ -224,13 +291,26 @@ TYPED_TEST(SmallVectorTest, ResizeGrowTest) { this->theVector.resize(2); - // The extra constructor/destructor calls come from the temporary object used - // to initialize the contents of the resized array (via copy construction). - EXPECT_EQ(3, Constructable::getNumConstructorCalls()); - EXPECT_EQ(1, Constructable::getNumDestructorCalls()); + EXPECT_EQ(2, Constructable::getNumConstructorCalls()); + EXPECT_EQ(0, Constructable::getNumDestructorCalls()); EXPECT_EQ(2u, this->theVector.size()); } +TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) { + this->theVector.resize(2); + + Constructable::reset(); + + this->theVector.resize(4); + + size_t Ctors = Constructable::getNumConstructorCalls(); + EXPECT_TRUE(Ctors == 2 || Ctors == 4); + size_t MoveCtors = Constructable::getNumMoveConstructorCalls(); + EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2); + size_t Dtors = Constructable::getNumDestructorCalls(); + EXPECT_TRUE(Dtors == 0 || Dtors == 2); +} + // Resize with fill value. TYPED_TEST(SmallVectorTest, ResizeFillTest) { SCOPED_TRACE("ResizeFillTest"); @@ -338,6 +418,36 @@ TYPED_TEST(SmallVectorTest, AssignTest) { this->assertValuesInOrder(this->theVector, 2u, 77, 77); } +// Move-assign test +TYPED_TEST(SmallVectorTest, MoveAssignTest) { + SCOPED_TRACE("MoveAssignTest"); + + // Set up our vector with a single element, but enough capacity for 4. + this->theVector.reserve(4); + this->theVector.push_back(Constructable(1)); + + // Set up the other vector with 2 elements. + this->otherVector.push_back(Constructable(2)); + this->otherVector.push_back(Constructable(3)); + + // Move-assign from the other vector. + this->theVector = std::move(this->otherVector); + + // Make sure we have the right result. + this->assertValuesInOrder(this->theVector, 2u, 2, 3); + + // Make sure the # of constructor/destructor calls line up. There + // are two live objects after clearing the other vector. + this->otherVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls()-2, + Constructable::getNumDestructorCalls()); + + // There shouldn't be any live objects any more. + this->theVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls(), + Constructable::getNumDestructorCalls()); +} + // Erase a single element TYPED_TEST(SmallVectorTest, EraseTest) { SCOPED_TRACE("EraseTest"); @@ -367,22 +477,67 @@ TYPED_TEST(SmallVectorTest, InsertTest) { this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); } +// Insert a copy of a single element. +TYPED_TEST(SmallVectorTest, InsertCopy) { + SCOPED_TRACE("InsertTest"); + + this->makeSequence(this->theVector, 1, 3); + Constructable C(77); + typename TypeParam::iterator I = + this->theVector.insert(this->theVector.begin() + 1, C); + EXPECT_EQ(this->theVector.begin() + 1, I); + this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); +} + // Insert repeated elements. TYPED_TEST(SmallVectorTest, InsertRepeatedTest) { SCOPED_TRACE("InsertRepeatedTest"); - this->makeSequence(this->theVector, 10, 15); - typename TypeParam::iterator I = - this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16)); + this->makeSequence(this->theVector, 1, 4); + Constructable::reset(); + auto I = + this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16)); + // Move construct the top element into newly allocated space, and optionally + // reallocate the whole buffer, move constructing into it. + // FIXME: This is inefficient, we shouldn't move things into newly allocated + // space, then move them up/around, there should only be 2 or 4 move + // constructions here. + EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || + Constructable::getNumMoveConstructorCalls() == 6); + // Move assign the next two to shift them up and make a gap. + EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls()); + // Copy construct the two new elements from the parameter. + EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); + // All without any copy construction. + EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls()); EXPECT_EQ(this->theVector.begin() + 1, I); - this->assertValuesInOrder(this->theVector, 8u, - 10, 16, 16, 11, 12, 13, 14, 15); + this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4); +} - // Insert at end. - I = this->theVector.insert(this->theVector.end(), 2, Constructable(16)); - EXPECT_EQ(this->theVector.begin() + 8, I); - this->assertValuesInOrder(this->theVector, 10u, - 10, 16, 16, 11, 12, 13, 14, 15, 16, 16); + +TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) { + SCOPED_TRACE("InsertRepeatedTest"); + + this->makeSequence(this->theVector, 1, 4); + Constructable::reset(); + auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16)); + // Just copy construct them into newly allocated space + EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls()); + // Move everything across if reallocation is needed. + EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || + Constructable::getNumMoveConstructorCalls() == 4); + // Without ever moving or copying anything else. + EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); + EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); + + EXPECT_EQ(this->theVector.begin() + 4, I); + this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16); +} + +TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) { + SCOPED_TRACE("InsertRepeatedTest"); + + this->makeSequence(this->theVector, 10, 15); // Empty insert. EXPECT_EQ(this->theVector.end(), @@ -401,16 +556,53 @@ TYPED_TEST(SmallVectorTest, InsertRangeTest) { { Constructable(77), Constructable(77), Constructable(77) }; this->makeSequence(this->theVector, 1, 3); - typename TypeParam::iterator I = - this->theVector.insert(this->theVector.begin() + 1, Arr, Arr+3); + Constructable::reset(); + auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3); + // Move construct the top 3 elements into newly allocated space. + // Possibly move the whole sequence into new space first. + // FIXME: This is inefficient, we shouldn't move things into newly allocated + // space, then move them up/around, there should only be 2 or 3 move + // constructions here. + EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || + Constructable::getNumMoveConstructorCalls() == 5); + // Copy assign the lower 2 new elements into existing space. + EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); + // Copy construct the third element into newly allocated space. + EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls()); EXPECT_EQ(this->theVector.begin() + 1, I); this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3); +} + + +TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) { + SCOPED_TRACE("InsertRangeTest"); + + Constructable Arr[3] = + { Constructable(77), Constructable(77), Constructable(77) }; + + this->makeSequence(this->theVector, 1, 3); // Insert at end. - I = this->theVector.insert(this->theVector.end(), Arr, Arr+3); - EXPECT_EQ(this->theVector.begin() + 6, I); - this->assertValuesInOrder(this->theVector, 9u, - 1, 77, 77, 77, 2, 3, 77, 77, 77); + Constructable::reset(); + auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3); + // Copy construct the 3 elements into new space at the top. + EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls()); + // Don't copy/move anything else. + EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); + // Reallocation might occur, causing all elements to be moved into the new + // buffer. + EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || + Constructable::getNumMoveConstructorCalls() == 3); + EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); + EXPECT_EQ(this->theVector.begin() + 3, I); + this->assertValuesInOrder(this->theVector, 6u, + 1, 2, 3, 77, 77, 77); +} + +TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) { + SCOPED_TRACE("InsertRangeTest"); + + this->makeSequence(this->theVector, 1, 3); // Empty insert. EXPECT_EQ(this->theVector.end(), @@ -455,13 +647,12 @@ TYPED_TEST(SmallVectorTest, DirectVectorTest) { this->theVector.reserve(4); EXPECT_LE(4u, this->theVector.capacity()); EXPECT_EQ(0, Constructable::getNumConstructorCalls()); - this->theVector.end()[0] = 1; - this->theVector.end()[1] = 2; - this->theVector.end()[2] = 3; - this->theVector.end()[3] = 4; - this->theVector.set_size(4); + this->theVector.push_back(1); + this->theVector.push_back(2); + this->theVector.push_back(3); + this->theVector.push_back(4); EXPECT_EQ(4u, this->theVector.size()); - EXPECT_EQ(4, Constructable::getNumConstructorCalls()); + EXPECT_EQ(8, Constructable::getNumConstructorCalls()); EXPECT_EQ(1, this->theVector[0].getValue()); EXPECT_EQ(2, this->theVector[1].getValue()); EXPECT_EQ(3, this->theVector[2].getValue()); @@ -486,4 +677,26 @@ TEST(SmallVectorCustomTest, NoAssignTest) { EXPECT_EQ(42, vec.pop_back_val().x); } +struct MovedFrom { + bool hasValue; + MovedFrom() : hasValue(true) { + } + MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) { + m.hasValue = false; + } + MovedFrom &operator=(MovedFrom&& m) { + hasValue = m.hasValue; + m.hasValue = false; + return *this; + } +}; + +TEST(SmallVectorTest, MidInsert) { + SmallVector<MovedFrom, 3> v; + v.push_back(MovedFrom()); + v.insert(v.begin(), MovedFrom()); + for (MovedFrom &m : v) + EXPECT_TRUE(m.hasValue); +} + } diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 5bb65cbd7aa3..028375d7b4be 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -10,6 +10,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/DataTypes.h" +#include <tuple> using namespace llvm; namespace { @@ -183,28 +184,11 @@ TEST_F(StringMapTest, IterationTest) { } } -} // end anonymous namespace - -namespace llvm { - -template <> -class StringMapEntryInitializer<uint32_t> { -public: - template <typename InitTy> - static void Initialize(StringMapEntry<uint32_t> &T, InitTy InitVal) { - T.second = InitVal; - } -}; - -} // end llvm namespace - -namespace { - // Test StringMapEntry::Create() method. TEST_F(StringMapTest, StringMapEntryTest) { StringMap<uint32_t>::value_type* entry = StringMap<uint32_t>::value_type::Create( - testKeyFirst, testKeyFirst + testKeyLength, 1u); + StringRef(testKeyFirst, testKeyLength), 1u); EXPECT_STREQ(testKey, entry->first().data()); EXPECT_EQ(1u, entry->second); free(entry); @@ -215,9 +199,149 @@ TEST_F(StringMapTest, InsertTest) { SCOPED_TRACE("InsertTest"); testMap.insert( StringMap<uint32_t>::value_type::Create( - testKeyFirst, testKeyFirst + testKeyLength, + StringRef(testKeyFirst, testKeyLength), testMap.getAllocator(), 1u)); assertSingleItemMap(); } +// Test insert(pair<K, V>) method +TEST_F(StringMapTest, InsertPairTest) { + bool Inserted; + StringMap<uint32_t>::iterator NewIt; + std::tie(NewIt, Inserted) = + testMap.insert(std::make_pair(testKeyFirst, testValue)); + EXPECT_EQ(1u, testMap.size()); + EXPECT_EQ(testValue, testMap[testKeyFirst]); + EXPECT_EQ(testKeyFirst, NewIt->first()); + EXPECT_EQ(testValue, NewIt->second); + EXPECT_TRUE(Inserted); + + StringMap<uint32_t>::iterator ExistingIt; + std::tie(ExistingIt, Inserted) = + testMap.insert(std::make_pair(testKeyFirst, testValue + 1)); + EXPECT_EQ(1u, testMap.size()); + EXPECT_EQ(testValue, testMap[testKeyFirst]); + EXPECT_FALSE(Inserted); + EXPECT_EQ(NewIt, ExistingIt); +} + +// Test insert(pair<K, V>) method when rehashing occurs +TEST_F(StringMapTest, InsertRehashingPairTest) { + // Check that the correct iterator is returned when the inserted element is + // moved to a different bucket during internal rehashing. This depends on + // the particular key, and the implementation of StringMap and HashString. + // Changes to those might result in this test not actually checking that. + StringMap<uint32_t> t(1); + EXPECT_EQ(1u, t.getNumBuckets()); + + StringMap<uint32_t>::iterator It = + t.insert(std::make_pair("abcdef", 42)).first; + EXPECT_EQ(2u, t.getNumBuckets()); + EXPECT_EQ("abcdef", It->first()); + EXPECT_EQ(42u, It->second); +} + +// Create a non-default constructable value +struct StringMapTestStruct { + StringMapTestStruct(int i) : i(i) {} + StringMapTestStruct() LLVM_DELETED_FUNCTION; + int i; +}; + +TEST_F(StringMapTest, NonDefaultConstructable) { + StringMap<StringMapTestStruct> t; + t.GetOrCreateValue("Test", StringMapTestStruct(123)); + StringMap<StringMapTestStruct>::iterator iter = t.find("Test"); + ASSERT_NE(iter, t.end()); + ASSERT_EQ(iter->second.i, 123); +} + +struct MoveOnly { + int i; + MoveOnly(int i) : i(i) {} + MoveOnly(MoveOnly &&RHS) : i(RHS.i) {} + MoveOnly &operator=(MoveOnly &&RHS) { + i = RHS.i; + return *this; + } + +private: + MoveOnly(const MoveOnly &) LLVM_DELETED_FUNCTION; + MoveOnly &operator=(const MoveOnly &) LLVM_DELETED_FUNCTION; +}; + +TEST_F(StringMapTest, MoveOnlyKey) { + StringMap<MoveOnly> t; + t.GetOrCreateValue("Test", MoveOnly(42)); + StringRef Key = "Test"; + StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42)) + ->Destroy(); +} + +TEST_F(StringMapTest, MoveConstruct) { + StringMap<int> A; + A.GetOrCreateValue("x", 42); + StringMap<int> B = std::move(A); + ASSERT_EQ(A.size(), 0u); + ASSERT_EQ(B.size(), 1u); + ASSERT_EQ(B["x"], 42); + ASSERT_EQ(B.count("y"), 0u); +} + +TEST_F(StringMapTest, MoveAssignment) { + StringMap<int> A; + A["x"] = 42; + StringMap<int> B; + B["y"] = 117; + A = std::move(B); + ASSERT_EQ(A.size(), 1u); + ASSERT_EQ(B.size(), 0u); + ASSERT_EQ(A["y"], 117); + ASSERT_EQ(B.count("x"), 0u); +} + +struct Countable { + int &InstanceCount; + int Number; + Countable(int Number, int &InstanceCount) + : InstanceCount(InstanceCount), Number(Number) { + ++InstanceCount; + } + Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) { + ++InstanceCount; + C.Number = -1; + } + Countable(const Countable &C) + : InstanceCount(C.InstanceCount), Number(C.Number) { + ++InstanceCount; + } + Countable &operator=(Countable C) { + Number = C.Number; + return *this; + } + ~Countable() { --InstanceCount; } +}; + +TEST_F(StringMapTest, MoveDtor) { + int InstanceCount = 0; + StringMap<Countable> A; + A.GetOrCreateValue("x", Countable(42, InstanceCount)); + ASSERT_EQ(InstanceCount, 1); + auto I = A.find("x"); + ASSERT_NE(I, A.end()); + ASSERT_EQ(I->second.Number, 42); + + StringMap<Countable> B; + B = std::move(A); + ASSERT_EQ(InstanceCount, 1); + ASSERT_TRUE(A.empty()); + I = B.find("x"); + ASSERT_NE(I, B.end()); + ASSERT_EQ(I->second.Number, 42); + + B = StringMap<Countable>(); + ASSERT_EQ(InstanceCount, 0); + ASSERT_TRUE(B.empty()); +} + } // end anonymous namespace diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index 88691ae19749..d80179bd7873 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -8,9 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -531,4 +533,18 @@ TEST(StringRefTest, joinStrings) { EXPECT_TRUE(v2_join3); } + +TEST(StringRefTest, AllocatorCopy) { + BumpPtrAllocator Alloc; + StringRef Str1 = "hello"; + StringRef Str2 = "bye"; + StringRef Str1c = Str1.copy(Alloc); + StringRef Str2c = Str2.copy(Alloc); + EXPECT_TRUE(Str1.equals(Str1c)); + EXPECT_NE(Str1.data(), Str1c.data()); + EXPECT_TRUE(Str2.equals(Str2c)); + EXPECT_NE(Str2.data(), Str2c.data()); +} + + } // end anonymous namespace diff --git a/unittests/ADT/TinyPtrVectorTest.cpp b/unittests/ADT/TinyPtrVectorTest.cpp index a4f92ffbe383..ec868d4258a2 100644 --- a/unittests/ADT/TinyPtrVectorTest.cpp +++ b/unittests/ADT/TinyPtrVectorTest.cpp @@ -36,7 +36,7 @@ template <typename VectorT> class TinyPtrVectorTest : public testing::Test { protected: typedef typename VectorT::value_type PtrT; - typedef typename remove_pointer<PtrT>::type ValueT; + typedef typename std::remove_pointer<PtrT>::type ValueT; VectorT V; VectorT V2; @@ -72,9 +72,9 @@ protected: EXPECT_EQ(Values.size(), V.size()); for (size_t i = 0, e = Values.size(); i != e; ++i) { EXPECT_EQ(Values[i], V[i]); - EXPECT_EQ(Values[i], *llvm::next(V.begin(), i)); + EXPECT_EQ(Values[i], *std::next(V.begin(), i)); } - EXPECT_EQ(V.end(), llvm::next(V.begin(), Values.size())); + EXPECT_EQ(V.end(), std::next(V.begin(), Values.size())); } }; @@ -157,170 +157,136 @@ TYPED_TEST(TinyPtrVectorTest, CopyAndMoveCtorTest) { this->expectValues(Copy2, this->testArray(42)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES TypeParam Move(std::move(Copy2)); this->expectValues(Move, this->testArray(42)); this->expectValues(Copy2, this->testArray(0)); -#endif } TYPED_TEST(TinyPtrVectorTest, CopyAndMoveTest) { this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(1), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(2), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(42), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(0), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(0), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(0), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(1), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(1), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(1), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(2), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(2), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(2), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(42), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(42), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(42), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif } TYPED_TEST(TinyPtrVectorTest, EraseTest) { @@ -334,17 +300,17 @@ TYPED_TEST(TinyPtrVectorTest, EraseTest) { this->V.erase(this->V.begin()); this->TestPtrs.erase(this->TestPtrs.begin()); this->expectValues(this->V, this->testArray(41)); - this->V.erase(llvm::next(this->V.begin(), 1)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1)); + this->V.erase(std::next(this->V.begin(), 1)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1)); this->expectValues(this->V, this->testArray(40)); - this->V.erase(llvm::next(this->V.begin(), 2)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2)); + this->V.erase(std::next(this->V.begin(), 2)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(39)); - this->V.erase(llvm::next(this->V.begin(), 5)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5)); + this->V.erase(std::next(this->V.begin(), 5)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5)); this->expectValues(this->V, this->testArray(38)); - this->V.erase(llvm::next(this->V.begin(), 13)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13)); + this->V.erase(std::next(this->V.begin(), 13)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13)); this->expectValues(this->V, this->testArray(37)); typename TypeParam::iterator I = this->V.begin(); @@ -366,27 +332,27 @@ TYPED_TEST(TinyPtrVectorTest, EraseRangeTest) { this->appendValues(this->V, this->testArray(42)); this->expectValues(this->V, this->testArray(42)); - this->V.erase(this->V.begin(), llvm::next(this->V.begin(), 1)); + this->V.erase(this->V.begin(), std::next(this->V.begin(), 1)); this->TestPtrs.erase(this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 1)); + std::next(this->TestPtrs.begin(), 1)); this->expectValues(this->V, this->testArray(41)); - this->V.erase(llvm::next(this->V.begin(), 1), llvm::next(this->V.begin(), 2)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1), - llvm::next(this->TestPtrs.begin(), 2)); + this->V.erase(std::next(this->V.begin(), 1), std::next(this->V.begin(), 2)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1), + std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(40)); - this->V.erase(llvm::next(this->V.begin(), 2), llvm::next(this->V.begin(), 4)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2), - llvm::next(this->TestPtrs.begin(), 4)); + this->V.erase(std::next(this->V.begin(), 2), std::next(this->V.begin(), 4)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2), + std::next(this->TestPtrs.begin(), 4)); this->expectValues(this->V, this->testArray(38)); - this->V.erase(llvm::next(this->V.begin(), 5), llvm::next(this->V.begin(), 10)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5), - llvm::next(this->TestPtrs.begin(), 10)); + this->V.erase(std::next(this->V.begin(), 5), std::next(this->V.begin(), 10)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5), + std::next(this->TestPtrs.begin(), 10)); this->expectValues(this->V, this->testArray(33)); - this->V.erase(llvm::next(this->V.begin(), 13), llvm::next(this->V.begin(), 26)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13), - llvm::next(this->TestPtrs.begin(), 26)); + this->V.erase(std::next(this->V.begin(), 13), std::next(this->V.begin(), 26)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13), + std::next(this->TestPtrs.begin(), 26)); this->expectValues(this->V, this->testArray(20)); - this->V.erase(llvm::next(this->V.begin(), 7), this->V.end()); + this->V.erase(std::next(this->V.begin(), 7), this->V.end()); this->expectValues(this->V, this->testArray(7)); this->V.erase(this->V.begin(), this->V.end()); this->expectValues(this->V, this->testArray(0)); @@ -403,8 +369,8 @@ TYPED_TEST(TinyPtrVectorTest, Insert) { this->V.insert(this->V.begin(), this->TestPtrs[42]); this->TestPtrs.insert(this->TestPtrs.begin(), this->TestPtrs[42]); this->expectValues(this->V, this->testArray(6)); - this->V.insert(llvm::next(this->V.begin(), 3), this->TestPtrs[43]); - this->TestPtrs.insert(llvm::next(this->TestPtrs.begin(), 3), + this->V.insert(std::next(this->V.begin(), 3), this->TestPtrs[43]); + this->TestPtrs.insert(std::next(this->TestPtrs.begin(), 3), this->TestPtrs[43]); this->expectValues(this->V, this->testArray(7)); } @@ -418,30 +384,30 @@ TYPED_TEST(TinyPtrVectorTest, InsertRange) { this->V.insert(this->V.end(), this->TestPtrs.end(), this->TestPtrs.end()); this->expectValues(this->V, this->testArray(0)); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin())); + std::next(this->TestPtrs.begin())); this->expectValues(this->V, this->testArray(1)); this->V.clear(); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 2)); + std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(2)); this->V.clear(); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 42)); + std::next(this->TestPtrs.begin(), 42)); this->expectValues(this->V, this->testArray(42)); this->V.clear(); this->V.insert(this->V.end(), - llvm::next(this->TestPtrs.begin(), 5), - llvm::next(this->TestPtrs.begin(), 13)); + std::next(this->TestPtrs.begin(), 5), + std::next(this->TestPtrs.begin(), 13)); this->V.insert(this->V.begin(), - llvm::next(this->TestPtrs.begin(), 0), - llvm::next(this->TestPtrs.begin(), 3)); - this->V.insert(llvm::next(this->V.begin(), 2), - llvm::next(this->TestPtrs.begin(), 2), - llvm::next(this->TestPtrs.begin(), 4)); - this->V.erase(llvm::next(this->V.begin(), 4)); - this->V.insert(llvm::next(this->V.begin(), 4), - llvm::next(this->TestPtrs.begin(), 4), - llvm::next(this->TestPtrs.begin(), 5)); + std::next(this->TestPtrs.begin(), 0), + std::next(this->TestPtrs.begin(), 3)); + this->V.insert(std::next(this->V.begin(), 2), + std::next(this->TestPtrs.begin(), 2), + std::next(this->TestPtrs.begin(), 4)); + this->V.erase(std::next(this->V.begin(), 4)); + this->V.insert(std::next(this->V.begin(), 4), + std::next(this->TestPtrs.begin(), 4), + std::next(this->TestPtrs.begin(), 5)); this->expectValues(this->V, this->testArray(13)); } diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index b4028963908c..dfc99837d4bc 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -190,6 +190,9 @@ TEST(TripleTest, Normalization) { ++Vendor) { C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor)); for (int OS = 1+Triple::UnknownOS; OS <= Triple::Minix; ++OS) { + if (OS == Triple::Cygwin || OS == Triple::MinGW32 || OS == Triple::Win32) + continue; + C[2] = Triple::getOSTypeName(Triple::OSType(OS)); std::string E = Join(C[0], C[1], C[2]); @@ -201,7 +204,7 @@ TEST(TripleTest, Normalization) { EXPECT_EQ(E, Triple::normalize(Join(C[2], C[0], C[1]))); EXPECT_EQ(E, Triple::normalize(Join(C[2], C[1], C[0]))); - for (int Env = 1+Triple::UnknownEnvironment; Env <= Triple::MachO; + for (int Env = 1 + Triple::UnknownEnvironment; Env <= Triple::Android; ++Env) { C[3] = Triple::getEnvironmentTypeName(Triple::EnvironmentType(Env)); @@ -238,7 +241,7 @@ TEST(TripleTest, Normalization) { // Various real-world funky triples. The value returned by GCC's config.sub // is given in the comment. - EXPECT_EQ("i386--mingw32", Triple::normalize("i386-mingw32")); // i386-pc-mingw32 + EXPECT_EQ("i386--windows-gnu", Triple::normalize("i386-mingw32")); // i386-pc-mingw32 EXPECT_EQ("x86_64--linux-gnu", Triple::normalize("x86_64-linux-gnu")); // x86_64-pc-linux-gnu EXPECT_EQ("i486--linux-gnu", Triple::normalize("i486-linux-gnu")); // i486-pc-linux-gnu EXPECT_EQ("i386-redhat-linux", Triple::normalize("i386-redhat-linux")); // i386-redhat-linux-gnu @@ -349,10 +352,6 @@ TEST(TripleTest, BitWidthArchVariants) { EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); - T.setArch(Triple::arm); - EXPECT_EQ(Triple::arm, T.get32BitArchVariant().getArch()); - EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); - T.setArch(Triple::mips); EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch()); @@ -417,7 +416,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)5, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -432,7 +431,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)5, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -447,7 +446,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -462,7 +461,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)7, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -477,11 +476,11 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); - T = Triple("armv7-apple-ios5.0"); + T = Triple("armv7-apple-ios7.0"); EXPECT_FALSE(T.isMacOSX()); EXPECT_TRUE(T.isiOS()); EXPECT_FALSE(T.isArch16Bit()); @@ -492,9 +491,89 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)5, Major); + EXPECT_EQ((unsigned)7, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); } +TEST(TripleTest, FileFormat) { + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-linux-gnu").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-freebsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-netbsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686--win32-elf").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686---elf").getObjectFormat()); + + EXPECT_EQ(Triple::MachO, Triple("i686-apple-macosx").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686-apple-ios").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686---macho").getObjectFormat()); + + EXPECT_EQ(Triple::COFF, Triple("i686--win32").getObjectFormat()); + + EXPECT_EQ(Triple::ELF, Triple("i686-pc-windows-msvc-elf").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-pc-cygwin-elf").getObjectFormat()); + + Triple MSVCNormalized(Triple::normalize("i686-pc-windows-msvc-elf")); + EXPECT_EQ(Triple::ELF, MSVCNormalized.getObjectFormat()); + + Triple GNUWindowsNormalized(Triple::normalize("i686-pc-windows-gnu-elf")); + EXPECT_EQ(Triple::ELF, GNUWindowsNormalized.getObjectFormat()); + + Triple CygnusNormalised(Triple::normalize("i686-pc-windows-cygnus-elf")); + EXPECT_EQ(Triple::ELF, CygnusNormalised.getObjectFormat()); + + Triple CygwinNormalized(Triple::normalize("i686-pc-cygwin-elf")); + EXPECT_EQ(Triple::ELF, CygwinNormalized.getObjectFormat()); + + Triple T = Triple(""); + T.setObjectFormat(Triple::ELF); + EXPECT_EQ(Triple::ELF, T.getObjectFormat()); +} + +TEST(TripleTest, NormalizeWindows) { + EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-win32")); + EXPECT_EQ("i686--windows-msvc", Triple::normalize("i686-win32")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32")); + EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32-w64")); + EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32-w64")); + EXPECT_EQ("i686-pc-windows-cygnus", Triple::normalize("i686-pc-cygwin")); + EXPECT_EQ("i686--windows-cygnus", Triple::normalize("i686-cygwin")); + + EXPECT_EQ("x86_64-pc-windows-msvc", Triple::normalize("x86_64-pc-win32")); + EXPECT_EQ("x86_64--windows-msvc", Triple::normalize("x86_64-win32")); + EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32")); + EXPECT_EQ("x86_64--windows-gnu", Triple::normalize("x86_64-mingw32")); + EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32-w64")); + EXPECT_EQ("x86_64--windows-gnu", Triple::normalize("x86_64-mingw32-w64")); + + EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-win32-elf")); + EXPECT_EQ("i686--windows-elf", Triple::normalize("i686-win32-elf")); + EXPECT_EQ("i686-pc-windows-macho", Triple::normalize("i686-pc-win32-macho")); + EXPECT_EQ("i686--windows-macho", Triple::normalize("i686-win32-macho")); + + EXPECT_EQ("x86_64-pc-windows-elf", Triple::normalize("x86_64-pc-win32-elf")); + EXPECT_EQ("x86_64--windows-elf", Triple::normalize("x86_64-win32-elf")); + EXPECT_EQ("x86_64-pc-windows-macho", Triple::normalize("x86_64-pc-win32-macho")); + EXPECT_EQ("x86_64--windows-macho", Triple::normalize("x86_64-win32-macho")); + + EXPECT_EQ("i686-pc-windows-cygnus", + Triple::normalize("i686-pc-windows-cygnus")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-windows-gnu")); + EXPECT_EQ("i686-pc-windows-itanium", Triple::normalize("i686-pc-windows-itanium")); + EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-windows-msvc")); + + EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-windows-elf-elf")); +} + +TEST(TripleTest, getARMCPUForArch) { + { + llvm::Triple Triple("armv7s-apple-ios7"); + EXPECT_STREQ("swift", Triple.getARMCPUForArch()); + } + { + llvm::Triple Triple("armv7-apple-ios7"); + EXPECT_STREQ("cortex-a8", Triple.getARMCPUForArch()); + EXPECT_STREQ("swift", Triple.getARMCPUForArch("armv7s")); + } +} } diff --git a/unittests/ADT/ilistTest.cpp b/unittests/ADT/ilistTest.cpp index 0c0cd0fd56fe..44442ebf75ad 100644 --- a/unittests/ADT/ilistTest.cpp +++ b/unittests/ADT/ilistTest.cpp @@ -29,8 +29,8 @@ TEST(ilistTest, Basic) { ilist<Node> List; List.push_back(Node(1)); EXPECT_EQ(1, List.back().Value); - EXPECT_EQ(0, List.back().getPrevNode()); - EXPECT_EQ(0, List.back().getNextNode()); + EXPECT_EQ(nullptr, List.back().getPrevNode()); + EXPECT_EQ(nullptr, List.back().getNextNode()); List.push_back(Node(2)); EXPECT_EQ(2, List.back().Value); @@ -51,15 +51,15 @@ TEST(ilistTest, SpliceOne) { List.splice(List.begin(), List, List.begin()); EXPECT_EQ(1u, List.size()); EXPECT_EQ(1, List.front().Value); - EXPECT_TRUE(llvm::next(List.begin()) == List.end()); + EXPECT_TRUE(std::next(List.begin()) == List.end()); // Altenative noop. Move the first element behind itself. List.push_back(2); List.push_back(3); - List.splice(llvm::next(List.begin()), List, List.begin()); + List.splice(std::next(List.begin()), List, List.begin()); EXPECT_EQ(3u, List.size()); EXPECT_EQ(1, List.front().Value); - EXPECT_EQ(2, llvm::next(List.begin())->Value); + EXPECT_EQ(2, std::next(List.begin())->Value); EXPECT_EQ(3, List.back().Value); } diff --git a/unittests/ADT/polymorphic_ptr_test.cpp b/unittests/ADT/polymorphic_ptr_test.cpp deleted file mode 100644 index bd5d83879a83..000000000000 --- a/unittests/ADT/polymorphic_ptr_test.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//===- llvm/unittest/ADT/polymorphic_ptr.h - polymorphic_ptr<T> tests -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "gtest/gtest.h" -#include "llvm/ADT/polymorphic_ptr.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -namespace { - -struct S { - S(int x) : x(x) {} - S *clone() { return new S(*this); } - int x; -}; - -// A function that forces the return of a copy. -template <typename T> -T dummy_copy(const T &arg) { return arg; } - -TEST(polymorphic_ptr_test, Basic) { - polymorphic_ptr<S> null; - EXPECT_FALSE((bool)null); - EXPECT_TRUE(!null); - EXPECT_EQ((S*)0, null.get()); - - S *s = new S(42); - polymorphic_ptr<S> p(s); - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_TRUE(p != null); - EXPECT_FALSE(p == null); - EXPECT_TRUE(p == s); - EXPECT_TRUE(s == p); - EXPECT_FALSE(p != s); - EXPECT_FALSE(s != p); - EXPECT_EQ(s, &*p); - EXPECT_EQ(s, p.operator->()); - EXPECT_EQ(s, p.get()); - EXPECT_EQ(42, p->x); - - EXPECT_EQ(s, p.take()); - EXPECT_FALSE((bool)p); - EXPECT_TRUE(!p); - p = s; - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_EQ(s, &*p); - EXPECT_EQ(s, p.operator->()); - EXPECT_EQ(s, p.get()); - EXPECT_EQ(42, p->x); - - polymorphic_ptr<S> p2((llvm_move(p))); -#if !LLVM_HAS_RVALUE_REFERENCES - // 'p' may not have been moved from in C++98, fake it for the test. - p2 = p.take(); -#endif - EXPECT_FALSE((bool)p); - EXPECT_TRUE(!p); - EXPECT_TRUE((bool)p2); - EXPECT_FALSE(!p2); - EXPECT_EQ(s, &*p2); - - using std::swap; - swap(p, p2); - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_EQ(s, &*p); - EXPECT_FALSE((bool)p2); - EXPECT_TRUE(!p2); - - // Force copies and that everything survives. - polymorphic_ptr<S> p3 = dummy_copy(polymorphic_ptr<S>(p)); - EXPECT_TRUE((bool)p3); - EXPECT_FALSE(!p3); - EXPECT_NE(s, &*p3); - EXPECT_EQ(42, p3->x); - - // Force copies of null without trying to dereference anything. - polymorphic_ptr<S> null_copy = dummy_copy(polymorphic_ptr<S>(null)); - EXPECT_FALSE((bool)null_copy); - EXPECT_TRUE(!null_copy); - EXPECT_EQ(null, null_copy); -} - -struct Base { - virtual ~Base() {} - virtual Base *clone() = 0; - virtual StringRef name() { return "Base"; } -}; - -struct DerivedA : Base { - virtual DerivedA *clone() { return new DerivedA(); } - virtual StringRef name() { return "DerivedA"; } -}; -struct DerivedB : Base { - virtual DerivedB *clone() { return new DerivedB(); } - virtual StringRef name() { return "DerivedB"; } -}; - -TEST(polymorphic_ptr_test, Polymorphism) { - polymorphic_ptr<Base> a(new DerivedA()); - polymorphic_ptr<Base> b(new DerivedB()); - - EXPECT_EQ("DerivedA", a->name()); - EXPECT_EQ("DerivedB", b->name()); - - polymorphic_ptr<Base> copy = dummy_copy(a); - EXPECT_NE(a, copy); - EXPECT_EQ("DerivedA", copy->name()); - - copy = dummy_copy(b); - EXPECT_NE(b, copy); - EXPECT_EQ("DerivedB", copy->name()); - - // Test creating a copy out of a temporary directly. - copy = dummy_copy<polymorphic_ptr<Base> >(new DerivedA()); - EXPECT_NE(a, copy); - EXPECT_EQ("DerivedA", copy->name()); -} - -} diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index e931709620f3..ac5e71061d8a 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -8,18 +8,17 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CFG.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/IR/LLVMContext.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/InstIterator.h" -#include "llvm/Support/SourceMgr.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -47,10 +46,10 @@ protected: } Function *F = M->getFunction("test"); - if (F == NULL) + if (F == nullptr) report_fatal_error("Test must have a function named @test"); - A = B = NULL; + A = B = nullptr; for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { if (I->hasName()) { if (I->getName() == "A") @@ -59,9 +58,9 @@ protected: B = &*I; } } - if (A == NULL) + if (A == nullptr) report_fatal_error("@test must have an instruction %A"); - if (B == NULL) + if (B == nullptr) report_fatal_error("@test must have an instruction %B"); } @@ -75,17 +74,18 @@ protected: static int initialize() { PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass", - "", &ID, 0, true, true); + "", &ID, nullptr, true, true); PassRegistry::getPassRegistry()->registerPass(*PI, false); initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - initializeDominatorTreePass(*PassRegistry::getPassRegistry()); + initializeDominatorTreeWrapperPassPass( + *PassRegistry::getPassRegistry()); return 0; } void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired<LoopInfo>(); - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); } bool runOnFunction(Function &F) { @@ -93,10 +93,12 @@ protected: return false; LoopInfo *LI = &getAnalysis<LoopInfo>(); - DominatorTree *DT = &getAnalysis<DominatorTree>(); - EXPECT_EQ(isPotentiallyReachable(A, B, 0, 0), ExpectedResult); - EXPECT_EQ(isPotentiallyReachable(A, B, DT, 0), ExpectedResult); - EXPECT_EQ(isPotentiallyReachable(A, B, 0, LI), ExpectedResult); + DominatorTree *DT = + &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr), + ExpectedResult); + EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult); + EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult); EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult); return false; } @@ -113,8 +115,8 @@ protected: PM.add(P); PM.run(*M); } -private: - OwningPtr<Module> M; + + std::unique_ptr<Module> M; Instruction *A, *B; }; @@ -350,27 +352,40 @@ TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) { ExpectPath(true); } +static const char *BranchInsideLoopIR = + "declare i1 @switch()\n" + "\n" + "define void @test() {\n" + "entry:\n" + " br label %loop\n" + "loop:\n" + " %x = call i1 @switch()\n" + " br i1 %x, label %nextloopblock, label %exit\n" + "nextloopblock:\n" + " %y = call i1 @switch()\n" + " br i1 %y, label %left, label %right\n" + "left:\n" + " %A = bitcast i8 undef to i8\n" + " br label %loop\n" + "right:\n" + " %B = bitcast i8 undef to i8\n" + " br label %loop\n" + "exit:\n" + " ret void\n" + "}"; + TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) { - ParseAssembly( - "declare i1 @switch()\n" - "\n" - "define void @test() {\n" - "entry:\n" - " br label %loop\n" - "loop:\n" - " %x = call i1 @switch()\n" - " br i1 %x, label %nextloopblock, label %exit\n" - "nextloopblock:\n" - " %y = call i1 @switch()\n" - " br i1 %y, label %left, label %right\n" - "left:\n" - " %A = bitcast i8 undef to i8\n" - " br label %loop\n" - "right:\n" - " %B = bitcast i8 undef to i8\n" - " br label %loop\n" - "exit:\n" - " ret void\n" - "}"); + ParseAssembly(BranchInsideLoopIR); + ExpectPath(true); +} + +TEST_F(IsPotentiallyReachableTest, ModifyTest) { + ParseAssembly(BranchInsideLoopIR); + + succ_iterator S = succ_begin(++M->getFunction("test")->begin()); + BasicBlock *OldBB = S[0]; + S[0] = S[1]; + ExpectPath(false); + S[0] = OldBB; ExpectPath(true); } diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 7e5b35852749..84548609edea 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -1,9 +1,13 @@ set(LLVM_LINK_COMPONENTS Analysis AsmParser + Core + Support ) add_llvm_unittest(AnalysisTests CFGTest.cpp + LazyCallGraphTest.cpp ScalarEvolutionTest.cpp + MixedTBAATest.cpp ) diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp new file mode 100644 index 000000000000..d7c70453c9b0 --- /dev/null +++ b/unittests/Analysis/LazyCallGraphTest.cpp @@ -0,0 +1,720 @@ +//===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" +#include <memory> + +using namespace llvm; + +namespace { + +std::unique_ptr<Module> parseAssembly(const char *Assembly) { + auto M = make_unique<Module>("Module", getGlobalContext()); + + SMDiagnostic Error; + bool Parsed = + ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); + + std::string ErrMsg; + raw_string_ostream OS(ErrMsg); + Error.print("", OS); + + // A failure here means that the test itself is buggy. + if (!Parsed) + report_fatal_error(OS.str().c_str()); + + return M; +} + +// IR forming a call graph with a diamond of triangle-shaped SCCs: +// +// d1 +// / \ +// d3--d2 +// / \ +// b1 c1 +// / \ / \ +// b3--b2 c3--c2 +// \ / +// a1 +// / \ +// a3--a2 +// +// All call edges go up between SCCs, and clockwise around the SCC. +static const char DiamondOfTriangles[] = + "define void @a1() {\n" + "entry:\n" + " call void @a2()\n" + " call void @b2()\n" + " call void @c3()\n" + " ret void\n" + "}\n" + "define void @a2() {\n" + "entry:\n" + " call void @a3()\n" + " ret void\n" + "}\n" + "define void @a3() {\n" + "entry:\n" + " call void @a1()\n" + " ret void\n" + "}\n" + "define void @b1() {\n" + "entry:\n" + " call void @b2()\n" + " call void @d3()\n" + " ret void\n" + "}\n" + "define void @b2() {\n" + "entry:\n" + " call void @b3()\n" + " ret void\n" + "}\n" + "define void @b3() {\n" + "entry:\n" + " call void @b1()\n" + " ret void\n" + "}\n" + "define void @c1() {\n" + "entry:\n" + " call void @c2()\n" + " call void @d2()\n" + " ret void\n" + "}\n" + "define void @c2() {\n" + "entry:\n" + " call void @c3()\n" + " ret void\n" + "}\n" + "define void @c3() {\n" + "entry:\n" + " call void @c1()\n" + " ret void\n" + "}\n" + "define void @d1() {\n" + "entry:\n" + " call void @d2()\n" + " ret void\n" + "}\n" + "define void @d2() {\n" + "entry:\n" + " call void @d3()\n" + " ret void\n" + "}\n" + "define void @d3() {\n" + "entry:\n" + " call void @d1()\n" + " ret void\n" + "}\n"; + +TEST(LazyCallGraphTest, BasicGraphFormation) { + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // The order of the entry nodes should be stable w.r.t. the source order of + // the IR, and everything in our module is an entry node, so just directly + // build variables for each node. + auto I = CG.begin(); + LazyCallGraph::Node &A1 = *I++; + EXPECT_EQ("a1", A1.getFunction().getName()); + LazyCallGraph::Node &A2 = *I++; + EXPECT_EQ("a2", A2.getFunction().getName()); + LazyCallGraph::Node &A3 = *I++; + EXPECT_EQ("a3", A3.getFunction().getName()); + LazyCallGraph::Node &B1 = *I++; + EXPECT_EQ("b1", B1.getFunction().getName()); + LazyCallGraph::Node &B2 = *I++; + EXPECT_EQ("b2", B2.getFunction().getName()); + LazyCallGraph::Node &B3 = *I++; + EXPECT_EQ("b3", B3.getFunction().getName()); + LazyCallGraph::Node &C1 = *I++; + EXPECT_EQ("c1", C1.getFunction().getName()); + LazyCallGraph::Node &C2 = *I++; + EXPECT_EQ("c2", C2.getFunction().getName()); + LazyCallGraph::Node &C3 = *I++; + EXPECT_EQ("c3", C3.getFunction().getName()); + LazyCallGraph::Node &D1 = *I++; + EXPECT_EQ("d1", D1.getFunction().getName()); + LazyCallGraph::Node &D2 = *I++; + EXPECT_EQ("d2", D2.getFunction().getName()); + LazyCallGraph::Node &D3 = *I++; + EXPECT_EQ("d3", D3.getFunction().getName()); + EXPECT_EQ(CG.end(), I); + + // Build vectors and sort them for the rest of the assertions to make them + // independent of order. + std::vector<std::string> Nodes; + + for (LazyCallGraph::Node &N : A1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("a2", Nodes[0]); + EXPECT_EQ("b2", Nodes[1]); + EXPECT_EQ("c3", Nodes[2]); + Nodes.clear(); + + EXPECT_EQ(A2.end(), std::next(A2.begin())); + EXPECT_EQ("a3", A2.begin()->getFunction().getName()); + EXPECT_EQ(A3.end(), std::next(A3.begin())); + EXPECT_EQ("a1", A3.begin()->getFunction().getName()); + + for (LazyCallGraph::Node &N : B1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("b2", Nodes[0]); + EXPECT_EQ("d3", Nodes[1]); + Nodes.clear(); + + EXPECT_EQ(B2.end(), std::next(B2.begin())); + EXPECT_EQ("b3", B2.begin()->getFunction().getName()); + EXPECT_EQ(B3.end(), std::next(B3.begin())); + EXPECT_EQ("b1", B3.begin()->getFunction().getName()); + + for (LazyCallGraph::Node &N : C1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("c2", Nodes[0]); + EXPECT_EQ("d2", Nodes[1]); + Nodes.clear(); + + EXPECT_EQ(C2.end(), std::next(C2.begin())); + EXPECT_EQ("c3", C2.begin()->getFunction().getName()); + EXPECT_EQ(C3.end(), std::next(C3.begin())); + EXPECT_EQ("c1", C3.begin()->getFunction().getName()); + + EXPECT_EQ(D1.end(), std::next(D1.begin())); + EXPECT_EQ("d2", D1.begin()->getFunction().getName()); + EXPECT_EQ(D2.end(), std::next(D2.begin())); + EXPECT_EQ("d3", D2.begin()->getFunction().getName()); + EXPECT_EQ(D3.end(), std::next(D3.begin())); + EXPECT_EQ("d1", D3.begin()->getFunction().getName()); + + // Now lets look at the SCCs. + auto SCCI = CG.postorder_scc_begin(); + + LazyCallGraph::SCC &D = *SCCI++; + for (LazyCallGraph::Node *N : D) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("d1", Nodes[0]); + EXPECT_EQ("d2", Nodes[1]); + EXPECT_EQ("d3", Nodes[2]); + Nodes.clear(); + EXPECT_FALSE(D.isParentOf(D)); + EXPECT_FALSE(D.isChildOf(D)); + EXPECT_FALSE(D.isAncestorOf(D)); + EXPECT_FALSE(D.isDescendantOf(D)); + + LazyCallGraph::SCC &C = *SCCI++; + for (LazyCallGraph::Node *N : C) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("c1", Nodes[0]); + EXPECT_EQ("c2", Nodes[1]); + EXPECT_EQ("c3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(C.isParentOf(D)); + EXPECT_FALSE(C.isChildOf(D)); + EXPECT_TRUE(C.isAncestorOf(D)); + EXPECT_FALSE(C.isDescendantOf(D)); + + LazyCallGraph::SCC &B = *SCCI++; + for (LazyCallGraph::Node *N : B) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("b1", Nodes[0]); + EXPECT_EQ("b2", Nodes[1]); + EXPECT_EQ("b3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(B.isParentOf(D)); + EXPECT_FALSE(B.isChildOf(D)); + EXPECT_TRUE(B.isAncestorOf(D)); + EXPECT_FALSE(B.isDescendantOf(D)); + EXPECT_FALSE(B.isAncestorOf(C)); + EXPECT_FALSE(C.isAncestorOf(B)); + + LazyCallGraph::SCC &A = *SCCI++; + for (LazyCallGraph::Node *N : A) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("a1", Nodes[0]); + EXPECT_EQ("a2", Nodes[1]); + EXPECT_EQ("a3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(A.isParentOf(B)); + EXPECT_TRUE(A.isParentOf(C)); + EXPECT_FALSE(A.isParentOf(D)); + EXPECT_TRUE(A.isAncestorOf(B)); + EXPECT_TRUE(A.isAncestorOf(C)); + EXPECT_TRUE(A.isAncestorOf(D)); + + EXPECT_EQ(CG.postorder_scc_end(), SCCI); +} + +static Function &lookupFunction(Module &M, StringRef Name) { + for (Function &F : M) + if (F.getName() == Name) + return F; + report_fatal_error("Couldn't find function!"); +} + +TEST(LazyCallGraphTest, BasicGraphMutation) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b")); + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + EXPECT_EQ(0, std::distance(B.begin(), B.end())); + + CG.insertEdge(B, lookupFunction(*M, "c")); + EXPECT_EQ(1, std::distance(B.begin(), B.end())); + LazyCallGraph::Node &C = *B.begin(); + EXPECT_EQ(0, std::distance(C.begin(), C.end())); + + CG.insertEdge(C, B.getFunction()); + EXPECT_EQ(1, std::distance(C.begin(), C.end())); + EXPECT_EQ(&B, &*C.begin()); + + CG.insertEdge(C, C.getFunction()); + EXPECT_EQ(2, std::distance(C.begin(), C.end())); + EXPECT_EQ(&B, &*C.begin()); + EXPECT_EQ(&C, &*std::next(C.begin())); + + CG.removeEdge(C, B.getFunction()); + EXPECT_EQ(1, std::distance(C.begin(), C.end())); + EXPECT_EQ(&C, &*C.begin()); + + CG.removeEdge(C, C.getFunction()); + EXPECT_EQ(0, std::distance(C.begin(), C.end())); + + CG.removeEdge(B, C.getFunction()); + EXPECT_EQ(0, std::distance(B.begin(), B.end())); +} + +TEST(LazyCallGraphTest, MultiArmSCC) { + // Two interlocking cycles. The really useful thing about this SCC is that it + // will require Tarjan's DFS to backtrack and finish processing all of the + // children of each node in the SCC. + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n" + "define void @d() {\n" + "entry:\n" + " call void @e()\n" + " ret void\n" + "}\n" + "define void @e() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + auto SCCI = CG.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c")); + LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d")); + LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e")); + EXPECT_EQ(&SCC, CG.lookupSCC(A)); + EXPECT_EQ(&SCC, CG.lookupSCC(B)); + EXPECT_EQ(&SCC, CG.lookupSCC(C)); + EXPECT_EQ(&SCC, CG.lookupSCC(D)); + EXPECT_EQ(&SCC, CG.lookupSCC(E)); +} + +TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @d() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c")); + LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B); + LazyCallGraph::SCC &CC = *CG.lookupSCC(C); + LazyCallGraph::SCC &DC = *CG.lookupSCC(D); + EXPECT_TRUE(AC.isAncestorOf(BC)); + EXPECT_TRUE(AC.isAncestorOf(CC)); + EXPECT_TRUE(AC.isAncestorOf(DC)); + EXPECT_TRUE(DC.isDescendantOf(AC)); + EXPECT_TRUE(DC.isDescendantOf(BC)); + EXPECT_TRUE(DC.isDescendantOf(CC)); + + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + AC.insertOutgoingEdge(A, D); + EXPECT_EQ(3, std::distance(A.begin(), A.end())); + EXPECT_TRUE(AC.isParentOf(DC)); + EXPECT_EQ(&AC, CG.lookupSCC(A)); + EXPECT_EQ(&BC, CG.lookupSCC(B)); + EXPECT_EQ(&CC, CG.lookupSCC(C)); + EXPECT_EQ(&DC, CG.lookupSCC(D)); +} + +TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) { + // We want to ensure we can add edges even across complex diamond graphs, so + // we use the diamond of triangles graph defined above. The ascii diagram is + // repeated here for easy reference. + // + // d1 | + // / \ | + // d3--d2 | + // / \ | + // b1 c1 | + // / \ / \ | + // b3--b2 c3--c2 | + // \ / | + // a1 | + // / \ | + // a3--a2 | + // + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1")); + LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2")); + LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3")); + LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1")); + LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2")); + LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3")); + LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1")); + LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2")); + LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3")); + LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1")); + LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2")); + LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A1); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B1); + LazyCallGraph::SCC &CC = *CG.lookupSCC(C1); + LazyCallGraph::SCC &DC = *CG.lookupSCC(D1); + ASSERT_EQ(&AC, CG.lookupSCC(A2)); + ASSERT_EQ(&AC, CG.lookupSCC(A3)); + ASSERT_EQ(&BC, CG.lookupSCC(B2)); + ASSERT_EQ(&BC, CG.lookupSCC(B3)); + ASSERT_EQ(&CC, CG.lookupSCC(C2)); + ASSERT_EQ(&CC, CG.lookupSCC(C3)); + ASSERT_EQ(&DC, CG.lookupSCC(D2)); + ASSERT_EQ(&DC, CG.lookupSCC(D3)); + ASSERT_EQ(1, std::distance(D2.begin(), D2.end())); + + // Add an edge to make the graph: + // + // d1 | + // / \ | + // d3--d2---. | + // / \ | | + // b1 c1 | | + // / \ / \ / | + // b3--b2 c3--c2 | + // \ / | + // a1 | + // / \ | + // a3--a2 | + CC.insertIncomingEdge(D2, C2); + // Make sure we connected the nodes. + EXPECT_EQ(2, std::distance(D2.begin(), D2.end())); + + // Make sure we have the correct nodes in the SCC sets. + EXPECT_EQ(&AC, CG.lookupSCC(A1)); + EXPECT_EQ(&AC, CG.lookupSCC(A2)); + EXPECT_EQ(&AC, CG.lookupSCC(A3)); + EXPECT_EQ(&BC, CG.lookupSCC(B1)); + EXPECT_EQ(&BC, CG.lookupSCC(B2)); + EXPECT_EQ(&BC, CG.lookupSCC(B3)); + EXPECT_EQ(&CC, CG.lookupSCC(C1)); + EXPECT_EQ(&CC, CG.lookupSCC(C2)); + EXPECT_EQ(&CC, CG.lookupSCC(C3)); + EXPECT_EQ(&CC, CG.lookupSCC(D1)); + EXPECT_EQ(&CC, CG.lookupSCC(D2)); + EXPECT_EQ(&CC, CG.lookupSCC(D3)); + + // And that ancestry tests have been updated. + EXPECT_TRUE(AC.isParentOf(BC)); + EXPECT_TRUE(AC.isParentOf(CC)); + EXPECT_FALSE(AC.isAncestorOf(DC)); + EXPECT_FALSE(BC.isAncestorOf(DC)); + EXPECT_FALSE(CC.isAncestorOf(DC)); +} + +TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) { + // This is the same fundamental test as the previous, but we perform it + // having only partially walked the SCCs of the graph. + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // Walk the SCCs until we find the one containing 'c1'. + auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end(); + ASSERT_NE(SCCI, SCCE); + LazyCallGraph::SCC &DC = *SCCI; + ASSERT_NE(&DC, nullptr); + ++SCCI; + ASSERT_NE(SCCI, SCCE); + LazyCallGraph::SCC &CC = *SCCI; + ASSERT_NE(&CC, nullptr); + + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3"))); + LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1")); + LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2")); + LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3")); + LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1")); + LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2")); + LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3")); + ASSERT_EQ(&CC, CG.lookupSCC(C1)); + ASSERT_EQ(&CC, CG.lookupSCC(C2)); + ASSERT_EQ(&CC, CG.lookupSCC(C3)); + ASSERT_EQ(&DC, CG.lookupSCC(D1)); + ASSERT_EQ(&DC, CG.lookupSCC(D2)); + ASSERT_EQ(&DC, CG.lookupSCC(D3)); + ASSERT_EQ(1, std::distance(D2.begin(), D2.end())); + + CC.insertIncomingEdge(D2, C2); + EXPECT_EQ(2, std::distance(D2.begin(), D2.end())); + + // Make sure we have the correct nodes in the SCC sets. + EXPECT_EQ(&CC, CG.lookupSCC(C1)); + EXPECT_EQ(&CC, CG.lookupSCC(C2)); + EXPECT_EQ(&CC, CG.lookupSCC(C3)); + EXPECT_EQ(&CC, CG.lookupSCC(D1)); + EXPECT_EQ(&CC, CG.lookupSCC(D2)); + EXPECT_EQ(&CC, CG.lookupSCC(D3)); + + // Check that we can form the last two SCCs now in a coherent way. + ++SCCI; + EXPECT_NE(SCCI, SCCE); + LazyCallGraph::SCC &BC = *SCCI; + EXPECT_NE(&BC, nullptr); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1")))); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2")))); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3")))); + ++SCCI; + EXPECT_NE(SCCI, SCCE); + LazyCallGraph::SCC &AC = *SCCI; + EXPECT_NE(&AC, nullptr); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1")))); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2")))); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3")))); + ++SCCI; + EXPECT_EQ(SCCI, SCCE); +} + +TEST(LazyCallGraphTest, InterSCCEdgeRemoval) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B); + + EXPECT_EQ("b", A.begin()->getFunction().getName()); + EXPECT_EQ(B.end(), B.begin()); + EXPECT_EQ(&AC, &*BC.parent_begin()); + + AC.removeInterSCCEdge(A, B); + + EXPECT_EQ(A.end(), A.begin()); + EXPECT_EQ(B.end(), B.begin()); + EXPECT_EQ(BC.parent_end(), BC.parent_begin()); +} + +TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) { + std::unique_ptr<Module> M1 = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG1(*M1); + + // Force the graph to be fully expanded. + auto SCCI = CG1.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG1.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a")); + LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b")); + LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c")); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs. + SCC.insertIntraSCCEdge(A, C); + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Insert a self edge from 'a' back to 'a'. + SCC.insertIntraSCCEdge(A, A); + EXPECT_EQ(3, std::distance(A.begin(), A.end())); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); +} + +TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) { + // A nice fully connected (including self-edges) SCC. + std::unique_ptr<Module> M1 = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG1(*M1); + + // Force the graph to be fully expanded. + auto SCCI = CG1.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG1.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a")); + LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b")); + LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c")); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Remove the edge from b -> a, which should leave the 3 functions still in + // a single connected component because of a -> b -> c -> a. + SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A); + EXPECT_EQ(0u, NewSCCs.size()); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Remove the edge from c -> a, which should leave 'a' in the original SCC + // and form a new SCC for 'b' and 'c'. + NewSCCs = SCC.removeIntraSCCEdge(C, A); + EXPECT_EQ(1u, NewSCCs.size()); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end())); + LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B); + EXPECT_EQ(SCC2, CG1.lookupSCC(C)); + EXPECT_EQ(SCC2, NewSCCs[0]); +} + +} diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp new file mode 100644 index 000000000000..142e04789d43 --- /dev/null +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -0,0 +1,77 @@ +//===--- MixedTBAATest.cpp - Mixed TBAA 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/Analysis/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +class MixedTBAATest : public testing::Test { +protected: + MixedTBAATest() : M("MixedTBAATest", C), MD(C) {} + + LLVMContext C; + Module M; + MDBuilder MD; + PassManager PM; +}; + +TEST_F(MixedTBAATest, MixedTBAA) { + // Setup function. + FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), + std::vector<Type *>(), false); + auto *F = cast<Function>(M.getOrInsertFunction("f", FTy)); + auto *BB = BasicBlock::Create(C, "entry", F); + auto IntType = Type::getInt32Ty(C); + auto PtrType = Type::getInt32PtrTy(C); + auto *Value = ConstantInt::get(IntType, 42); + auto *Addr = ConstantPointerNull::get(PtrType); + + auto *Store1 = new StoreInst(Value, Addr, BB); + auto *Store2 = new StoreInst(Value, Addr, BB); + ReturnInst::Create(C, nullptr, BB); + + // New TBAA metadata + { + auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA"); + auto MD1 = MD.createTBAAScalarTypeNode("omnipotent char", RootMD); + auto MD2 = MD.createTBAAScalarTypeNode("int", MD1); + auto MD3 = MD.createTBAAStructTagNode(MD2, MD2, 0); + Store2->setMetadata(LLVMContext::MD_tbaa, MD3); + } + + // Old TBAA metadata + { + auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA"); + auto MD1 = MD.createTBAANode("omnipotent char", RootMD); + auto MD2 = MD.createTBAANode("int", MD1); + Store1->setMetadata(LLVMContext::MD_tbaa, MD2); + } + + // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA. + // The order of the metadata (path-aware vs non-path-aware) is important, + // because the AA eval pass only runs one test per store-pair. + const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" }; + cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); + PM.add(createTypeBasedAliasAnalysisPass()); + PM.add(createAAEvalPass()); + PM.run(M); +} + +} // end anonymous namspace +} // end llvm namespace + diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp index 398d09e5a873..90f6997e98cd 100644 --- a/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/unittests/Analysis/ScalarEvolutionTest.cpp @@ -41,7 +41,7 @@ TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) { std::vector<Type *>(), false); Function *F = cast<Function>(M.getOrInsertFunction("f", FTy)); BasicBlock *BB = BasicBlock::Create(Context, "entry", F); - ReturnInst::Create(Context, 0, BB); + ReturnInst::Create(Context, nullptr, BB); Type *Ty = Type::getInt1Ty(Context); Constant *Init = Constant::getNullValue(Ty); @@ -94,7 +94,7 @@ TEST_F(ScalarEvolutionsTest, SCEVMultiplyAddRecs) { FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Types, false); Function *F = cast<Function>(M.getOrInsertFunction("f", FTy)); BasicBlock *BB = BasicBlock::Create(Context, "entry", F); - ReturnInst::Create(Context, 0, BB); + ReturnInst::Create(Context, nullptr, BB); // Create a ScalarEvolution and "run" it so that it gets initialized. PM.add(&SE); diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index f33af2ff474f..b6a3e9a7b75a 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallString.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/PassManager.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" @@ -45,7 +45,7 @@ static Module *makeLLVMModule() { } static void writeModuleToBuffer(SmallVectorImpl<char> &Buffer) { - OwningPtr<Module> Mod(makeLLVMModule()); + std::unique_ptr<Module> Mod(makeLLVMModule()); raw_svector_ostream OS(Buffer); WriteBitcodeToFile(Mod.get(), OS); } @@ -54,10 +54,12 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 SmallString<1024> Mem; writeModuleToBuffer(Mem); MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); - std::string errMsg; - OwningPtr<Module> m(getLazyBitcodeModule(Buffer, getGlobalContext(), &errMsg)); + ErrorOr<Module *> ModuleOrErr = + getLazyBitcodeModule(Buffer, getGlobalContext()); + std::unique_ptr<Module> m(ModuleOrErr.get()); PassManager passes; passes.add(createVerifierPass()); + passes.add(createDebugInfoVerifierPass()); passes.run(*m); } diff --git a/unittests/Bitcode/CMakeLists.txt b/unittests/Bitcode/CMakeLists.txt index d8f5fe1f191d..743ab18ad2c7 100644 --- a/unittests/Bitcode/CMakeLists.txt +++ b/unittests/Bitcode/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS BitReader BitWriter + Core + Support ) add_llvm_unittest(BitcodeTests diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 52702ba23aac..65930b5e4a1b 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -1,6 +1,12 @@ add_custom_target(UnitTests) set_target_properties(UnitTests PROPERTIES FOLDER "Tests") +if (APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path/../../lib") +else(UNIX) + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib") +endif() + function(add_llvm_unittest test_dirname) add_unittest(UnitTests ${test_dirname} ${ARGN}) endfunction() @@ -12,8 +18,9 @@ add_subdirectory(CodeGen) add_subdirectory(DebugInfo) add_subdirectory(ExecutionEngine) add_subdirectory(IR) +add_subdirectory(LineEditor) +add_subdirectory(Linker) add_subdirectory(MC) -add_subdirectory(Object) add_subdirectory(Option) add_subdirectory(Support) add_subdirectory(Transforms) diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt index 5973bae3aaba..65c0ac3f20e4 100644 --- a/unittests/CodeGen/CMakeLists.txt +++ b/unittests/CodeGen/CMakeLists.txt @@ -1,7 +1,6 @@ set(LLVM_LINK_COMPONENTS - asmprinter - codegen - support + AsmPrinter + Support ) set(CodeGenSources diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp index 8d8fc39a30f5..04c5a8ac0199 100644 --- a/unittests/CodeGen/DIEHashTest.cpp +++ b/unittests/CodeGen/DIEHashTest.cpp @@ -9,9 +9,10 @@ #include "../lib/CodeGen/AsmPrinter/DIE.h" #include "../lib/CodeGen/AsmPrinter/DIEHash.h" -#include "llvm/Support/Dwarf.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" +#include "llvm/ADT/STLExtras.h" #include "gtest/gtest.h" using namespace llvm; @@ -59,7 +60,7 @@ TEST(DIEHashTest, NamedType) { TEST(DIEHashTest, NamespacedType) { DIE CU(dwarf::DW_TAG_compile_unit); - DIE *Space = new DIE(dwarf::DW_TAG_namespace); + auto Space = make_unique<DIE>(dwarf::DW_TAG_namespace); DIEInteger One(1); DIEString SpaceStr(&One, "space"); Space->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &SpaceStr); @@ -67,15 +68,16 @@ TEST(DIEHashTest, NamespacedType) { Space->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); // sibling? - DIE *Foo = new DIE(dwarf::DW_TAG_structure_type); + auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type); DIEString FooStr(&One, "foo"); Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - Space->addChild(Foo); - CU.addChild(Space); + DIE &N = *Foo; + Space->addChild(std::move(Foo)); + CU.addChild(std::move(Space)); - uint64_t MD5Res = DIEHash().computeTypeSignature(*Foo); + uint64_t MD5Res = DIEHash().computeTypeSignature(N); // The exact same hash GCC produces for this DIE. ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res); @@ -87,14 +89,6 @@ TEST(DIEHashTest, TypeWithMember) { DIEInteger Four(4); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); - DIE *Member = new DIE(dwarf::DW_TAG_member); - DIEString MemberStr(&Four, "member"); - Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); - DIEInteger Zero(0); - Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); - - Unnamed.addChild(Member); - DIE Int(dwarf::DW_TAG_base_type); DIEString IntStr(&Four, "int"); Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); @@ -102,9 +96,18 @@ TEST(DIEHashTest, TypeWithMember) { DIEInteger Five(5); Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); - DIEEntry IntRef(&Int); + DIEEntry IntRef(Int); + + auto Member = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString MemberStr(&Four, "member"); + Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); + DIEInteger Zero(0); + Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Zero); Member->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + Unnamed.addChild(std::move(Member)); + uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res); @@ -116,22 +119,7 @@ TEST(DIEHashTest, ReusedType) { DIEInteger Eight(8); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIE *Mem1 = new DIE(dwarf::DW_TAG_member); DIEInteger Four(4); - DIEString Mem1Str(&Four, "mem1"); - Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str); - DIEInteger Zero(0); - Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); - - Unnamed.addChild(Mem1); - - DIE *Mem2 = new DIE(dwarf::DW_TAG_member); - DIEString Mem2Str(&Four, "mem2"); - Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str); - Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Four); - - Unnamed.addChild(Mem2); - DIE Int(dwarf::DW_TAG_base_type); DIEString IntStr(&Four, "int"); Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); @@ -139,10 +127,27 @@ TEST(DIEHashTest, ReusedType) { DIEInteger Five(5); Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); - DIEEntry IntRef(&Int); + DIEEntry IntRef(Int); + + auto Mem1 = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString Mem1Str(&Four, "mem1"); + Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str); + DIEInteger Zero(0); + Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Zero); Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + + Unnamed.addChild(std::move(Mem1)); + + auto Mem2 = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString Mem2Str(&Four, "mem2"); + Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str); + Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Four); Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + Unnamed.addChild(std::move(Mem2)); + uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res); @@ -156,14 +161,14 @@ TEST(DIEHashTest, RecursiveType) { DIEString FooStr(&One, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&One, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); - DIEEntry FooRef(&Foo); + DIEEntry FooRef(Foo); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef); // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them. - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -178,7 +183,7 @@ TEST(DIEHashTest, Pointer) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -186,13 +191,13 @@ TEST(DIEHashTest, Pointer) { DIE FooPtr(dwarf::DW_TAG_pointer_type); FooPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooRef(&Foo); + DIEEntry FooRef(Foo); FooPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef); - DIEEntry FooPtrRef(&FooPtr); + DIEEntry FooPtrRef(FooPtr); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooPtrRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -207,7 +212,7 @@ TEST(DIEHashTest, Reference) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -215,17 +220,17 @@ TEST(DIEHashTest, Reference) { DIE FooRef(dwarf::DW_TAG_reference_type); FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); DIE FooRefConst(dwarf::DW_TAG_const_type); - DIEEntry FooRefRef(&FooRef); + DIEEntry FooRefRef(FooRef); FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef); - DIEEntry FooRefConstRef(&FooRefConst); + DIEEntry FooRefConstRef(FooRefConst); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -240,7 +245,7 @@ TEST(DIEHashTest, RValueReference) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -248,17 +253,17 @@ TEST(DIEHashTest, RValueReference) { DIE FooRef(dwarf::DW_TAG_rvalue_reference_type); FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); DIE FooRefConst(dwarf::DW_TAG_const_type); - DIEEntry FooRefRef(&FooRef); + DIEEntry FooRefRef(FooRef); FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef); - DIEEntry FooRefConstRef(&FooRefConst); + DIEEntry FooRefConstRef(FooRefConst); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -273,21 +278,22 @@ TEST(DIEHashTest, PtrToMember) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); - PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); + PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -316,22 +322,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDecl = DIEHash().computeTypeSignature(Foo); } @@ -345,22 +351,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDef = DIEHash().computeTypeSignature(Foo); } @@ -389,21 +395,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDecl = DIEHash().computeTypeSignature(Foo); } @@ -417,21 +423,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDef = DIEHash().computeTypeSignature(Foo); } @@ -459,37 +465,37 @@ TEST(DIEHashTest, RefUnnamedType) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE UnnamedPtr(dwarf::DW_TAG_pointer_type); UnnamedPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry UnnamedRef(&Unnamed); + DIEEntry UnnamedRef(Unnamed); UnnamedPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedRef); - DIEEntry UnnamedPtrRef(&UnnamedPtr); + DIEEntry UnnamedPtrRef(UnnamedPtr); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedPtrRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); ASSERT_EQ(0x954e026f01c02529ULL, MD5Res); } -// struct { struct bar { }; }; +// struct { struct foo { }; }; TEST(DIEHashTest, NestedType) { DIE Unnamed(dwarf::DW_TAG_structure_type); DIEInteger One(1); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - DIE *Foo = new DIE(dwarf::DW_TAG_structure_type); + auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type); DIEString FooStr(&One, "foo"); Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - Unnamed.addChild(Foo); + Unnamed.addChild(std::move(Foo)); uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); @@ -503,15 +509,146 @@ TEST(DIEHashTest, MemberFunc) { DIEInteger One(1); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - DIE *Func = new DIE(dwarf::DW_TAG_subprogram); + auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram); DIEString FuncStr(&One, "func"); Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr); - Unnamed.addChild(Func); + Unnamed.addChild(std::move(Func)); uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); // The exact same hash GCC produces for this DIE. ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res); } + +// struct A { +// static void func(); +// }; +TEST(DIEHashTest, MemberFuncFlag) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram); + DIEString FuncStr(&One, "func"); + DIEString FuncLinkage(&One, "_ZN1A4funcEv"); + DIEInteger Two(2); + Func->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr); + Func->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + Func->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + Func->addValue(dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, &FuncLinkage); + Func->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + + A.addChild(std::move(Func)); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + + // The exact same hash GCC produces for this DIE. + ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res); +} + +// Derived from: +// struct A { +// const static int PI = -3; +// }; +// A a; +TEST(DIEHashTest, MemberSdata) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + DIEInteger Four(4); + DIEInteger Five(5); + DIEString FStr(&One, "int"); + DIE IntTyDIE(dwarf::DW_TAG_base_type); + IntTyDIE.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + IntTyDIE.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); + IntTyDIE.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); + + DIEEntry IntTy(IntTyDIE); + auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type); + PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntTy); + + DIEEntry PITy(*PITyDIE); + auto PI = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString PIStr(&One, "PI"); + DIEInteger Two(2); + DIEInteger NegThree(-3); + PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr); + PI->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + PI->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + PI->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PITy); + PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, &NegThree); + + A.addChild(std::move(PI)); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res); +} + +// Derived from: +// struct A { +// const static float PI = 3.14; +// }; +// A a; +TEST(DIEHashTest, MemberBlock) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + DIEInteger Four(4); + DIEString FStr(&One, "float"); + auto FloatTyDIE = make_unique<DIE>(dwarf::DW_TAG_base_type); + FloatTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + FloatTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Four); + FloatTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); + + DIEEntry FloatTy(*FloatTyDIE); + auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type); + PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FloatTy); + + DIEEntry PITy(*PITyDIE); + auto PI = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString PIStr(&One, "PI"); + DIEInteger Two(2); + PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr); + PI->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + PI->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + PI->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PITy); + PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + + DIEBlock PIBlock; + DIEInteger Blk1(0xc3); + DIEInteger Blk2(0xf5); + DIEInteger Blk3(0x48); + DIEInteger Blk4(0x40); + + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4); + + PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, &PIBlock); + + A.addChild(std::move(PI)); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res); +} } diff --git a/unittests/DebugInfo/CMakeLists.txt b/unittests/DebugInfo/CMakeLists.txt index ec580b7f69a4..e844e95251ab 100644 --- a/unittests/DebugInfo/CMakeLists.txt +++ b/unittests/DebugInfo/CMakeLists.txt @@ -1,7 +1,5 @@ set(LLVM_LINK_COMPONENTS - debuginfo - object - support + DebugInfo ) set(DebugInfoSources diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 4eefc1e3bb1b..5e462220e5cd 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -1,14 +1,19 @@ set(LLVM_LINK_COMPONENTS - interpreter + Core + ExecutionEngine + Interpreter + MC + Support ) add_llvm_unittest(ExecutionEngineTests ExecutionEngineTest.cpp ) -# Include JIT/MCJIT tests only if native arch is a JIT target. -list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" have_jit) -if (NOT have_jit EQUAL -1 ) +# Include JIT/MCJIT tests only if native arch is a built JIT target. +list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx) +list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx) +if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0) add_subdirectory(JIT) add_subdirectory(MCJIT) endif() diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp index 3e304e79860b..f23745c19dbb 100644 --- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" @@ -27,18 +26,18 @@ protected: } virtual void SetUp() { - ASSERT_TRUE(Engine.get() != NULL) << "EngineBuilder returned error: '" + ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '" << Error << "'"; } GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) { return new GlobalVariable(*M, T, false, // Not constant. - GlobalValue::ExternalLinkage, NULL, Name); + GlobalValue::ExternalLinkage, nullptr, Name); } Module *const M; std::string Error; - const OwningPtr<ExecutionEngine> Engine; + const std::unique_ptr<ExecutionEngine> Engine; }; TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { @@ -50,14 +49,14 @@ TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { int32_t Mem2 = 4; Engine->updateGlobalMapping(G1, &Mem2); EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); - Engine->updateGlobalMapping(G1, NULL); - EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G1)); + Engine->updateGlobalMapping(G1, nullptr); + EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1)); Engine->updateGlobalMapping(G1, &Mem2); EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); - EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G2)) + EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2)) << "The NULL return shouldn't depend on having called" << " updateGlobalMapping(..., NULL)"; // Check that update...() can be called before add...(). @@ -76,7 +75,7 @@ TEST_F(ExecutionEngineTest, ReverseGlobalMapping) { EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); int32_t Mem2 = 4; Engine->updateGlobalMapping(G1, &Mem2); - EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); GlobalVariable *G2 = @@ -84,12 +83,12 @@ TEST_F(ExecutionEngineTest, ReverseGlobalMapping) { Engine->updateGlobalMapping(G2, &Mem1); EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); - Engine->updateGlobalMapping(G1, NULL); + Engine->updateGlobalMapping(G1, nullptr); EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)) << "Removing one mapping doesn't affect a different one."; - EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem2)); + EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2)); Engine->updateGlobalMapping(G2, &Mem2); - EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2)) << "Once a mapping is removed, we can point another GV at the" << " now-free address."; @@ -105,7 +104,7 @@ TEST_F(ExecutionEngineTest, ClearModuleMappings) { Engine->clearGlobalMappingsFromModule(M); - EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); @@ -125,7 +124,7 @@ TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { // When the GV goes away, the ExecutionEngine should remove any // mappings that refer to it. G1->eraseFromParent(); - EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1)); + EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); } } diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt index ef37026dfc9f..5ace1c6ee48a 100644 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/JIT/CMakeLists.txt @@ -1,8 +1,12 @@ set(LLVM_LINK_COMPONENTS - asmparser - bitreader - bitwriter - jit + AsmParser + BitReader + BitWriter + Core + ExecutionEngine + JIT + MC + Support nativecodegen ) @@ -48,6 +52,9 @@ if(MSVC) list(APPEND JITTestsSources JITTests.def) endif() +# The JIT tests need to dlopen things. +set(LLVM_NO_DEAD_STRIP 1) + add_llvm_unittest(JITTests ${JITTestsSources} ) diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp index d3f66a27e942..db9088777a91 100644 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp @@ -83,7 +83,7 @@ public: EXPECT_TRUE(0 != MockWrapper); Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.take())); + MockWrapper.release())); EXPECT_TRUE(0 != Listener); EE->RegisterJITEventListener(Listener.get()); } diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp index 87f482444f41..175b9fb107b8 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Instructions.h" @@ -21,8 +20,6 @@ using namespace llvm; -int dummy; - namespace { struct FunctionEmittedEvent { @@ -71,11 +68,11 @@ class JITEventListenerTest : public testing::Test { } Module *M; - const OwningPtr<ExecutionEngine> EE; + const std::unique_ptr<ExecutionEngine> EE; }; // Tests on SystemZ disabled as we're running the old JIT -#if !defined(__s390__) +#if !defined(__s390__) && !defined(__aarch64__) Function *buildFunction(Module *M) { Function *Result = Function::Create( TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()), diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h index d1c2124b9b10..61220f545f9f 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h @@ -12,10 +12,10 @@ #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/Config/config.h" -#include "llvm/DIBuilder.h" -#include "llvm/DebugInfo.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" @@ -53,8 +53,8 @@ inline const char* getFilename() { template<typename WrapperT> class JITEventListenerTestBase : public testing::Test { protected: - llvm::OwningPtr<WrapperT> MockWrapper; - llvm::OwningPtr<llvm::JITEventListener> Listener; + std::unique_ptr<WrapperT> MockWrapper; + std::unique_ptr<llvm::JITEventListener> Listener; public: llvm::Module* M; diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp index 731f7807f593..296838de61b3 100644 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp @@ -9,7 +9,6 @@ #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -31,27 +30,27 @@ Function *makeFakeFunction() { // the code in the case that we don't have to allocate more memory to store the // function bodies. TEST(JITMemoryManagerTest, NoAllocations) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; // Allocate the functions. - OwningPtr<Function> F1(makeFakeFunction()); + std::unique_ptr<Function> F1(makeFakeFunction()); size = 1024; uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); memset(FunctionBody1, 0xFF, 1024); MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F2(makeFakeFunction()); + std::unique_ptr<Function> F2(makeFakeFunction()); size = 1024; uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); memset(FunctionBody2, 0xFF, 1024); MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F3(makeFakeFunction()); + std::unique_ptr<Function> F3(makeFakeFunction()); size = 1024; uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); memset(FunctionBody3, 0xFF, 1024); @@ -70,7 +69,7 @@ TEST(JITMemoryManagerTest, NoAllocations) { // Make three large functions that take up most of the space in the slab. Then // try allocating three smaller functions that don't require additional slabs. TEST(JITMemoryManagerTest, TestCodeAllocation) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; @@ -81,7 +80,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { smallFuncSize * 2); // Allocate big functions - OwningPtr<Function> F1(makeFakeFunction()); + std::unique_ptr<Function> F1(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); ASSERT_LE(bigFuncSize, size); @@ -89,7 +88,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F2(makeFakeFunction()); + std::unique_ptr<Function> F2(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); ASSERT_LE(bigFuncSize, size); @@ -97,7 +96,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F3(makeFakeFunction()); + std::unique_ptr<Function> F3(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); ASSERT_LE(bigFuncSize, size); @@ -109,7 +108,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); // Allocate small functions - OwningPtr<Function> F4(makeFakeFunction()); + std::unique_ptr<Function> F4(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); ASSERT_LE(smallFuncSize, size); @@ -118,7 +117,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { FunctionBody4 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F5(makeFakeFunction()); + std::unique_ptr<Function> F5(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); ASSERT_LE(smallFuncSize, size); @@ -127,7 +126,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { FunctionBody5 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F6(makeFakeFunction()); + std::unique_ptr<Function> F6(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); ASSERT_LE(smallFuncSize, size); @@ -157,7 +156,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { // Allocate five global ints of varying widths and alignment, and check their // alignment and overlap. TEST(JITMemoryManagerTest, TestSmallGlobalInts) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 0); uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); @@ -204,7 +203,7 @@ TEST(JITMemoryManagerTest, TestSmallGlobalInts) { // Allocate a small global, a big global, and a third global, and make sure we // only use two slabs for that. TEST(JITMemoryManagerTest, TestLargeGlobalArray) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); @@ -234,7 +233,7 @@ TEST(JITMemoryManagerTest, TestLargeGlobalArray) { // Allocate lots of medium globals so that we can test moving the bump allocator // to a new slab. TEST(JITMemoryManagerTest, TestManyGlobals) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); size_t Size = 128; @@ -257,7 +256,7 @@ TEST(JITMemoryManagerTest, TestManyGlobals) { // Allocate lots of function stubs so that we can test moving the stub bump // allocator to a new slab. TEST(JITMemoryManagerTest, TestManyStubs) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); size_t Size = 128; @@ -268,18 +267,18 @@ TEST(JITMemoryManagerTest, TestManyStubs) { // After allocating a bunch of stubs, we should have two. for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(NULL, Size, 8); + MemMgr->allocateStub(nullptr, Size, 8); EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); // And after much more, we should have three. for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(NULL, Size, 8); + MemMgr->allocateStub(nullptr, Size, 8); EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); } // Check section allocation and alignment TEST(JITMemoryManagerTest, AllocateSection) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); @@ -287,10 +286,10 @@ TEST(JITMemoryManagerTest, AllocateSection) { uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); - EXPECT_NE((uint8_t*)0, code1); - EXPECT_NE((uint8_t*)0, code2); - EXPECT_NE((uint8_t*)0, data1); - EXPECT_NE((uint8_t*)0, data2); + EXPECT_NE((uint8_t*)nullptr, code1); + EXPECT_NE((uint8_t*)nullptr, code2); + EXPECT_NE((uint8_t*)nullptr, data1); + EXPECT_NE((uint8_t*)nullptr, data2); // Check alignment EXPECT_EQ((uint64_t)code1 & 0xf, 0u); diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 4c7b1e23195d..817d207c2dca 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -8,9 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/IR/BasicBlock.h" @@ -52,7 +51,8 @@ extern "C" int32_t JITTest_AvailableExternallyFunction() { namespace { // Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ + && !defined(__aarch64__) Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { std::vector<Type*> params; @@ -76,7 +76,8 @@ std::string DumpFunction(const Function *F) { } class RecordingJITMemoryManager : public JITMemoryManager { - const OwningPtr<JITMemoryManager> Base; + const std::unique_ptr<JITMemoryManager> Base; + public: RecordingJITMemoryManager() : Base(JITMemoryManager::CreateDefaultMemManager()) { @@ -113,8 +114,8 @@ public: return Result; } int stubsAllocated; - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { + uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, + unsigned Alignment) override { stubsAllocated++; return Base->allocateStub(F, StubSize, Alignment); } @@ -168,7 +169,7 @@ public: bool LoadAssemblyInto(Module *M, const char *assembly) { SMDiagnostic Error; bool success = - NULL != ParseAssemblyString(assembly, M, Error, M->getContext()); + nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); std::string errMsg; raw_string_ostream os(errMsg); Error.print("", os); @@ -192,7 +193,7 @@ class JITTest : public testing::Test { .setJITMemoryManager(RJMM) .setErrorStr(&Error) .setTargetOptions(Options).create()); - ASSERT_TRUE(TheJIT.get() != NULL) << Error; + ASSERT_TRUE(TheJIT.get() != nullptr) << Error; } void LoadAssembly(const char *assembly) { @@ -202,7 +203,7 @@ class JITTest : public testing::Test { LLVMContext Context; Module *M; // Owned by ExecutionEngine. RecordingJITMemoryManager *RJMM; - OwningPtr<ExecutionEngine> TheJIT; + std::unique_ptr<ExecutionEngine> TheJIT; }; // Regression test for a bug. The JIT used to allocate globals inside the same @@ -219,13 +220,13 @@ TEST(JIT, GlobalInFunction) { // memory is more easily tested. MemMgr->setPoisonMemory(true); std::string Error; - OwningPtr<ExecutionEngine> JIT(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); + std::unique_ptr<ExecutionEngine> JIT(EngineBuilder(M) + .setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setJITMemoryManager(MemMgr) + // The next line enables the fix: + .setAllocateGVsWithCode(false) + .create()); ASSERT_EQ(Error, ""); // Create a global variable. @@ -248,7 +249,7 @@ TEST(JIT, GlobalInFunction) { // Since F1 was codegen'd, a pointer to G should be available. int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); - ASSERT_NE((int32_t*)NULL, GPtr); + ASSERT_NE((int32_t*)nullptr, GPtr); EXPECT_EQ(0, *GPtr); // F1() should increment G. @@ -438,7 +439,7 @@ TEST_F(JITTest, ModuleDeletion) { // too far away to call directly. This #if can probably be removed when // http://llvm.org/PR5201 is fixed. #if !defined(__arm__) && !defined(__mips__) && \ - !defined(__powerpc__) && !defined(__ppc__) + !defined(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) typedef int (*FooPtr) (); TEST_F(JITTest, NoStubs) { @@ -514,7 +515,7 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { // ARM does not have an implementation of replaceMachineCodeForFunction(), // so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) +#if !defined(__arm__) && !defined(__aarch64__) TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), GlobalValue::ExternalLinkage, "test", M); @@ -631,22 +632,23 @@ ExecutionEngine *getJITFromBitcode( // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. MemoryBuffer *BitcodeBuffer = MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); - std::string errMsg; - M = getLazyBitcodeModule(BitcodeBuffer, Context, &errMsg); - if (M == NULL) { - ADD_FAILURE() << errMsg; + ErrorOr<Module*> ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); + if (std::error_code EC = ModuleOrErr.getError()) { + ADD_FAILURE() << EC.message(); delete BitcodeBuffer; - return NULL; + return nullptr; } + M = ModuleOrErr.get(); + std::string errMsg; ExecutionEngine *TheJIT = EngineBuilder(M) .setEngineKind(EngineKind::JIT) .setErrorStr(&errMsg) .create(); - if (TheJIT == NULL) { + if (TheJIT == nullptr) { ADD_FAILURE() << errMsg; delete M; - M = NULL; - return NULL; + M = nullptr; + return nullptr; } return TheJIT; } @@ -667,7 +669,8 @@ TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { "} "); ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; Module *M; - OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr<ExecutionEngine> TheJIT( + getJITFromBitcode(Context, Bitcode, M)); ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; TheJIT->DisableLazyCompilation(true); @@ -706,7 +709,8 @@ TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { "} "); ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; Module *M; - OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr<ExecutionEngine> TheJIT( + getJITFromBitcode(Context, Bitcode, M)); ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; TheJIT->DisableLazyCompilation(true); diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile index ef8b827a862e..d86c03bfc807 100644 --- a/unittests/ExecutionEngine/JIT/Makefile +++ b/unittests/ExecutionEngine/JIT/Makefile @@ -11,6 +11,9 @@ LEVEL = ../../.. TESTNAME = JIT LINK_COMPONENTS := asmparser bitreader bitwriter jit native +# The JIT tests need to dlopen things. +NO_DEAD_STRIP := 1 + include $(LEVEL)/Makefile.config SOURCES := JITEventListenerTest.cpp JITMemoryManagerTest.cpp JITTest.cpp MultiJITTest.cpp diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp index 4018cd5ce2f2..f530e0de5d51 100644 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JIT.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -21,12 +21,13 @@ using namespace llvm; namespace { // ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ + && !defined(__aarch64__) bool LoadAssemblyInto(Module *M, const char *assembly) { SMDiagnostic Error; bool success = - NULL != ParseAssemblyString(assembly, M, Error, M->getContext()); + nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); std::string errMsg; raw_string_ostream os(errMsg); Error.print("", os); @@ -70,19 +71,19 @@ void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) { TEST(MultiJitTest, EagerMode) { LLVMContext Context1; - Module *M1 = 0; - Function *FooF1 = 0; + Module *M1 = nullptr; + Function *FooF1 = nullptr; createModule1(Context1, M1, FooF1); LLVMContext Context2; - Module *M2 = 0; - Function *FooF2 = 0; + Module *M2 = nullptr; + Function *FooF2 = nullptr; createModule2(Context2, M2, FooF2); // Now we create the JIT in eager mode - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); + std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(true); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); EE2->DisableLazyCompilation(true); // Call the `foo' function with no arguments: @@ -100,19 +101,19 @@ TEST(MultiJitTest, EagerMode) { TEST(MultiJitTest, LazyMode) { LLVMContext Context1; - Module *M1 = 0; - Function *FooF1 = 0; + Module *M1 = nullptr; + Function *FooF1 = nullptr; createModule1(Context1, M1, FooF1); LLVMContext Context2; - Module *M2 = 0; - Function *FooF2 = 0; + Module *M2 = nullptr; + Function *FooF2 = nullptr; createModule2(Context2, M2, FooF2); // Now we create the JIT in lazy mode - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); + std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(false); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); EE2->DisableLazyCompilation(false); // Call the `foo' function with no arguments: @@ -134,18 +135,18 @@ extern "C" { TEST(MultiJitTest, JitPool) { LLVMContext Context1; - Module *M1 = 0; - Function *FooF1 = 0; + Module *M1 = nullptr; + Function *FooF1 = nullptr; createModule1(Context1, M1, FooF1); LLVMContext Context2; - Module *M2 = 0; - Function *FooF2 = 0; + Module *M2 = nullptr; + Function *FooF2 = nullptr; createModule2(Context2, M2, FooF2); // Now we create two JITs - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); + std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); Function *F1 = EE1->FindFunctionNamed("foo1"); void *foo1 = EE1->getPointerToFunction(F1); @@ -173,6 +174,14 @@ TEST(MultiJitTest, JitPool) { EXPECT_TRUE(fa != 0); fa = *(intptr_t *)fa; // Bound value of IAT } +#elif defined(__x86_64__) + // getPointerToNamedFunction might be indirect jump + // on Win32 x64 --enable-shared. + // FF 25 <pcrel32>: jmp *(RIP + pointer to IAT) + if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { + fa += *(int32_t *)(fa + 2) + 6; // Address to IAT(RIP) + fa = *(intptr_t *)fa; // Bound value of IAT + } #endif EXPECT_TRUE(sa == fa); } diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index ed4309919387..cbd08fe9b8e2 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -1,8 +1,14 @@ set(LLVM_LINK_COMPONENTS - asmparser - bitreader - bitwriter - mcjit + Analysis + Core + ExecutionEngine + IPO + JIT + MC + MCJIT + ScalarOpts + Support + Target nativecodegen ) diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index 46d6d9b8a9a6..d03de898b4e6 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -13,18 +13,22 @@ //===----------------------------------------------------------------------===// #include "llvm-c/Analysis.h" +#include "MCJITTestAPICommon.h" #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Host.h" -#include "MCJITTestAPICommon.h" #include "gtest/gtest.h" using namespace llvm; static bool didCallAllocateCodeSection; +static bool didAllocateCompactUnwindSection; +static bool didCallYield; static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size, unsigned alignment, @@ -40,6 +44,8 @@ static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size, unsigned sectionID, const char *sectionName, LLVMBool isReadOnly) { + if (!strcmp(sectionName, "__compact_unwind")) + didAllocateCompactUnwindSection = true; return static_cast<SectionMemoryManager*>(object)->allocateDataSection( size, alignment, sectionID, sectionName, isReadOnly); } @@ -59,7 +65,59 @@ static void roundTripDestroy(void *object) { delete static_cast<SectionMemoryManager*>(object); } +static void yield(LLVMContextRef, void *) { + didCallYield = true; +} + namespace { + +// memory manager to test reserve allocation space callback +class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager { +public: + uintptr_t ReservedCodeSize; + uintptr_t UsedCodeSize; + uintptr_t ReservedDataSizeRO; + uintptr_t UsedDataSizeRO; + uintptr_t ReservedDataSizeRW; + uintptr_t UsedDataSizeRW; + + TestReserveAllocationSpaceMemoryManager() : + ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0), + UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) { + } + + virtual bool needsToReserveAllocationSpace() { + return true; + } + + virtual void reserveAllocationSpace( + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { + ReservedCodeSize = CodeSize; + ReservedDataSizeRO = DataSizeRO; + ReservedDataSizeRW = DataSizeRW; + } + + void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) { + uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment; + uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment; + *UsedSize = AlignedBegin + AlignedSize; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, bool IsReadOnly) { + useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment); + return SectionMemoryManager::allocateDataSection(Size, Alignment, + SectionID, SectionName, IsReadOnly); + } + + uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName) { + useSpace(&UsedCodeSize, Size, Alignment); + return SectionMemoryManager::allocateCodeSection(Size, Alignment, + SectionID, SectionName); + } +}; + class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon { protected: MCJITCAPITest() { @@ -82,14 +140,18 @@ protected: // The operating systems below are known to be sufficiently incompatible // that they will fail the MCJIT C API tests. UnsupportedOSs.push_back(Triple::Cygwin); + + UnsupportedEnvironments.push_back(Triple::Cygnus); } virtual void SetUp() { didCallAllocateCodeSection = false; - Module = 0; - Function = 0; - Engine = 0; - Error = 0; + didAllocateCompactUnwindSection = false; + didCallYield = false; + Module = nullptr; + Function = nullptr; + Engine = nullptr; + Error = nullptr; } virtual void TearDown() { @@ -104,8 +166,8 @@ protected: LLVMSetTarget(Module, HostTriple.c_str()); - Function = LLVMAddFunction( - Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + Function = LLVMAddFunction(Module, "simple_function", + LLVMFunctionType(LLVMInt32Type(), nullptr,0, 0)); LLVMSetFunctionCallConv(Function, LLVMCCallConv); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry"); @@ -119,6 +181,84 @@ protected: LLVMDisposeBuilder(builder); } + void buildFunctionThatUsesStackmap() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() }; + LLVMValueRef stackmap = LLVMAddFunction( + Module, "llvm.experimental.stackmap", + LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1)); + LLVMSetLinkage(stackmap, LLVMExternalLinkage); + + Function = LLVMAddFunction(Module, "simple_function", + LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0)); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMValueRef stackmapArgs[] = { + LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0), + LLVMConstInt(LLVMInt32Type(), 42, 0) + }; + LLVMBuildCall(builder, stackmap, stackmapArgs, 3, ""); + LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(builder); + } + + void buildModuleWithCodeAndData() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + // build a global int32 variable initialized to 42. + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal"); + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + { + Function = LLVMAddFunction(Module, "getGlobal", + LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0)); + LLVMSetFunctionCallConv(Function, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal"); + LLVMBuildRet(Builder, IntVal); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + + { + LLVMTypeRef ParamTypes[] = { LLVMInt32Type() }; + Function2 = LLVMAddFunction( + Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0)); + LLVMSetFunctionCallConv(Function2, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef Arg = LLVMGetParam(Function2, 0); + LLVMBuildStore(Builder, Arg, GlobalVar); + LLVMBuildRetVoid(Builder); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + } + void buildMCJITOptions() { LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); Options.OptLevel = 2; @@ -135,7 +275,7 @@ protected: roundTripFinalizeMemory, roundTripDestroy); } - + void buildMCJITEngine() { ASSERT_EQ( 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options, @@ -151,8 +291,41 @@ protected: LLVMDisposePassManager(pass); } + void buildAndRunOptPasses() { + LLVMPassManagerBuilderRef passBuilder; + + passBuilder = LLVMPassManagerBuilderCreate(); + LLVMPassManagerBuilderSetOptLevel(passBuilder, 2); + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0); + + LLVMPassManagerRef functionPasses = + LLVMCreateFunctionPassManagerForModule(Module); + LLVMPassManagerRef modulePasses = + LLVMCreatePassManager(); + + LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses); + + LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, + functionPasses); + LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); + + LLVMPassManagerBuilderDispose(passBuilder); + + LLVMInitializeFunctionPassManager(functionPasses); + for (LLVMValueRef value = LLVMGetFirstFunction(Module); + value; value = LLVMGetNextFunction(value)) + LLVMRunFunctionPassManager(functionPasses, value); + LLVMFinalizeFunctionPassManager(functionPasses); + + LLVMRunPassManager(modulePasses, Module); + + LLVMDisposePassManager(functionPasses); + LLVMDisposePassManager(modulePasses); + } + LLVMModuleRef Module; LLVMValueRef Function; + LLVMValueRef Function2; LLVMMCJITCompilerOptions Options; LLVMExecutionEngineRef Engine; char *Error; @@ -194,3 +367,92 @@ TEST_F(MCJITCAPITest, custom_memory_manager) { EXPECT_EQ(42, functionPointer.usable()); EXPECT_TRUE(didCallAllocateCodeSection); } + +TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) { + SKIP_UNSUPPORTED_PLATFORM; + + // This test is also not supported on non-x86 platforms. + if (Triple(HostTriple).getArch() != Triple::x86_64) + return; + + buildFunctionThatUsesStackmap(); + buildMCJITOptions(); + useRoundTripSectionMemoryManager(); + buildMCJITEngine(); + buildAndRunOptPasses(); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + + EXPECT_EQ(42, functionPointer.usable()); + EXPECT_TRUE(didCallAllocateCodeSection); + + // Up to this point, the test is specific only to X86-64. But this next + // expectation is only valid on Darwin because it assumes that unwind + // data is made available only through compact_unwind. It would be + // worthwhile to extend this to handle non-Darwin platforms, in which + // case you'd want to look for an eh_frame or something. + // + // FIXME: Currently, MCJIT relies on a configure-time check to determine which + // sections to emit. The JIT client should have runtime control over this. + EXPECT_TRUE( + Triple(HostTriple).getOS() != Triple::Darwin || + Triple(HostTriple).isMacOSXVersionLT(10, 7) || + didAllocateCompactUnwindSection); +} + +TEST_F(MCJITCAPITest, reserve_allocation_space) { + SKIP_UNSUPPORTED_PLATFORM; + + TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager(); + + buildModuleWithCodeAndData(); + buildMCJITOptions(); + Options.MCJMM = wrap(MM); + buildMCJITEngine(); + buildAndRunPasses(); + + union { + void *raw; + int (*usable)(); + } GetGlobalFct; + GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function); + + union { + void *raw; + void (*usable)(int); + } SetGlobalFct; + SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2); + + SetGlobalFct.usable(789); + EXPECT_EQ(789, GetGlobalFct.usable()); + EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize); + EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO); + EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW); + EXPECT_TRUE(MM->UsedCodeSize > 0); + EXPECT_TRUE(MM->UsedDataSizeRW > 0); +} + +TEST_F(MCJITCAPITest, yield) { + SKIP_UNSUPPORTED_PLATFORM; + + buildSimpleFunction(); + buildMCJITOptions(); + buildMCJITEngine(); + LLVMContextRef C = LLVMGetGlobalContext(); + LLVMContextSetYieldCallback(C, yield, nullptr); + buildAndRunPasses(); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + + EXPECT_EQ(42, functionPointer.usable()); + EXPECT_TRUE(didCallYield); +} + diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index c24346de84ee..98587f7e85cf 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ExecutionEngine/JIT.h" #include "gtest/gtest.h" @@ -17,17 +16,17 @@ using namespace llvm; namespace { TEST(MCJITMemoryManagerTest, BasicAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, ""); uint8_t *data1 = MemMgr->allocateDataSection(256, 0, 2, "", true); uint8_t *code2 = MemMgr->allocateCodeSection(256, 0, 3, ""); uint8_t *data2 = MemMgr->allocateDataSection(256, 0, 4, "", false); - EXPECT_NE((uint8_t*)0, code1); - EXPECT_NE((uint8_t*)0, code2); - EXPECT_NE((uint8_t*)0, data1); - EXPECT_NE((uint8_t*)0, data2); + EXPECT_NE((uint8_t*)nullptr, code1); + EXPECT_NE((uint8_t*)nullptr, code2); + EXPECT_NE((uint8_t*)nullptr, data1); + EXPECT_NE((uint8_t*)nullptr, data2); // Initialize the data for (unsigned i = 0; i < 256; ++i) { @@ -50,17 +49,17 @@ TEST(MCJITMemoryManagerTest, BasicAllocations) { } TEST(MCJITMemoryManagerTest, LargeAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1, ""); uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, "", true); uint8_t *code2 = MemMgr->allocateCodeSection(0x100000, 0, 3, ""); uint8_t *data2 = MemMgr->allocateDataSection(0x100000, 0, 4, "", false); - EXPECT_NE((uint8_t*)0, code1); - EXPECT_NE((uint8_t*)0, code2); - EXPECT_NE((uint8_t*)0, data1); - EXPECT_NE((uint8_t*)0, data2); + EXPECT_NE((uint8_t*)nullptr, code1); + EXPECT_NE((uint8_t*)nullptr, code2); + EXPECT_NE((uint8_t*)nullptr, data1); + EXPECT_NE((uint8_t*)nullptr, data2); // Initialize the data for (unsigned i = 0; i < 0x100000; ++i) { @@ -83,7 +82,7 @@ TEST(MCJITMemoryManagerTest, LargeAllocations) { } TEST(MCJITMemoryManagerTest, ManyAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t* code[10000]; uint8_t* data[10000]; @@ -99,8 +98,8 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) { data[i][j] = 2 + (i % 254); } - EXPECT_NE((uint8_t *)0, code[i]); - EXPECT_NE((uint8_t *)0, data[i]); + EXPECT_NE((uint8_t *)nullptr, code[i]); + EXPECT_NE((uint8_t *)nullptr, data[i]); } // Verify the data (this is checking for overlaps in the addresses) @@ -118,7 +117,7 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) { } TEST(MCJITMemoryManagerTest, ManyVariedAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t* code[10000]; uint8_t* data[10000]; @@ -142,8 +141,8 @@ TEST(MCJITMemoryManagerTest, ManyVariedAllocations) { data[i][j] = 2 + (i % 254); } - EXPECT_NE((uint8_t *)0, code[i]); - EXPECT_NE((uint8_t *)0, data[i]); + EXPECT_NE((uint8_t *)nullptr, code[i]); + EXPECT_NE((uint8_t *)nullptr, data[i]); uintptr_t CodeAlign = Align ? (uintptr_t)code[i] % Align : 0; uintptr_t DataAlign = Align ? (uintptr_t)data[i] % Align : 0; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index 7c3239ea2598..c5ca36e417cf 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -90,12 +90,12 @@ TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) { TEST_F(MCJITMultipleModuleTest, two_module_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -110,12 +110,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) { TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -131,12 +131,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -152,12 +152,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -172,13 +172,13 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA1, *FA2, *FB; createTwoModuleExternCase(A, FA1, B, FB); FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -199,7 +199,7 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; GlobalVariable *GVA, *GVB; A.reset(createEmptyModule("A")); @@ -213,8 +213,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { FB = startFunction<int32_t(void)>(B.get(), "FB"); endFunctionWithRet(FB, Builder.CreateLoad(GVB)); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -237,13 +237,13 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { TEST_F(MCJITMultipleModuleTest, three_module_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -262,13 +262,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) { TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -287,13 +287,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -312,13 +312,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -337,12 +337,12 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAccumulate(ptr); @@ -358,12 +358,12 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); @@ -379,12 +379,12 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index 7073a5265d62..fbbab42dbb02 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" +#include "MCJITTestBase.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" @@ -15,7 +15,6 @@ #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "MCJITTestBase.h" #include "gtest/gtest.h" using namespace llvm; @@ -49,7 +48,7 @@ public: const MemoryBuffer* BufferFound = getObjectInternal(M); ModulesLookedUp.insert(M->getModuleIdentifier()); if (!BufferFound) - return NULL; + return nullptr; // Our test cache wants to maintain ownership of its object buffers // so we make a copy here for the execution engine. return MemoryBuffer::getMemBufferCopy(BufferFound->getBuffer()); @@ -68,7 +67,7 @@ public: const std::string ModuleID = M->getModuleIdentifier(); StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID); if (it == ObjMap.end()) - return 0; + return nullptr; return it->second; } @@ -101,14 +100,14 @@ protected: void compileAndRun(int ExpectedRC = OriginalRC) { // This function shouldn't be called until after SetUp. - ASSERT_TRUE(TheJIT.isValid()); - ASSERT_TRUE(0 != Main); + ASSERT_TRUE(bool(TheJIT)); + ASSERT_TRUE(nullptr != Main); // We may be using a null cache, so ensure compilation is valid. TheJIT->finalizeObject(); void *vPtr = TheJIT->getPointerToFunction(Main); - EXPECT_TRUE(0 != vPtr) + EXPECT_TRUE(nullptr != vPtr) << "Unable to get pointer to main() from JIT"; int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr; @@ -122,9 +121,9 @@ protected: TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { SKIP_UNSUPPORTED_PLATFORM; - createJIT(M.take()); + createJIT(M.release()); - TheJIT->setObjectCache(NULL); + TheJIT->setObjectCache(nullptr); compileAndRun(); } @@ -133,18 +132,18 @@ TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Save a copy of the module pointer before handing it off to MCJIT. const Module * SavedModulePointer = M.get(); - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); // Verify that our object cache does not contain the module yet. const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer); - EXPECT_EQ(0, ObjBuffer); + EXPECT_EQ(nullptr, ObjBuffer); compileAndRun(); @@ -153,7 +152,7 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { // Verify that our object cache now contains the module. ObjBuffer = Cache->getObjectInternal(SavedModulePointer); - EXPECT_TRUE(0 != ObjBuffer); + EXPECT_TRUE(nullptr != ObjBuffer); // Verify that the cache was only notified once. EXPECT_FALSE(Cache->wereDuplicatesInserted()); @@ -162,10 +161,10 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -182,7 +181,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); compileAndRun(); @@ -196,10 +195,10 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -217,12 +216,12 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); // Verify that our object cache does not contain the module yet. const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer); - EXPECT_EQ(0, ObjBuffer); + EXPECT_EQ(nullptr, ObjBuffer); // Run the function and look for the replacement return code. compileAndRun(ReplacementRC); @@ -232,7 +231,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { // Verify that our object cache now contains the module. ObjBuffer = Cache->getObjectInternal(SecondModulePointer); - EXPECT_TRUE(0 != ObjBuffer); + EXPECT_TRUE(nullptr != ObjBuffer); // Verify that MCJIT didn't try to cache this again. EXPECT_FALSE(Cache->wereDuplicatesInserted()); diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index fab81551fa5e..c37c1d1d599d 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -49,9 +49,9 @@ TEST_F(MCJITTest, global_variable) { int initialValue = 5; GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); - createJIT(M.take()); + createJIT(M.release()); void *globalPtr = TheJIT->getPointerToGlobal(Global); - EXPECT_TRUE(0 != globalPtr) + EXPECT_TRUE(nullptr != globalPtr) << "Unable to get pointer to global value from JIT"; EXPECT_EQ(initialValue, *(int32_t*)globalPtr) @@ -62,7 +62,7 @@ TEST_F(MCJITTest, add_function) { SKIP_UNSUPPORTED_PLATFORM; Function *F = insertAddFunction(M.get()); - createJIT(M.take()); + createJIT(M.release()); uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); EXPECT_TRUE(0 != addPtr) << "Unable to get pointer to function from JIT"; @@ -83,7 +83,7 @@ TEST_F(MCJITTest, run_main) { int rc = 6; Function *Main = insertMainFunction(M.get(), 6); - createJIT(M.take()); + createJIT(M.release()); uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to main() from JIT"; @@ -104,7 +104,7 @@ TEST_F(MCJITTest, return_global) { Value *ReadGlobal = Builder.CreateLoad(GV); endFunctionWithRet(ReturnGlobal, ReadGlobal); - createJIT(M.take()); + createJIT(M.release()); uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); EXPECT_TRUE(0 != rgvPtr); @@ -175,7 +175,7 @@ TEST_F(MCJITTest, multiple_functions) { Inner = Outer; } - createJIT(M.take()); + createJIT(M.release()); uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h index 7b6e39fb2385..a48c0713f9b8 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -71,10 +71,15 @@ protected: /// Returns true if the host OS is known to support MCJIT bool OSSupportsMCJIT() { Triple Host(HostTriple); + + if (std::find(UnsupportedEnvironments.begin(), UnsupportedEnvironments.end(), + Host.getEnvironment()) != UnsupportedEnvironments.end()) + return false; + if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS()) - == UnsupportedOSs.end()) { + == UnsupportedOSs.end()) return true; - } + return false; } @@ -83,6 +88,7 @@ protected: SmallVector<Triple::ArchType, 1> HasSubArchs; SmallVector<std::string, 2> SupportedSubArchs; // We need to own the memory SmallVector<Triple::OSType, 4> UnsupportedOSs; + SmallVector<Triple::EnvironmentType, 1> UnsupportedEnvironments; }; } // namespace llvm diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index b42a9c0980db..25de312e0e87 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -17,6 +17,7 @@ #ifndef MCJIT_TEST_BASE_H #define MCJIT_TEST_BASE_H +#include "MCJITTestAPICommon.h" #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -26,7 +27,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" #include "llvm/Support/CodeGen.h" -#include "MCJITTestAPICommon.h" namespace llvm { @@ -185,11 +185,9 @@ protected: // Populates Modules A and B: // Module A { Extern FB1, Function FA which calls FB1 }, // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, - void createCrossModuleRecursiveCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB1, - Function *&FB2) { + void createCrossModuleRecursiveCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, + Function *&FB1, Function *&FB2) { // Define FB1 in B. B.reset(createEmptyModule("B")); FB1 = insertAccumulateFunction(B.get(), 0, "FB1"); @@ -211,12 +209,10 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA }, // Module C { Extern FB, Function FC which calls FB }, - void createThreeModuleChainedCallsCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB, - OwningPtr<Module> &C, - Function *&FC) { + void + createThreeModuleChainedCallsCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB, + std::unique_ptr<Module> &C, Function *&FC) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -233,8 +229,8 @@ protected: // Module A { Function FA }, // Populates Modules A and B: // Module B { Function FB } - void createTwoModuleCase(OwningPtr<Module> &A, Function *&FA, - OwningPtr<Module> &B, Function *&FB) { + void createTwoModuleCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -244,8 +240,8 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA } - void createTwoModuleExternCase(OwningPtr<Module> &A, Function *&FA, - OwningPtr<Module> &B, Function *&FB) { + void createTwoModuleExternCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -258,12 +254,9 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA }, // Module C { Extern FB, Function FC which calls FA }, - void createThreeModuleCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB, - OwningPtr<Module> &C, - Function *&FC) { + void createThreeModuleCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB, + std::unique_ptr<Module> &C, Function *&FC) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -311,6 +304,8 @@ protected: // should be kept in sync. UnsupportedOSs.push_back(Triple::Cygwin); UnsupportedOSs.push_back(Triple::Darwin); + + UnsupportedEnvironments.push_back(Triple::Cygnus); } void createJIT(Module *M) { @@ -342,10 +337,10 @@ protected: CodeModel::Model CodeModel; StringRef MArch; SmallVector<std::string, 1> MAttrs; - OwningPtr<ExecutionEngine> TheJIT; + std::unique_ptr<ExecutionEngine> TheJIT; RTDyldMemoryManager *MM; - OwningPtr<Module> M; + std::unique_ptr<Module> M; }; } // namespace llvm diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index 33b043be9ebd..c4dd740e0575 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = MCJIT -LINK_COMPONENTS := core mcjit native support +LINK_COMPONENTS := core ipo jit mcjit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index fd0831f8e1fa..b439d59dec7b 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -1,15 +1,19 @@ set(LLVM_LINK_COMPONENTS - asmparser - core - ipa + Analysis + AsmParser + Core + IPA + Support ) set(IRSources AttributesTest.cpp + ConstantRangeTest.cpp ConstantsTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp + LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp @@ -17,18 +21,14 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + UserTest.cpp + ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp VerifierTest.cpp WaymarkTest.cpp ) -# MSVC9 and 8 cannot compile ValueMapTest.cpp due to their bug. -# See issue#331418 in Visual Studio. -if(MSVC AND MSVC_VERSION LESS 1600) - list(REMOVE_ITEM IRSources ValueMapTest.cpp) -endif() - # HACK: Declare a couple of source files as optionally compiled to satisfy the # missing-file-checker in LLVM's weird CMake build. set(LLVM_OPTIONAL_SOURCES diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp index 3e0a085ed1e7..fa03302ad2bb 100644 --- a/unittests/Support/ConstantRangeTest.cpp +++ b/unittests/IR/ConstantRangeTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange tests --===// +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/ConstantRange.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Instructions.h" #include "gtest/gtest.h" @@ -99,11 +99,11 @@ TEST_F(ConstantRangeTest, Equality) { } TEST_F(ConstantRangeTest, SingleElement) { - EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL)); - EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(nullptr)); + EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(nullptr)); EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); - EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL)); - EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(nullptr)); + EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(nullptr)); EXPECT_FALSE(Full.isSingleElement()); EXPECT_FALSE(Empty.isSingleElement()); diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index fee38b891de4..0cd854998286 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -162,7 +162,7 @@ TEST(ConstantsTest, PointerCast) { } TEST(ConstantsTest, AsInstructionsTest) { - OwningPtr<Module> M(new Module("MyModule", getGlobalContext())); + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); Type *Int64Ty = Type::getInt64Ty(getGlobalContext()); Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); @@ -254,6 +254,24 @@ TEST(ConstantsTest, AsInstructionsTest) { P6STR ", i32 1"); } +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(ConstantsTest, ReplaceWithConstantTest) { + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); + + Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); + Constant *One = ConstantInt::get(Int32Ty, 1); + + Constant *Global = + M->getOrInsertGlobal("dummy", PointerType::getUnqual(Int32Ty)); + Constant *GEP = ConstantExpr::getGetElementPtr(Global, One); + EXPECT_DEATH(Global->replaceAllUsesWith(GEP), + "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!"); +} + +#endif +#endif + #undef CHECK } // end anonymous namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index 4e5af9395cc8..ab43d1c91fcd 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Dominators.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -25,7 +26,9 @@ namespace llvm { struct DPass : public FunctionPass { static char ID; virtual bool runOnFunction(Function &F) { - DominatorTree *DT = &getAnalysis<DominatorTree>(); + DominatorTree *DT = + &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + PostDominatorTree *PDT = &getAnalysis<PostDominatorTree>(); Function::iterator FI = F.begin(); BasicBlock *BB0 = FI++; @@ -148,10 +151,34 @@ namespace llvm { EXPECT_TRUE(DT->dominates(Y6, BB3)); + // Post dominance. + EXPECT_TRUE(PDT->dominates(BB0, BB0)); + EXPECT_FALSE(PDT->dominates(BB1, BB0)); + EXPECT_FALSE(PDT->dominates(BB2, BB0)); + EXPECT_FALSE(PDT->dominates(BB3, BB0)); + EXPECT_TRUE(PDT->dominates(BB4, BB1)); + + // Dominance descendants. + SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs; + + DT->getDescendants(BB0, DominatedBBs); + PDT->getDescendants(BB0, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 4UL); + EXPECT_EQ(PostDominatedBBs.size(), 1UL); + + // BB3 is unreachable. It should have no dominators nor postdominators. + DominatedBBs.clear(); + PostDominatedBBs.clear(); + DT->getDescendants(BB3, DominatedBBs); + DT->getDescendants(BB3, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 0UL); + EXPECT_EQ(PostDominatedBBs.size(), 0UL); + return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); + AU.addRequired<PostDominatorTree>(); } DPass() : FunctionPass(ID) { initializeDPassPass(*PassRegistry::getPassRegistry()); @@ -186,12 +213,12 @@ namespace llvm { "}\n"; LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(ModuleStrig, NULL, Err, C); + return ParseAssemblyString(ModuleStrig, nullptr, Err, C); } TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - OwningPtr<Module> M(makeLLVMModule(P)); + std::unique_ptr<Module> M(makeLLVMModule(P)); PassManager Passes; Passes.add(P); Passes.run(*M); @@ -200,5 +227,6 @@ namespace llvm { } INITIALIZE_PASS_BEGIN(DPass, "dpass", "dpass", false, false) -INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_END(DPass, "dpass", "dpass", false, false) diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2f390f7f75a2..21085755fbad 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/IRBuilder.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" @@ -16,6 +15,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "gtest/gtest.h" using namespace llvm; @@ -31,16 +31,16 @@ protected: F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); BB = BasicBlock::Create(Ctx, "", F); GV = new GlobalVariable(*M, Type::getFloatTy(Ctx), true, - GlobalValue::ExternalLinkage, 0); + GlobalValue::ExternalLinkage, nullptr); } virtual void TearDown() { - BB = 0; + BB = nullptr; M.reset(); } LLVMContext Ctx; - OwningPtr<Module> M; + std::unique_ptr<Module> M; Function *F; BasicBlock *BB; GlobalVariable *GV; @@ -71,9 +71,9 @@ TEST_F(IRBuilderTest, Lifetime) { IntrinsicInst *II_Start1 = dyn_cast<IntrinsicInst>(Start1); IntrinsicInst *II_End1 = dyn_cast<IntrinsicInst>(End1); - ASSERT_TRUE(II_Start1 != NULL); + ASSERT_TRUE(II_Start1 != nullptr); EXPECT_EQ(II_Start1->getIntrinsicID(), Intrinsic::lifetime_start); - ASSERT_TRUE(II_End1 != NULL); + ASSERT_TRUE(II_End1 != nullptr); EXPECT_EQ(II_End1->getIntrinsicID(), Intrinsic::lifetime_end); } @@ -107,6 +107,14 @@ TEST_F(IRBuilderTest, LandingPadName) { EXPECT_EQ(LP->getName(), "LP"); } +TEST_F(IRBuilderTest, DataLayout) { + std::unique_ptr<Module> M(new Module("test", Ctx)); + M->setDataLayout("e-n32"); + EXPECT_TRUE(M->getDataLayout()->isLegalInteger(32)); + M->setDataLayout("e"); + EXPECT_FALSE(M->getDataLayout()->isLegalInteger(32)); +} + TEST_F(IRBuilderTest, GetIntTy) { IRBuilder<> Builder(BB); IntegerType *Ty1 = Builder.getInt1Ty(); @@ -147,6 +155,13 @@ TEST_F(IRBuilderTest, FastMathFlags) { FAdd = cast<Instruction>(F); EXPECT_TRUE(FAdd->hasNoNaNs()); + // Now, try it with CreateBinOp + F = Builder.CreateBinOp(Instruction::FAdd, F, F); + EXPECT_TRUE(Builder.getFastMathFlags().any()); + ASSERT_TRUE(isa<Instruction>(F)); + FAdd = cast<Instruction>(F); + EXPECT_TRUE(FAdd->hasNoNaNs()); + F = Builder.CreateFDiv(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); EXPECT_TRUE(Builder.getFastMathFlags().UnsafeAlgebra); @@ -183,6 +198,56 @@ TEST_F(IRBuilderTest, FastMathFlags) { } +TEST_F(IRBuilderTest, WrapFlags) { + IRBuilder<true, NoFolder> Builder(BB); + + // Test instructions. + GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true, + GlobalValue::ExternalLinkage, nullptr); + Value *V = Builder.CreateLoad(G); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); + + // Test operators created with constants. + Constant *C = Builder.getInt32(42); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); +} + TEST_F(IRBuilderTest, RAIIHelpersTest) { IRBuilder<> Builder(BB); EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal()); diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 65f85ba1b707..7ec9b62207fb 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -14,11 +14,14 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" +#include <memory> namespace llvm { namespace { @@ -47,6 +50,58 @@ TEST(InstructionsTest, ReturnInst) { delete r1; } +// Test fixture that provides a module and a single function within it. Useful +// for tests that need to refer to the function in some way. +class ModuleWithFunctionTest : public testing::Test { +protected: + ModuleWithFunctionTest() : M(new Module("MyModule", Ctx)) { + FArgTypes.push_back(Type::getInt8Ty(Ctx)); + FArgTypes.push_back(Type::getInt32Ty(Ctx)); + FArgTypes.push_back(Type::getInt64Ty(Ctx)); + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Ctx), FArgTypes, false); + F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); + } + + LLVMContext Ctx; + std::unique_ptr<Module> M; + SmallVector<Type *, 3> FArgTypes; + Function *F; +}; + +TEST_F(ModuleWithFunctionTest, CallInst) { + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<CallInst> Call(CallInst::Create(F, Args)); + + // Make sure iteration over a call's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Call->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Call->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + +TEST_F(ModuleWithFunctionTest, InvokeInst) { + BasicBlock *BB1 = BasicBlock::Create(Ctx, "", F); + BasicBlock *BB2 = BasicBlock::Create(Ctx, "", F); + + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<InvokeInst> Invoke(InvokeInst::Create(F, BB1, BB2, Args)); + + // Make sure iteration over invoke's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Invoke->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Invoke->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + TEST(InstructionsTest, BranchInst) { LLVMContext &C(getGlobalContext()); @@ -65,9 +120,9 @@ TEST(InstructionsTest, BranchInst) { EXPECT_EQ(1U, b0->getNumOperands()); EXPECT_NE(b0->op_begin(), b0->op_end()); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); IntegerType* Int1 = IntegerType::get(C, 1); Constant* One = ConstantInt::get(Int1, 1, true); @@ -145,6 +200,7 @@ TEST(InstructionsTest, CastInst) { Type *V2Int64PtrTy = VectorType::get(Int64PtrTy, 2); Type *V2Int32PtrTy = VectorType::get(Int32PtrTy, 2); + Type *V4Int32PtrTy = VectorType::get(Int32PtrTy, 4); const Constant* c8 = Constant::getNullValue(V8x8Ty); const Constant* c64 = Constant::getNullValue(V8x64Ty); @@ -205,6 +261,21 @@ TEST(InstructionsTest, CastInst) { EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V4Int32PtrTy), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrTy)); + + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V4Int32PtrAS1Ty), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrAS1Ty)); + + // Check that assertion is not hit when creating a cast with a vector of // pointers // First form @@ -269,7 +340,7 @@ TEST(InstructionsTest, VectorGep) { int64_t Offset; DataLayout TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3" - "2:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80" + "2:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-s:64:64-f80" ":128:128-n8:16:32:64-S128"); // Make sure we don't crash GetPointerBaseWithConstantOffset(Gep0, Offset, &TD); @@ -344,7 +415,7 @@ TEST(InstructionsTest, isEliminableCastPair) { EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, CastInst::IntToPtr, Int64PtrTy, Int64Ty, Int64PtrTy, - Int32Ty, 0, Int32Ty), + Int32Ty, nullptr, Int32Ty), CastInst::BitCast); // Source and destination have unknown sizes, but the same address space and @@ -352,7 +423,7 @@ TEST(InstructionsTest, isEliminableCastPair) { EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, CastInst::IntToPtr, Int64PtrTy, Int64Ty, Int64PtrTy, - 0, 0, 0), + nullptr, nullptr, nullptr), CastInst::BitCast); // Source and destination have unknown sizes, but the same address space and @@ -360,28 +431,28 @@ TEST(InstructionsTest, isEliminableCastPair) { EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, CastInst::IntToPtr, Int64PtrTy, Int32Ty, Int64PtrTy, - 0, 0, 0), + nullptr, nullptr, nullptr), 0U); // Middle pointer big enough -> bitcast. EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, CastInst::PtrToInt, Int64Ty, Int64PtrTy, Int64Ty, - 0, Int64Ty, 0), + nullptr, Int64Ty, nullptr), CastInst::BitCast); // Middle pointer too small -> fail. EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, CastInst::PtrToInt, Int64Ty, Int64PtrTy, Int64Ty, - 0, Int32Ty, 0), + nullptr, Int32Ty, nullptr), 0U); // Test that we don't eliminate bitcasts between different address spaces, // or if we don't have available pointer size information. DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16" "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64" - "-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"); + "-v128:128:128-a:0:64-s:64:64-f80:128:128-n8:16:32:64-S128"); Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1); Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2); @@ -393,25 +464,58 @@ TEST(InstructionsTest, isEliminableCastPair) { EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, CastInst::AddrSpaceCast, Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2, - 0, Int16SizePtr, Int64SizePtr), + nullptr, Int16SizePtr, Int64SizePtr), 0U); // Cannot simplify addrspacecast, ptrtoint EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::AddrSpaceCast, CastInst::PtrToInt, Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty, - Int64SizePtr, Int16SizePtr, 0), + Int64SizePtr, Int16SizePtr, nullptr), 0U); // Pass since the bitcast address spaces are the same EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, CastInst::BitCast, Int16Ty, Int64PtrTyAS1, Int64PtrTyAS1, - 0, 0, 0), + nullptr, nullptr, nullptr), CastInst::IntToPtr); } +TEST(InstructionsTest, CloneCall) { + LLVMContext &C(getGlobalContext()); + Type *Int32Ty = Type::getInt32Ty(C); + Type *ArgTys[] = {Int32Ty, Int32Ty, Int32Ty}; + Type *FnTy = FunctionType::get(Int32Ty, ArgTys, /*isVarArg=*/false); + Value *Callee = Constant::getNullValue(FnTy->getPointerTo()); + Value *Args[] = { + ConstantInt::get(Int32Ty, 1), + ConstantInt::get(Int32Ty, 2), + ConstantInt::get(Int32Ty, 3) + }; + std::unique_ptr<CallInst> Call(CallInst::Create(Callee, Args, "result")); + + // Test cloning the tail call kind. + CallInst::TailCallKind Kinds[] = {CallInst::TCK_None, CallInst::TCK_Tail, + CallInst::TCK_MustTail}; + for (CallInst::TailCallKind TCK : Kinds) { + Call->setTailCallKind(TCK); + std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone())); + EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind()); + } + Call->setTailCallKind(CallInst::TCK_None); + + // Test cloning an attribute. + { + AttrBuilder AB; + AB.addAttribute(Attribute::ReadOnly); + Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB)); + std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone())); + EXPECT_TRUE(Clone->onlyReadsMemory()); + } +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/Support/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp index d198c7a8bda0..94eed4c1432b 100644 --- a/unittests/Support/LeakDetectorTest.cpp +++ b/unittests/IR/LeakDetectorTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/LeakDetector/LeakDetector.cpp - LeakDetector tests ---===// +//===- LeakDetectorTest.cpp -----------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/LeakDetector.h" #include "gtest/gtest.h" -#include "llvm/Support/LeakDetector.h" using namespace llvm; diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 11841bdeac0d..9c2a835ca099 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -19,8 +19,6 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/PrintModulePass.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" @@ -28,10 +26,12 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -99,7 +99,7 @@ namespace llvm { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run++; return false; } @@ -176,7 +176,7 @@ namespace llvm { initializeCGPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnSCC(CallGraphSCC &SCMM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -215,7 +215,7 @@ namespace llvm { return false; } virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -252,7 +252,7 @@ namespace llvm { return false; } virtual bool runOnBasicBlock(BasicBlock &BB) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -277,7 +277,7 @@ namespace llvm { initializeFPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; { @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); Passes.add(mNDM2); Passes.add(mNDM); Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -346,10 +346,10 @@ namespace llvm { template<typename T> void MemoryTestHelper(int run) { - OwningPtr<Module> M(makeLLVMModule()); + std::unique_ptr<Module> M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayout(M.get())); + Passes.add(new DataLayoutPass(M.get())); Passes.add(P); Passes.run(*M); T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm { Module *M = makeLLVMModule(); T *P = new T(); PassManager Passes; - Passes.add(new DataLayout(M)); + Passes.add(new DataLayoutPass(M)); Passes.add(P); Passes.run(*M); T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); PassManager Passes; - Passes.add(new DataLayout(M)); + Passes.add(new DataLayoutPass(M)); Passes.add(O); Passes.run(*M); @@ -412,7 +412,7 @@ namespace llvm { Module* mod = new Module("test-mem", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" - "a0:0:64-s0:64:64-f80:128:128"); + "a:0:64-s:64:64-f80:128:128"); mod->setTargetTriple("x86_64-unknown-linux-gnu"); // Type Definitions @@ -476,7 +476,7 @@ namespace llvm { // Function: test1 (func_test1) { - BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0); + BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,nullptr); // Block entry (label_entry) CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry); @@ -491,7 +491,7 @@ namespace llvm { // Function: test2 (func_test2) { - BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0); + BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,nullptr); // Block entry (label_entry_5) CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5); @@ -506,7 +506,7 @@ namespace llvm { // Function: test3 (func_test3) { - BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0); + BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,nullptr); // Block entry (label_entry_8) CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8); @@ -524,10 +524,10 @@ namespace llvm { Value* int1_f = args++; int1_f->setName("f"); - BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0); - BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0); - BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0); - BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0); + BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,nullptr); + BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,nullptr); + BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,nullptr); + BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,nullptr); // Block entry (label_entry_11) BranchInst::Create(label_bb, label_entry_11); @@ -550,7 +550,7 @@ namespace llvm { INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) -INITIALIZE_PASS_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS(FPass, "fp","fp", false, false) INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp index 665d559bf0b7..fc4674ea1357 100644 --- a/unittests/IR/MDBuilderTest.cpp +++ b/unittests/IR/MDBuilderTest.cpp @@ -9,6 +9,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" @@ -32,8 +33,8 @@ TEST_F(MDBuilderTest, createFPMath) { MDBuilder MDHelper(Context); MDNode *MD0 = MDHelper.createFPMath(0.0); MDNode *MD1 = MDHelper.createFPMath(1.0); - EXPECT_EQ(MD0, (MDNode *)0); - EXPECT_NE(MD1, (MDNode *)0); + EXPECT_EQ(MD0, (MDNode *)nullptr); + EXPECT_NE(MD1, (MDNode *)nullptr); EXPECT_EQ(MD1->getNumOperands(), 1U); Value *Op = MD1->getOperand(0); EXPECT_TRUE(isa<ConstantFP>(Op)); @@ -46,8 +47,8 @@ TEST_F(MDBuilderTest, createRangeMetadata) { APInt A(8, 1), B(8, 2); MDNode *R0 = MDHelper.createRange(A, A); MDNode *R1 = MDHelper.createRange(A, B); - EXPECT_EQ(R0, (MDNode *)0); - EXPECT_NE(R1, (MDNode *)0); + EXPECT_EQ(R0, (MDNode *)nullptr); + EXPECT_NE(R1, (MDNode *)nullptr); EXPECT_EQ(R1->getNumOperands(), 2U); EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(0))); EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(1))); @@ -65,8 +66,8 @@ TEST_F(MDBuilderTest, createAnonymousTBAARoot) { EXPECT_GE(R1->getNumOperands(), 1U); EXPECT_EQ(R0->getOperand(0), R0); EXPECT_EQ(R1->getOperand(0), R1); - EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == 0); - EXPECT_TRUE(R1->getNumOperands() == 1 || R1->getOperand(1) == 0); + EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr); + EXPECT_TRUE(R1->getNumOperands() == 1 || R1->getOperand(1) == nullptr); } TEST_F(MDBuilderTest, createTBAARoot) { MDBuilder MDHelper(Context); @@ -76,7 +77,7 @@ TEST_F(MDBuilderTest, createTBAARoot) { EXPECT_GE(R0->getNumOperands(), 1U); EXPECT_TRUE(isa<MDString>(R0->getOperand(0))); EXPECT_EQ(cast<MDString>(R0->getOperand(0))->getString(), "Root"); - EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == 0); + EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr); } TEST_F(MDBuilderTest, createTBAANode) { MDBuilder MDHelper(Context); diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 352e83ee662e..4f7bd720d1c3 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -103,7 +103,7 @@ TEST_F(MDNodeTest, Simple) { #endif EXPECT_EQ(n4, n1); EXPECT_EQ(n5, n2); - EXPECT_EQ(n6, (Value*)0); + EXPECT_EQ(n6, (Value*)nullptr); EXPECT_EQ(3u, n1->getNumOperands()); EXPECT_EQ(s1, n1->getOperand(0)); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 7b60e3899a0e..25037a773cfc 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -19,21 +19,21 @@ using namespace llvm; namespace { -class TestAnalysisPass { +class TestFunctionAnalysis { public: - typedef Function IRUnitT; - struct Result { Result(int Count) : InstructionCount(Count) {} - bool invalidate(Function *) { return true; } int InstructionCount; }; /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} + /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F) { + Result run(Function *F, FunctionAnalysisManager *AM) { + ++Runs; int Count = 0; for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; @@ -45,49 +45,135 @@ public: private: /// \brief Private static data to provide unique ID. static char PassID; + + int &Runs; }; -char TestAnalysisPass::PassID; +char TestFunctionAnalysis::PassID; + +class TestModuleAnalysis { +public: + struct Result { + Result(int Count) : FunctionCount(Count) {} + int FunctionCount; + }; + + static void *ID() { return (void *)&PassID; } + + TestModuleAnalysis(int &Runs) : Runs(Runs) {} + + Result run(Module *M, ModuleAnalysisManager *AM) { + ++Runs; + int Count = 0; + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + ++Count; + return Result(Count); + } + +private: + static char PassID; + + int &Runs; +}; + +char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - bool run(Module *M) { + PreservedAnalyses run(Module *M) { ++RunCount; - return true; + return PreservedAnalyses::none(); } + static StringRef name() { return "TestModulePass"; } + int &RunCount; }; -struct TestFunctionPass { - TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount) - : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) { +struct TestPreservingModulePass { + PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + + static StringRef name() { return "TestPreservingModulePass"; } +}; + +struct TestMinPreservingModulePass { + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses PA; + + // Force running an analysis. + (void)AM->getResult<TestModuleAnalysis>(M); + + PA.preserve<FunctionAnalysisManagerModuleProxy>(); + return PA; } - bool run(Function *F) { + static StringRef name() { return "TestMinPreservingModulePass"; } +}; + +struct TestFunctionPass { + TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, + int &AnalyzedFunctionCount, + bool OnlyUseCachedResults = false) + : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), + AnalyzedFunctionCount(AnalyzedFunctionCount), + OnlyUseCachedResults(OnlyUseCachedResults) {} + + PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { ++RunCount; - const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F); - AnalyzedInstrCount += AR.InstructionCount; + const ModuleAnalysisManager &MAM = + AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + if (TestModuleAnalysis::Result *TMA = + MAM.getCachedResult<TestModuleAnalysis>(F->getParent())) + AnalyzedFunctionCount += TMA->FunctionCount; - return true; + if (OnlyUseCachedResults) { + // Hack to force the use of the cached interface. + if (TestFunctionAnalysis::Result *AR = + AM->getCachedResult<TestFunctionAnalysis>(F)) + AnalyzedInstrCount += AR->InstructionCount; + } else { + // Typical path just runs the analysis as needed. + TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F); + AnalyzedInstrCount += AR.InstructionCount; + } + + return PreservedAnalyses::all(); } - AnalysisManager &AM; + static StringRef name() { return "TestFunctionPass"; } + int &RunCount; int &AnalyzedInstrCount; + int &AnalyzedFunctionCount; + bool OnlyUseCachedResults; +}; + +// A test function pass that invalidates all function analyses for a function +// with a specific name. +struct TestInvalidationFunctionPass { + TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} + + PreservedAnalyses run(Function *F) { + return F->getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + } + + static StringRef name() { return "TestInvalidationFunctionPass"; } + + StringRef Name; }; Module *parseIR(const char *IR) { LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(IR, 0, Err, C); + return ParseAssemblyString(IR, nullptr, Err, C); } class PassManagerTest : public ::testing::Test { protected: - OwningPtr<Module> M; + std::unique_ptr<Module> M; public: PassManagerTest() @@ -105,27 +191,154 @@ public: "}\n")) {} }; +TEST_F(PassManagerTest, BasicPreservedAnalyses) { + PreservedAnalyses PA1 = PreservedAnalyses(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA2 = PreservedAnalyses::none(); + EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA3 = PreservedAnalyses::all(); + EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA4 = PA1; + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4 = PA3; + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>()); + PA4 = std::move(PA2); + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA1.preserve<TestModuleAnalysis>(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.intersect(PA4); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); +} + TEST_F(PassManagerTest, Basic) { - AnalysisManager AM(M.get()); - AM.registerAnalysisPass(TestAnalysisPass()); + FunctionAnalysisManager FAM; + int FunctionAnalysisRuns = 0; + FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns)); - ModulePassManager MPM(M.get(), &AM); - FunctionPassManager FPM(&AM); + ModuleAnalysisManager MAM; + int ModuleAnalysisRuns = 0; + MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns)); + MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); + FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); + + ModulePassManager MPM; + + // Count the runs over a Function. + int FunctionPassRunCount1 = 0; + int AnalyzedInstrCount1 = 0; + int AnalyzedFunctionCount1 = 0; + { + // Pointless scoped copy to test move assignment. + ModulePassManager NestedMPM; + FunctionPassManager FPM; + { + // Pointless scope to test move assignment. + FunctionPassManager NestedFPM; + NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1, + AnalyzedFunctionCount1)); + FPM = std::move(NestedFPM); + } + NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + MPM = std::move(NestedMPM); + } // Count the runs over a module. int ModulePassRunCount = 0; MPM.addPass(TestModulePass(ModulePassRunCount)); - // Count the runs over a Function. - int FunctionPassRunCount = 0; - int AnalyzedInstrCount = 0; - FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount)); - MPM.addPass(FPM); + // Count the runs over a Function in a separate manager. + int FunctionPassRunCount2 = 0; + int AnalyzedInstrCount2 = 0; + int AnalyzedFunctionCount2 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, + AnalyzedFunctionCount2)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A third function pass manager but with only preserving intervening passes + // and with a function pass that invalidates exactly one analysis. + MPM.addPass(TestPreservingModulePass()); + int FunctionPassRunCount3 = 0; + int AnalyzedInstrCount3 = 0; + int AnalyzedFunctionCount3 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, + AnalyzedFunctionCount3)); + FPM.addPass(TestInvalidationFunctionPass("f")); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A fourth function pass manager but with a minimal intervening passes. + MPM.addPass(TestMinPreservingModulePass()); + int FunctionPassRunCount4 = 0; + int AnalyzedInstrCount4 = 0; + int AnalyzedFunctionCount4 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, + AnalyzedFunctionCount4)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } - MPM.run(); + // A fifth function pass manager but which uses only cached results. + int FunctionPassRunCount5 = 0; + int AnalyzedInstrCount5 = 0; + int AnalyzedFunctionCount5 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestInvalidationFunctionPass("f")); + FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, + AnalyzedFunctionCount5, + /*OnlyUseCachedResults=*/true)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + MPM.run(M.get(), &MAM); + + // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); - EXPECT_EQ(3, FunctionPassRunCount); - EXPECT_EQ(5, AnalyzedInstrCount); -} + // Validate all function pass counter sets are the same. + EXPECT_EQ(3, FunctionPassRunCount1); + EXPECT_EQ(5, AnalyzedInstrCount1); + EXPECT_EQ(0, AnalyzedFunctionCount1); + EXPECT_EQ(3, FunctionPassRunCount2); + EXPECT_EQ(5, AnalyzedInstrCount2); + EXPECT_EQ(0, AnalyzedFunctionCount2); + EXPECT_EQ(3, FunctionPassRunCount3); + EXPECT_EQ(5, AnalyzedInstrCount3); + EXPECT_EQ(0, AnalyzedFunctionCount3); + EXPECT_EQ(3, FunctionPassRunCount4); + EXPECT_EQ(5, AnalyzedInstrCount4); + EXPECT_EQ(0, AnalyzedFunctionCount4); + EXPECT_EQ(3, FunctionPassRunCount5); + EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. + EXPECT_EQ(0, AnalyzedFunctionCount5); + + // Validate the analysis counters: + // first run over 3 functions, then module pass invalidates + // second run over 3 functions, nothing invalidates + // third run over 0 functions, but 1 function invalidated + // fourth run over 1 function + EXPECT_EQ(7, FunctionAnalysisRuns); + + EXPECT_EQ(1, ModuleAnalysisRuns); +} } diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp index 7c6d8ce61586..f3a27b8d2509 100644 --- a/unittests/IR/PatternMatch.cpp +++ b/unittests/IR/PatternMatch.cpp @@ -13,253 +13,286 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Instructions.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/NoFolder.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" #include "gtest/gtest.h" +using namespace llvm; using namespace llvm::PatternMatch; -namespace llvm { namespace { -/// Ordered floating point minimum/maximum tests. - -static void m_OrdFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; +struct PatternMatchTest : ::testing::Test { + LLVMContext Ctx; + std::unique_ptr<Module> M; + Function *F; + BasicBlock *BB; + IRBuilder<true, NoFolder> IRB; + + PatternMatchTest() + : M(new Module("PatternMatchTestModule", Ctx)), + F(Function::Create( + FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false), + Function::ExternalLinkage, "f", M.get())), + BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {} +}; + +TEST_F(PatternMatchTest, OneUse) { + // Build up a little tree of values: + // + // One = (1 + 2) + 42 + // Two = One + 42 + // Leaf = (Two + 8) + (Two + 13) + Value *One = IRB.CreateAdd(IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2)), + IRB.getInt32(42)); + Value *Two = IRB.CreateAdd(One, IRB.getInt32(42)); + Value *Leaf = IRB.CreateAdd(IRB.CreateAdd(Two, IRB.getInt32(8)), + IRB.CreateAdd(Two, IRB.getInt32(13))); + Value *V; + + EXPECT_TRUE(m_OneUse(m_Value(V)).match(One)); + EXPECT_EQ(One, V); + + EXPECT_FALSE(m_OneUse(m_Value()).match(Two)); + EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf)); } -static void m_OrdFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - - - -TEST(PatternMatchTest, FloatingPointOrderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OLT. - Value *Cmp = Builder.CreateFCmpOLT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); // Test no match on OGT. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); // Test match on OGE with inverted select. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on OGT with inverted select. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointOrderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OGT. - Value *Cmp = Builder.CreateFCmpOGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); // Test no match on OLT. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); // Test match on OLE with inverted select. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); - - // Test match on OLT with inverted select. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); -} - -/// Unordered floating point minimum/maximum tests. - -static void m_UnordFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} -static void m_UnordFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + // Test match on OLT with inverted select. + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; } -TEST(PatternMatchTest, FloatingPointUnorderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test ULT. - Value *Cmp = Builder.CreateFCmpULT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); // Test no match on UGT. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); // Test match on UGE with inverted select. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on UGT with inverted select. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointUnorderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test UGT. - Value *Cmp = Builder.CreateFCmpUGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); // Test no match on ULT. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); // Test match on ULE with inverted select. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on ULT with inverted select. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); +} + +TEST_F(PatternMatchTest, OverflowingBinOps) { + Value *L = IRB.getInt32(1); + Value *R = IRB.getInt32(2); + Value *MatchL, *MatchR; + + EXPECT_TRUE( + m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE( + m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE( + m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_TRUE( + m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE( + m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE( + m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = nullptr; + EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); } } // anonymous namespace. -} // llvm namespace. diff --git a/unittests/IR/TypeBuilderTest.cpp b/unittests/IR/TypeBuilderTest.cpp index be493cdc6396..b7b3e45e35ed 100644 --- a/unittests/IR/TypeBuilderTest.cpp +++ b/unittests/IR/TypeBuilderTest.cpp @@ -234,19 +234,19 @@ TEST(TypeBuilderTest, Extensions) { TypeBuilder<int, false>::get(getGlobalContext()), TypeBuilder<int*, false>::get(getGlobalContext()), TypeBuilder<void*[], false>::get(getGlobalContext()), - (void*)0)), + (void*)nullptr)), (TypeBuilder<MyType*, false>::get(getGlobalContext()))); EXPECT_EQ(PointerType::getUnqual(StructType::get( TypeBuilder<types::i<32>, false>::get(getGlobalContext()), TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), - (void*)0)), + (void*)nullptr)), (TypeBuilder<MyPortableType*, false>::get(getGlobalContext()))); EXPECT_EQ(PointerType::getUnqual(StructType::get( TypeBuilder<types::i<32>, false>::get(getGlobalContext()), TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), - (void*)0)), + (void*)nullptr)), (TypeBuilder<MyPortableType*, true>::get(getGlobalContext()))); } diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp new file mode 100644 index 000000000000..eb07e824d8b8 --- /dev/null +++ b/unittests/IR/UserTest.cpp @@ -0,0 +1,96 @@ +//===- llvm/unittest/IR/UserTest.cpp - User 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/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { + +TEST(UserTest, ValueOpIteration) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n" + "entry:\n" + " switch i32 undef, label %s0\n" + " [ i32 1, label %s1\n" + " i32 2, label %s2\n" + " i32 3, label %s3\n" + " i32 4, label %s4\n" + " i32 5, label %s5\n" + " i32 6, label %s6\n" + " i32 7, label %s7\n" + " i32 8, label %s8\n" + " i32 9, label %s9 ]\n" + "\n" + "s0:\n" + " br label %exit\n" + "s1:\n" + " br label %exit\n" + "s2:\n" + " br label %exit\n" + "s3:\n" + " br label %exit\n" + "s4:\n" + " br label %exit\n" + "s5:\n" + " br label %exit\n" + "s6:\n" + " br label %exit\n" + "s7:\n" + " br label %exit\n" + "s8:\n" + " br label %exit\n" + "s9:\n" + " br label %exit\n" + "\n" + "exit:\n" + " %phi = phi i32 [ 0, %s0 ], [ 1, %s1 ],\n" + " [ 2, %s2 ], [ 3, %s3 ],\n" + " [ 4, %s4 ], [ 5, %s5 ],\n" + " [ 6, %s6 ], [ 7, %s7 ],\n" + " [ 8, %s8 ], [ 9, %s9 ]\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + + Function *F = M->getFunction("f"); + BasicBlock &ExitBB = F->back(); + PHINode &P = cast<PHINode>(ExitBB.front()); + EXPECT_TRUE(P.value_op_begin() == P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() == P.value_op_end()); + EXPECT_TRUE(P.value_op_begin() != P.value_op_end()); + EXPECT_FALSE(P.value_op_end() != P.value_op_end()); + EXPECT_TRUE(P.value_op_begin() < P.value_op_end()); + EXPECT_FALSE(P.value_op_begin() < P.value_op_begin()); + EXPECT_TRUE(P.value_op_end() > P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() > P.value_op_begin()); + EXPECT_TRUE(P.value_op_begin() <= P.value_op_begin()); + EXPECT_FALSE(P.value_op_end() <= P.value_op_begin()); + EXPECT_TRUE(P.value_op_begin() >= P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() >= P.value_op_end()); + EXPECT_EQ(10, std::distance(P.value_op_begin(), P.value_op_end())); + + User::value_op_iterator I = P.value_op_begin(); + I += 3; + EXPECT_EQ(std::next(P.value_op_begin(), 3), I); + EXPECT_EQ(P.getOperand(3), *I); + I++; + EXPECT_EQ(P.getOperand(6), I[2]); + EXPECT_EQ(P.value_op_end(), (I - 2) + 8); +} + +} // end anonymous namespace diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp index 05aafa2d05d8..403d2bcbda16 100644 --- a/unittests/Support/ValueHandleTest.cpp +++ b/unittests/IR/ValueHandleTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle tests --------===// +//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/ValueHandle.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" @@ -95,7 +94,7 @@ TEST_F(ValueHandle, WeakVH_NullOnDeletion) { WeakVH WVH_Copy(WVH); WeakVH WVH_Recreated(BitcastV.get()); BitcastV.reset(); - Value *null_value = NULL; + Value *null_value = nullptr; EXPECT_EQ(null_value, WVH); EXPECT_EQ(null_value, WVH_Copy); EXPECT_EQ(null_value, WVH_Recreated); @@ -179,10 +178,10 @@ TEST_F(ValueHandle, AssertingVH_Asserts) { EXPECT_DEATH({BitcastV.reset();}, "An asserting value handle still pointed to this value!"); AssertingVH<Value> Copy(AVH); - AVH = NULL; + AVH = nullptr; EXPECT_DEATH({BitcastV.reset();}, "An asserting value handle still pointed to this value!"); - Copy = NULL; + Copy = nullptr; BitcastV.reset(); } @@ -264,14 +263,14 @@ TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { int DeletedCalls; Value *AURWArgument; - RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {} RecordingVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr) {} private: virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } virtual void allUsesReplacedWith(Value *new_value) { - EXPECT_EQ(NULL, AURWArgument); + EXPECT_EQ(nullptr, AURWArgument); AURWArgument = new_value; } }; @@ -279,7 +278,7 @@ TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { RecordingVH RVH; RVH = BitcastV.get(); EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(NULL, RVH.AURWArgument); + EXPECT_EQ(nullptr, RVH.AURWArgument); BitcastV->replaceAllUsesWith(ConstantV); EXPECT_EQ(0, RVH.DeletedCalls); EXPECT_EQ(ConstantV, RVH.AURWArgument); @@ -292,21 +291,21 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { Value *AURWArgument; LLVMContext *Context; - RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + RecoveringVH() : DeletedCalls(0), AURWArgument(nullptr), Context(&getGlobalContext()) {} RecoveringVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr), Context(&getGlobalContext()) {} private: virtual void deleted() { getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); - setValPtr(NULL); + setValPtr(nullptr); } virtual void allUsesReplacedWith(Value *new_value) { - ASSERT_TRUE(NULL != getValPtr()); + ASSERT_TRUE(nullptr != getValPtr()); EXPECT_EQ(1U, getValPtr()->getNumUses()); - EXPECT_EQ(NULL, AURWArgument); + EXPECT_EQ(nullptr, AURWArgument); AURWArgument = new_value; } }; @@ -336,7 +335,7 @@ TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { class DestroyingVH : public CallbackVH { public: - OwningPtr<WeakVH> ToClear[2]; + std::unique_ptr<WeakVH> ToClear[2]; DestroyingVH(Value *V) { ToClear[0].reset(new WeakVH(V)); setValPtr(V); @@ -369,8 +368,8 @@ TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { WeakVH ShouldBeVisited2(BitcastV.get()); BitcastV.reset(); - EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1)); - EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2)); + EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited2)); } } @@ -390,8 +389,8 @@ TEST_F(ValueHandle, AssertingVHCheckedLast) { } virtual void deleted() { - *ToClear[0] = 0; - *ToClear[1] = 0; + *ToClear[0] = nullptr; + *ToClear[1] = nullptr; CallbackVH::deleted(); } }; diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 5aaf90583628..0b7198fc6ecb 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ValueMap.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -24,8 +23,8 @@ template<typename T> class ValueMapTest : public testing::Test { protected: Constant *ConstantV; - OwningPtr<BitCastInst> BitcastV; - OwningPtr<BinaryOperator> AddV; + std::unique_ptr<BitCastInst> BitcastV; + std::unique_ptr<BinaryOperator> AddV; ValueMapTest() : ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), @@ -41,21 +40,21 @@ TYPED_TEST_CASE(ValueMapTest, KeyTypes); TYPED_TEST(ValueMapTest, Null) { ValueMap<TypeParam*, int> VM1; - VM1[NULL] = 7; - EXPECT_EQ(7, VM1.lookup(NULL)); + VM1[nullptr] = 7; + EXPECT_EQ(7, VM1.lookup(nullptr)); } TYPED_TEST(ValueMapTest, FollowsValue) { ValueMap<TypeParam*, int> VM; VM[this->BitcastV.get()] = 7; EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.count(this->AddV.get())); + EXPECT_EQ(0u, VM.count(this->AddV.get())); this->BitcastV->replaceAllUsesWith(this->AddV.get()); EXPECT_EQ(7, VM.lookup(this->AddV.get())); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); + EXPECT_EQ(0u, VM.count(this->BitcastV.get())); this->AddV.reset(); - EXPECT_EQ(0, VM.count(this->AddV.get())); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); + EXPECT_EQ(0u, VM.count(this->AddV.get())); + EXPECT_EQ(0u, VM.count(this->BitcastV.get())); EXPECT_EQ(0U, VM.size()); } @@ -91,7 +90,7 @@ TYPED_TEST(ValueMapTest, OperationsWork) { EXPECT_EQ(this->AddV.get(), InsertResult1.first->first); EXPECT_EQ(3, InsertResult1.first->second); EXPECT_TRUE(InsertResult1.second); - EXPECT_EQ(true, VM.count(this->AddV.get())); + EXPECT_EQ(1u, VM.count(this->AddV.get())); std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult2 = VM.insert(std::make_pair(this->AddV.get(), 5)); EXPECT_EQ(this->AddV.get(), InsertResult2.first->first); @@ -117,7 +116,8 @@ TYPED_TEST(ValueMapTest, OperationsWork) { template<typename ExpectedType, typename VarType> void CompileAssertHasType(VarType) { - typedef char assert[is_same<ExpectedType, VarType>::value ? 1 : -1]; + static_assert(std::is_same<ExpectedType, VarType>::value, + "Not the same type"); } TYPED_TEST(ValueMapTest, Iteration) { @@ -169,7 +169,7 @@ TYPED_TEST(ValueMapTest, DefaultCollisionBehavior) { VM[this->BitcastV.get()] = 7; VM[this->AddV.get()] = 9; this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_EQ(0, VM.count(this->BitcastV.get())); + EXPECT_EQ(0u, VM.count(this->BitcastV.get())); EXPECT_EQ(9, VM.lookup(this->AddV.get())); } @@ -177,10 +177,10 @@ TYPED_TEST(ValueMapTest, ConfiguredCollisionBehavior) { // TODO: Implement this when someone needs it. } -template<typename KeyT> -struct LockMutex : ValueMapConfig<KeyT> { +template<typename KeyT, typename MutexT> +struct LockMutex : ValueMapConfig<KeyT, MutexT> { struct ExtraData { - sys::Mutex *M; + MutexT *M; bool *CalledRAUW; bool *CalledDeleted; }; @@ -192,15 +192,15 @@ struct LockMutex : ValueMapConfig<KeyT> { *Data.CalledDeleted = true; EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; } - static sys::Mutex *getMutex(const ExtraData &Data) { return Data.M; } + static MutexT *getMutex(const ExtraData &Data) { return Data.M; } }; #if LLVM_ENABLE_THREADS TYPED_TEST(ValueMapTest, LocksMutex) { sys::Mutex M(false); // Not recursive. bool CalledRAUW = false, CalledDeleted = false; - typename LockMutex<TypeParam*>::ExtraData Data = - {&M, &CalledRAUW, &CalledDeleted}; - ValueMap<TypeParam*, int, LockMutex<TypeParam*> > VM(Data); + typedef LockMutex<TypeParam*, sys::Mutex> ConfigType; + typename ConfigType::ExtraData Data = {&M, &CalledRAUW, &CalledDeleted}; + ValueMap<TypeParam*, int, ConfigType> VM(Data); VM[this->BitcastV.get()] = 7; this->BitcastV->replaceAllUsesWith(this->AddV.get()); this->AddV.reset(); @@ -218,7 +218,7 @@ TYPED_TEST(ValueMapTest, NoFollowRAUW) { ValueMap<TypeParam*, int, NoFollow<TypeParam*> > VM; VM[this->BitcastV.get()] = 7; EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); - EXPECT_EQ(0, VM.count(this->AddV.get())); + EXPECT_EQ(0u, VM.count(this->AddV.get())); this->BitcastV->replaceAllUsesWith(this->AddV.get()); EXPECT_EQ(7, VM.lookup(this->BitcastV.get())); EXPECT_EQ(0, VM.lookup(this->AddV.get())); @@ -284,11 +284,11 @@ TYPED_TEST(ValueMapTest, SurvivesModificationByConfig) { // Now the ModifyingConfig can modify the Map inside a callback. VM[this->BitcastV.get()] = 7; this->BitcastV->replaceAllUsesWith(this->AddV.get()); - EXPECT_FALSE(VM.count(this->BitcastV.get())); - EXPECT_FALSE(VM.count(this->AddV.get())); + EXPECT_EQ(0u, VM.count(this->BitcastV.get())); + EXPECT_EQ(0u, VM.count(this->AddV.get())); VM[this->AddV.get()] = 7; this->AddV.reset(); - EXPECT_FALSE(VM.count(this->AddV.get())); + EXPECT_EQ(0u, VM.count(this->AddV.get())); } } diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index ebe23e869401..61e44a908d4e 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -34,7 +34,7 @@ TEST(ValueTest, UsedInBasicBlock) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, NULL, Err, C); + Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); Function *F = M->getFunction("f"); @@ -45,7 +45,7 @@ TEST(ValueTest, UsedInBasicBlock) { TEST(GlobalTest, CreateAddressSpace) { LLVMContext &Ctx = getGlobalContext(); - OwningPtr<Module> M(new Module("TestModule", Ctx)); + std::unique_ptr<Module> M(new Module("TestModule", Ctx)); Type *Int8Ty = Type::getInt8Ty(Ctx); Type *Int32Ty = Type::getInt32Ty(Ctx); @@ -56,7 +56,7 @@ TEST(GlobalTest, CreateAddressSpace) { GlobalValue::ExternalLinkage, Constant::getAllOnesValue(Int32Ty), "dummy", - 0, + nullptr, GlobalVariable::NotThreadLocal, 1); @@ -74,7 +74,7 @@ TEST(GlobalTest, CreateAddressSpace) { GlobalValue::ExternalLinkage, Constant::getAllOnesValue(Int32Ty), "dummy_cast", - 0, + nullptr, GlobalVariable::NotThreadLocal, 1); diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp index 31936c392d84..71e3168b686b 100644 --- a/unittests/IR/VerifierTest.cpp +++ b/unittests/IR/VerifierTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Verifier.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Verifier.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -42,24 +41,7 @@ TEST(VerifierTest, Branch_i1) { Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0); BI->setOperand(0, Zero32); - EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction)); -} - -TEST(VerifierTest, AliasUnnamedAddr) { - LLVMContext &C = getGlobalContext(); - Module M("M", C); - Type *Ty = Type::getInt8Ty(C); - Constant *Init = Constant::getNullValue(Ty); - GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true, - GlobalValue::ExternalLinkage, - Init, "foo"); - GlobalAlias *GA = new GlobalAlias(Type::getInt8PtrTy(C), - GlobalValue::ExternalLinkage, - "bar", Aliasee, &M); - GA->setUnnamedAddr(true); - std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr")); + EXPECT_TRUE(verifyFunction(*F)); } TEST(VerifierTest, InvalidRetAttribute) { @@ -72,9 +54,10 @@ TEST(VerifierTest, InvalidRetAttribute) { Attribute::UWTable)); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error). - startswith("Attribute 'uwtable' only applies to functions!")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE(StringRef(ErrorOS.str()).startswith( + "Attribute 'uwtable' only applies to functions!")); } } diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 9a9b4a2ad4e7..8e3cd45808f8 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -31,7 +31,7 @@ TEST(WaymarkTest, NativeArray) { FunctionType *FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), true); Function *F = Function::Create(FT, GlobalValue::ExternalLinkage); const CallInst *A = CallInst::Create(F, makeArrayRef(values)); - ASSERT_NE(A, (const CallInst*)NULL); + ASSERT_NE(A, (const CallInst*)nullptr); ASSERT_EQ(1U + 22, A->getNumOperands()); const Use *U = &A->getOperandUse(0); const Use *Ue = &A->getOperandUse(22); diff --git a/unittests/LineEditor/CMakeLists.txt b/unittests/LineEditor/CMakeLists.txt new file mode 100644 index 000000000000..c6823d8f9098 --- /dev/null +++ b/unittests/LineEditor/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_LINK_COMPONENTS + LineEditor + ) + +add_llvm_unittest(LineEditorTests + LineEditor.cpp + ) diff --git a/unittests/LineEditor/LineEditor.cpp b/unittests/LineEditor/LineEditor.cpp new file mode 100644 index 000000000000..26053c0ede24 --- /dev/null +++ b/unittests/LineEditor/LineEditor.cpp @@ -0,0 +1,83 @@ +//===-- LineEditor.cpp ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "gtest/gtest.h" + +using namespace llvm; + +class LineEditorTest : public testing::Test { +public: + SmallString<64> HistPath; + LineEditor *LE; + + LineEditorTest() { + init(); + } + + void init() { + sys::fs::createTemporaryFile("temp", "history", HistPath); + ASSERT_FALSE(HistPath.empty()); + LE = new LineEditor("test", HistPath); + } + + ~LineEditorTest() { + delete LE; + sys::fs::remove(HistPath.str()); + } +}; + +TEST_F(LineEditorTest, HistorySaveLoad) { + LE->saveHistory(); + LE->loadHistory(); +} + +struct TestListCompleter { + std::vector<LineEditor::Completion> Completions; + + TestListCompleter(const std::vector<LineEditor::Completion> &Completions) + : Completions(Completions) {} + + std::vector<LineEditor::Completion> operator()(StringRef Buffer, + size_t Pos) const { + EXPECT_TRUE(Buffer.empty()); + EXPECT_EQ(0u, Pos); + return Completions; + } +}; + +TEST_F(LineEditorTest, ListCompleters) { + std::vector<LineEditor::Completion> Comps; + + Comps.push_back(LineEditor::Completion("foo", "int foo()")); + LE->setListCompleter(TestListCompleter(Comps)); + LineEditor::CompletionAction CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind); + EXPECT_EQ("foo", CA.Text); + + Comps.push_back(LineEditor::Completion("bar", "int bar()")); + LE->setListCompleter(TestListCompleter(Comps)); + CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_ShowCompletions, CA.Kind); + ASSERT_EQ(2u, CA.Completions.size()); + ASSERT_EQ("int foo()", CA.Completions[0]); + ASSERT_EQ("int bar()", CA.Completions[1]); + + Comps.clear(); + Comps.push_back(LineEditor::Completion("fee", "int fee()")); + Comps.push_back(LineEditor::Completion("fi", "int fi()")); + Comps.push_back(LineEditor::Completion("foe", "int foe()")); + Comps.push_back(LineEditor::Completion("fum", "int fum()")); + LE->setListCompleter(TestListCompleter(Comps)); + CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind); + EXPECT_EQ("f", CA.Text); +} diff --git a/unittests/LineEditor/Makefile b/unittests/LineEditor/Makefile new file mode 100644 index 000000000000..058b6e46eb93 --- /dev/null +++ b/unittests/LineEditor/Makefile @@ -0,0 +1,15 @@ +##===- unittests/LineEditor/Makefile -----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TESTNAME = LineEditor +LINK_COMPONENTS := lineeditor + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt new file mode 100644 index 000000000000..c3dccb6c7bb8 --- /dev/null +++ b/unittests/Linker/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + core + linker + ) + +set(LinkerSources + LinkModulesTest.cpp + ) + +add_llvm_unittest(LinkerTests + ${LinkerSources} + ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp new file mode 100644 index 000000000000..4ccced195d24 --- /dev/null +++ b/unittests/Linker/LinkModulesTest.cpp @@ -0,0 +1,156 @@ +//===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker/Linker.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class LinkModuleTest : public testing::Test { +protected: + virtual void SetUp() { + M.reset(new Module("MyModule", Ctx)); + FunctionType *FTy = FunctionType::get( + Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/); + F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get()); + F->setCallingConv(CallingConv::C); + + EntryBB = BasicBlock::Create(Ctx, "entry", F); + SwitchCase1BB = BasicBlock::Create(Ctx, "switch.case.1", F); + SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F); + ExitBB = BasicBlock::Create(Ctx, "exit", F); + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + + GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/, + GlobalValue::InternalLinkage, nullptr,"switch.bas"); + + // Global Initializer + std::vector<Constant *> Init; + Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB); + Init.push_back(SwitchCase1BA); + + Constant *SwitchCase2BA = BlockAddress::get(SwitchCase2BB); + Init.push_back(SwitchCase2BA); + + ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1); + Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, One, + Type::getInt8PtrTy(Ctx)); + Init.push_back(OnePtr); + + GV->setInitializer(ConstantArray::get(AT, Init)); + } + + virtual void TearDown() { M.reset(); } + + LLVMContext Ctx; + std::unique_ptr<Module> M; + Function *F; + GlobalVariable *GV; + BasicBlock *EntryBB; + BasicBlock *SwitchCase1BB; + BasicBlock *SwitchCase2BB; + BasicBlock *ExitBB; +}; + +TEST_F(LinkModuleTest, BlockAddress) { + IRBuilder<> Builder(EntryBB); + + std::vector<Value *> GEPIndices; + GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0)); + GEPIndices.push_back(F->arg_begin()); + + Value *GEP = Builder.CreateGEP(GV, GEPIndices, "switch.gep"); + Value *Load = Builder.CreateLoad(GEP, "switch.load"); + + Builder.CreateRet(Load); + + Builder.SetInsertPoint(SwitchCase1BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(SwitchCase2BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(ExitBB); + Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); + + Module *LinkedModule = new Module("MyModuleLinked", Ctx); + Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, nullptr); + + // Delete the original module. + M.reset(); + + // Check that the global "@switch.bas" is well-formed. + const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas"); + const Constant *Init = LinkedGV->getInitializer(); + + // @switch.bas = internal global [3 x i8*] + // [i8* blockaddress(@ba_func, %switch.case.1), + // i8* blockaddress(@ba_func, %switch.case.2), + // i8* inttoptr (i32 1 to i8*)] + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + EXPECT_EQ(AT, Init->getType()); + + Value *Elem = Init->getOperand(0); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + Elem = Init->getOperand(1); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + delete LinkedModule; +} + +TEST_F(LinkModuleTest, EmptyModule) { + Module *InternalM = new Module("InternalModule", Ctx); + FunctionType *FTy = FunctionType::get( + Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/); + + F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); + F->setCallingConv(CallingConv::C); + + BasicBlock *BB = BasicBlock::Create(Ctx, "", F); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0)); + + GlobalVariable *GV = + new GlobalVariable(*InternalM, STy, false /*=isConstant*/, + GlobalValue::InternalLinkage, nullptr, "g"); + + GV->setInitializer(ConstantStruct::get(STy, F)); + + Module *EmptyM = new Module("EmptyModule1", Ctx); + Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, nullptr); + + delete EmptyM; + EmptyM = new Module("EmptyModule2", Ctx); + Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, nullptr); + + delete EmptyM; + delete InternalM; +} + +} // end anonymous namespace diff --git a/unittests/Object/Makefile b/unittests/Linker/Makefile index 9062149a24d9..c6058c4d60df 100644 --- a/unittests/Object/Makefile +++ b/unittests/Linker/Makefile @@ -1,4 +1,4 @@ -##===- unittests/Object/Makefile ---------------------------*- Makefile -*-===## +##===- unittests/Linker/Makefile ---------------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -8,8 +8,8 @@ ##===----------------------------------------------------------------------===## LEVEL = ../.. -TESTNAME = Object -LINK_COMPONENTS := object +TESTNAME = Linker +LINK_COMPONENTS := core linker include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt index 0e4782c83f40..37543f48bcef 100644 --- a/unittests/MC/CMakeLists.txt +++ b/unittests/MC/CMakeLists.txt @@ -1,11 +1,11 @@ set(LLVM_LINK_COMPONENTS MC - ) - -set(MCSources - MCAtomTest.cpp + MCAnalysis + Support ) add_llvm_unittest(MCTests - ${MCSources} + MCAtomTest.cpp + StringTableBuilderTest.cpp + YAMLTest.cpp ) diff --git a/unittests/MC/MCAtomTest.cpp b/unittests/MC/MCAtomTest.cpp index 17b056cd2dea..16228b521f42 100644 --- a/unittests/MC/MCAtomTest.cpp +++ b/unittests/MC/MCAtomTest.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAtom.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCAtom.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "gtest/gtest.h" namespace llvm { diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile index 4c25697d28dc..07a608e65a34 100644 --- a/unittests/MC/Makefile +++ b/unittests/MC/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = MC -LINK_COMPONENTS := MC +LINK_COMPONENTS := MCAnalysis include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/StringTableBuilderTest.cpp b/unittests/MC/StringTableBuilderTest.cpp new file mode 100644 index 000000000000..d30dc6222d23 --- /dev/null +++ b/unittests/MC/StringTableBuilderTest.cpp @@ -0,0 +1,40 @@ +//===----------- StringTableBuilderTest.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/StringTableBuilder.h" +#include "gtest/gtest.h" +#include <string> + +using namespace llvm; + +namespace { + +TEST(StringTableBuilderTest, Basic) { + StringTableBuilder B; + + B.add("foo"); + B.add("bar"); + B.add("foobar"); + + B.finalize(); + + std::string Expected; + Expected += '\x00'; + Expected += "foobar"; + Expected += '\x00'; + Expected += "foo"; + Expected += '\x00'; + + EXPECT_EQ(Expected, B.data()); + EXPECT_EQ(1U, B.getOffset("foobar")); + EXPECT_EQ(4U, B.getOffset("bar")); + EXPECT_EQ(8U, B.getOffset("foo")); +} + +} diff --git a/unittests/Object/YAMLTest.cpp b/unittests/MC/YAMLTest.cpp index 3ae92ae1baea..09709ad73fc7 100644 --- a/unittests/Object/YAMLTest.cpp +++ b/unittests/MC/YAMLTest.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/YAMLTraits.h" #include "gtest/gtest.h" using namespace llvm; struct BinaryHolder { - object::yaml::BinaryRef Binary; + yaml::BinaryRef Binary; }; namespace llvm { @@ -34,5 +34,5 @@ TEST(ObjectYAML, BinaryRef) { llvm::raw_svector_ostream OS(Buf); yaml::Output YOut(OS); YOut << BH; - EXPECT_NE(OS.str().find("\"\""), StringRef::npos); + EXPECT_NE(OS.str().find("''"), StringRef::npos); } diff --git a/unittests/Makefile b/unittests/Makefile index 06ba93243e38..603e7d58f8c7 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -10,9 +10,10 @@ LEVEL = .. PARALLEL_DIRS = ADT Analysis Bitcode CodeGen DebugInfo ExecutionEngine IR \ - MC Object Option Support Transforms + LineEditor Linker MC Option Support Transforms -include $(LEVEL)/Makefile.common +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest clean:: $(Verb) $(RM) -f *Tests diff --git a/unittests/Makefile.unittest b/unittests/Makefile.unittest index bd32aed4b0a2..a39edc675698 100644 --- a/unittests/Makefile.unittest +++ b/unittests/Makefile.unittest @@ -11,13 +11,23 @@ # ##===----------------------------------------------------------------------===## -# Set up variables for building a unit test. -ifdef TESTNAME - ifndef MAKEFILE_UNITTEST_NO_INCLUDE_COMMON include $(LEVEL)/Makefile.common endif +# Clean up out-of-tree stray unittests for Lit not to pick one up. +.PHONY: cleanup-local +cleanup-local: + -$(Verb) $(FIND) $(filter-out $(PARALLEL_DIRS), $(wildcard *)) -type f \ + -path '*/$(BuildMode)/*Tests$(EXEEXT)' \ + -exec rm -f '{}' \; + +all:: cleanup-local +clean:: cleanup-local + +# Set up variables for building a unit test. +ifdef TESTNAME + LLVMUnitTestExe = $(BuildMode)/$(TESTNAME)Tests$(EXEEXT) # Note that these flags are duplicated when building GoogleTest itself in @@ -42,9 +52,6 @@ ifeq ($(ENABLE_SHARED), 1) # we'll never install unittests. LD.Flags += $(RPATH) -Wl,$(SharedLibDir) endif - # Also set {DYLD,LD}_LIBRARY_PATH because OSX ignores the rpath most - # of the time. - Run.Shared := $(SHLIBPATH_VAR)="$(SharedLibDir)$${$(SHLIBPATH_VAR):+:}$$$(SHLIBPATH_VAR)" endif $(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) @@ -57,6 +64,6 @@ $(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) all:: $(LLVMUnitTestExe) unitcheck:: $(LLVMUnitTestExe) - $(Run.Shared) $(LLVMUnitTestExe) + $(LLVMUnitTestExe) endif diff --git a/unittests/Object/CMakeLists.txt b/unittests/Object/CMakeLists.txt deleted file mode 100644 index b491dd7f6bdf..000000000000 --- a/unittests/Object/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(LLVM_LINK_COMPONENTS - object - ) - -add_llvm_unittest(ObjectTests - YAMLTest.cpp - ) diff --git a/unittests/Option/CMakeLists.txt b/unittests/Option/CMakeLists.txt index 185d503912fd..07f7b91d5f5b 100644 --- a/unittests/Option/CMakeLists.txt +++ b/unittests/Option/CMakeLists.txt @@ -11,5 +11,3 @@ add_public_tablegen_target(OptsTestTableGen) add_llvm_unittest(OptionTests OptionParsingTest.cpp ) - -add_dependencies(OptionTests OptsTestTableGen) diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp index 11d6d1e87ebb..aa32da3a595f 100644 --- a/unittests/Option/OptionParsingTest.cpp +++ b/unittests/Option/OptionParsingTest.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -68,7 +67,8 @@ const char *Args[] = { TEST(Option, OptionParsing) { TestOptTable T; unsigned MAI, MAC; - OwningPtr<InputArgList> AL(T.ParseArgs(Args, array_endof(Args), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC)); // Check they all exist. EXPECT_TRUE(AL->hasArg(OPT_A)); @@ -111,10 +111,10 @@ TEST(Option, OptionParsing) { TEST(Option, ParseWithFlagExclusions) { TestOptTable T; unsigned MAI, MAC; - OwningPtr<InputArgList> AL; + std::unique_ptr<InputArgList> AL; // Exclude flag3 to avoid parsing as OPT_SLASH_C. - AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, + AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC, /*FlagsToInclude=*/0, /*FlagsToExclude=*/OptFlag3)); EXPECT_TRUE(AL->hasArg(OPT_A)); @@ -122,7 +122,7 @@ TEST(Option, ParseWithFlagExclusions) { EXPECT_FALSE(AL->hasArg(OPT_SLASH_C)); // Exclude flag1 to avoid parsing as OPT_C. - AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, + AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC, /*FlagsToInclude=*/0, /*FlagsToExclude=*/OptFlag1)); EXPECT_TRUE(AL->hasArg(OPT_B)); @@ -130,7 +130,7 @@ TEST(Option, ParseWithFlagExclusions) { EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); const char *NewArgs[] = { "/C", "foo", "--C=bar" }; - AL.reset(T.ParseArgs(NewArgs, array_endof(NewArgs), MAI, MAC)); + AL.reset(T.ParseArgs(std::begin(NewArgs), std::end(NewArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); EXPECT_TRUE(AL->hasArg(OPT_C)); EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo"); @@ -142,7 +142,8 @@ TEST(Option, ParseAliasInGroup) { unsigned MAI, MAC; const char *MyArgs[] = { "-I" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_H)); } @@ -151,7 +152,8 @@ TEST(Option, AliasArgs) { unsigned MAI, MAC; const char *MyArgs[] = { "-J", "-Joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_B)); EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo"); EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar"); @@ -162,7 +164,8 @@ TEST(Option, IgnoreCase) { unsigned MAI, MAC; const char *MyArgs[] = { "-a", "-joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_B)); } @@ -172,7 +175,8 @@ TEST(Option, DoNotIgnoreCase) { unsigned MAI, MAC; const char *MyArgs[] = { "-a", "-joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_FALSE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); } @@ -182,7 +186,8 @@ TEST(Option, SlurpEmpty) { unsigned MAI, MAC; const char *MyArgs[] = { "-A", "-slurp" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_Slurp)); EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U); @@ -193,7 +198,8 @@ TEST(Option, Slurp) { unsigned MAI, MAC; const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_EQ(AL->size(), 2U); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index cb9fa430369b..0fc84c7613f3 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -29,11 +29,26 @@ TEST(AllocatorTest, Basics) { EXPECT_EQ(2, b[9]); EXPECT_EQ(3, *c); EXPECT_EQ(1U, Alloc.GetNumSlabs()); + + BumpPtrAllocator Alloc2 = std::move(Alloc); + EXPECT_EQ(0U, Alloc.GetNumSlabs()); + EXPECT_EQ(1U, Alloc2.GetNumSlabs()); + + // Make sure the old pointers still work. These are especially interesting + // under ASan or Valgrind. + EXPECT_EQ(1, *a); + EXPECT_EQ(2, b[0]); + EXPECT_EQ(2, b[9]); + EXPECT_EQ(3, *c); + + Alloc = std::move(Alloc2); + EXPECT_EQ(0U, Alloc2.GetNumSlabs()); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); } // Allocate enough bytes to create three slabs. TEST(AllocatorTest, ThreeSlabs) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; Alloc.Allocate(3000, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); Alloc.Allocate(3000, 0); @@ -45,7 +60,7 @@ TEST(AllocatorTest, ThreeSlabs) { // Allocate enough bytes to create two slabs, reset the allocator, and do it // again. TEST(AllocatorTest, TestReset) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; Alloc.Allocate(3000, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); Alloc.Allocate(3000, 0); @@ -81,10 +96,10 @@ TEST(AllocatorTest, TestAlignment) { // Test allocating just over the slab size. This tests a bug where before the // allocator incorrectly calculated the buffer end pointer. TEST(AllocatorTest, TestOverflow) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. - Alloc.Allocate(4096 - sizeof(MemSlab), 0); + Alloc.Allocate(4096, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); // If we don't allocate a new slab, then we will have overflowed. @@ -94,57 +109,60 @@ TEST(AllocatorTest, TestOverflow) { // Test allocating with a size larger than the initial slab size. TEST(AllocatorTest, TestSmallSlabSize) { - BumpPtrAllocator Alloc(128); + BumpPtrAllocator Alloc; - Alloc.Allocate(200, 0); + Alloc.Allocate(8000, 0); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no // easy portable way to do this, so this is kind of a hack. -class MockSlabAllocator : public SlabAllocator { - MemSlab *LastSlab; +class MockSlabAllocator { + static size_t LastSlabSize; public: - virtual ~MockSlabAllocator() { } + ~MockSlabAllocator() { } - virtual MemSlab *Allocate(size_t Size) { + void *Allocate(size_t Size, size_t /*Alignment*/) { // Allocate space for the alignment, the slab, and a void* that goes right // before the slab. size_t Alignment = 4096; void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); - // Make the slab. - MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) & - ~(uintptr_t)(Alignment - 1)); - Slab->Size = Size; - Slab->NextPtr = 0; + // Find the slab start. + void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); // Hold a pointer to the base so we can free the whole malloced block. ((void**)Slab)[-1] = MemBase; - LastSlab = Slab; + LastSlabSize = Size; return Slab; } - virtual void Deallocate(MemSlab *Slab) { + void Deallocate(void *Slab, size_t Size) { free(((void**)Slab)[-1]); } - MemSlab *GetLastSlab() { - return LastSlab; - } + static size_t GetLastSlabSize() { return LastSlabSize; } }; +size_t MockSlabAllocator::LastSlabSize = 0; + // Allocate a large-ish block with a really large alignment so that the // allocator will think that it has space, but after it does the alignment it // will not. TEST(AllocatorTest, TestBigAlignment) { - MockSlabAllocator SlabAlloc; - BumpPtrAllocator Alloc(4096, 4096, SlabAlloc); - uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); - MemSlab *Slab = SlabAlloc.GetLastSlab(); - EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); + BumpPtrAllocatorImpl<MockSlabAllocator> Alloc; + + // First allocate a tiny bit to ensure we have to re-align things. + (void)Alloc.Allocate(1, 0); + + // Now the big chunk with a big alignment. + (void)Alloc.Allocate(3000, 2048); + + // We test that the last slab size is not the default 4096 byte slab, but + // rather a custom sized slab that is larger. + EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u); } } // anonymous namespace diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index ffdea2c1790f..f6e3537de91a 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -15,9 +15,8 @@ TEST(BlockFrequencyTest, OneToZero) { EXPECT_EQ(Freq.getFrequency(), 0u); Freq = BlockFrequency(1); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 0u); - EXPECT_EQ(Remainder, UINT32_MAX - 1); } TEST(BlockFrequencyTest, OneToOne) { @@ -27,9 +26,8 @@ TEST(BlockFrequencyTest, OneToOne) { EXPECT_EQ(Freq.getFrequency(), 1u); Freq = BlockFrequency(1); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 1u); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, ThreeToOne) { @@ -39,9 +37,8 @@ TEST(BlockFrequencyTest, ThreeToOne) { EXPECT_EQ(Freq.getFrequency(), 1u); Freq = BlockFrequency(3); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 1u); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, MaxToHalfMax) { @@ -51,9 +48,8 @@ TEST(BlockFrequencyTest, MaxToHalfMax) { EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL); Freq = BlockFrequency(UINT64_MAX); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, BigToBig) { @@ -65,9 +61,8 @@ TEST(BlockFrequencyTest, BigToBig) { EXPECT_EQ(Freq.getFrequency(), Big); Freq = BlockFrequency(Big); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), Big); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, MaxToMax) { @@ -80,109 +75,8 @@ TEST(BlockFrequencyTest, MaxToMax) { // value, we do not signal saturation if the result equals said value, but // saturating does not occur. Freq = BlockFrequency(UINT64_MAX); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), UINT64_MAX); - EXPECT_EQ(Remainder, 0u); -} - -TEST(BlockFrequencyTest, ScaleResultRemainderTest) { - struct { - uint64_t Freq; - uint32_t Prob[2]; - uint64_t ExpectedFreq; - uint32_t ExpectedRemainder; - } Tests[80] = { - // Data for scaling that results in <= 64 bit division. - { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL, 0x92b9d25 }, - { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL, 0x2c0fd0b6 }, - { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL, 0x4a06dd }, - { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL, 0x265d1c2a }, - { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL, 0x324c27b8 }, - { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL, 0x490c1dc4 }, - { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL, 0x1df47c30 }, - { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL, 0x1d0c1b6b }, - { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL, 0x3f2c696a }, - { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL, 0x4dafc7c }, - { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL, 0x343589ee }, - { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL, 0x4948e49 }, - { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL, 0x73e3b96 }, - { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL, 0x86a882c }, - { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL, 0x29b0653 }, - { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL, 0x2383d33f }, - { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL, 0x7aa5da }, - { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL, 0x7ba8c38 }, - { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL, 0x6b612167 }, - { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL, 0x28bbf5e }, - { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL, 0x4b27097e }, - { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL, 0x688e828 }, - { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL, 0x111f0cb }, - { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL, 0x59c4939b }, - { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL, 0x66bb8a80 }, - { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL, 0x28910321 }, - { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL, 0xff8e2ed }, - { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL, 0xd85e134 }, - { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL, 0x49ea31e }, - { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL, 0x11d5b9c4 }, - { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL, 0x6f93b2c }, - { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL, 0x54b09ffa }, - { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL, 0x15ad6ed7 }, - { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL, 0x1b2a9565 }, - { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL, 0x22ff53e4 }, - { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL, 0xa8aa816 }, - { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL, 0x4ea09c }, - { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL, 0xbee1099 }, - { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL, 0x1eaed76e }, - { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL, 0x158d9020 }, - // Data for scaling that results in > 64 bit division. - { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL, 0xf627f79 }, - { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL, 0x1c8f33e1 }, - { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL, 0x29cde3ae }, - { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL, 0x5170574 }, - { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL, 0x3026dfab }, - { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL, 0x298d9919 }, - { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL, 0x93afeb8 }, - { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL, 0x4ff96b9e }, - { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL, 0x51b1fb5b }, - { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL, 0x7a7b5608 }, - { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL, 0xfddc6a3 }, - { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL, 0x14e2564c }, - { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL, 0x15145eec }, - { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL, 0x3a38ebe2 }, - { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL, 0x7431f4d }, - { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL, 0x202817a3 }, - { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL, 0x1e27284b }, - { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL, 0xf7ad89e }, - { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL, 0xfe1a5ce }, - { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL, 0x11c4a26c }, - { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL, 0xcd51e7c }, - { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL, 0x3df05434 }, - { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL, 0x26d939e }, - { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL, 0x1b588512 }, - { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL, 0x35c0a5f0 }, - { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL, 0x5e23a5eb }, - { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL, 0x3fcf4527 }, - { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL, 0x3607801f }, - { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL, 0x5ab576 }, - { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL, 0x221220a8 }, - { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL, 0x4e97b195 }, - { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL, 0x516f5bd }, - { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL, 0x8b65 }, - { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL, 0x11dc6a51 }, - { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL, 0xfb871c }, - { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL, 0xb8add57 }, - { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL, 0x10d3ae7 }, - { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL, 0x4fee45a }, - { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL, 0x3b65f514 }, - { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL, 0x336b6106 } - }; - - for (unsigned i = 0; i < 80; i++) { - BlockFrequency Freq(Tests[i].Freq); - uint32_t Remainder = Freq.scale(BranchProbability(Tests[i].Prob[0], - Tests[i].Prob[1])); - EXPECT_EQ(Tests[i].ExpectedFreq, Freq.getFrequency()); - EXPECT_EQ(Tests[i].ExpectedRemainder, Remainder); - } } TEST(BlockFrequency, Divide) { @@ -208,33 +102,12 @@ TEST(BlockFrequencyTest, Saturate) { EXPECT_EQ(33506781356485509ULL, Freq.getFrequency()); } -TEST(BlockFrequencyTest, ProbabilityCompare) { - BranchProbability A(4, 5); - BranchProbability B(4U << 29, 5U << 29); - BranchProbability C(3, 4); - - EXPECT_TRUE(A == B); - EXPECT_FALSE(A != B); - EXPECT_FALSE(A < B); - EXPECT_FALSE(A > B); - EXPECT_TRUE(A <= B); - EXPECT_TRUE(A >= B); - - EXPECT_FALSE(B == C); - EXPECT_TRUE(B != C); - EXPECT_FALSE(B < C); - EXPECT_TRUE(B > C); - EXPECT_FALSE(B <= C); - EXPECT_TRUE(B >= C); - - BranchProbability BigZero(0, UINT32_MAX); - BranchProbability BigOne(UINT32_MAX, UINT32_MAX); - EXPECT_FALSE(BigZero == BigOne); - EXPECT_TRUE(BigZero != BigOne); - EXPECT_TRUE(BigZero < BigOne); - EXPECT_FALSE(BigZero > BigOne); - EXPECT_TRUE(BigZero <= BigOne); - EXPECT_FALSE(BigZero >= BigOne); +TEST(BlockFrequencyTest, SaturatingRightShift) { + BlockFrequency Freq(0x10080ULL); + Freq >>= 2; + EXPECT_EQ(Freq.getFrequency(), 0x4020ULL); + Freq >>= 20; + EXPECT_EQ(Freq.getFrequency(), 0x1ULL); } } diff --git a/unittests/Support/BranchProbabilityTest.cpp b/unittests/Support/BranchProbabilityTest.cpp new file mode 100644 index 000000000000..bbd4d4eba1c0 --- /dev/null +++ b/unittests/Support/BranchProbabilityTest.cpp @@ -0,0 +1,282 @@ +//===- unittest/Support/BranchProbabilityTest.cpp - BranchProbability tests -=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { +void PrintTo(const BranchProbability &P, ::std::ostream *os) { + *os << P.getNumerator() << "/" << P.getDenominator(); +} +} +namespace { + +typedef BranchProbability BP; +TEST(BranchProbabilityTest, Accessors) { + EXPECT_EQ(1u, BP(1, 7).getNumerator()); + EXPECT_EQ(7u, BP(1, 7).getDenominator()); + EXPECT_EQ(0u, BP::getZero().getNumerator()); + EXPECT_EQ(1u, BP::getZero().getDenominator()); + EXPECT_EQ(1u, BP::getOne().getNumerator()); + EXPECT_EQ(1u, BP::getOne().getDenominator()); +} + +TEST(BranchProbabilityTest, Operators) { + EXPECT_TRUE(BP(1, 7) < BP(2, 7)); + EXPECT_TRUE(BP(1, 7) < BP(1, 4)); + EXPECT_TRUE(BP(5, 7) < BP(3, 4)); + EXPECT_FALSE(BP(1, 7) < BP(1, 7)); + EXPECT_FALSE(BP(1, 7) < BP(2, 14)); + EXPECT_FALSE(BP(4, 7) < BP(1, 2)); + EXPECT_FALSE(BP(4, 7) < BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) > BP(2, 7)); + EXPECT_FALSE(BP(1, 7) > BP(1, 4)); + EXPECT_FALSE(BP(5, 7) > BP(3, 4)); + EXPECT_FALSE(BP(1, 7) > BP(1, 7)); + EXPECT_FALSE(BP(1, 7) > BP(2, 14)); + EXPECT_TRUE(BP(4, 7) > BP(1, 2)); + EXPECT_TRUE(BP(4, 7) > BP(3, 7)); + + EXPECT_TRUE(BP(1, 7) <= BP(2, 7)); + EXPECT_TRUE(BP(1, 7) <= BP(1, 4)); + EXPECT_TRUE(BP(5, 7) <= BP(3, 4)); + EXPECT_TRUE(BP(1, 7) <= BP(1, 7)); + EXPECT_TRUE(BP(1, 7) <= BP(2, 14)); + EXPECT_FALSE(BP(4, 7) <= BP(1, 2)); + EXPECT_FALSE(BP(4, 7) <= BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) >= BP(2, 7)); + EXPECT_FALSE(BP(1, 7) >= BP(1, 4)); + EXPECT_FALSE(BP(5, 7) >= BP(3, 4)); + EXPECT_TRUE(BP(1, 7) >= BP(1, 7)); + EXPECT_TRUE(BP(1, 7) >= BP(2, 14)); + EXPECT_TRUE(BP(4, 7) >= BP(1, 2)); + EXPECT_TRUE(BP(4, 7) >= BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) == BP(2, 7)); + EXPECT_FALSE(BP(1, 7) == BP(1, 4)); + EXPECT_FALSE(BP(5, 7) == BP(3, 4)); + EXPECT_TRUE(BP(1, 7) == BP(1, 7)); + EXPECT_TRUE(BP(1, 7) == BP(2, 14)); + EXPECT_FALSE(BP(4, 7) == BP(1, 2)); + EXPECT_FALSE(BP(4, 7) == BP(3, 7)); + + EXPECT_TRUE(BP(1, 7) != BP(2, 7)); + EXPECT_TRUE(BP(1, 7) != BP(1, 4)); + EXPECT_TRUE(BP(5, 7) != BP(3, 4)); + EXPECT_FALSE(BP(1, 7) != BP(1, 7)); + EXPECT_FALSE(BP(1, 7) != BP(2, 14)); + EXPECT_TRUE(BP(4, 7) != BP(1, 2)); + EXPECT_TRUE(BP(4, 7) != BP(3, 7)); +} + +TEST(BranchProbabilityTest, MoreOperators) { + BP A(4, 5); + BP B(4U << 29, 5U << 29); + BP C(3, 4); + + EXPECT_TRUE(A == B); + EXPECT_FALSE(A != B); + EXPECT_FALSE(A < B); + EXPECT_FALSE(A > B); + EXPECT_TRUE(A <= B); + EXPECT_TRUE(A >= B); + + EXPECT_FALSE(B == C); + EXPECT_TRUE(B != C); + EXPECT_FALSE(B < C); + EXPECT_TRUE(B > C); + EXPECT_FALSE(B <= C); + EXPECT_TRUE(B >= C); + + BP BigZero(0, UINT32_MAX); + BP BigOne(UINT32_MAX, UINT32_MAX); + EXPECT_FALSE(BigZero == BigOne); + EXPECT_TRUE(BigZero != BigOne); + EXPECT_TRUE(BigZero < BigOne); + EXPECT_FALSE(BigZero > BigOne); + EXPECT_TRUE(BigZero <= BigOne); + EXPECT_FALSE(BigZero >= BigOne); +} + +TEST(BranchProbabilityTest, getCompl) { + EXPECT_EQ(BP(5, 7), BP(2, 7).getCompl()); + EXPECT_EQ(BP(2, 7), BP(5, 7).getCompl()); + EXPECT_EQ(BP::getZero(), BP(7, 7).getCompl()); + EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl()); +} + +TEST(BranchProbabilityTest, scale) { + // Multiply by 1.0. + EXPECT_EQ(UINT64_MAX, BP(1, 1).scale(UINT64_MAX)); + EXPECT_EQ(UINT64_MAX, BP(7, 7).scale(UINT64_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, 1).scale(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(7, 7).scale(UINT32_MAX)); + EXPECT_EQ(0u, BP(1, 1).scale(0)); + EXPECT_EQ(0u, BP(7, 7).scale(0)); + + // Multiply by 0.0. + EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX)); + EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX)); + EXPECT_EQ(0u, BP(0, 1).scale(0)); + + auto Two63 = UINT64_C(1) << 63; + auto Two31 = UINT64_C(1) << 31; + + // Multiply by 0.5. + EXPECT_EQ(Two63 - 1, BP(1, 2).scale(UINT64_MAX)); + + // Big fractions. + EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scale(2)); + EXPECT_EQ(Two31, BP(Two31, UINT32_MAX).scale(Two31 * 2)); + EXPECT_EQ(Two63 + Two31, BP(Two31, UINT32_MAX).scale(UINT64_MAX)); + + // High precision. + EXPECT_EQ(UINT64_C(9223372047592194055), + BP(Two31 + 1, UINT32_MAX - 2).scale(UINT64_MAX)); +} + +TEST(BranchProbabilityTest, scaleByInverse) { + // Divide by 1.0. + EXPECT_EQ(UINT64_MAX, BP(1, 1).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(UINT64_MAX, BP(7, 7).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, 1).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(7, 7).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(0u, BP(1, 1).scaleByInverse(0)); + EXPECT_EQ(0u, BP(7, 7).scaleByInverse(0)); + + // Divide by something very small. + EXPECT_EQ(UINT64_MAX, BP(1, UINT32_MAX).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(uint64_t(UINT32_MAX) * UINT32_MAX, + BP(1, UINT32_MAX).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, UINT32_MAX).scaleByInverse(1)); + + auto Two63 = UINT64_C(1) << 63; + auto Two31 = UINT64_C(1) << 31; + + // Divide by 0.5. + EXPECT_EQ(UINT64_MAX - 1, BP(1, 2).scaleByInverse(Two63 - 1)); + EXPECT_EQ(UINT64_MAX, BP(1, 2).scaleByInverse(Two63)); + + // Big fractions. + EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scaleByInverse(1)); + EXPECT_EQ(2u, BP(Two31 - 1, UINT32_MAX).scaleByInverse(1)); + EXPECT_EQ(Two31 * 2 - 1, BP(Two31, UINT32_MAX).scaleByInverse(Two31)); + EXPECT_EQ(Two31 * 2 + 1, BP(Two31 - 1, UINT32_MAX).scaleByInverse(Two31)); + EXPECT_EQ(UINT64_MAX, BP(Two31, UINT32_MAX).scaleByInverse(Two63 + Two31)); + + // High precision. The exact answers to these are close to the successors of + // the floor. If we were rounding, these would round up. + EXPECT_EQ(UINT64_C(18446744065119617030), + BP(Two31 + 2, UINT32_MAX - 2) + .scaleByInverse(UINT64_C(9223372047592194055))); + EXPECT_EQ(UINT64_C(18446744065119617026), + BP(Two31 + 1, UINT32_MAX).scaleByInverse(Two63 + Two31)); +} + +TEST(BranchProbabilityTest, scaleBruteForce) { + struct { + uint64_t Num; + uint32_t Prob[2]; + uint64_t Result; + } Tests[] = { + // Data for scaling that results in <= 64 bit division. + { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL }, + { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL }, + { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL }, + { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL }, + { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL }, + { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL }, + { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL }, + { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL }, + { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL }, + { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL }, + { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL }, + { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL }, + { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL }, + { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL }, + { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL }, + { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL }, + { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL }, + { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL }, + { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL }, + { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL }, + { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL }, + { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL }, + { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL }, + { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL }, + { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL }, + { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL }, + { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL }, + { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL }, + { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL }, + { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL }, + { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL }, + { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL }, + { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL }, + { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL }, + { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL }, + { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL }, + { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL }, + { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL }, + { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL }, + { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL }, + // Data for scaling that results in > 64 bit division. + { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL }, + { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL }, + { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL }, + { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL }, + { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL }, + { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL }, + { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL }, + { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL }, + { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL }, + { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL }, + { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL }, + { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL }, + { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL }, + { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL }, + { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL }, + { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL }, + { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL }, + { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL }, + { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL }, + { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL }, + { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL }, + { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL }, + { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL }, + { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL }, + { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL }, + { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL }, + { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL }, + { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL }, + { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL }, + { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL }, + { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL }, + { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL }, + { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL }, + { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL }, + { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL }, + { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL }, + { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL }, + { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL }, + { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL }, + { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL } + }; + + for (const auto &T : Tests) { + EXPECT_EQ(T.Result, BP(T.Prob[0], T.Prob[1]).scale(T.Num)); + } +} + +} diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 0abc2ffe1d9c..97c5c43aeb6e 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -1,6 +1,5 @@ set(LLVM_LINK_COMPONENTS Support - Core ) add_llvm_unittest(SupportTests @@ -8,32 +7,36 @@ add_llvm_unittest(SupportTests AllocatorTest.cpp ArrayRecyclerTest.cpp BlockFrequencyTest.cpp + BranchProbabilityTest.cpp Casting.cpp CommandLineTest.cpp CompressionTest.cpp - ConstantRangeTest.cpp ConvertUTFTest.cpp DataExtractorTest.cpp EndianTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp - LeakDetectorTest.cpp + IteratorTest.cpp + LEB128Test.cpp + LineIteratorTest.cpp LockFileManagerTest.cpp + MD5Test.cpp ManagedStatic.cpp MathExtrasTest.cpp - MD5Test.cpp MemoryBufferTest.cpp MemoryTest.cpp Path.cpp ProcessTest.cpp ProgramTest.cpp RegexTest.cpp + ScaledNumberTest.cpp SourceMgrTest.cpp + SpecialCaseListTest.cpp + StringPool.cpp SwapByteOrderTest.cpp ThreadLocalTest.cpp TimeValueTest.cpp UnicodeTest.cpp - ValueHandleTest.cpp YAMLIOTest.cpp YAMLParserTest.cpp formatted_raw_ostream_test.cpp diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 362abeecd07a..88c7d19aa464 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Casting.h" +#include "llvm/IR/User.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/IR/User.h" #include "gtest/gtest.h" #include <cstdlib> @@ -18,7 +18,7 @@ namespace llvm { // Used to test illegal cast. If a cast doesn't match any of the "real" ones, // it will match this one. struct IllegalCast; -template <typename T> IllegalCast *cast(...) { return 0; } +template <typename T> IllegalCast *cast(...) { return nullptr; } // set up two example classes // with conversion facility @@ -77,16 +77,20 @@ using namespace llvm; // Test the peculiar behavior of Use in simplify_type. -int Check1[is_same<simplify_type<Use>::SimpleType, Value *>::value ? 1 : -1]; -int Check2[is_same<simplify_type<Use *>::SimpleType, Value *>::value ? 1 : -1]; +static_assert(std::is_same<simplify_type<Use>::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); +static_assert(std::is_same<simplify_type<Use *>::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); // Test that a regular class behaves as expected. -int Check3[is_same<simplify_type<foo>::SimpleType, int>::value ? 1 : -1]; -int Check4[is_same<simplify_type<foo *>::SimpleType, foo *>::value ? 1 : -1]; +static_assert(std::is_same<simplify_type<foo>::SimpleType, int>::value, + "Unexpected simplify_type result!"); +static_assert(std::is_same<simplify_type<foo *>::SimpleType, foo *>::value, + "Unexpected simplify_type result!"); namespace { -const foo *null_foo = NULL; +const foo *null_foo = nullptr; bar B; extern bar &B1; @@ -171,7 +175,7 @@ TEST(CastingTest, dyn_cast_or_null) { const bar *B2 = &B; } // anonymous namespace -bar *llvm::fub() { return 0; } +bar *llvm::fub() { return nullptr; } namespace { namespace inferred_upcasting { @@ -199,7 +203,7 @@ TEST(CastingTest, UpcastIsInferred) { Derived D; EXPECT_TRUE(isa<Base>(D)); Base *BP = dyn_cast<Base>(&D); - EXPECT_TRUE(BP != NULL); + EXPECT_TRUE(BP != nullptr); } diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index c54e1b9570f8..e4a1b67c47ea 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Config/config.h" +#include "llvm/Support/CommandLine.h" #include "gtest/gtest.h" #include <stdlib.h> #include <string> @@ -23,7 +23,7 @@ class TempEnvVar { TempEnvVar(const char *name, const char *value) : name(name) { const char *old_value = getenv(name); - EXPECT_EQ(NULL, old_value) << old_value; + EXPECT_EQ(nullptr, old_value) << old_value; #if HAVE_SETENV setenv(name, value, true); #else @@ -42,6 +42,33 @@ class TempEnvVar { const char *const name; }; +template <typename T> +class StackOption : public cl::opt<T> { + typedef cl::opt<T> Base; +public: + // One option... + template<class M0t> + explicit StackOption(const M0t &M0) : Base(M0) {} + + // Two options... + template<class M0t, class M1t> + StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {} + + // Three options... + template<class M0t, class M1t, class M2t> + StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {} + + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Base(M0, M1, M2, M3) {} + + ~StackOption() { + this->removeArgument(); + } +}; + + cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { @@ -103,7 +130,7 @@ TEST(CommandLineTest, ParseEnvironment) { // command line system will still hold a pointer to a deallocated cl::Option. TEST(CommandLineTest, ParseEnvironmentToLocalVar) { // Put cl::opt on stack to check for proper initialization of fields. - cl::opt<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); + StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local"); EXPECT_EQ("", EnvironmentTestOptionLocal); cl::ParseEnvironmentOptions("CommandLineTest", test_env_var); @@ -113,14 +140,14 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) { #endif // SKIP_ENVIRONMENT_TESTS TEST(CommandLineTest, UseOptionCategory) { - cl::opt<int> TestOption2("test-option", cl::cat(TestCategory)); + StackOption<int> TestOption2("test-option", cl::cat(TestCategory)); ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option " "Category."; } class StrDupSaver : public cl::StringSaver { - const char *SaveString(const char *Str) LLVM_OVERRIDE { + const char *SaveString(const char *Str) override { return strdup(Str); } }; @@ -161,4 +188,47 @@ TEST(CommandLineTest, TokenizeWindowsCommandLine) { array_lengthof(Output)); } +TEST(CommandLineTest, AliasesWithArguments) { + static const size_t ARGC = 3; + const char *const Inputs[][ARGC] = { + { "-tool", "-actual=x", "-extra" }, + { "-tool", "-actual", "x" }, + { "-tool", "-alias=x", "-extra" }, + { "-tool", "-alias", "x" } + }; + + for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) { + StackOption<std::string> Actual("actual"); + StackOption<bool> Extra("extra"); + StackOption<std::string> Input(cl::Positional); + + cl::alias Alias("alias", llvm::cl::aliasopt(Actual)); + + cl::ParseCommandLineOptions(ARGC, Inputs[i]); + EXPECT_EQ("x", Actual); + EXPECT_EQ(0, Input.getNumOccurrences()); + + Alias.removeArgument(); + } +} + +void testAliasRequired(int argc, const char *const *argv) { + StackOption<std::string> Option("option", cl::Required); + cl::alias Alias("o", llvm::cl::aliasopt(Option)); + + cl::ParseCommandLineOptions(argc, argv); + EXPECT_EQ("x", Option); + EXPECT_EQ(1, Option.getNumOccurrences()); + + Alias.removeArgument(); +} + +TEST(CommandLineTest, AliasRequired) { + const char *opts1[] = { "-tool", "-option=x" }; + const char *opts2[] = { "-tool", "-o", "x" }; + testAliasRequired(array_lengthof(opts1), opts1); + testAliasRequired(array_lengthof(opts2), opts2); +} + + } // anonymous namespace diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index c0a9adadb788..698ae3aa2fc0 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,10 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" -#include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" using namespace llvm; @@ -25,20 +24,17 @@ namespace { #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { - OwningPtr<MemoryBuffer> Compressed; - OwningPtr<MemoryBuffer> Uncompressed; + SmallString<32> Compressed; + SmallString<32> Uncompressed; EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); // Check that uncompressed buffer is the same as original. - EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(), - Uncompressed, Input.size())); - EXPECT_EQ(Input.size(), Uncompressed->getBufferSize()); - EXPECT_EQ(0, - memcmp(Input.data(), Uncompressed->getBufferStart(), Input.size())); + EXPECT_EQ(zlib::StatusOK, + zlib::uncompress(Compressed, Uncompressed, Input.size())); + EXPECT_EQ(Input, Uncompressed); if (Input.size() > 0) { // Uncompression fails if expected length is too short. EXPECT_EQ(zlib::StatusBufferTooShort, - zlib::uncompress(Compressed->getBuffer(), Uncompressed, - Input.size() - 1)); + zlib::uncompress(Compressed, Uncompressed, Input.size() - 1)); } } diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 13ea75b1573b..16c9bebfde16 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -10,6 +10,8 @@ #include "llvm/Support/ConvertUTF.h" #include "gtest/gtest.h" #include <string> +#include <vector> +#include <utility> using namespace llvm; @@ -63,3 +65,1600 @@ TEST(ConvertUTFTest, HasUTF16BOM) { HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe", 1)); EXPECT_FALSE(HasBOM); } + +struct ConvertUTFResultContainer { + ConversionResult ErrorCode; + std::vector<unsigned> UnicodeScalars; + + ConvertUTFResultContainer(ConversionResult ErrorCode) + : ErrorCode(ErrorCode) {} + + ConvertUTFResultContainer + withScalars(unsigned US0 = 0x110000, unsigned US1 = 0x110000, + unsigned US2 = 0x110000, unsigned US3 = 0x110000, + unsigned US4 = 0x110000, unsigned US5 = 0x110000, + unsigned US6 = 0x110000, unsigned US7 = 0x110000) { + ConvertUTFResultContainer Result(*this); + if (US0 != 0x110000) + Result.UnicodeScalars.push_back(US0); + if (US1 != 0x110000) + Result.UnicodeScalars.push_back(US1); + if (US2 != 0x110000) + Result.UnicodeScalars.push_back(US2); + if (US3 != 0x110000) + Result.UnicodeScalars.push_back(US3); + if (US4 != 0x110000) + Result.UnicodeScalars.push_back(US4); + if (US5 != 0x110000) + Result.UnicodeScalars.push_back(US5); + if (US6 != 0x110000) + Result.UnicodeScalars.push_back(US6); + if (US7 != 0x110000) + Result.UnicodeScalars.push_back(US7); + return Result; + } +}; + +std::pair<ConversionResult, std::vector<unsigned>> +ConvertUTF8ToUnicodeScalarsLenient(StringRef S) { + const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(S.data()); + + const UTF8 *SourceNext = SourceStart; + std::vector<UTF32> Decoded(S.size(), 0); + UTF32 *TargetStart = Decoded.data(); + + auto ErrorCode = + ConvertUTF8toUTF32(&SourceNext, SourceStart + S.size(), &TargetStart, + Decoded.data() + Decoded.size(), lenientConversion); + + Decoded.resize(TargetStart - Decoded.data()); + + return std::make_pair(ErrorCode, Decoded); +} + +std::pair<ConversionResult, std::vector<unsigned>> +ConvertUTF8ToUnicodeScalarsPartialLenient(StringRef S) { + const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(S.data()); + + const UTF8 *SourceNext = SourceStart; + std::vector<UTF32> Decoded(S.size(), 0); + UTF32 *TargetStart = Decoded.data(); + + auto ErrorCode = ConvertUTF8toUTF32Partial( + &SourceNext, SourceStart + S.size(), &TargetStart, + Decoded.data() + Decoded.size(), lenientConversion); + + Decoded.resize(TargetStart - Decoded.data()); + + return std::make_pair(ErrorCode, Decoded); +} + +::testing::AssertionResult +CheckConvertUTF8ToUnicodeScalars(ConvertUTFResultContainer Expected, + StringRef S, bool Partial = false) { + ConversionResult ErrorCode; + std::vector<unsigned> Decoded; + if (!Partial) + std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsLenient(S); + else + + std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsPartialLenient(S); + if (Expected.ErrorCode != ErrorCode) + return ::testing::AssertionFailure() << "Expected error code " + << Expected.ErrorCode << ", actual " + << ErrorCode; + + if (Expected.UnicodeScalars != Decoded) + return ::testing::AssertionFailure() + << "Expected lenient decoded result:\n" + << ::testing::PrintToString(Expected.UnicodeScalars) << "\n" + << "Actual result:\n" << ::testing::PrintToString(Decoded); + + return ::testing::AssertionSuccess(); +} + +TEST(ConvertUTFTest, UTF8ToUTF32Lenient) { + + // + // 1-byte sequences + // + + // U+0041 LATIN CAPITAL LETTER A + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0041), "\x41")); + + // + // 2-byte sequences + // + + // U+0283 LATIN SMALL LETTER ESH + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0283), + "\xca\x83")); + + // U+03BA GREEK SMALL LETTER KAPPA + // U+1F79 GREEK SMALL LETTER OMICRON WITH OXIA + // U+03C3 GREEK SMALL LETTER SIGMA + // U+03BC GREEK SMALL LETTER MU + // U+03B5 GREEK SMALL LETTER EPSILON + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK) + .withScalars(0x03ba, 0x1f79, 0x03c3, 0x03bc, 0x03b5), + "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5")); + + // + // 3-byte sequences + // + + // U+4F8B CJK UNIFIED IDEOGRAPH-4F8B + // U+6587 CJK UNIFIED IDEOGRAPH-6587 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x4f8b, 0x6587), + "\xe4\xbe\x8b\xe6\x96\x87")); + + // U+D55C HANGUL SYLLABLE HAN + // U+AE00 HANGUL SYLLABLE GEUL + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xd55c, 0xae00), + "\xed\x95\x9c\xea\xb8\x80")); + + // U+1112 HANGUL CHOSEONG HIEUH + // U+1161 HANGUL JUNGSEONG A + // U+11AB HANGUL JONGSEONG NIEUN + // U+1100 HANGUL CHOSEONG KIYEOK + // U+1173 HANGUL JUNGSEONG EU + // U+11AF HANGUL JONGSEONG RIEUL + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK) + .withScalars(0x1112, 0x1161, 0x11ab, 0x1100, 0x1173, 0x11af), + "\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab\xe1\x84\x80\xe1\x85\xb3" + "\xe1\x86\xaf")); + + // + // 4-byte sequences + // + + // U+E0100 VARIATION SELECTOR-17 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x000E0100), + "\xf3\xa0\x84\x80")); + + // + // First possible sequence of a certain length + // + + // U+0000 NULL + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0000), + StringRef("\x00", 1))); + + // U+0080 PADDING CHARACTER + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0080), + "\xc2\x80")); + + // U+0800 SAMARITAN LETTER ALAF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0800), + "\xe0\xa0\x80")); + + // U+10000 LINEAR B SYLLABLE B008 A + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x10000), + "\xf0\x90\x80\x80")); + + // U+200000 (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x88\x80\x80\x80")); + + // U+4000000 (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x84\x80\x80\x80\x80")); + + // + // Last possible sequence of a certain length + // + + // U+007F DELETE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x007f), "\x7f")); + + // U+07FF (unassigned) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x07ff), + "\xdf\xbf")); + + // U+FFFF (noncharacter) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xffff), + "\xef\xbf\xbf")); + + // U+1FFFFF (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf7\xbf\xbf\xbf")); + + // U+3FFFFFF (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfb\xbf\xbf\xbf\xbf")); + + // U+7FFFFFFF (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfd\xbf\xbf\xbf\xbf\xbf")); + + // + // Other boundary conditions + // + + // U+D7FF (unassigned) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xd7ff), + "\xed\x9f\xbf")); + + // U+E000 (private use) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xe000), + "\xee\x80\x80")); + + // U+FFFD REPLACEMENT CHARACTER + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfffd), + "\xef\xbf\xbd")); + + // U+10FFFF (noncharacter) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x10ffff), + "\xf4\x8f\xbf\xbf")); + + // U+110000 (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf4\x90\x80\x80")); + + // + // Unexpected continuation bytes + // + + // A sequence of unexpected continuation bytes that don't follow a first + // byte, every byte is a maximal subpart. + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\x80\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xbf\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\x80\xbf\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\x80\xbf\x80\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\x80\xbf\x82\xbf\xaa")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xaa\xb0\xbb\xbf\xaa\xa0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xaa\xb0\xbb\xbf\xaa\xa0\x8f")); + + // All continuation bytes (0x80--0xbf). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf")); + + // + // Lonely start bytes + // + + // Start bytes of 2-byte sequences (0xc0--0xdf). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020), + "\xc0\x20\xc1\x20\xc2\x20\xc3\x20\xc4\x20\xc5\x20\xc6\x20\xc7\x20" + "\xc8\x20\xc9\x20\xca\x20\xcb\x20\xcc\x20\xcd\x20\xce\x20\xcf\x20" + "\xd0\x20\xd1\x20\xd2\x20\xd3\x20\xd4\x20\xd5\x20\xd6\x20\xd7\x20" + "\xd8\x20\xd9\x20\xda\x20\xdb\x20\xdc\x20\xdd\x20\xde\x20\xdf\x20")); + + // Start bytes of 3-byte sequences (0xe0--0xef). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020), + "\xe0\x20\xe1\x20\xe2\x20\xe3\x20\xe4\x20\xe5\x20\xe6\x20\xe7\x20" + "\xe8\x20\xe9\x20\xea\x20\xeb\x20\xec\x20\xed\x20\xee\x20\xef\x20")); + + // Start bytes of 4-byte sequences (0xf0--0xf7). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, + 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020), + "\xf0\x20\xf1\x20\xf2\x20\xf3\x20\xf4\x20\xf5\x20\xf6\x20\xf7\x20")); + + // Start bytes of 5-byte sequences (0xf8--0xfb). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\xf9\xfa\xfb")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020), + "\xf8\x20\xf9\x20\xfa\x20\xfb\x20")); + + // Start bytes of 6-byte sequences (0xfc--0xfd). + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfc\xfd")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020), + "\xfc\x20\xfd\x20")); + + // + // Other bytes (0xc0--0xc1, 0xfe--0xff). + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc1")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfe")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xff")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xc0\xc1\xfe\xff")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfe\xfe\xff\xff")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfe\x80\x80\x80\x80\x80")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xff\x80\x80\x80\x80\x80")); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020, + 0xfffd, 0x0020, 0xfffd, 0x0020), + "\xc0\x20\xc1\x20\xfe\x20\xff\x20")); + + // + // Sequences with one continuation byte missing + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc2")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xdf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xe0\xa0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xe0\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xe1\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xec\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xed\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xed\x9f")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xee\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xef\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf0\x90\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf0\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf1\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf3\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf4\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf4\x8f\xbf")); + + // Overlong sequences with one trailing byte missing. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xc0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xc1")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xe0\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xe0\x9f")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf0\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf0\x8f\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x80\x80\x80\x80")); + + // Sequences that represent surrogates with one trailing byte missing. + // High surrogates + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xa0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xac")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xaf")); + // Low surrogates + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xb0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xb4")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xed\xbf")); + + // Ill-formed 4-byte sequences. + // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+1100xx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf4\x90\x80")); + // U+13FBxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf4\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf5\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf6\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf7\x80\x80")); + // U+1FFBxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf7\xbf\xbf")); + + // Ill-formed 5-byte sequences. + // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+2000xx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x88\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\xbf\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf9\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfa\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfb\x80\x80\x80")); + // U+3FFFFxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfb\xbf\xbf\xbf")); + + // Ill-formed 6-byte sequences. + // 1111110u 10uuuuuu 10uzzzzz 10zzzyyyy 10yyyyxx 10xxxxxx + // U+40000xx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x84\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\xbf\xbf\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfd\x80\x80\x80\x80")); + // U+7FFFFFxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfd\xbf\xbf\xbf\xbf")); + + // + // Sequences with two continuation bytes missing + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf0\x90")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf0\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf1\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf3\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf4\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), + "\xf4\x8f")); + + // Overlong sequences with two trailing byte missing. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xe0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf0\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf0\x8f")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf8\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x80\x80\x80")); + + // Sequences that represent surrogates with two trailing bytes missing. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xed")); + + // Ill-formed 4-byte sequences. + // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+110yxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf4\x90")); + // U+13Fyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf4\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf5\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf6\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf7\x80")); + // U+1FFyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf7\xbf")); + + // Ill-formed 5-byte sequences. + // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+200yxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf8\x88\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf8\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xf9\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfa\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfb\x80\x80")); + // U+3FFFyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfb\xbf\xbf")); + + // Ill-formed 6-byte sequences. + // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+4000yxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x84\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\xbf\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfd\x80\x80\x80")); + // U+7FFFFyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfd\xbf\xbf\xbf")); + + // + // Sequences with three continuation bytes missing + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf1")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf2")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf3")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf4")); + + // Broken overlong sequences. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf0")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf8\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfc\x80\x80")); + + // Ill-formed 4-byte sequences. + // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+14yyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf5")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf6")); + // U+1Cyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf7")); + + // Ill-formed 5-byte sequences. + // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+20yyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf8\x88")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf8\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xf9\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfa\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfb\x80")); + // U+3FCyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfb\xbf")); + + // Ill-formed 6-byte sequences. + // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+400yyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfc\x84\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfc\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfd\x80\x80")); + // U+7FFCyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd), + "\xfd\xbf\xbf")); + + // + // Sequences with four continuation bytes missing + // + + // Ill-formed 5-byte sequences. + // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+uzyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf8")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf9")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfa")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfb")); + // U+3zyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfb")); + + // Broken overlong sequences. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf8")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfc\x80")); + + // Ill-formed 6-byte sequences. + // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+uzzyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfc\x84")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfc\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfd\x80")); + // U+7Fzzyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xfd\xbf")); + + // + // Sequences with five continuation bytes missing + // + + // Ill-formed 6-byte sequences. + // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx + // U+uzzyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfc")); + // U+uuzzyyxx (invalid) + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfd")); + + // + // Consecutive sequences with trailing bytes missing + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, /**/ 0xfffd, 0xfffd, /**/ 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, /**/ 0xfffd, /**/ 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xc0" "\xe0\x80" "\xf0\x80\x80" + "\xf8\x80\x80\x80" + "\xfc\x80\x80\x80\x80" + "\xdf" "\xef\xbf" "\xf7\xbf\xbf" + "\xfb\xbf\xbf\xbf" + "\xfd\xbf\xbf\xbf\xbf")); + + // + // Overlong UTF-8 sequences + // + + // U+002F SOLIDUS + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x002f), "\x2f")); + + // Overlong sequences of the above. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xc0\xaf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xe0\x80\xaf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf0\x80\x80\xaf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x80\x80\x80\xaf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x80\x80\x80\x80\xaf")); + + // U+0000 NULL + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0000), + StringRef("\x00", 1))); + + // Overlong sequences of the above. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xc0\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xe0\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf0\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x80\x80\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x80\x80\x80\x80\x80")); + + // Other overlong sequences. + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xc0\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xc1\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd), + "\xc1\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xe0\x9f\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xa0\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf0\x8f\x80\x80")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf0\x8f\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xf8\x87\xbf\xbf\xbf")); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xfc\x83\xbf\xbf\xbf\xbf")); + + // + // Isolated surrogates + // + + // Unicode 6.3.0: + // + // D71. High-surrogate code point: A Unicode code point in the range + // U+D800 to U+DBFF. + // + // D73. Low-surrogate code point: A Unicode code point in the range + // U+DC00 to U+DFFF. + + // Note: U+E0100 is <DB40 DD00> in UTF16. + + // High surrogates + + // U+D800 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xa0\x80")); + + // U+DB40 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xac\xa0")); + + // U+DBFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xaf\xbf")); + + // Low surrogates + + // U+DC00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xb0\x80")); + + // U+DD00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xb4\x80")); + + // U+DFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd), + "\xed\xbf\xbf")); + + // Surrogate pairs + + // U+D800 U+DC00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xa0\x80\xed\xb0\x80")); + + // U+D800 U+DD00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xa0\x80\xed\xb4\x80")); + + // U+D800 U+DFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xa0\x80\xed\xbf\xbf")); + + // U+DB40 U+DC00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xac\xa0\xed\xb0\x80")); + + // U+DB40 U+DD00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xac\xa0\xed\xb4\x80")); + + // U+DB40 U+DFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xac\xa0\xed\xbf\xbf")); + + // U+DBFF U+DC00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xaf\xbf\xed\xb0\x80")); + + // U+DBFF U+DD00 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xaf\xbf\xed\xb4\x80")); + + // U+DBFF U+DFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceIllegal) + .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd), + "\xed\xaf\xbf\xed\xbf\xbf")); + + // + // Noncharacters + // + + // Unicode 6.3.0: + // + // D14. Noncharacter: A code point that is permanently reserved for + // internal use and that should never be interchanged. Noncharacters + // consist of the values U+nFFFE and U+nFFFF (where n is from 0 to 1016) + // and the values U+FDD0..U+FDEF. + + // U+FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfffe), + "\xef\xbf\xbe")); + + // U+FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xffff), + "\xef\xbf\xbf")); + + // U+1FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x1fffe), + "\xf0\x9f\xbf\xbe")); + + // U+1FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x1ffff), + "\xf0\x9f\xbf\xbf")); + + // U+2FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x2fffe), + "\xf0\xaf\xbf\xbe")); + + // U+2FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x2ffff), + "\xf0\xaf\xbf\xbf")); + + // U+3FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x3fffe), + "\xf0\xbf\xbf\xbe")); + + // U+3FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x3ffff), + "\xf0\xbf\xbf\xbf")); + + // U+4FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x4fffe), + "\xf1\x8f\xbf\xbe")); + + // U+4FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x4ffff), + "\xf1\x8f\xbf\xbf")); + + // U+5FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x5fffe), + "\xf1\x9f\xbf\xbe")); + + // U+5FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x5ffff), + "\xf1\x9f\xbf\xbf")); + + // U+6FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x6fffe), + "\xf1\xaf\xbf\xbe")); + + // U+6FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x6ffff), + "\xf1\xaf\xbf\xbf")); + + // U+7FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x7fffe), + "\xf1\xbf\xbf\xbe")); + + // U+7FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x7ffff), + "\xf1\xbf\xbf\xbf")); + + // U+8FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x8fffe), + "\xf2\x8f\xbf\xbe")); + + // U+8FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x8ffff), + "\xf2\x8f\xbf\xbf")); + + // U+9FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x9fffe), + "\xf2\x9f\xbf\xbe")); + + // U+9FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x9ffff), + "\xf2\x9f\xbf\xbf")); + + // U+AFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xafffe), + "\xf2\xaf\xbf\xbe")); + + // U+AFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xaffff), + "\xf2\xaf\xbf\xbf")); + + // U+BFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xbfffe), + "\xf2\xbf\xbf\xbe")); + + // U+BFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xbffff), + "\xf2\xbf\xbf\xbf")); + + // U+CFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xcfffe), + "\xf3\x8f\xbf\xbe")); + + // U+CFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xcfffF), + "\xf3\x8f\xbf\xbf")); + + // U+DFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xdfffe), + "\xf3\x9f\xbf\xbe")); + + // U+DFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xdffff), + "\xf3\x9f\xbf\xbf")); + + // U+EFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xefffe), + "\xf3\xaf\xbf\xbe")); + + // U+EFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xeffff), + "\xf3\xaf\xbf\xbf")); + + // U+FFFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xffffe), + "\xf3\xbf\xbf\xbe")); + + // U+FFFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfffff), + "\xf3\xbf\xbf\xbf")); + + // U+10FFFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x10fffe), + "\xf4\x8f\xbf\xbe")); + + // U+10FFFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x10ffff), + "\xf4\x8f\xbf\xbf")); + + // U+FDD0 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd0), + "\xef\xb7\x90")); + + // U+FDD1 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd1), + "\xef\xb7\x91")); + + // U+FDD2 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd2), + "\xef\xb7\x92")); + + // U+FDD3 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd3), + "\xef\xb7\x93")); + + // U+FDD4 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd4), + "\xef\xb7\x94")); + + // U+FDD5 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd5), + "\xef\xb7\x95")); + + // U+FDD6 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd6), + "\xef\xb7\x96")); + + // U+FDD7 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd7), + "\xef\xb7\x97")); + + // U+FDD8 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd8), + "\xef\xb7\x98")); + + // U+FDD9 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdd9), + "\xef\xb7\x99")); + + // U+FDDA + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdda), + "\xef\xb7\x9a")); + + // U+FDDB + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfddb), + "\xef\xb7\x9b")); + + // U+FDDC + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfddc), + "\xef\xb7\x9c")); + + // U+FDDD + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfddd), + "\xef\xb7\x9d")); + + // U+FDDE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdde), + "\xef\xb7\x9e")); + + // U+FDDF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfddf), + "\xef\xb7\x9f")); + + // U+FDE0 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde0), + "\xef\xb7\xa0")); + + // U+FDE1 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde1), + "\xef\xb7\xa1")); + + // U+FDE2 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde2), + "\xef\xb7\xa2")); + + // U+FDE3 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde3), + "\xef\xb7\xa3")); + + // U+FDE4 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde4), + "\xef\xb7\xa4")); + + // U+FDE5 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde5), + "\xef\xb7\xa5")); + + // U+FDE6 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde6), + "\xef\xb7\xa6")); + + // U+FDE7 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde7), + "\xef\xb7\xa7")); + + // U+FDE8 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde8), + "\xef\xb7\xa8")); + + // U+FDE9 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfde9), + "\xef\xb7\xa9")); + + // U+FDEA + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdea), + "\xef\xb7\xaa")); + + // U+FDEB + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdeb), + "\xef\xb7\xab")); + + // U+FDEC + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdec), + "\xef\xb7\xac")); + + // U+FDED + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfded), + "\xef\xb7\xad")); + + // U+FDEE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdee), + "\xef\xb7\xae")); + + // U+FDEF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdef), + "\xef\xb7\xaf")); + + // U+FDF0 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf0), + "\xef\xb7\xb0")); + + // U+FDF1 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf1), + "\xef\xb7\xb1")); + + // U+FDF2 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf2), + "\xef\xb7\xb2")); + + // U+FDF3 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf3), + "\xef\xb7\xb3")); + + // U+FDF4 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf4), + "\xef\xb7\xb4")); + + // U+FDF5 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf5), + "\xef\xb7\xb5")); + + // U+FDF6 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf6), + "\xef\xb7\xb6")); + + // U+FDF7 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf7), + "\xef\xb7\xb7")); + + // U+FDF8 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf8), + "\xef\xb7\xb8")); + + // U+FDF9 + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdf9), + "\xef\xb7\xb9")); + + // U+FDFA + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdfa), + "\xef\xb7\xba")); + + // U+FDFB + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdfb), + "\xef\xb7\xbb")); + + // U+FDFC + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdfc), + "\xef\xb7\xbc")); + + // U+FDFD + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdfd), + "\xef\xb7\xbd")); + + // U+FDFE + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdfe), + "\xef\xb7\xbe")); + + // U+FDFF + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0xfdff), + "\xef\xb7\xbf")); +} + +TEST(ConvertUTFTest, UTF8ToUTF32PartialLenient) { + // U+0041 LATIN CAPITAL LETTER A + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(conversionOK).withScalars(0x0041), + "\x41", true)); + + // + // Sequences with one continuation byte missing + // + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xc2", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xdf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xe0\xa0", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xe0\xbf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xe1\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xec\xbf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xed\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xed\x9f", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xee\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xef\xbf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf0\x90\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf0\xbf\xbf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf1\x80\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf3\xbf\xbf", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf4\x80\x80", true)); + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted), + "\xf4\x8f\xbf", true)); + + EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars( + ConvertUTFResultContainer(sourceExhausted).withScalars(0x0041), + "\x41\xc2", true)); +} + diff --git a/unittests/Support/DataExtractorTest.cpp b/unittests/Support/DataExtractorTest.cpp index ec8bd3d18c8a..81de983d2265 100644 --- a/unittests/Support/DataExtractorTest.cpp +++ b/unittests/Support/DataExtractorTest.cpp @@ -94,7 +94,7 @@ TEST(DataExtractorTest, Strings) { EXPECT_EQ(stringData, DE.getCStr(&offset)); EXPECT_EQ(11U, offset); - EXPECT_EQ(NULL, DE.getCStr(&offset)); + EXPECT_EQ(nullptr, DE.getCStr(&offset)); EXPECT_EQ(11U, offset); } diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index feb6a086e194..d76e7d62421f 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -8,9 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ErrorOr.h" - +#include "llvm/Support/Errc.h" #include "gtest/gtest.h" - #include <memory> using namespace llvm; @@ -22,22 +21,25 @@ ErrorOr<int> t2() { return errc::invalid_argument; } TEST(ErrorOr, SimpleValue) { ErrorOr<int> a = t1(); - EXPECT_TRUE(a); + // FIXME: This is probably a bug in gtest. EXPECT_TRUE should expand to + // include the !! to make it friendly to explicit bool operators. + EXPECT_TRUE(!!a); EXPECT_EQ(1, *a); + ErrorOr<int> b = a; + EXPECT_EQ(1, *b); + a = t2(); EXPECT_FALSE(a); - EXPECT_EQ(errc::invalid_argument, a); + EXPECT_EQ(a.getError(), errc::invalid_argument); #ifdef EXPECT_DEBUG_DEATH EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists"); #endif } -#if LLVM_HAS_CXX11_STDLIB ErrorOr<std::unique_ptr<int> > t3() { return std::unique_ptr<int>(new int(3)); } -#endif TEST(ErrorOr, Types) { int x; @@ -45,22 +47,18 @@ TEST(ErrorOr, Types) { *a = 42; EXPECT_EQ(42, x); -#if LLVM_HAS_CXX11_STDLIB // Move only types. EXPECT_EQ(3, **t3()); -#endif } struct B {}; struct D : B {}; TEST(ErrorOr, Covariant) { - ErrorOr<B*> b(ErrorOr<D*>(0)); - b = ErrorOr<D*>(0); + ErrorOr<B*> b(ErrorOr<D*>(nullptr)); + b = ErrorOr<D*>(nullptr); -#if LLVM_HAS_CXX11_STDLIB - ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(0)); - b1 = ErrorOr<std::unique_ptr<D> >(0); -#endif + ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(nullptr)); + b1 = ErrorOr<std::unique_ptr<D> >(nullptr); } } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index 5e873193f288..b086f1e118d2 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileOutputBuffer.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -18,12 +17,13 @@ using namespace llvm; using namespace llvm::sys; -#define ASSERT_NO_ERROR(x) \ - if (error_code ASSERT_NO_ERROR_ec = x) { \ - errs() << #x ": did not return errc::success.\n" \ - << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ - << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ - } else {} +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + errs() << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + } else { \ + } namespace { TEST(FileOutputBuffer, Test) { @@ -38,7 +38,7 @@ TEST(FileOutputBuffer, Test) { SmallString<128> File1(TestDirectory); File1.append("/file1"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File1, 8192, Buffer)); // Start buffer with special header. memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -47,36 +47,34 @@ TEST(FileOutputBuffer, Test) { // Commit buffer. ASSERT_NO_ERROR(Buffer->commit()); } - // Verify file exists and starts with special header. - bool MagicMatches = false; - ASSERT_NO_ERROR(fs::has_magic(Twine(File1), Twine("AABBCCDDEEFFGGHHIIJJ"), - MagicMatches)); - EXPECT_TRUE(MagicMatches); + // Verify file is correct size. uint64_t File1Size; ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size)); ASSERT_EQ(File1Size, 8192ULL); + ASSERT_NO_ERROR(fs::remove(File1.str())); // TEST 2: Verify abort case. SmallString<128> File2(TestDirectory); File2.append("/file2"); { - OwningPtr<FileOutputBuffer> Buffer2; + std::unique_ptr<FileOutputBuffer> Buffer2; ASSERT_NO_ERROR(FileOutputBuffer::create(File2, 8192, Buffer2)); // Fill buffer with special header. memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); // Do *not* commit buffer. } - // Verify file does not exist (because buffer not commited). + // Verify file does not exist (because buffer not committed). bool Exists = false; ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); EXPECT_FALSE(Exists); + ASSERT_NO_ERROR(fs::remove(File2.str())); // TEST 3: Verify sizing down case. SmallString<128> File3(TestDirectory); File3.append("/file3"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File3, 8192000, Buffer)); // Start buffer with special header. memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -85,21 +83,18 @@ TEST(FileOutputBuffer, Test) { // Commit buffer, but size down to smaller size ASSERT_NO_ERROR(Buffer->commit(5000)); } - // Verify file exists and starts with special header. - bool MagicMatches3 = false; - ASSERT_NO_ERROR(fs::has_magic(Twine(File3), Twine("AABBCCDDEEFFGGHHIIJJ"), - MagicMatches3)); - EXPECT_TRUE(MagicMatches3); + // Verify file is correct size. uint64_t File3Size; ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); ASSERT_EQ(File3Size, 5000ULL); + ASSERT_NO_ERROR(fs::remove(File3.str())); // TEST 4: Verify file can be made executable. SmallString<128> File4(TestDirectory); File4.append("/file4"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File4, 8192, Buffer, FileOutputBuffer::F_executable)); // Start buffer with special header. @@ -112,9 +107,9 @@ TEST(FileOutputBuffer, Test) { ASSERT_NO_ERROR(fs::status(Twine(File4), Status)); bool IsExecutable = (Status.permissions() & fs::owner_exe); EXPECT_TRUE(IsExecutable); + ASSERT_NO_ERROR(fs::remove(File4.str())); // Clean up. - uint32_t RemovedCount; - ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), RemovedCount)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } } // anonymous namespace diff --git a/unittests/Support/IteratorTest.cpp b/unittests/Support/IteratorTest.cpp new file mode 100644 index 000000000000..83848328c0c6 --- /dev/null +++ b/unittests/Support/IteratorTest.cpp @@ -0,0 +1,101 @@ +//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(PointeeIteratorTest, Basic) { + int arr[4] = { 1, 2, 3, 4 }; + SmallVector<int *, 4> V; + V.push_back(&arr[0]); + V.push_back(&arr[1]); + V.push_back(&arr[2]); + V.push_back(&arr[3]); + + typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator> test_iterator; + + test_iterator Begin, End; + Begin = V.begin(); + End = test_iterator(V.end()); + + test_iterator I = Begin; + for (int i = 0; i < 4; ++i) { + EXPECT_EQ(*V[i], *I); + + EXPECT_EQ(I, Begin + i); + EXPECT_EQ(I, std::next(Begin, i)); + test_iterator J = Begin; + J += i; + EXPECT_EQ(I, J); + EXPECT_EQ(*V[i], Begin[i]); + + EXPECT_NE(I, End); + EXPECT_GT(End, I); + EXPECT_LT(I, End); + EXPECT_GE(I, Begin); + EXPECT_LE(Begin, I); + + EXPECT_EQ(i, I - Begin); + EXPECT_EQ(i, std::distance(Begin, I)); + EXPECT_EQ(Begin, I - i); + + test_iterator K = I++; + EXPECT_EQ(K, std::prev(I)); + } + EXPECT_EQ(End, I); +} + +TEST(PointeeIteratorTest, SmartPointer) { + SmallVector<std::unique_ptr<int>, 4> V; + V.push_back(make_unique<int>(1)); + V.push_back(make_unique<int>(2)); + V.push_back(make_unique<int>(3)); + V.push_back(make_unique<int>(4)); + + typedef pointee_iterator< + SmallVectorImpl<std::unique_ptr<int>>::const_iterator> test_iterator; + + test_iterator Begin, End; + Begin = V.begin(); + End = test_iterator(V.end()); + + test_iterator I = Begin; + for (int i = 0; i < 4; ++i) { + EXPECT_EQ(*V[i], *I); + + EXPECT_EQ(I, Begin + i); + EXPECT_EQ(I, std::next(Begin, i)); + test_iterator J = Begin; + J += i; + EXPECT_EQ(I, J); + EXPECT_EQ(*V[i], Begin[i]); + + EXPECT_NE(I, End); + EXPECT_GT(End, I); + EXPECT_LT(I, End); + EXPECT_GE(I, Begin); + EXPECT_LE(Begin, I); + + EXPECT_EQ(i, I - Begin); + EXPECT_EQ(i, std::distance(Begin, I)); + EXPECT_EQ(Begin, I - i); + + test_iterator K = I++; + EXPECT_EQ(K, std::prev(I)); + } + EXPECT_EQ(End, I); +} + +} // anonymous namespace diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp new file mode 100644 index 000000000000..b1ca13ef2416 --- /dev/null +++ b/unittests/Support/LEB128Test.cpp @@ -0,0 +1,311 @@ +//===- llvm/unittest/Support/LEB128Test.cpp - LEB128 function tests -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +using namespace llvm; + +namespace { + +TEST(LEB128Test, EncodeSLEB128) { +#define EXPECT_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + /* encodeSLEB128(uint64_t, raw_ostream &) */ \ + std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \ + std::string Actual; \ + raw_string_ostream Stream(Actual); \ + encodeSLEB128(VALUE, Stream); \ + Stream.flush(); \ + EXPECT_EQ(Expected, Actual); \ + } while (0) + + // Encode SLEB128 + EXPECT_SLEB128_EQ("\x00", 0); + EXPECT_SLEB128_EQ("\x01", 1); + EXPECT_SLEB128_EQ("\x7f", -1); + EXPECT_SLEB128_EQ("\x3f", 63); + EXPECT_SLEB128_EQ("\x41", -63); + EXPECT_SLEB128_EQ("\x40", -64); + EXPECT_SLEB128_EQ("\xbf\x7f", -65); + EXPECT_SLEB128_EQ("\xc0\x00", 64); + +#undef EXPECT_SLEB128_EQ +} + +TEST(LEB128Test, EncodeULEB128) { +#define EXPECT_ULEB128_EQ(EXPECTED, VALUE, PAD) \ + do { \ + std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \ + \ + /* encodeULEB128(uint64_t, raw_ostream &, unsigned) */ \ + std::string Actual1; \ + raw_string_ostream Stream(Actual1); \ + encodeULEB128(VALUE, Stream, PAD); \ + Stream.flush(); \ + EXPECT_EQ(Expected, Actual1); \ + \ + /* encodeULEB128(uint64_t, uint8_t *, unsigned) */ \ + uint8_t Buffer[32]; \ + unsigned Size = encodeULEB128(VALUE, Buffer, PAD); \ + std::string Actual2(reinterpret_cast<const char *>(Buffer), Size); \ + EXPECT_EQ(Expected, Actual2); \ + } while (0) + + // Encode ULEB128 + EXPECT_ULEB128_EQ("\x00", 0, 0); + EXPECT_ULEB128_EQ("\x01", 1, 0); + EXPECT_ULEB128_EQ("\x3f", 63, 0); + EXPECT_ULEB128_EQ("\x40", 64, 0); + EXPECT_ULEB128_EQ("\x7f", 0x7f, 0); + EXPECT_ULEB128_EQ("\x80\x01", 0x80, 0); + EXPECT_ULEB128_EQ("\x81\x01", 0x81, 0); + EXPECT_ULEB128_EQ("\x90\x01", 0x90, 0); + EXPECT_ULEB128_EQ("\xff\x01", 0xff, 0); + EXPECT_ULEB128_EQ("\x80\x02", 0x100, 0); + EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0); + + // Encode ULEB128 with some extra padding bytes + EXPECT_ULEB128_EQ("\x80\x00", 0, 1); + EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 2); + EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 1); + EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 2); + EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 1); + EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 2); + +#undef EXPECT_ULEB128_EQ +} + +TEST(LEB128Test, DecodeULEB128) { +#define EXPECT_DECODE_ULEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + uint64_t Actual = decodeULEB128(reinterpret_cast<const uint8_t *>(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode ULEB128 + EXPECT_DECODE_ULEB128_EQ(0u, "\x00"); + EXPECT_DECODE_ULEB128_EQ(1u, "\x01"); + EXPECT_DECODE_ULEB128_EQ(63u, "\x3f"); + EXPECT_DECODE_ULEB128_EQ(64u, "\x40"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\x7f"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x01"); + EXPECT_DECODE_ULEB128_EQ(0x81u, "\x81\x01"); + EXPECT_DECODE_ULEB128_EQ(0x90u, "\x90\x01"); + EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01"); + EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02"); + EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); + + // Decode ULEB128 with extra padding bytes + EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x00"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x00"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_ULEB128_EQ +} + +TEST(LEB128Test, SLEB128Size) { + // Positive Value Testing Plan: + // (1) 128 ^ n - 1 ........ need (n+1) bytes + // (2) 128 ^ n ............ need (n+1) bytes + // (3) 128 ^ n * 63 ....... need (n+1) bytes + // (4) 128 ^ n * 64 - 1 ... need (n+1) bytes + // (5) 128 ^ n * 64 ....... need (n+2) bytes + + EXPECT_EQ(1u, getSLEB128Size(0x0LL)); + EXPECT_EQ(1u, getSLEB128Size(0x1LL)); + EXPECT_EQ(1u, getSLEB128Size(0x3fLL)); + EXPECT_EQ(1u, getSLEB128Size(0x3fLL)); + EXPECT_EQ(2u, getSLEB128Size(0x40LL)); + + EXPECT_EQ(2u, getSLEB128Size(0x7fLL)); + EXPECT_EQ(2u, getSLEB128Size(0x80LL)); + EXPECT_EQ(2u, getSLEB128Size(0x1f80LL)); + EXPECT_EQ(2u, getSLEB128Size(0x1fffLL)); + EXPECT_EQ(3u, getSLEB128Size(0x2000LL)); + + EXPECT_EQ(3u, getSLEB128Size(0x3fffLL)); + EXPECT_EQ(3u, getSLEB128Size(0x4000LL)); + EXPECT_EQ(3u, getSLEB128Size(0xfc000LL)); + EXPECT_EQ(3u, getSLEB128Size(0xfffffLL)); + EXPECT_EQ(4u, getSLEB128Size(0x100000LL)); + + EXPECT_EQ(4u, getSLEB128Size(0x1fffffLL)); + EXPECT_EQ(4u, getSLEB128Size(0x200000LL)); + EXPECT_EQ(4u, getSLEB128Size(0x7e00000LL)); + EXPECT_EQ(4u, getSLEB128Size(0x7ffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(0x8000000LL)); + + EXPECT_EQ(5u, getSLEB128Size(0xfffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(0x10000000LL)); + EXPECT_EQ(5u, getSLEB128Size(0x3f0000000LL)); + EXPECT_EQ(5u, getSLEB128Size(0x3ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(0x400000000LL)); + + EXPECT_EQ(6u, getSLEB128Size(0x7ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(0x800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(0x1f800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(0x1ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(0x20000000000LL)); + + EXPECT_EQ(7u, getSLEB128Size(0x3ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(0x40000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(0xfc0000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(0xffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(0x1000000000000LL)); + + EXPECT_EQ(8u, getSLEB128Size(0x1ffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(0x2000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(0x7e000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(0x7fffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(0x80000000000000LL)); + + EXPECT_EQ(9u, getSLEB128Size(0xffffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(0x100000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(0x3f00000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(0x3fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(0x4000000000000000LL)); + + EXPECT_EQ(10u, getSLEB128Size(0x7fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(INT64_MAX)); + + // Negative Value Testing Plan: + // (1) - 128 ^ n - 1 ........ need (n+1) bytes + // (2) - 128 ^ n ............ need (n+1) bytes + // (3) - 128 ^ n * 63 ....... need (n+1) bytes + // (4) - 128 ^ n * 64 ....... need (n+1) bytes (different from positive one) + // (5) - 128 ^ n * 65 - 1 ... need (n+2) bytes (if n > 0) + // (6) - 128 ^ n * 65 ....... need (n+2) bytes + + EXPECT_EQ(1u, getSLEB128Size(0x0LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x1LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x3fLL)); + EXPECT_EQ(1u, getSLEB128Size(-0x40LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x40LL)); // special case + EXPECT_EQ(2u, getSLEB128Size(-0x41LL)); + + EXPECT_EQ(2u, getSLEB128Size(-0x7fLL)); + EXPECT_EQ(2u, getSLEB128Size(-0x80LL)); + EXPECT_EQ(2u, getSLEB128Size(-0x1f80LL)); + EXPECT_EQ(2u, getSLEB128Size(-0x2000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0x207fLL)); + EXPECT_EQ(3u, getSLEB128Size(-0x2080LL)); + + EXPECT_EQ(3u, getSLEB128Size(-0x3fffLL)); + EXPECT_EQ(3u, getSLEB128Size(-0x4000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0xfc000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0x100000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x103fffLL)); + EXPECT_EQ(4u, getSLEB128Size(-0x104000LL)); + + EXPECT_EQ(4u, getSLEB128Size(-0x1fffffLL)); + EXPECT_EQ(4u, getSLEB128Size(-0x200000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x7e00000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x8000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x81fffffLL)); + EXPECT_EQ(5u, getSLEB128Size(-0x8200000LL)); + + EXPECT_EQ(5u, getSLEB128Size(-0xfffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(-0x10000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x3f0000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x400000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x40fffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(-0x410000000LL)); + + EXPECT_EQ(6u, getSLEB128Size(-0x7ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(-0x800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x1f800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x20000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0x207ffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(-0x20800000000LL)); + + EXPECT_EQ(7u, getSLEB128Size(-0x3ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(-0x40000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0xfc0000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0x1000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x103ffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(-0x1040000000000LL)); + + EXPECT_EQ(8u, getSLEB128Size(-0x1ffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(-0x2000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x7e000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x80000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x81ffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(-0x82000000000000LL)); + + EXPECT_EQ(9u, getSLEB128Size(-0xffffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(-0x100000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x3f00000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x4000000000000000LL)); + EXPECT_EQ(10u, getSLEB128Size(-0x40ffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(-0x4100000000000000LL)); + + EXPECT_EQ(10u, getSLEB128Size(-0x7fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(-0x8000000000000000LL)); + EXPECT_EQ(10u, getSLEB128Size(INT64_MIN)); +} + +TEST(LEB128Test, ULEB128Size) { + // Testing Plan: + // (1) 128 ^ n ............ need (n+1) bytes + // (2) 128 ^ n * 64 ....... need (n+1) bytes + // (3) 128 ^ (n+1) - 1 .... need (n+1) bytes + + EXPECT_EQ(1u, getULEB128Size(0)); // special case + + EXPECT_EQ(1u, getULEB128Size(0x1ULL)); + EXPECT_EQ(1u, getULEB128Size(0x40ULL)); + EXPECT_EQ(1u, getULEB128Size(0x7fULL)); + + EXPECT_EQ(2u, getULEB128Size(0x80ULL)); + EXPECT_EQ(2u, getULEB128Size(0x2000ULL)); + EXPECT_EQ(2u, getULEB128Size(0x3fffULL)); + + EXPECT_EQ(3u, getULEB128Size(0x4000ULL)); + EXPECT_EQ(3u, getULEB128Size(0x100000ULL)); + EXPECT_EQ(3u, getULEB128Size(0x1fffffULL)); + + EXPECT_EQ(4u, getULEB128Size(0x200000ULL)); + EXPECT_EQ(4u, getULEB128Size(0x8000000ULL)); + EXPECT_EQ(4u, getULEB128Size(0xfffffffULL)); + + EXPECT_EQ(5u, getULEB128Size(0x10000000ULL)); + EXPECT_EQ(5u, getULEB128Size(0x400000000ULL)); + EXPECT_EQ(5u, getULEB128Size(0x7ffffffffULL)); + + EXPECT_EQ(6u, getULEB128Size(0x800000000ULL)); + EXPECT_EQ(6u, getULEB128Size(0x20000000000ULL)); + EXPECT_EQ(6u, getULEB128Size(0x3ffffffffffULL)); + + EXPECT_EQ(7u, getULEB128Size(0x40000000000ULL)); + EXPECT_EQ(7u, getULEB128Size(0x1000000000000ULL)); + EXPECT_EQ(7u, getULEB128Size(0x1ffffffffffffULL)); + + EXPECT_EQ(8u, getULEB128Size(0x2000000000000ULL)); + EXPECT_EQ(8u, getULEB128Size(0x80000000000000ULL)); + EXPECT_EQ(8u, getULEB128Size(0xffffffffffffffULL)); + + EXPECT_EQ(9u, getULEB128Size(0x100000000000000ULL)); + EXPECT_EQ(9u, getULEB128Size(0x4000000000000000ULL)); + EXPECT_EQ(9u, getULEB128Size(0x7fffffffffffffffULL)); + + EXPECT_EQ(10u, getULEB128Size(0x8000000000000000ULL)); + + EXPECT_EQ(10u, getULEB128Size(UINT64_MAX)); +} + +} // anonymous namespace diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp new file mode 100644 index 000000000000..18f3fa99bcde --- /dev/null +++ b/unittests/Support/LineIteratorTest.cpp @@ -0,0 +1,115 @@ +//===- LineIterator.cpp - 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/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::sys; + +namespace { + +TEST(LineIteratorTest, Basic) { + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3")); + + line_iterator I = line_iterator(*Buffer), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkipping) { + std::unique_ptr<MemoryBuffer> Buffer( + MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "# Comment 1\n" + "line 4\n" + "# Comment 2")); + + line_iterator I = line_iterator(*Buffer, '#'), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 4", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, BlankSkipping) { + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("\n\n\n" + "line 1\n" + "\n\n\n" + "line 2\n" + "\n\n\n")); + + line_iterator I = line_iterator(*Buffer), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(8, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, EmptyBuffers) { + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("")); + EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + + Buffer.reset(MemoryBuffer::getMemBuffer("\n\n\n")); + EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + + Buffer.reset(MemoryBuffer::getMemBuffer("# foo\n" + "\n" + "# bar")); + EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); + + Buffer.reset(MemoryBuffer::getMemBuffer("\n" + "# baz\n" + "\n")); + EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); +} + +} // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 5c73b9f5e235..885b7d605367 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -10,9 +10,7 @@ #include "llvm/Support/LockFileManager.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" - #include "gtest/gtest.h" - #include <memory> using namespace llvm; @@ -21,7 +19,7 @@ namespace { TEST(LockFileManagerTest, Basic) { SmallString<64> TmpDir; - error_code EC; + std::error_code EC; EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir); ASSERT_FALSE(EC); @@ -42,7 +40,88 @@ TEST(LockFileManagerTest, Basic) { // Now that the lock is out of scope, the file should be gone. EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile))); - sys::fs::remove_all(StringRef(TmpDir)); + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); +} + +TEST(LockFileManagerTest, LinkLockExists) { + SmallString<64> TmpDir; + std::error_code EC; + EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir); + ASSERT_FALSE(EC); + + SmallString<64> LockedFile(TmpDir); + sys::path::append(LockedFile, "file"); + + SmallString<64> FileLocK(TmpDir); + sys::path::append(FileLocK, "file.lock"); + + SmallString<64> TmpFileLock(TmpDir); + sys::path::append(TmpFileLock, "file.lock-000"); + + int FD; + EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD, sys::fs::F_None); + ASSERT_FALSE(EC); + + int Ret = close(FD); + ASSERT_EQ(Ret, 0); + + EC = sys::fs::create_link(TmpFileLock.str(), FileLocK.str()); + ASSERT_FALSE(EC); + + EC = sys::fs::remove(StringRef(TmpFileLock)); + ASSERT_FALSE(EC); + + { + // The lock file doesn't point to a real file, so we should successfully + // acquire it. + LockFileManager Locked(LockedFile); + EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState()); + } + + // Now that the lock is out of scope, the file should be gone. + EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile))); + + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); +} + + +TEST(LockFileManagerTest, RelativePath) { + SmallString<64> TmpDir; + std::error_code EC; + EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir); + ASSERT_FALSE(EC); + + char PathBuf[1024]; + const char *OrigPath = getcwd(PathBuf, 1024); + chdir(TmpDir.c_str()); + + sys::fs::create_directory("inner"); + SmallString<64> LockedFile("inner"); + sys::path::append(LockedFile, "file"); + + SmallString<64> FileLock(LockedFile); + FileLock += ".lock"; + + { + // The lock file should not exist, so we should successfully acquire it. + LockFileManager Locked(LockedFile); + EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState()); + EXPECT_TRUE(sys::fs::exists(FileLock.str())); + } + + // Now that the lock is out of scope, the file should be gone. + EXPECT_FALSE(sys::fs::exists(LockedFile.str())); + EXPECT_FALSE(sys::fs::exists(FileLock.str())); + + EC = sys::fs::remove("inner"); + ASSERT_FALSE(EC); + + chdir(OrigPath); + + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); } } // end anonymous namespace diff --git a/unittests/Support/ManagedStatic.cpp b/unittests/Support/ManagedStatic.cpp index 1497f4e34082..153884ba4298 100644 --- a/unittests/Support/ManagedStatic.cpp +++ b/unittests/Support/ManagedStatic.cpp @@ -25,7 +25,7 @@ namespace test1 { llvm::ManagedStatic<int> ms; void *helper(void*) { *ms; - return NULL; + return nullptr; } // Valgrind's leak checker complains glibc's stack allocation. @@ -47,15 +47,13 @@ TEST(Initialize, MultipleThreads) { void *p1 = test1::allocate_stack(a1); void *p2 = test1::allocate_stack(a2); - llvm_start_multithreaded(); pthread_t t1, t2; - pthread_create(&t1, &a1, test1::helper, NULL); - pthread_create(&t2, &a2, test1::helper, NULL); - pthread_join(t1, NULL); - pthread_join(t2, NULL); + pthread_create(&t1, &a1, test1::helper, nullptr); + pthread_create(&t2, &a2, test1::helper, nullptr); + pthread_join(t1, nullptr); + pthread_join(t2, nullptr); free(p1); free(p2); - llvm_stop_multithreaded(); } #endif diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 2b8806c394f3..93bf301267ea 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -14,7 +14,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/OwningPtr.h" #include "gtest/gtest.h" using namespace llvm; @@ -36,7 +35,7 @@ protected: /// anew before using MemoryBuffer. void testGetOpenFileSlice(bool Reopen); - typedef OwningPtr<MemoryBuffer> OwningBuffer; + typedef std::unique_ptr<MemoryBuffer> OwningBuffer; std::string data; }; @@ -44,15 +43,15 @@ protected: TEST_F(MemoryBufferTest, get) { // Default name and null-terminator flag OwningBuffer MB1(MemoryBuffer::getMemBuffer(data)); - EXPECT_TRUE(0 != MB1.get()); + EXPECT_TRUE(nullptr != MB1.get()); // RequiresNullTerminator = false OwningBuffer MB2(MemoryBuffer::getMemBuffer(data, "one", false)); - EXPECT_TRUE(0 != MB2.get()); + EXPECT_TRUE(nullptr != MB2.get()); // RequiresNullTerminator = true OwningBuffer MB3(MemoryBuffer::getMemBuffer(data, "two", true)); - EXPECT_TRUE(0 != MB3.get()); + EXPECT_TRUE(nullptr != MB3.get()); // verify all 3 buffers point to the same address EXPECT_EQ(MB1->getBufferStart(), MB2->getBufferStart()); @@ -78,11 +77,11 @@ TEST_F(MemoryBufferTest, NullTerminator4K) { } OF.close(); - OwningPtr<MemoryBuffer> MB; - error_code EC = MemoryBuffer::getFile(TestPath.c_str(), MB); + ErrorOr<OwningBuffer> MB = MemoryBuffer::getFile(TestPath.c_str()); + std::error_code EC = MB.getError(); ASSERT_FALSE(EC); - const char *BufData = MB->getBufferStart(); + const char *BufData = MB.get()->getBufferStart(); EXPECT_EQ('f', BufData[4095]); EXPECT_EQ('\0', BufData[4096]); } @@ -90,11 +89,11 @@ TEST_F(MemoryBufferTest, NullTerminator4K) { TEST_F(MemoryBufferTest, copy) { // copy with no name OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data)); - EXPECT_TRUE(0 != MBC1.get()); + EXPECT_TRUE(nullptr != MBC1.get()); // copy with a name OwningBuffer MBC2(MemoryBuffer::getMemBufferCopy(data, "copy")); - EXPECT_TRUE(0 != MBC2.get()); + EXPECT_TRUE(nullptr != MBC2.get()); // verify the two copies do not point to the same place EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart()); @@ -103,25 +102,25 @@ TEST_F(MemoryBufferTest, copy) { TEST_F(MemoryBufferTest, make_new) { // 0-sized buffer OwningBuffer Zero(MemoryBuffer::getNewUninitMemBuffer(0)); - EXPECT_TRUE(0 != Zero.get()); + EXPECT_TRUE(nullptr != Zero.get()); // uninitialized buffer with no name OwningBuffer One(MemoryBuffer::getNewUninitMemBuffer(321)); - EXPECT_TRUE(0 != One.get()); + EXPECT_TRUE(nullptr != One.get()); // uninitialized buffer with name OwningBuffer Two(MemoryBuffer::getNewUninitMemBuffer(123, "bla")); - EXPECT_TRUE(0 != Two.get()); + EXPECT_TRUE(nullptr != Two.get()); // 0-initialized buffer with no name OwningBuffer Three(MemoryBuffer::getNewMemBuffer(321, data)); - EXPECT_TRUE(0 != Three.get()); + EXPECT_TRUE(nullptr != Three.get()); for (size_t i = 0; i < 321; ++i) EXPECT_EQ(0, Three->getBufferStart()[0]); // 0-initialized buffer with name OwningBuffer Four(MemoryBuffer::getNewMemBuffer(123, "zeros")); - EXPECT_TRUE(0 != Four.get()); + EXPECT_TRUE(nullptr != Four.get()); for (size_t i = 0; i < 123; ++i) EXPECT_EQ(0, Four->getBufferStart()[0]); } @@ -147,14 +146,16 @@ void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) { EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD)); } - OwningBuffer Buf; - error_code EC = MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(), Buf, - 40000, // Size - 80000 // Offset - ); + ErrorOr<OwningBuffer> Buf = + MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(), + 40000, // Size + 80000 // Offset + ); + + std::error_code EC = Buf.getError(); EXPECT_FALSE(EC); - StringRef BufData = Buf->getBuffer(); + StringRef BufData = Buf.get()->getBuffer(); EXPECT_EQ(BufData.size(), 40000U); EXPECT_EQ(BufData[0], '0'); EXPECT_EQ(BufData[9], '9'); diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index fae67a8dd256..8ad90e045de9 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -57,30 +57,30 @@ protected: }; TEST_P(MappedMemoryTest, AllocAndRelease) { - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(sizeof(int), M1.size()); EXPECT_FALSE(Memory::releaseMappedMemory(M1)); } TEST_P(MappedMemoryTest, MultipleAllocAndRelease) { - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M2 = Memory::allocateMappedMemory(64, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M3 = Memory::allocateMappedMemory(32, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - - EXPECT_NE((void*)0, M1.base()); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); + + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(16U, M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(64U, M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(32U, M3.size()); EXPECT_FALSE(doesOverlap(M1, M2)); @@ -89,9 +89,9 @@ TEST_P(MappedMemoryTest, MultipleAllocAndRelease) { EXPECT_FALSE(Memory::releaseMappedMemory(M1)); EXPECT_FALSE(Memory::releaseMappedMemory(M3)); - MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - EXPECT_NE((void*)0, M4.base()); + MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); + EXPECT_NE((void*)nullptr, M4.base()); EXPECT_LE(16U, M4.size()); EXPECT_FALSE(Memory::releaseMappedMemory(M4)); EXPECT_FALSE(Memory::releaseMappedMemory(M2)); @@ -103,11 +103,11 @@ TEST_P(MappedMemoryTest, BasicWrite) { !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) return; - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(sizeof(int), M1.size()); int *a = (int*)M1.base(); @@ -122,23 +122,26 @@ TEST_P(MappedMemoryTest, MultipleWrite) { if (Flags && !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE))) return; - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); EXPECT_FALSE(doesOverlap(M1, M2)); EXPECT_FALSE(doesOverlap(M2, M3)); EXPECT_FALSE(doesOverlap(M1, M3)); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(1U * sizeof(int), M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(8U * sizeof(int), M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(4U * sizeof(int), M3.size()); int *x = (int*)M1.base(); @@ -159,9 +162,10 @@ TEST_P(MappedMemoryTest, MultipleWrite) { EXPECT_FALSE(Memory::releaseMappedMemory(M1)); EXPECT_FALSE(Memory::releaseMappedMemory(M3)); - MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - EXPECT_NE((void*)0, M4.base()); + MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr, + Flags, EC); + EXPECT_EQ(std::error_code(), EC); + EXPECT_NE((void*)nullptr, M4.base()); EXPECT_LE(64U * sizeof(int), M4.size()); x = (int*)M4.base(); *x = 4; @@ -176,19 +180,22 @@ TEST_P(MappedMemoryTest, MultipleWrite) { } TEST_P(MappedMemoryTest, EnabledWrite) { - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - - EXPECT_NE((void*)0, M1.base()); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); + MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags, + EC); + EXPECT_EQ(std::error_code(), EC); + + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(2U * sizeof(int), M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(8U * sizeof(int), M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(4U * sizeof(int), M3.size()); EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags))); @@ -216,11 +223,12 @@ TEST_P(MappedMemoryTest, EnabledWrite) { EXPECT_FALSE(Memory::releaseMappedMemory(M3)); EXPECT_EQ(6, y[6]); - MemoryBlock M4 = Memory::allocateMappedMemory(16, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); - EXPECT_NE((void*)0, M4.base()); + MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); + EXPECT_NE((void*)nullptr, M4.base()); EXPECT_LE(16U, M4.size()); - EXPECT_EQ(error_code::success(), Memory::protectMappedMemory(M4, getTestableEquivalent(Flags))); + EXPECT_EQ(std::error_code(), + Memory::protectMappedMemory(M4, getTestableEquivalent(Flags))); x = (int*)M4.base(); *x = 4; EXPECT_EQ(4, *x); @@ -229,19 +237,19 @@ TEST_P(MappedMemoryTest, EnabledWrite) { } TEST_P(MappedMemoryTest, SuccessiveNear) { - error_code EC; - MemoryBlock M1 = Memory::allocateMappedMemory(16, 0, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + std::error_code EC; + MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(16U, M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(64U, M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(32U, M3.size()); EXPECT_FALSE(doesOverlap(M1, M2)); @@ -254,20 +262,20 @@ TEST_P(MappedMemoryTest, SuccessiveNear) { } TEST_P(MappedMemoryTest, DuplicateNear) { - error_code EC; + std::error_code EC; MemoryBlock Near((void*)(3*PageSize), 16); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(16U, M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(64U, M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(32U, M3.size()); EXPECT_FALSE(Memory::releaseMappedMemory(M1)); @@ -276,20 +284,20 @@ TEST_P(MappedMemoryTest, DuplicateNear) { } TEST_P(MappedMemoryTest, ZeroNear) { - error_code EC; - MemoryBlock Near(0, 0); + std::error_code EC; + MemoryBlock Near(nullptr, 0); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(16U, M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(64U, M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(32U, M3.size()); EXPECT_FALSE(doesOverlap(M1, M2)); @@ -302,20 +310,20 @@ TEST_P(MappedMemoryTest, ZeroNear) { } TEST_P(MappedMemoryTest, ZeroSizeNear) { - error_code EC; + std::error_code EC; MemoryBlock Near((void*)(4*PageSize), 0); MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(16U, M1.size()); - EXPECT_NE((void*)0, M2.base()); + EXPECT_NE((void*)nullptr, M2.base()); EXPECT_LE(64U, M2.size()); - EXPECT_NE((void*)0, M3.base()); + EXPECT_NE((void*)nullptr, M3.base()); EXPECT_LE(32U, M3.size()); EXPECT_FALSE(doesOverlap(M1, M2)); @@ -328,12 +336,12 @@ TEST_P(MappedMemoryTest, ZeroSizeNear) { } TEST_P(MappedMemoryTest, UnalignedNear) { - error_code EC; + std::error_code EC; MemoryBlock Near((void*)(2*PageSize+5), 0); MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC); - EXPECT_EQ(error_code::success(), EC); + EXPECT_EQ(std::error_code(), EC); - EXPECT_NE((void*)0, M1.base()); + EXPECT_NE((void*)nullptr, M1.base()); EXPECT_LE(sizeof(int), M1.size()); EXPECT_FALSE(Memory::releaseMappedMemory(M1)); diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 031624162d0f..db85347e9212 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -8,24 +8,30 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Path.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" +#ifdef LLVM_ON_WIN32 +#include <winerror.h> +#endif + using namespace llvm; using namespace llvm::sys; -#define ASSERT_NO_ERROR(x) \ - if (error_code ASSERT_NO_ERROR_ec = x) { \ - SmallString<128> MessageStorage; \ - raw_svector_ostream Message(MessageStorage); \ - Message << #x ": did not return errc::success.\n" \ - << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ - << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ - GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ - } else {} +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } namespace { @@ -85,6 +91,7 @@ TEST(Support, Path) { paths.push_back("c:\\foo/"); paths.push_back("c:/foo\\bar"); + SmallVector<StringRef, 5> ComponentStack; for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(), e = paths.end(); i != e; @@ -94,18 +101,17 @@ TEST(Support, Path) { ci != ce; ++ci) { ASSERT_FALSE(ci->empty()); + ComponentStack.push_back(*ci); } -#if 0 // Valgrind is whining about this. - outs() << " Reverse Iteration: ["; for (sys::path::reverse_iterator ci = sys::path::rbegin(*i), ce = sys::path::rend(*i); ci != ce; ++ci) { - outs() << *ci << ','; + ASSERT_TRUE(*ci == ComponentStack.back()); + ComponentStack.pop_back(); } - outs() << "]\n"; -#endif + ASSERT_TRUE(ComponentStack.empty()); path::has_root_path(*i); path::root_path(*i); @@ -210,6 +216,48 @@ TEST(Support, AbsolutePathIteratorWin32) { } #endif // LLVM_ON_WIN32 +TEST(Support, AbsolutePathIteratorEnd) { + // Trailing slashes are converted to '.' unless they are part of the root path. + SmallVector<StringRef, 4> Paths; + Paths.push_back("/foo/"); + Paths.push_back("/foo//"); + Paths.push_back("//net//"); +#ifdef LLVM_ON_WIN32 + Paths.push_back("c:\\\\"); +#endif + + for (StringRef Path : Paths) { + StringRef LastComponent = *--path::end(Path); + EXPECT_EQ(".", LastComponent); + } + + SmallVector<StringRef, 3> RootPaths; + RootPaths.push_back("/"); + RootPaths.push_back("//net/"); +#ifdef LLVM_ON_WIN32 + RootPaths.push_back("c:\\"); +#endif + + for (StringRef Path : RootPaths) { + StringRef LastComponent = *--path::end(Path); + EXPECT_EQ(1u, LastComponent.size()); + EXPECT_TRUE(path::is_separator(LastComponent[0])); + } +} + +TEST(Support, HomeDirectory) { +#ifdef LLVM_ON_UNIX + // This test only makes sense on Unix if $HOME is set. + if (::getenv("HOME")) { +#endif + SmallString<128> HomeDir; + EXPECT_TRUE(path::home_directory(HomeDir)); + EXPECT_FALSE(HomeDir.empty()); +#ifdef LLVM_ON_UNIX + } +#endif +} + class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must @@ -225,8 +273,7 @@ protected: } virtual void TearDown() { - uint32_t removed; - ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), removed)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } }; @@ -258,7 +305,7 @@ TEST_F(FileSystemTest, Unique) { // Two paths representing the same file on disk should still provide the // same unique id. We can test this by making a hard link. - ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); + ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); fs::UniqueID D2; ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2)); ASSERT_EQ(D2, F1); @@ -306,10 +353,12 @@ TEST_F(FileSystemTest, TempFiles) { ::close(FD2); // Remove Temp2. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_EQ(fs::remove(Twine(TempPath2), false), + errc::no_such_file_or_directory); - error_code EC = fs::status(TempPath2.c_str(), B); + std::error_code EC = fs::status(TempPath2.c_str(), B); EXPECT_EQ(EC, errc::no_such_file_or_directory); EXPECT_EQ(B.type(), fs::file_type::file_not_found); @@ -322,7 +371,7 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_FALSE(TempPath3.endswith(".")); // Create a hard link to Temp1. - ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); + ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); bool equal; ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal)); EXPECT_TRUE(equal); @@ -332,12 +381,10 @@ TEST_F(FileSystemTest, TempFiles) { // Remove Temp1. ::close(FileDescriptor); - ASSERT_NO_ERROR(fs::remove(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); // Remove the hard link. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); @@ -352,27 +399,34 @@ TEST_F(FileSystemTest, TempFiles) { "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), - windows_error::path_not_found); + errc::no_such_file_or_directory); #endif } +TEST_F(FileSystemTest, CreateDir) { + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), + errc::file_exists); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); +} + TEST_F(FileSystemTest, DirectoryIteration) { - error_code ec; + std::error_code ec; for (fs::directory_iterator i(".", ec), e; i != e; i.increment(ec)) ASSERT_NO_ERROR(ec); // Create a known hierarchy to recurse over. - bool existed; - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/aa1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/ab1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/dontlookhere/da1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/z0/za1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/pop/p1", existed)); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/pop/p1")); typedef std::vector<std::string> v_t; v_t visited; for (fs::recursive_directory_iterator i(Twine(TestDirectory) @@ -414,6 +468,18 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_LT(a0, aa1); ASSERT_LT(a0, ab1); ASSERT_LT(z0, za1); + + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0")); + ASSERT_NO_ERROR( + fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop/p1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive")); } const char archive[] = "!<arch>\x0A"; @@ -470,15 +536,13 @@ TEST_F(FileSystemTest, Magic) { SmallString<128> file_pathname(TestDirectory); path::append(file_pathname, i->filename); std::string ErrMsg; - raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_Binary); + raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; file.close(); - bool res = false; - ASSERT_NO_ERROR(fs::has_magic(file_pathname.c_str(), magic, res)); - EXPECT_TRUE(res); EXPECT_EQ(i->magic, fs::identify_magic(magic)); + ASSERT_NO_ERROR(fs::remove(Twine(file_pathname))); } } @@ -489,26 +553,27 @@ TEST_F(FileSystemTest, CarriageReturn) { path::append(FilePathname, "test"); { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg); + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); EXPECT_EQ(ErrMsg, ""); File << '\n'; } { - OwningPtr<MemoryBuffer> Buf; - MemoryBuffer::getFile(FilePathname.c_str(), Buf); - EXPECT_EQ(Buf->getBuffer(), "\r\n"); + auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + EXPECT_TRUE((bool)Buf); + EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); } { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Binary); + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); EXPECT_EQ(ErrMsg, ""); File << '\n'; } { - OwningPtr<MemoryBuffer> Buf; - MemoryBuffer::getFile(FilePathname.c_str(), Buf); - EXPECT_EQ(Buf->getBuffer(), "\n"); + auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + EXPECT_TRUE((bool)Buf); + EXPECT_EQ(Buf.get()->getBuffer(), "\n"); } + ASSERT_NO_ERROR(fs::remove(Twine(FilePathname))); } #endif @@ -519,7 +584,7 @@ TEST_F(FileSystemTest, FileMapping) { ASSERT_NO_ERROR( fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Map in temp file and add some content - error_code EC; + std::error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, @@ -548,7 +613,6 @@ TEST_F(FileSystemTest, FileMapping) { // Unmap temp file -#if LLVM_HAS_RVALUE_REFERENCES fs::mapped_file_region m(Twine(TempPath), fs::mapped_file_region::readonly, 0, @@ -556,8 +620,44 @@ TEST_F(FileSystemTest, FileMapping) { EC); ASSERT_NO_ERROR(EC); const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(llvm_move(m)); + fs::mapped_file_region mfrrv(std::move(m)); EXPECT_EQ(mfrrv.const_data(), Data); +} + +TEST(Support, NormalizePath) { +#if defined(LLVM_ON_WIN32) +#define EXPECT_PATH_IS(path__, windows__, not_windows__) \ + EXPECT_EQ(path__, windows__); +#else +#define EXPECT_PATH_IS(path__, windows__, not_windows__) \ + EXPECT_EQ(path__, not_windows__); #endif + + SmallString<64> Path1("a"); + SmallString<64> Path2("a/b"); + SmallString<64> Path3("a\\b"); + SmallString<64> Path4("a\\\\b"); + SmallString<64> Path5("\\a"); + SmallString<64> Path6("a\\"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path1)); + EXPECT_PATH_IS(Path1, "a", "a"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path2)); + EXPECT_PATH_IS(Path2, "a/b", "a/b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path3)); + EXPECT_PATH_IS(Path3, "a\\b", "a/b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path4)); + EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path5)); + EXPECT_PATH_IS(Path5, "\\a", "/a"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path6)); + EXPECT_PATH_IS(Path6, "a\\", "a/"); + +#undef EXPECT_PATH_IS } } // anonymous namespace diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index 27c2318215d6..f4060720961b 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -11,7 +11,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 -#include "windows.h" +#include <windows.h> #endif namespace { @@ -39,6 +39,13 @@ TEST(ProcessTest, SelfProcess) { EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time()); } +TEST(ProcessTest, GetRandomNumberTest) { + const unsigned r1 = Process::GetRandomNumber(); + const unsigned r2 = Process::GetRandomNumber(); + // It should be extremely unlikely that both r1 and r2 are 0. + EXPECT_NE((r1 | r2), 0u); +} + #ifdef _MSC_VER #define setenv(name, var, ignore) _putenv_s(name, var) #endif diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 6eb990f29d2a..4e7316fb3ace 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -12,7 +12,6 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "gtest/gtest.h" - #include <stdlib.h> #if defined(__APPLE__) # include <crt_externs.h> @@ -55,7 +54,7 @@ static void CopyEnvironment(std::vector<const char *> &out) { // environ seems to work for Windows and most other Unices. char **envp = environ; #endif - while (*envp != 0) { + while (*envp != nullptr) { out.push_back(*envp); ++envp; } @@ -77,14 +76,14 @@ TEST(ProgramTest, CreateProcessTrailingSlash) { "--gtest_filter=ProgramTest.CreateProcessTrailingSlash", "-program-test-string-arg1", "has\\\\ trailing\\", "-program-test-string-arg2", "has\\\\ trailing\\", - 0 + nullptr }; // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. std::vector<const char *> envp; CopyEnvironment(envp); envp.push_back("LLVM_PROGRAM_TEST_CHILD=1"); - envp.push_back(0); + envp.push_back(nullptr); std::string error; bool ExecutionFailed; @@ -94,7 +93,7 @@ TEST(ProgramTest, CreateProcessTrailingSlash) { #else StringRef nul("/dev/null"); #endif - const StringRef *redirects[] = { &nul, &nul, 0 }; + const StringRef *redirects[] = { &nul, &nul, nullptr }; int rc = ExecuteAndWait(my_exe, argv, &envp[0], redirects, /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error, &ExecutionFailed); @@ -115,19 +114,19 @@ TEST(ProgramTest, TestExecuteNoWait) { const char *argv[] = { Executable.c_str(), "--gtest_filter=ProgramTest.TestExecuteNoWait", - 0 + nullptr }; // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child. std::vector<const char *> envp; CopyEnvironment(envp); envp.push_back("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); - envp.push_back(0); + envp.push_back(nullptr); std::string Error; bool ExecutionFailed; - ProcessInfo PI1 = - ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed); + ProcessInfo PI1 = ExecuteNoWait(Executable, argv, &envp[0], nullptr, 0, + &Error, &ExecutionFailed); ASSERT_FALSE(ExecutionFailed) << Error; ASSERT_NE(PI1.Pid, 0) << "Invalid process id"; @@ -145,8 +144,8 @@ TEST(ProgramTest, TestExecuteNoWait) { EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1"; - ProcessInfo PI2 = - ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed); + ProcessInfo PI2 = ExecuteNoWait(Executable, argv, &envp[0], nullptr, 0, + &Error, &ExecutionFailed); ASSERT_FALSE(ExecutionFailed) << Error; ASSERT_NE(PI2.Pid, 0) << "Invalid process id"; @@ -163,15 +162,45 @@ TEST(ProgramTest, TestExecuteNoWait) { ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1"; } +TEST(ProgramTest, TestExecuteAndWaitTimeout) { + using namespace llvm::sys; + + if (getenv("LLVM_PROGRAM_TEST_TIMEOUT")) { + sleep_for(/*seconds*/ 10); + exit(0); + } + + std::string Executable = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + const char *argv[] = { + Executable.c_str(), + "--gtest_filter=ProgramTest.TestExecuteAndWaitTimeout", + nullptr + }; + + // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child. + std::vector<const char *> envp; + CopyEnvironment(envp); + envp.push_back("LLVM_PROGRAM_TEST_TIMEOUT=1"); + envp.push_back(nullptr); + + std::string Error; + bool ExecutionFailed; + int RetCode = + ExecuteAndWait(Executable, argv, &envp[0], nullptr, /*secondsToWait=*/1, 0, + &Error, &ExecutionFailed); + ASSERT_EQ(-2, RetCode); +} + TEST(ProgramTest, TestExecuteNegative) { std::string Executable = "i_dont_exist"; - const char *argv[] = { Executable.c_str(), 0 }; + const char *argv[] = { Executable.c_str(), nullptr }; { std::string Error; bool ExecutionFailed; - int RetCode = - ExecuteAndWait(Executable, argv, 0, 0, 0, 0, &Error, &ExecutionFailed); + int RetCode = ExecuteAndWait(Executable, argv, nullptr, nullptr, 0, 0, + &Error, &ExecutionFailed); ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " "positive value indicating the result code"; ASSERT_TRUE(ExecutionFailed); @@ -181,8 +210,8 @@ TEST(ProgramTest, TestExecuteNegative) { { std::string Error; bool ExecutionFailed; - ProcessInfo PI = - ExecuteNoWait(Executable, argv, 0, 0, 0, &Error, &ExecutionFailed); + ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0, + &Error, &ExecutionFailed); ASSERT_EQ(PI.Pid, 0) << "On error ExecuteNoWait should return an invalid ProcessInfo"; ASSERT_TRUE(ExecutionFailed); diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp index 7b977f744668..c045c49bc3d7 100644 --- a/unittests/Support/RegexTest.cpp +++ b/unittests/Support/RegexTest.cpp @@ -90,23 +90,23 @@ TEST_F(RegexTest, Substitution) { // Standard Escapes EXPECT_EQ("a\\ber", Regex("[0-9]+").sub("\\\\", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a\nber", Regex("[0-9]+").sub("\\n", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a\tber", Regex("[0-9]+").sub("\\t", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("ajber", Regex("[0-9]+").sub("\\j", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("aber", Regex("[0-9]+").sub("\\", "a1234ber", &Error)); EXPECT_EQ(Error, "replacement string contained trailing backslash"); // Backreferences EXPECT_EQ("aa1234bber", Regex("a[0-9]+b").sub("a\\0b", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a1234ber", Regex("a([0-9]+)b").sub("a\\1b", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("aber", Regex("a[0-9]+b").sub("a\\100b", "a1234ber", &Error)); EXPECT_EQ(Error, "invalid backreference string '100'"); @@ -127,6 +127,11 @@ TEST_F(RegexTest, IsLiteralERE) { EXPECT_FALSE(Regex::isLiteralERE("abc{1,2}")); } +TEST_F(RegexTest, Escape) { + EXPECT_EQ("a\\[bc\\]", Regex::escape("a[bc]")); + EXPECT_EQ("abc\\{1\\\\,2\\}", Regex::escape("abc{1\\,2}")); +} + TEST_F(RegexTest, IsValid) { std::string Error; EXPECT_FALSE(Regex("(foo").isValid(Error)); @@ -135,4 +140,17 @@ TEST_F(RegexTest, IsValid) { EXPECT_EQ("invalid character range", Error); } +TEST_F(RegexTest, MoveConstruct) { + Regex r1("^[0-9]+$"); + Regex r2(std::move(r1)); + EXPECT_TRUE(r2.match("916")); +} + +TEST_F(RegexTest, MoveAssign) { + Regex r1("^[0-9]+$"); + Regex r2("abc"); + r2 = std::move(r1); + EXPECT_TRUE(r2.match("916")); +} + } diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp new file mode 100644 index 000000000000..7bbef7e4e58d --- /dev/null +++ b/unittests/Support/ScaledNumberTest.cpp @@ -0,0 +1,536 @@ +//===- llvm/unittest/Support/ScaledNumberTest.cpp - ScaledPair tests -----==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ScaledNumber.h" + +#include "llvm/Support/DataTypes.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::ScaledNumbers; + +namespace { + +template <class UIntT> struct ScaledPair { + UIntT D; + int S; + ScaledPair(const std::pair<UIntT, int16_t> &F) : D(F.first), S(F.second) {} + ScaledPair(UIntT D, int S) : D(D), S(S) {} + + bool operator==(const ScaledPair<UIntT> &X) const { + return D == X.D && S == X.S; + } +}; +template <class UIntT> +bool operator==(const std::pair<UIntT, int16_t> &L, + const ScaledPair<UIntT> &R) { + return ScaledPair<UIntT>(L) == R; +} +template <class UIntT> +void PrintTo(const ScaledPair<UIntT> &F, ::std::ostream *os) { + *os << F.D << "*2^" << F.S; +} + +typedef ScaledPair<uint32_t> SP32; +typedef ScaledPair<uint64_t> SP64; + +TEST(ScaledNumberHelpersTest, getRounded) { + EXPECT_EQ(getRounded32(0, 0, false), SP32(0, 0)); + EXPECT_EQ(getRounded32(0, 0, true), SP32(1, 0)); + EXPECT_EQ(getRounded32(20, 21, true), SP32(21, 21)); + EXPECT_EQ(getRounded32(UINT32_MAX, 0, false), SP32(UINT32_MAX, 0)); + EXPECT_EQ(getRounded32(UINT32_MAX, 0, true), SP32(1 << 31, 1)); + + EXPECT_EQ(getRounded64(0, 0, false), SP64(0, 0)); + EXPECT_EQ(getRounded64(0, 0, true), SP64(1, 0)); + EXPECT_EQ(getRounded64(20, 21, true), SP64(21, 21)); + EXPECT_EQ(getRounded64(UINT32_MAX, 0, false), SP64(UINT32_MAX, 0)); + EXPECT_EQ(getRounded64(UINT32_MAX, 0, true), SP64(UINT64_C(1) << 32, 0)); + EXPECT_EQ(getRounded64(UINT64_MAX, 0, false), SP64(UINT64_MAX, 0)); + EXPECT_EQ(getRounded64(UINT64_MAX, 0, true), SP64(UINT64_C(1) << 63, 1)); +} + +TEST(ScaledNumberHelpersTest, getAdjusted) { + const uint64_t Max32In64 = UINT32_MAX; + EXPECT_EQ(getAdjusted32(0), SP32(0, 0)); + EXPECT_EQ(getAdjusted32(0, 5), SP32(0, 5)); + EXPECT_EQ(getAdjusted32(UINT32_MAX), SP32(UINT32_MAX, 0)); + EXPECT_EQ(getAdjusted32(Max32In64 << 1), SP32(UINT32_MAX, 1)); + EXPECT_EQ(getAdjusted32(Max32In64 << 1, 1), SP32(UINT32_MAX, 2)); + EXPECT_EQ(getAdjusted32(Max32In64 << 31), SP32(UINT32_MAX, 31)); + EXPECT_EQ(getAdjusted32(Max32In64 << 32), SP32(UINT32_MAX, 32)); + EXPECT_EQ(getAdjusted32(Max32In64 + 1), SP32(1u << 31, 1)); + EXPECT_EQ(getAdjusted32(UINT64_MAX), SP32(1u << 31, 33)); + + EXPECT_EQ(getAdjusted64(0), SP64(0, 0)); + EXPECT_EQ(getAdjusted64(0, 5), SP64(0, 5)); + EXPECT_EQ(getAdjusted64(UINT32_MAX), SP64(UINT32_MAX, 0)); + EXPECT_EQ(getAdjusted64(Max32In64 << 1), SP64(Max32In64 << 1, 0)); + EXPECT_EQ(getAdjusted64(Max32In64 << 1, 1), SP64(Max32In64 << 1, 1)); + EXPECT_EQ(getAdjusted64(Max32In64 << 31), SP64(Max32In64 << 31, 0)); + EXPECT_EQ(getAdjusted64(Max32In64 << 32), SP64(Max32In64 << 32, 0)); + EXPECT_EQ(getAdjusted64(Max32In64 + 1), SP64(Max32In64 + 1, 0)); + EXPECT_EQ(getAdjusted64(UINT64_MAX), SP64(UINT64_MAX, 0)); +} + +TEST(ScaledNumberHelpersTest, getProduct) { + // Zero. + EXPECT_EQ(SP32(0, 0), getProduct32(0, 0)); + EXPECT_EQ(SP32(0, 0), getProduct32(0, 1)); + EXPECT_EQ(SP32(0, 0), getProduct32(0, 33)); + + // Basic. + EXPECT_EQ(SP32(6, 0), getProduct32(2, 3)); + EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0), + getProduct32(UINT16_MAX / 3, UINT16_MAX / 5 * 2)); + + // Overflow, no loss of precision. + // ==> 0xf00010 * 0x1001 + // ==> 0xf00f00000 + 0x10010 + // ==> 0xf00f10010 + // ==> 0xf00f1001 * 2^4 + EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0xf00010, 0x1001)); + + // Overflow, loss of precision, rounds down. + // ==> 0xf000070 * 0x1001 + // ==> 0xf00f000000 + 0x70070 + // ==> 0xf00f070070 + // ==> 0xf00f0700 * 2^8 + EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0xf000070, 0x1001)); + + // Overflow, loss of precision, rounds up. + // ==> 0xf000080 * 0x1001 + // ==> 0xf00f000000 + 0x80080 + // ==> 0xf00f080080 + // ==> 0xf00f0801 * 2^8 + EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0xf000080, 0x1001)); + + // Reverse operand order. + EXPECT_EQ(SP32(0, 0), getProduct32(1, 0)); + EXPECT_EQ(SP32(0, 0), getProduct32(33, 0)); + EXPECT_EQ(SP32(6, 0), getProduct32(3, 2)); + EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0), + getProduct32(UINT16_MAX / 5 * 2, UINT16_MAX / 3)); + EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0x1001, 0xf00010)); + EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0x1001, 0xf000070)); + EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0x1001, 0xf000080)); + + // Round to overflow. + EXPECT_EQ(SP64(UINT64_C(1) << 63, 64), + getProduct64(UINT64_C(10376293541461622786), + UINT64_C(16397105843297379211))); + + // Big number with rounding. + EXPECT_EQ(SP64(UINT64_C(9223372036854775810), 64), + getProduct64(UINT64_C(18446744073709551556), + UINT64_C(9223372036854775840))); +} + +TEST(ScaledNumberHelpersTest, getQuotient) { + // Zero. + EXPECT_EQ(SP32(0, 0), getQuotient32(0, 0)); + EXPECT_EQ(SP32(0, 0), getQuotient32(0, 1)); + EXPECT_EQ(SP32(0, 0), getQuotient32(0, 73)); + EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(1, 0)); + EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(6, 0)); + + // Powers of two. + EXPECT_EQ(SP32(1u << 31, -31), getQuotient32(1, 1)); + EXPECT_EQ(SP32(1u << 31, -30), getQuotient32(2, 1)); + EXPECT_EQ(SP32(1u << 31, -33), getQuotient32(4, 16)); + EXPECT_EQ(SP32(7u << 29, -29), getQuotient32(7, 1)); + EXPECT_EQ(SP32(7u << 29, -30), getQuotient32(7, 2)); + EXPECT_EQ(SP32(7u << 29, -33), getQuotient32(7, 16)); + + // Divide evenly. + EXPECT_EQ(SP32(3u << 30, -30), getQuotient32(9, 3)); + EXPECT_EQ(SP32(9u << 28, -28), getQuotient32(63, 7)); + + // Divide unevenly. + EXPECT_EQ(SP32(0xaaaaaaab, -33), getQuotient32(1, 3)); + EXPECT_EQ(SP32(0xd5555555, -31), getQuotient32(5, 3)); + + // 64-bit division is hard to test, since divide64 doesn't canonicalized its + // output. However, this is the algorithm the implementation uses: + // + // - Shift divisor right. + // - If we have 1 (power of 2), return early -- not canonicalized. + // - Shift dividend left. + // - 64-bit integer divide. + // - If there's a remainder, continue with long division. + // + // TODO: require less knowledge about the implementation in the test. + + // Zero. + EXPECT_EQ(SP64(0, 0), getQuotient64(0, 0)); + EXPECT_EQ(SP64(0, 0), getQuotient64(0, 1)); + EXPECT_EQ(SP64(0, 0), getQuotient64(0, 73)); + EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(1, 0)); + EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(6, 0)); + + // Powers of two. + EXPECT_EQ(SP64(1, 0), getQuotient64(1, 1)); + EXPECT_EQ(SP64(2, 0), getQuotient64(2, 1)); + EXPECT_EQ(SP64(4, -4), getQuotient64(4, 16)); + EXPECT_EQ(SP64(7, 0), getQuotient64(7, 1)); + EXPECT_EQ(SP64(7, -1), getQuotient64(7, 2)); + EXPECT_EQ(SP64(7, -4), getQuotient64(7, 16)); + + // Divide evenly. + EXPECT_EQ(SP64(UINT64_C(3) << 60, -60), getQuotient64(9, 3)); + EXPECT_EQ(SP64(UINT64_C(9) << 58, -58), getQuotient64(63, 7)); + + // Divide unevenly. + EXPECT_EQ(SP64(0xaaaaaaaaaaaaaaab, -65), getQuotient64(1, 3)); + EXPECT_EQ(SP64(0xd555555555555555, -63), getQuotient64(5, 3)); +} + +TEST(ScaledNumberHelpersTest, getLg) { + EXPECT_EQ(0, getLg(UINT32_C(1), 0)); + EXPECT_EQ(1, getLg(UINT32_C(1), 1)); + EXPECT_EQ(1, getLg(UINT32_C(2), 0)); + EXPECT_EQ(3, getLg(UINT32_C(1), 3)); + EXPECT_EQ(3, getLg(UINT32_C(7), 0)); + EXPECT_EQ(3, getLg(UINT32_C(8), 0)); + EXPECT_EQ(3, getLg(UINT32_C(9), 0)); + EXPECT_EQ(3, getLg(UINT32_C(64), -3)); + EXPECT_EQ(31, getLg((UINT32_MAX >> 1) + 2, 0)); + EXPECT_EQ(32, getLg(UINT32_MAX, 0)); + EXPECT_EQ(-1, getLg(UINT32_C(1), -1)); + EXPECT_EQ(-1, getLg(UINT32_C(2), -2)); + EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 1)); + + EXPECT_EQ(0, getLg(UINT64_C(1), 0)); + EXPECT_EQ(1, getLg(UINT64_C(1), 1)); + EXPECT_EQ(1, getLg(UINT64_C(2), 0)); + EXPECT_EQ(3, getLg(UINT64_C(1), 3)); + EXPECT_EQ(3, getLg(UINT64_C(7), 0)); + EXPECT_EQ(3, getLg(UINT64_C(8), 0)); + EXPECT_EQ(3, getLg(UINT64_C(9), 0)); + EXPECT_EQ(3, getLg(UINT64_C(64), -3)); + EXPECT_EQ(63, getLg((UINT64_MAX >> 1) + 2, 0)); + EXPECT_EQ(64, getLg(UINT64_MAX, 0)); + EXPECT_EQ(-1, getLg(UINT64_C(1), -1)); + EXPECT_EQ(-1, getLg(UINT64_C(2), -2)); + EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 1)); +} + +TEST(ScaledNumberHelpersTest, getLgFloor) { + EXPECT_EQ(0, getLgFloor(UINT32_C(1), 0)); + EXPECT_EQ(1, getLgFloor(UINT32_C(1), 1)); + EXPECT_EQ(1, getLgFloor(UINT32_C(2), 0)); + EXPECT_EQ(2, getLgFloor(UINT32_C(7), 0)); + EXPECT_EQ(3, getLgFloor(UINT32_C(1), 3)); + EXPECT_EQ(3, getLgFloor(UINT32_C(8), 0)); + EXPECT_EQ(3, getLgFloor(UINT32_C(9), 0)); + EXPECT_EQ(3, getLgFloor(UINT32_C(64), -3)); + EXPECT_EQ(31, getLgFloor((UINT32_MAX >> 1) + 2, 0)); + EXPECT_EQ(31, getLgFloor(UINT32_MAX, 0)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 1)); + + EXPECT_EQ(0, getLgFloor(UINT64_C(1), 0)); + EXPECT_EQ(1, getLgFloor(UINT64_C(1), 1)); + EXPECT_EQ(1, getLgFloor(UINT64_C(2), 0)); + EXPECT_EQ(2, getLgFloor(UINT64_C(7), 0)); + EXPECT_EQ(3, getLgFloor(UINT64_C(1), 3)); + EXPECT_EQ(3, getLgFloor(UINT64_C(8), 0)); + EXPECT_EQ(3, getLgFloor(UINT64_C(9), 0)); + EXPECT_EQ(3, getLgFloor(UINT64_C(64), -3)); + EXPECT_EQ(63, getLgFloor((UINT64_MAX >> 1) + 2, 0)); + EXPECT_EQ(63, getLgFloor(UINT64_MAX, 0)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 1)); +} + +TEST(ScaledNumberHelpersTest, getLgCeiling) { + EXPECT_EQ(0, getLgCeiling(UINT32_C(1), 0)); + EXPECT_EQ(1, getLgCeiling(UINT32_C(1), 1)); + EXPECT_EQ(1, getLgCeiling(UINT32_C(2), 0)); + EXPECT_EQ(3, getLgCeiling(UINT32_C(1), 3)); + EXPECT_EQ(3, getLgCeiling(UINT32_C(7), 0)); + EXPECT_EQ(3, getLgCeiling(UINT32_C(8), 0)); + EXPECT_EQ(3, getLgCeiling(UINT32_C(64), -3)); + EXPECT_EQ(4, getLgCeiling(UINT32_C(9), 0)); + EXPECT_EQ(32, getLgCeiling(UINT32_MAX, 0)); + EXPECT_EQ(32, getLgCeiling((UINT32_MAX >> 1) + 2, 0)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 1)); + + EXPECT_EQ(0, getLgCeiling(UINT64_C(1), 0)); + EXPECT_EQ(1, getLgCeiling(UINT64_C(1), 1)); + EXPECT_EQ(1, getLgCeiling(UINT64_C(2), 0)); + EXPECT_EQ(3, getLgCeiling(UINT64_C(1), 3)); + EXPECT_EQ(3, getLgCeiling(UINT64_C(7), 0)); + EXPECT_EQ(3, getLgCeiling(UINT64_C(8), 0)); + EXPECT_EQ(3, getLgCeiling(UINT64_C(64), -3)); + EXPECT_EQ(4, getLgCeiling(UINT64_C(9), 0)); + EXPECT_EQ(64, getLgCeiling((UINT64_MAX >> 1) + 2, 0)); + EXPECT_EQ(64, getLgCeiling(UINT64_MAX, 0)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), -1)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 0)); + EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 1)); +} + +TEST(ScaledNumberHelpersTest, compare) { + EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 1)); + EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), -10)); + EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 20)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(64), -3)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(32), -2)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(16), -1)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(8), 0)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(4), 1)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(2), 2)); + EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(1), 3)); + EXPECT_EQ(-1, compare(UINT32_C(0), 0, UINT32_C(1), 3)); + EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(1), 3)); + EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(64), -3)); + EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(1), 3)); + EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(64), -3)); + EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(0), 0)); + + EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 1)); + EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), -10)); + EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 20)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(64), -3)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(32), -2)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(16), -1)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(8), 0)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(4), 1)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(2), 2)); + EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(1), 3)); + EXPECT_EQ(-1, compare(UINT64_C(0), 0, UINT64_C(1), 3)); + EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(1), 3)); + EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(64), -3)); + EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(1), 3)); + EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(64), -3)); + EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(0), 0)); + EXPECT_EQ(-1, compare(UINT64_MAX, 0, UINT64_C(1), 64)); +} + +TEST(ScaledNumberHelpersTest, matchScales) { +#define MATCH_SCALES(T, LDIn, LSIn, RDIn, RSIn, LDOut, RDOut, SOut) \ + do { \ + T LDx = LDIn; \ + T RDx = RDIn; \ + T LDy = LDOut; \ + T RDy = RDOut; \ + int16_t LSx = LSIn; \ + int16_t RSx = RSIn; \ + int16_t Sy = SOut; \ + \ + EXPECT_EQ(SOut, matchScales(LDx, LSx, RDx, RSx)); \ + EXPECT_EQ(LDy, LDx); \ + EXPECT_EQ(RDy, RDx); \ + if (LDy) \ + EXPECT_EQ(Sy, LSx); \ + if (RDy) \ + EXPECT_EQ(Sy, RSx); \ + } while (false) + + MATCH_SCALES(uint32_t, 0, 0, 0, 0, 0, 0, 0); + MATCH_SCALES(uint32_t, 0, 50, 7, 1, 0, 7, 1); + MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 1, 9, 0, UINT32_C(1) << 31, 4, 1); + MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 2, 9, 0, UINT32_C(1) << 31, 2, 2); + MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 3, 9, 0, UINT32_C(1) << 31, 1, 3); + MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 4, 9, 0, UINT32_C(1) << 31, 0, 4); + MATCH_SCALES(uint32_t, UINT32_C(1) << 30, 4, 9, 0, UINT32_C(1) << 31, 1, 3); + MATCH_SCALES(uint32_t, UINT32_C(1) << 29, 4, 9, 0, UINT32_C(1) << 31, 2, 2); + MATCH_SCALES(uint32_t, UINT32_C(1) << 28, 4, 9, 0, UINT32_C(1) << 31, 4, 1); + MATCH_SCALES(uint32_t, UINT32_C(1) << 27, 4, 9, 0, UINT32_C(1) << 31, 9, 0); + MATCH_SCALES(uint32_t, 7, 1, 0, 50, 7, 0, 1); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 1, 4, UINT32_C(1) << 31, 1); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 2, 2, UINT32_C(1) << 31, 2); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 3, 1, UINT32_C(1) << 31, 3); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 4, 0, UINT32_C(1) << 31, 4); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 30, 4, 1, UINT32_C(1) << 31, 3); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 29, 4, 2, UINT32_C(1) << 31, 2); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 28, 4, 4, UINT32_C(1) << 31, 1); + MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 27, 4, 9, UINT32_C(1) << 31, 0); + + MATCH_SCALES(uint64_t, 0, 0, 0, 0, 0, 0, 0); + MATCH_SCALES(uint64_t, 0, 100, 7, 1, 0, 7, 1); + MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 1, 9, 0, UINT64_C(1) << 63, 4, 1); + MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 2, 9, 0, UINT64_C(1) << 63, 2, 2); + MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 3, 9, 0, UINT64_C(1) << 63, 1, 3); + MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 4, 9, 0, UINT64_C(1) << 63, 0, 4); + MATCH_SCALES(uint64_t, UINT64_C(1) << 62, 4, 9, 0, UINT64_C(1) << 63, 1, 3); + MATCH_SCALES(uint64_t, UINT64_C(1) << 61, 4, 9, 0, UINT64_C(1) << 63, 2, 2); + MATCH_SCALES(uint64_t, UINT64_C(1) << 60, 4, 9, 0, UINT64_C(1) << 63, 4, 1); + MATCH_SCALES(uint64_t, UINT64_C(1) << 59, 4, 9, 0, UINT64_C(1) << 63, 9, 0); + MATCH_SCALES(uint64_t, 7, 1, 0, 100, 7, 0, 1); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 1, 4, UINT64_C(1) << 63, 1); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 2, 2, UINT64_C(1) << 63, 2); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 3, 1, UINT64_C(1) << 63, 3); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 4, 0, UINT64_C(1) << 63, 4); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 62, 4, 1, UINT64_C(1) << 63, 3); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 61, 4, 2, UINT64_C(1) << 63, 2); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 60, 4, 4, UINT64_C(1) << 63, 1); + MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 59, 4, 9, UINT64_C(1) << 63, 0); +} + +TEST(ScaledNumberHelpersTest, getSum) { + // Zero. + EXPECT_EQ(SP32(1, 0), getSum32(0, 0, 1, 0)); + EXPECT_EQ(SP32(8, -3), getSum32(0, 0, 8, -3)); + EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(0, 0, UINT32_MAX, 0)); + + // Basic. + EXPECT_EQ(SP32(2, 0), getSum32(1, 0, 1, 0)); + EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 2, 0)); + EXPECT_EQ(SP32(67, 0), getSum32(7, 0, 60, 0)); + + // Different scales. + EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 1, 1)); + EXPECT_EQ(SP32(4, 0), getSum32(2, 0, 1, 1)); + + // Loss of precision. + EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 32, 1, 0)); + EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, -32, 1, 0)); + + // Not quite loss of precision. + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 32, 1, 1)); + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -32, 1, -1)); + + // Overflow. + EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, UINT32_MAX, 0)); + + // Reverse operand order. + EXPECT_EQ(SP32(1, 0), getSum32(1, 0, 0, 0)); + EXPECT_EQ(SP32(8, -3), getSum32(8, -3, 0, 0)); + EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(UINT32_MAX, 0, 0, 0)); + EXPECT_EQ(SP32(3, 0), getSum32(2, 0, 1, 0)); + EXPECT_EQ(SP32(67, 0), getSum32(60, 0, 7, 0)); + EXPECT_EQ(SP32(3, 0), getSum32(1, 1, 1, 0)); + EXPECT_EQ(SP32(4, 0), getSum32(1, 1, 2, 0)); + EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, 1, 32)); + EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, 0, 1, -32)); + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 1, 1, 32)); + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -1, 1, -32)); + EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(UINT32_MAX, 0, 1, 0)); + + // Zero. + EXPECT_EQ(SP64(1, 0), getSum64(0, 0, 1, 0)); + EXPECT_EQ(SP64(8, -3), getSum64(0, 0, 8, -3)); + EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(0, 0, UINT64_MAX, 0)); + + // Basic. + EXPECT_EQ(SP64(2, 0), getSum64(1, 0, 1, 0)); + EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 2, 0)); + EXPECT_EQ(SP64(67, 0), getSum64(7, 0, 60, 0)); + + // Different scales. + EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 1, 1)); + EXPECT_EQ(SP64(4, 0), getSum64(2, 0, 1, 1)); + + // Loss of precision. + EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 64, 1, 0)); + EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, -64, 1, 0)); + + // Not quite loss of precision. + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 64, 1, 1)); + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -64, 1, -1)); + + // Overflow. + EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, UINT64_MAX, 0)); + + // Reverse operand order. + EXPECT_EQ(SP64(1, 0), getSum64(1, 0, 0, 0)); + EXPECT_EQ(SP64(8, -3), getSum64(8, -3, 0, 0)); + EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(UINT64_MAX, 0, 0, 0)); + EXPECT_EQ(SP64(3, 0), getSum64(2, 0, 1, 0)); + EXPECT_EQ(SP64(67, 0), getSum64(60, 0, 7, 0)); + EXPECT_EQ(SP64(3, 0), getSum64(1, 1, 1, 0)); + EXPECT_EQ(SP64(4, 0), getSum64(1, 1, 2, 0)); + EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, 1, 64)); + EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, 0, 1, -64)); + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 1, 1, 64)); + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -1, 1, -64)); + EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(UINT64_MAX, 0, 1, 0)); +} + +TEST(ScaledNumberHelpersTest, getDifference) { + // Basic. + EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 0)); + EXPECT_EQ(SP32(1, 0), getDifference32(2, 0, 1, 0)); + EXPECT_EQ(SP32(53, 0), getDifference32(60, 0, 7, 0)); + + // Equals "0", different scales. + EXPECT_EQ(SP32(0, 0), getDifference32(2, 0, 1, 1)); + + // Subtract "0". + EXPECT_EQ(SP32(1, 0), getDifference32(1, 0, 0, 0)); + EXPECT_EQ(SP32(8, -3), getDifference32(8, -3, 0, 0)); + EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(UINT32_MAX, 0, 0, 0)); + + // Loss of precision. + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), + getDifference32((UINT32_C(1) << 31) + 1, 1, 1, 0)); + EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -31), + getDifference32((UINT32_C(1) << 31) + 1, -31, 1, -32)); + + // Not quite loss of precision. + EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(1, 32, 1, 0)); + EXPECT_EQ(SP32(UINT32_MAX, -32), getDifference32(1, 0, 1, -32)); + + // Saturate to "0". + EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 1, 0)); + EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 8, -3)); + EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, UINT32_MAX, 0)); + EXPECT_EQ(SP32(0, 0), getDifference32(7, 0, 60, 0)); + EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 1)); + EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, 0)); + EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, -1)); + + // Regression tests for cases that failed during bringup. + EXPECT_EQ(SP32(UINT32_C(1) << 26, -31), + getDifference32(1, 0, UINT32_C(31) << 27, -32)); + + // Basic. + EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 0)); + EXPECT_EQ(SP64(1, 0), getDifference64(2, 0, 1, 0)); + EXPECT_EQ(SP64(53, 0), getDifference64(60, 0, 7, 0)); + + // Equals "0", different scales. + EXPECT_EQ(SP64(0, 0), getDifference64(2, 0, 1, 1)); + + // Subtract "0". + EXPECT_EQ(SP64(1, 0), getDifference64(1, 0, 0, 0)); + EXPECT_EQ(SP64(8, -3), getDifference64(8, -3, 0, 0)); + EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(UINT64_MAX, 0, 0, 0)); + + // Loss of precision. + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), + getDifference64((UINT64_C(1) << 63) + 1, 1, 1, 0)); + EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -63), + getDifference64((UINT64_C(1) << 63) + 1, -63, 1, -64)); + + // Not quite loss of precision. + EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(1, 64, 1, 0)); + EXPECT_EQ(SP64(UINT64_MAX, -64), getDifference64(1, 0, 1, -64)); + + // Saturate to "0". + EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 1, 0)); + EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 8, -3)); + EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, UINT64_MAX, 0)); + EXPECT_EQ(SP64(0, 0), getDifference64(7, 0, 60, 0)); + EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 1)); + EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, 0)); + EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, -1)); +} + +} // end namespace diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp new file mode 100644 index 000000000000..bb9c351415bf --- /dev/null +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -0,0 +1,126 @@ +//===- SpecialCaseListTest.cpp - Unit tests for SpecialCaseList -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SpecialCaseList.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class SpecialCaseListTest : public ::testing::Test { +protected: + SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { + std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); + return SpecialCaseList::create(MB.get(), Error); + } + + SpecialCaseList *makeSpecialCaseList(StringRef List) { + std::string Error; + SpecialCaseList *SCL = makeSpecialCaseList(List, Error); + assert(SCL); + assert(Error == ""); + return SCL; + } +}; + +TEST_F(SpecialCaseListTest, Basic) { + std::unique_ptr<SpecialCaseList> SCL( + makeSpecialCaseList("# This is a comment.\n" + "\n" + "src:hello\n" + "src:bye\n" + "src:hi=category\n" + "src:z*=category\n")); + EXPECT_TRUE(SCL->inSection("src", "hello")); + EXPECT_TRUE(SCL->inSection("src", "bye")); + EXPECT_TRUE(SCL->inSection("src", "hi", "category")); + EXPECT_TRUE(SCL->inSection("src", "zzzz", "category")); + EXPECT_FALSE(SCL->inSection("src", "hi")); + EXPECT_FALSE(SCL->inSection("fun", "hello")); + EXPECT_FALSE(SCL->inSection("src", "hello", "category")); +} + +TEST_F(SpecialCaseListTest, GlobalInitCompat) { + std::unique_ptr<SpecialCaseList> SCL( + makeSpecialCaseList("global:foo=init\n")); + EXPECT_FALSE(SCL->inSection("global", "foo")); + EXPECT_FALSE(SCL->inSection("global", "bar")); + EXPECT_TRUE(SCL->inSection("global", "foo", "init")); + EXPECT_FALSE(SCL->inSection("global", "bar", "init")); + + SCL.reset(makeSpecialCaseList("global-init:foo\n")); + EXPECT_FALSE(SCL->inSection("global", "foo")); + EXPECT_FALSE(SCL->inSection("global", "bar")); + EXPECT_TRUE(SCL->inSection("global", "foo", "init")); + EXPECT_FALSE(SCL->inSection("global", "bar", "init")); + + SCL.reset(makeSpecialCaseList("type:t2=init\n")); + EXPECT_FALSE(SCL->inSection("type", "t1")); + EXPECT_FALSE(SCL->inSection("type", "t2")); + EXPECT_FALSE(SCL->inSection("type", "t1", "init")); + EXPECT_TRUE(SCL->inSection("type", "t2", "init")); + + SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); + EXPECT_FALSE(SCL->inSection("type", "t1")); + EXPECT_FALSE(SCL->inSection("type", "t2")); + EXPECT_FALSE(SCL->inSection("type", "t1", "init")); + EXPECT_TRUE(SCL->inSection("type", "t2", "init")); + + SCL.reset(makeSpecialCaseList("src:hello=init\n")); + EXPECT_FALSE(SCL->inSection("src", "hello")); + EXPECT_FALSE(SCL->inSection("src", "bye")); + EXPECT_TRUE(SCL->inSection("src", "hello", "init")); + EXPECT_FALSE(SCL->inSection("src", "bye", "init")); + + SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); + EXPECT_FALSE(SCL->inSection("src", "hello")); + EXPECT_FALSE(SCL->inSection("src", "bye")); + EXPECT_TRUE(SCL->inSection("src", "hello", "init")); + EXPECT_FALSE(SCL->inSection("src", "bye", "init")); +} + +TEST_F(SpecialCaseListTest, Substring) { + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" + "fun:foo\n" + "global:bar\n")); + EXPECT_FALSE(SCL->inSection("src", "othello")); + EXPECT_FALSE(SCL->inSection("fun", "tomfoolery")); + EXPECT_FALSE(SCL->inSection("global", "bartender")); + + SCL.reset(makeSpecialCaseList("fun:*foo*\n")); + EXPECT_TRUE(SCL->inSection("fun", "tomfoolery")); + EXPECT_TRUE(SCL->inSection("fun", "foobar")); +} + +TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { + std::string Error; + EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error)); + EXPECT_EQ("Malformed line 1: 'badline'", Error); + EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error)); + EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range", + Error); + EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n" + "fun:fun(a\n", + Error)); + EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced", + Error); + EXPECT_EQ(nullptr, SpecialCaseList::create("unexisting", Error)); + EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':")); +} + +TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("")); + EXPECT_FALSE(SCL->inSection("foo", "bar")); +} + +} + + diff --git a/unittests/Support/StringPool.cpp b/unittests/Support/StringPool.cpp new file mode 100644 index 000000000000..7b7805f91710 --- /dev/null +++ b/unittests/Support/StringPool.cpp @@ -0,0 +1,31 @@ +//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StringPool.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(PooledStringPtrTest, OperatorEquals) { + StringPool pool; + const PooledStringPtr a = pool.intern("a"); + const PooledStringPtr b = pool.intern("b"); + EXPECT_FALSE(a == b); +} + +TEST(PooledStringPtrTest, OperatorNotEquals) { + StringPool pool; + const PooledStringPtr a = pool.intern("a"); + const PooledStringPtr b = pool.intern("b"); + EXPECT_TRUE(a != b); +} + +} diff --git a/unittests/Support/SwapByteOrderTest.cpp b/unittests/Support/SwapByteOrderTest.cpp index c2a0c2793889..525cfc1aea82 100644 --- a/unittests/Support/SwapByteOrderTest.cpp +++ b/unittests/Support/SwapByteOrderTest.cpp @@ -17,73 +17,73 @@ using namespace llvm; namespace { -// In these first two tests all of the origional_uintx values are truncated +// In these first two tests all of the original_uintx values are truncated // except for 64. We could avoid this, but there's really no point. -TEST(SwapByteOrder, UnsignedRoundTrip) { +TEST(getSwappedBytes, UnsignedRoundTrip) { // The point of the bit twiddling of magic is to test with and without bits // in every byte. uint64_t value = 1; for (std::size_t i = 0; i <= sizeof(value); ++i) { - uint8_t origional_uint8 = static_cast<uint8_t>(value); - EXPECT_EQ(origional_uint8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint8))); + uint8_t original_uint8 = static_cast<uint8_t>(value); + EXPECT_EQ(original_uint8, + sys::getSwappedBytes(sys::getSwappedBytes(original_uint8))); - uint16_t origional_uint16 = static_cast<uint16_t>(value); - EXPECT_EQ(origional_uint16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint16))); + uint16_t original_uint16 = static_cast<uint16_t>(value); + EXPECT_EQ(original_uint16, + sys::getSwappedBytes(sys::getSwappedBytes(original_uint16))); - uint32_t origional_uint32 = static_cast<uint32_t>(value); - EXPECT_EQ(origional_uint32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint32))); + uint32_t original_uint32 = static_cast<uint32_t>(value); + EXPECT_EQ(original_uint32, + sys::getSwappedBytes(sys::getSwappedBytes(original_uint32))); - uint64_t origional_uint64 = static_cast<uint64_t>(value); - EXPECT_EQ(origional_uint64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint64))); + uint64_t original_uint64 = static_cast<uint64_t>(value); + EXPECT_EQ(original_uint64, + sys::getSwappedBytes(sys::getSwappedBytes(original_uint64))); value = (value << 8) | 0x55; // binary 0101 0101. } } -TEST(SwapByteOrder, SignedRoundTrip) { +TEST(getSwappedBytes, SignedRoundTrip) { // The point of the bit twiddling of magic is to test with and without bits // in every byte. uint64_t value = 1; for (std::size_t i = 0; i <= sizeof(value); ++i) { - int8_t origional_int8 = static_cast<int8_t>(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + int8_t original_int8 = static_cast<int8_t>(value); + EXPECT_EQ(original_int8, + sys::getSwappedBytes(sys::getSwappedBytes(original_int8))); - int16_t origional_int16 = static_cast<int16_t>(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + int16_t original_int16 = static_cast<int16_t>(value); + EXPECT_EQ(original_int16, + sys::getSwappedBytes(sys::getSwappedBytes(original_int16))); - int32_t origional_int32 = static_cast<int32_t>(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + int32_t original_int32 = static_cast<int32_t>(value); + EXPECT_EQ(original_int32, + sys::getSwappedBytes(sys::getSwappedBytes(original_int32))); - int64_t origional_int64 = static_cast<int64_t>(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + int64_t original_int64 = static_cast<int64_t>(value); + EXPECT_EQ(original_int64, + sys::getSwappedBytes(sys::getSwappedBytes(original_int64))); // Test other sign. value *= -1; - origional_int8 = static_cast<int8_t>(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + original_int8 = static_cast<int8_t>(value); + EXPECT_EQ(original_int8, + sys::getSwappedBytes(sys::getSwappedBytes(original_int8))); - origional_int16 = static_cast<int16_t>(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + original_int16 = static_cast<int16_t>(value); + EXPECT_EQ(original_int16, + sys::getSwappedBytes(sys::getSwappedBytes(original_int16))); - origional_int32 = static_cast<int32_t>(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + original_int32 = static_cast<int32_t>(value); + EXPECT_EQ(original_int32, + sys::getSwappedBytes(sys::getSwappedBytes(original_int32))); - origional_int64 = static_cast<int64_t>(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + original_int64 = static_cast<int64_t>(value); + EXPECT_EQ(original_int64, + sys::getSwappedBytes(sys::getSwappedBytes(original_int64))); // Return to normal sign and twiddle. value *= -1; @@ -91,38 +91,86 @@ TEST(SwapByteOrder, SignedRoundTrip) { } } -TEST(SwapByteOrder, uint8_t) { - EXPECT_EQ(uint8_t(0x11), sys::SwapByteOrder(uint8_t(0x11))); +TEST(getSwappedBytes, uint8_t) { + EXPECT_EQ(uint8_t(0x11), sys::getSwappedBytes(uint8_t(0x11))); } -TEST(SwapByteOrder, uint16_t) { - EXPECT_EQ(uint16_t(0x1122), sys::SwapByteOrder(uint16_t(0x2211))); +TEST(getSwappedBytes, uint16_t) { + EXPECT_EQ(uint16_t(0x1122), sys::getSwappedBytes(uint16_t(0x2211))); } -TEST(SwapByteOrder, uint32_t) { - EXPECT_EQ(uint32_t(0x11223344), sys::SwapByteOrder(uint32_t(0x44332211))); +TEST(getSwappedBytes, uint32_t) { + EXPECT_EQ(uint32_t(0x11223344), sys::getSwappedBytes(uint32_t(0x44332211))); } -TEST(SwapByteOrder, uint64_t) { +TEST(getSwappedBytes, uint64_t) { EXPECT_EQ(uint64_t(0x1122334455667788ULL), - sys::SwapByteOrder(uint64_t(0x8877665544332211ULL))); + sys::getSwappedBytes(uint64_t(0x8877665544332211ULL))); } -TEST(SwapByteOrder, int8_t) { - EXPECT_EQ(int8_t(0x11), sys::SwapByteOrder(int8_t(0x11))); +TEST(getSwappedBytes, int8_t) { + EXPECT_EQ(int8_t(0x11), sys::getSwappedBytes(int8_t(0x11))); } -TEST(SwapByteOrder, int16_t) { - EXPECT_EQ(int16_t(0x1122), sys::SwapByteOrder(int16_t(0x2211))); +TEST(getSwappedBytes, int16_t) { + EXPECT_EQ(int16_t(0x1122), sys::getSwappedBytes(int16_t(0x2211))); } -TEST(SwapByteOrder, int32_t) { - EXPECT_EQ(int32_t(0x11223344), sys::SwapByteOrder(int32_t(0x44332211))); +TEST(getSwappedBytes, int32_t) { + EXPECT_EQ(int32_t(0x11223344), sys::getSwappedBytes(int32_t(0x44332211))); } -TEST(SwapByteOrder, int64_t) { +TEST(getSwappedBytes, int64_t) { EXPECT_EQ(int64_t(0x1122334455667788LL), - sys::SwapByteOrder(int64_t(0x8877665544332211LL))); + sys::getSwappedBytes(int64_t(0x8877665544332211LL))); +} + +TEST(swapByteOrder, uint8_t) { + uint8_t value = 0x11; + sys::swapByteOrder(value); + EXPECT_EQ(uint8_t(0x11), value); +} + +TEST(swapByteOrder, uint16_t) { + uint16_t value = 0x2211; + sys::swapByteOrder(value); + EXPECT_EQ(uint16_t(0x1122), value); +} + +TEST(swapByteOrder, uint32_t) { + uint32_t value = 0x44332211; + sys::swapByteOrder(value); + EXPECT_EQ(uint32_t(0x11223344), value); +} + +TEST(swapByteOrder, uint64_t) { + uint64_t value = 0x8877665544332211ULL; + sys::swapByteOrder(value); + EXPECT_EQ(uint64_t(0x1122334455667788ULL), value); +} + +TEST(swapByteOrder, int8_t) { + int8_t value = 0x11; + sys::swapByteOrder(value); + EXPECT_EQ(int8_t(0x11), value); +} + +TEST(swapByteOrder, int16_t) { + int16_t value = 0x2211; + sys::swapByteOrder(value); + EXPECT_EQ(int16_t(0x1122), value); +} + +TEST(swapByteOrder, int32_t) { + int32_t value = 0x44332211; + sys::swapByteOrder(value); + EXPECT_EQ(int32_t(0x11223344), value); +} + +TEST(swapByteOrder, int64_t) { + int64_t value = 0x8877665544332211LL; + sys::swapByteOrder(value); + EXPECT_EQ(int64_t(0x1122334455667788LL), value); } } diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp index dd4d706f5cf5..ea751be230cc 100644 --- a/unittests/Support/ThreadLocalTest.cpp +++ b/unittests/Support/ThreadLocalTest.cpp @@ -25,14 +25,14 @@ struct S { TEST_F(ThreadLocalTest, Basics) { ThreadLocal<const S> x; - EXPECT_EQ(0, x.get()); + EXPECT_EQ(nullptr, x.get()); S s; x.set(&s); EXPECT_EQ(&s, x.get()); x.erase(); - EXPECT_EQ(0, x.get()); + EXPECT_EQ(nullptr, x.get()); } } diff --git a/unittests/Support/TimeValueTest.cpp b/unittests/Support/TimeValueTest.cpp index fb2abe382932..3d2b9780c069 100644 --- a/unittests/Support/TimeValueTest.cpp +++ b/unittests/Support/TimeValueTest.cpp @@ -16,8 +16,8 @@ namespace { TEST(TimeValue, time_t) { sys::TimeValue now = sys::TimeValue::now(); - time_t now_t = time(NULL); - EXPECT_TRUE(abs(static_cast<long>(now_t - now.toEpochTime())) < 2); + time_t now_t = time(nullptr); + EXPECT_TRUE(std::abs(static_cast<long>(now_t - now.toEpochTime())) < 2); } TEST(TimeValue, Win32FILETIME) { @@ -30,7 +30,8 @@ TEST(TimeValue, Win32FILETIME) { epoch.fromWin32Time(ft1970); // The "seconds" part in Posix time may be expected as zero. - EXPECT_EQ(ns / 100, epoch.toPosixTime()); + EXPECT_EQ(0u, epoch.toEpochTime()); + EXPECT_EQ(ns, static_cast<uint32_t>(epoch.nanoseconds())); // Confirm it reversible. EXPECT_EQ(ft1970, epoch.toWin32Time()); diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 6c0b9e6151f2..8aed98012f10 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -27,6 +27,13 @@ using llvm::yaml::Hex32; using llvm::yaml::Hex64; + + +static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { +} + + + //===----------------------------------------------------------------------===// // Test MappingTraits //===----------------------------------------------------------------------===// @@ -140,6 +147,7 @@ TEST(YAMLIO, TestSequenceMapWriteAndRead) { struct BuiltInTypes { llvm::StringRef str; + std::string stdstr; uint64_t u64; uint32_t u32; uint16_t u16; @@ -163,6 +171,7 @@ namespace yaml { struct MappingTraits<BuiltInTypes> { static void mapping(IO &io, BuiltInTypes& bt) { io.mapRequired("str", bt.str); + io.mapRequired("stdstr", bt.stdstr); io.mapRequired("u64", bt.u64); io.mapRequired("u32", bt.u32); io.mapRequired("u16", bt.u16); @@ -191,6 +200,7 @@ TEST(YAMLIO, TestReadBuiltInTypes) { BuiltInTypes map; Input yin("---\n" "str: hello there\n" + "stdstr: hello where?\n" "u64: 5000000000\n" "u32: 4000000000\n" "u16: 65000\n" @@ -211,6 +221,7 @@ TEST(YAMLIO, TestReadBuiltInTypes) { EXPECT_FALSE(yin.error()); EXPECT_TRUE(map.str.equals("hello there")); + EXPECT_TRUE(map.stdstr == "hello where?"); EXPECT_EQ(map.u64, 5000000000ULL); EXPECT_EQ(map.u32, 4000000000U); EXPECT_EQ(map.u16, 65000); @@ -237,6 +248,7 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { { BuiltInTypes map; map.str = "one two"; + map.stdstr = "three four"; map.u64 = 6000000000ULL; map.u32 = 3000000000U; map.u16 = 50000; @@ -265,6 +277,7 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { EXPECT_FALSE(yin.error()); EXPECT_TRUE(map.str.equals("one two")); + EXPECT_TRUE(map.stdstr == "three four"); EXPECT_EQ(map.u64, 6000000000ULL); EXPECT_EQ(map.u32, 3000000000U); EXPECT_EQ(map.u16, 50000); @@ -289,6 +302,23 @@ struct StringTypes { llvm::StringRef str3; llvm::StringRef str4; llvm::StringRef str5; + llvm::StringRef str6; + llvm::StringRef str7; + llvm::StringRef str8; + llvm::StringRef str9; + llvm::StringRef str10; + llvm::StringRef str11; + std::string stdstr1; + std::string stdstr2; + std::string stdstr3; + std::string stdstr4; + std::string stdstr5; + std::string stdstr6; + std::string stdstr7; + std::string stdstr8; + std::string stdstr9; + std::string stdstr10; + std::string stdstr11; }; namespace llvm { @@ -301,6 +331,23 @@ namespace yaml { io.mapRequired("str3", st.str3); io.mapRequired("str4", st.str4); io.mapRequired("str5", st.str5); + io.mapRequired("str6", st.str6); + io.mapRequired("str7", st.str7); + io.mapRequired("str8", st.str8); + io.mapRequired("str9", st.str9); + io.mapRequired("str10", st.str10); + io.mapRequired("str11", st.str11); + io.mapRequired("stdstr1", st.stdstr1); + io.mapRequired("stdstr2", st.stdstr2); + io.mapRequired("stdstr3", st.stdstr3); + io.mapRequired("stdstr4", st.stdstr4); + io.mapRequired("stdstr5", st.stdstr5); + io.mapRequired("stdstr6", st.stdstr6); + io.mapRequired("stdstr7", st.stdstr7); + io.mapRequired("stdstr8", st.stdstr8); + io.mapRequired("stdstr9", st.stdstr9); + io.mapRequired("stdstr10", st.stdstr10); + io.mapRequired("stdstr11", st.stdstr11); } }; } @@ -315,6 +362,23 @@ TEST(YAMLIO, TestReadWriteStringTypes) { map.str3 = "`ccc"; map.str4 = "@ddd"; map.str5 = ""; + map.str6 = "0000000004000000"; + map.str7 = "true"; + map.str8 = "FALSE"; + map.str9 = "~"; + map.str10 = "0.2e20"; + map.str11 = "0x30"; + map.stdstr1 = "'eee"; + map.stdstr2 = "\"fff"; + map.stdstr3 = "`ggg"; + map.stdstr4 = "@hhh"; + map.stdstr5 = ""; + map.stdstr6 = "0000000004000000"; + map.stdstr7 = "true"; + map.stdstr8 = "FALSE"; + map.stdstr9 = "~"; + map.stdstr10 = "0.2e20"; + map.stdstr11 = "0x30"; llvm::raw_string_ostream ostr(intermediate); Output yout(ostr); @@ -327,6 +391,18 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); + EXPECT_NE(std::string::npos, flowOut.find("'''eee")); + EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); + EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); + EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); + EXPECT_NE(std::string::npos, flowOut.find("''\n")); + EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); { Input yin(intermediate); @@ -339,6 +415,13 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_TRUE(map.str3.equals("`ccc")); EXPECT_TRUE(map.str4.equals("@ddd")); EXPECT_TRUE(map.str5.equals("")); + EXPECT_TRUE(map.str6.equals("0000000004000000")); + EXPECT_TRUE(map.stdstr1 == "'eee"); + EXPECT_TRUE(map.stdstr2 == "\"fff"); + EXPECT_TRUE(map.stdstr3 == "`ggg"); + EXPECT_TRUE(map.stdstr4 == "@hhh"); + EXPECT_TRUE(map.stdstr5 == ""); + EXPECT_TRUE(map.stdstr6 == "0000000004000000"); } } @@ -564,6 +647,7 @@ namespace yaml { return "malformed by"; } } + static bool mustQuote(StringRef) { return true; } }; } } @@ -625,6 +709,8 @@ namespace yaml { value = n; return StringRef(); } + + static bool mustQuote(StringRef) { return false; } }; } } @@ -1085,86 +1171,49 @@ TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { //===----------------------------------------------------------------------===// -// Test dyn_cast<> on IO object +// Test mapping validation //===----------------------------------------------------------------------===// -struct DynCast { - int value; +struct MyValidation { + double value; }; -typedef std::vector<DynCast> DynCastSequence; -LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) namespace llvm { namespace yaml { template <> - struct MappingTraits<DynCast> { - static void mapping(IO &io, DynCast& info) { - // Change 10 to 13 when writing yaml. - if (Output *output = dyn_cast<Output>(&io)) { - (void)output; - if (info.value == 10) - info.value = 13; - } - io.mapRequired("value", info.value); - // Change 20 to 23 when parsing yaml. - if (Input *input = dyn_cast<Input>(&io)) { - (void)input; - if (info.value == 20) - info.value = 23; - } + struct MappingTraits<MyValidation> { + static void mapping(IO &io, MyValidation &d) { + io.mapRequired("value", d.value); + } + static StringRef validate(IO &io, MyValidation &d) { + if (d.value < 0) + return "negative value"; + return StringRef(); } }; + } } -} + // -// Test writing then reading back a sequence of mappings +// Test that validate() is called and complains about the negative value. // -TEST(YAMLIO, TestDynCast) { - std::string intermediate; - { - DynCast entry1; - entry1.value = 10; - DynCast entry2; - entry2.value = 20; - DynCast entry3; - entry3.value = 30; - DynCastSequence seq; - seq.push_back(entry1); - seq.push_back(entry2); - seq.push_back(entry3); - - llvm::raw_string_ostream ostr(intermediate); - Output yout(ostr); - yout << seq; - } - - { - Input yin(intermediate); - DynCastSequence seq2; - yin >> seq2; - - EXPECT_FALSE(yin.error()); - EXPECT_EQ(seq2.size(), 3UL); - EXPECT_EQ(seq2[0].value, 13); // Verify changed to 13. - EXPECT_EQ(seq2[1].value, 23); // Verify changed to 23. - EXPECT_EQ(seq2[2].value, 30); // Verify stays same. - } +TEST(YAMLIO, TestValidatingInput) { + std::vector<MyValidation> docList; + Input yin("--- \nvalue: 3.0\n" + "--- \nvalue: -1.0\n...\n", + nullptr, suppressErrorMessages); + yin >> docList; + EXPECT_TRUE(!!yin.error()); } - //===----------------------------------------------------------------------===// // Test error handling //===----------------------------------------------------------------------===// - - -static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { -} - - // // Test error handling of unknown enumerated scalar // @@ -1175,10 +1224,10 @@ TEST(YAMLIO, TestColorsReadError) { "c2: purple\n" "c3: green\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> map; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1192,11 +1241,11 @@ TEST(YAMLIO, TestFlagsReadError) { "f2: [ round, hollow ]\n" "f3: []\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> map; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1211,11 +1260,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { "- 0\n" "- 257\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1230,11 +1279,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { "- 0\n" "- 66000\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1249,11 +1298,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { "- 0\n" "- 5000000000\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1268,11 +1317,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { "- 0\n" "- 19446744073709551615\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1288,11 +1337,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { "- 127\n" "- 128\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1306,11 +1355,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { "- 127\n" "- -129\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1326,11 +1375,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { "- -32768\n" "- -32769\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1345,11 +1394,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { "- -32768\n" "- 32768\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1365,11 +1414,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { "- -2147483648\n" "- -2147483649\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1383,11 +1432,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { "- -2147483648\n" "- 2147483649\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1403,11 +1452,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { "- 9223372036854775807\n" "- -9223372036854775809\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1421,11 +1470,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { "- 9223372036854775807\n" "- 9223372036854775809\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1440,11 +1489,11 @@ TEST(YAMLIO, TestReadBuiltInTypesFloatError) { "- -123.456\n" "- 1.2.3\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1459,11 +1508,11 @@ TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { "- -123.456\n" "- 1.2.3\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1477,11 +1526,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { "- 0xFE\n" "- 0x123\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1496,11 +1545,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { "- 0xFEFF\n" "- 0x12345\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1514,11 +1563,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { "- 0xFEFF0000\n" "- 0x1234556789\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1532,11 +1581,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { "- 0xFFEEDDCCBBAA9988\n" "- 0x12345567890ABCDEF0\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } TEST(YAMLIO, TestMalformedMapFailsGracefully) { @@ -1544,15 +1593,15 @@ TEST(YAMLIO, TestMalformedMapFailsGracefully) { { // We pass the suppressErrorMessages handler to handle the error // message generated in the constructor of Input. - Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages); + Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } { - Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages); + Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } } @@ -1624,7 +1673,7 @@ TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { FooBar doc; Input yin(""); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { @@ -1636,7 +1685,7 @@ TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { std::vector<uint8_t> seq; - Input yin("", /*Ctxt=*/NULL, suppressErrorMessages); + Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; EXPECT_FALSE(yin.error()); diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 2b797b43666b..44d27d041021 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -69,7 +69,7 @@ TEST(raw_ostreamTest, Types_Buffered) { EXPECT_EQ("1.100000e+00", printToString(1.1)); // void* - EXPECT_EQ("0x0", printToString((void*) 0)); + EXPECT_EQ("0x0", printToString((void*) nullptr)); EXPECT_EQ("0xbeef", printToString((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef)); @@ -100,7 +100,7 @@ TEST(raw_ostreamTest, Types_Unbuffered) { EXPECT_EQ("1.100000e+00", printToStringUnbuffered(1.1)); // void* - EXPECT_EQ("0x0", printToStringUnbuffered((void*) 0)); + EXPECT_EQ("0x0", printToStringUnbuffered((void*) nullptr)); EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef)); diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt index 4b471939ef1f..88734d2b8fcf 100644 --- a/unittests/Transforms/DebugIR/CMakeLists.txt +++ b/unittests/Transforms/DebugIR/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS + Core Instrumentation + Support ) add_llvm_unittest(DebugIRTests diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp index 7d213fd0567a..41df14721684 100644 --- a/unittests/Transforms/DebugIR/DebugIR.cpp +++ b/unittests/Transforms/DebugIR/DebugIR.cpp @@ -13,17 +13,17 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" +#include "../lib/Transforms/Instrumentation/DebugIR.h" #include "llvm/Config/config.h" -#include "llvm/DebugInfo.h" -#include "llvm/DIBuilder.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Module.h" -#include "llvm/Support/Host.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Transforms/Instrumentation.h" -#include "../lib/Transforms/Instrumentation/DebugIR.h" - // These tests do not depend on MCJIT, but we use the TrivialModuleBuilder // helper class to construct some trivial Modules. #include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h" @@ -56,16 +56,17 @@ void insertCUDescriptor(Module *M, StringRef File, StringRef Dir, /// Attempts to remove file at Path and returns true if it existed, or false if /// it did not. bool removeIfExists(StringRef Path) { - bool existed = false; - sys::fs::remove(Path, existed); - return existed; + // This is an approximation, on error we don't know in general if the file + // existed or not. + std::error_code EC = sys::fs::remove(Path, false); + return EC != llvm::errc::no_such_file_or_directory; } char * current_dir() { #if defined(LLVM_ON_WIN32) || defined(HAVE_GETCWD) // calling getcwd (or _getcwd() on windows) with a null buffer makes it // allocate a sufficiently sized buffer to store the current working dir. - return getcwd_impl(0, 0); + return getcwd_impl(nullptr, 0); #else return 0; #endif @@ -90,8 +91,8 @@ protected: LLVMContext Context; char *cwd; - OwningPtr<Module> M; - OwningPtr<DebugIR> D; + std::unique_ptr<Module> M; + std::unique_ptr<DebugIR> D; }; // Test empty named Module that is not supposed to be output to disk. @@ -278,7 +279,7 @@ TEST_F(TestDebugIR, ExistingMetadataRetained) { // verify DebugIR did not generate a file ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; - DICompileUnit CU(*Finder.compile_unit_begin()); + DICompileUnit CU(*Finder.compile_units().begin()); // Verify original CU information is retained ASSERT_EQ(Filename, CU.getFilename()); diff --git a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp new file mode 100644 index 000000000000..0d3a239da347 --- /dev/null +++ b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp @@ -0,0 +1,102 @@ +//===- ASanStackFrameLayoutTest.cpp - Tests for ComputeASanStackFrameLayout===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/ASanStackFrameLayout.h" +#include "llvm/ADT/ArrayRef.h" +#include "gtest/gtest.h" +#include <sstream> + +using namespace llvm; + +static std::string +ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) { + std::ostringstream os; + for (size_t i = 0, n = ShadowBytes.size(); i < n; i++) { + switch (ShadowBytes[i]) { + case kAsanStackLeftRedzoneMagic: os << "L"; break; + case kAsanStackRightRedzoneMagic: os << "R"; break; + case kAsanStackMidRedzoneMagic: os << "M"; break; + default: os << (unsigned)ShadowBytes[i]; + } + } + return os.str(); +} + +static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars, + size_t Granularity, size_t MinHeaderSize, + const std::string &ExpectedDescr, + const std::string &ExpectedShadow) { + ASanStackFrameLayout L; + ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L); + EXPECT_EQ(ExpectedDescr, L.DescriptionString); + EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes)); +} + +TEST(ASanStackFrameLayout, Test) { +#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a) +#define VEC(a) \ + SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0])) + +#define VAR(name, size, alignment) \ + ASanStackVariableDescription name##size##_##alignment = { \ + #name #size "_" #alignment, \ + size, \ + alignment, \ + 0, \ + 0 \ + } + + VAR(a, 1, 1); + VAR(p, 1, 32); + VAR(p, 1, 256); + VAR(a, 2, 1); + VAR(a, 3, 1); + VAR(a, 4, 1); + VAR(a, 7, 1); + VAR(a, 8, 1); + VAR(a, 9, 1); + VAR(a, 16, 1); + VAR(a, 41, 1); + VAR(a, 105, 1); + + TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R"); + TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1"); + TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR"); + TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR"); + + TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR"); + TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR"); + TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR"); + TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR"); + TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR"); + TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLL0RRR"); + TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR"); + TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR"); + TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256", + "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR"); + TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR"); + TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1", + "LLLL00000000000001RRRRRR"); + + { + ASanStackVariableDescription t[] = {a1_1, p1_256}; + TestLayout(VEC(t), 8, 32, + "2 256 1 6 p1_256 272 1 4 a1_1", + "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "1M1R"); + } + + { + ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1}; + TestLayout(VEC(t), 8, 32, + "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1", + "LLLL" "1M00" "MM00" "0001" "RRRR"); + } +#undef VEC1 +#undef VEC +#undef VAR +} diff --git a/unittests/Transforms/Utils/CMakeLists.txt b/unittests/Transforms/Utils/CMakeLists.txt index 0656390cbbea..ffa1d49d380b 100644 --- a/unittests/Transforms/Utils/CMakeLists.txt +++ b/unittests/Transforms/Utils/CMakeLists.txt @@ -1,10 +1,12 @@ set(LLVM_LINK_COMPONENTS + Core + Support TransformUtils ) add_llvm_unittest(UtilsTests + ASanStackFrameLayoutTest.cpp Cloning.cpp IntegerDivision.cpp Local.cpp - SpecialCaseList.cpp ) diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index e19ae5bc2fb4..b3a1f5b10521 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -7,15 +7,22 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "gtest/gtest.h" using namespace llvm; @@ -25,7 +32,7 @@ namespace { class CloneInstruction : public ::testing::Test { protected: virtual void SetUp() { - V = NULL; + V = nullptr; } template <typename T> @@ -173,4 +180,230 @@ TEST_F(CloneInstruction, Attributes) { delete F2; } +TEST_F(CloneInstruction, CallingConvention) { + Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; + FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + + Function *F1 = Function::Create(FT1, Function::ExternalLinkage); + F1->setCallingConv(CallingConv::Cold); + BasicBlock *BB = BasicBlock::Create(context, "", F1); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + Function *F2 = Function::Create(FT1, Function::ExternalLinkage); + + SmallVector<ReturnInst*, 4> Returns; + ValueToValueMapTy VMap; + VMap[F1->arg_begin()] = F2->arg_begin(); + + CloneFunctionInto(F2, F1, VMap, false, Returns); + EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); + + delete F1; + delete F2; +} + +class CloneFunc : public ::testing::Test { +protected: + virtual void SetUp() { + SetupModule(); + CreateOldFunc(); + CreateNewFunc(); + SetupFinder(); + } + + virtual void TearDown() { + delete Finder; + } + + void SetupModule() { + M = new Module("", C); + } + + void CreateOldFunc() { + FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false); + OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M); + CreateOldFunctionBodyAndDI(); + } + + void CreateOldFunctionBodyAndDI() { + DIBuilder DBuilder(*M); + IRBuilder<> IBuilder(C); + + // Function DI + DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); + DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>()); + DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); + DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, + "filename.c", "/file/dir", "CloneFunc", false, "", 0); + + DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, + FuncType, true, true, 3, 0, false, OldFunc); + + // Function body + BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc); + IBuilder.SetInsertPoint(Entry); + DebugLoc Loc = DebugLoc::get(3, 2, Subprogram); + IBuilder.SetCurrentDebugLocation(Loc); + AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C)); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram)); + Value* AllocaContent = IBuilder.getInt32(1); + Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram)); + Instruction* Terminator = IBuilder.CreateRetVoid(); + + // Create a local variable around the alloca + DIType IntType = DBuilder.createBasicType("int", 32, 0, + dwarf::DW_ATE_signed); + DIVariable Variable = DBuilder.createLocalVariable( + dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); + DBuilder.insertDeclare(Alloca, Variable, Store); + DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator); + // Finalize the debug info + DBuilder.finalize(); + + + // Create another, empty, compile unit + DIBuilder DBuilder2(*M); + DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, + "extra.c", "/file/dir", "CloneFunc", false, "", 0); + DBuilder2.finalize(); + } + + void CreateNewFunc() { + ValueToValueMapTy VMap; + NewFunc = CloneFunction(OldFunc, VMap, true, nullptr); + M->getFunctionList().push_back(NewFunc); + } + + void SetupFinder() { + Finder = new DebugInfoFinder(); + Finder->processModule(*M); + } + + LLVMContext C; + Function* OldFunc; + Function* NewFunc; + Module* M; + DebugInfoFinder* Finder; +}; + +// Test that a new, distinct function was created. +TEST_F(CloneFunc, NewFunctionCreated) { + EXPECT_NE(OldFunc, NewFunc); +} + +// Test that a new subprogram entry was added and is pointing to the new +// function, while the original subprogram still points to the old one. +TEST_F(CloneFunc, Subprogram) { + unsigned SubprogramCount = Finder->subprogram_count(); + EXPECT_EQ(2U, SubprogramCount); + + auto Iter = Finder->subprograms().begin(); + DISubprogram Sub1(*Iter); + EXPECT_TRUE(Sub1.Verify()); + Iter++; + DISubprogram Sub2(*Iter); + EXPECT_TRUE(Sub2.Verify()); + + EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc) + || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc)); +} + +// Test that the new subprogram entry was not added to the CU which doesn't +// contain the old subprogram entry. +TEST_F(CloneFunc, SubprogramInRightCU) { + EXPECT_EQ(2U, Finder->compile_unit_count()); + + auto Iter = Finder->compile_units().begin(); + DICompileUnit CU1(*Iter); + EXPECT_TRUE(CU1.Verify()); + Iter++; + DICompileUnit CU2(*Iter); + EXPECT_TRUE(CU2.Verify()); + EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0 + || CU2.getSubprograms().getNumElements() == 0); +} + +// Test that instructions in the old function still belong to it in the +// metadata, while instruction in the new function belong to the new one. +TEST_F(CloneFunc, InstructionOwnership) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + EXPECT_NE(&OldI, &NewI); + + EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata()); + if (OldI.hasMetadata()) { + const DebugLoc& OldDL = OldI.getDebugLoc(); + const DebugLoc& NewDL = NewI.getDebugLoc(); + + // Verify that the debug location data is the same + EXPECT_EQ(OldDL.getLine(), NewDL.getLine()); + EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); + + // But that they belong to different functions + DISubprogram OldSubprogram(OldDL.getScope(C)); + DISubprogram NewSubprogram(NewDL.getScope(C)); + EXPECT_TRUE(OldSubprogram.Verify()); + EXPECT_TRUE(NewSubprogram.Verify()); + EXPECT_EQ(OldFunc, OldSubprogram.getFunction()); + EXPECT_EQ(NewFunc, NewSubprogram.getFunction()); + } + + ++OldIter; + ++NewIter; + } + EXPECT_EQ(OldEnd, OldIter); + EXPECT_EQ(NewEnd, NewIter); +} + +// Test that the arguments for debug intrinsics in the new function were +// properly cloned +TEST_F(CloneFunc, DebugIntrinsics) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) { + DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old address must belong to the old function + EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())-> + getParent()->getParent()); + // New address must belong to the new function + EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> + getParent()->getParent()); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { + DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } + + ++OldIter; + ++NewIter; + } +} + } diff --git a/unittests/Transforms/Utils/IntegerDivision.cpp b/unittests/Transforms/Utils/IntegerDivision.cpp index 44c2328ee354..f7318a2e7897 100644 --- a/unittests/Transforms/Utils/IntegerDivision.cpp +++ b/unittests/Transforms/Utils/IntegerDivision.cpp @@ -19,6 +19,7 @@ using namespace llvm; namespace { + TEST(IntegerDivision, SDiv) { LLVMContext &C(getGlobalContext()); Module M("test division", C); @@ -139,4 +140,125 @@ TEST(IntegerDivision, URem) { EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); } + +TEST(IntegerDivision, SDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateSDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, UDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateUDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI); +} + +TEST(IntegerDivision, SRem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateSRem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, URem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateURem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + } diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp deleted file mode 100644 index 07ac908caabc..000000000000 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ /dev/null @@ -1,232 +0,0 @@ -//===- SpecialCaseList.cpp - Unit tests for SpecialCaseList ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Transforms/Utils/SpecialCaseList.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -class SpecialCaseListTest : public ::testing::Test { -protected: - Function *makeFunction(StringRef Name, Module &M) { - return Function::Create(FunctionType::get(Type::getVoidTy(Ctx), false), - GlobalValue::ExternalLinkage, - Name, - &M); - } - - GlobalVariable *makeGlobal(StringRef Name, StringRef StructName, Module &M) { - StructType *ST = - StructType::create(StructName, Type::getInt32Ty(Ctx), (Type*)0); - return new GlobalVariable( - M, ST, false, GlobalValue::ExternalLinkage, 0, Name); - } - - GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) { - return new GlobalAlias(Aliasee->getType(), GlobalValue::ExternalLinkage, - Name, Aliasee, Aliasee->getParent()); - } - - SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); - return SpecialCaseList::create(MB.get(), Error); - } - - SpecialCaseList *makeSpecialCaseList(StringRef List) { - std::string Error; - SpecialCaseList *SCL = makeSpecialCaseList(List, Error); - assert(SCL); - assert(Error == ""); - return SCL; - } - - LLVMContext Ctx; -}; - -TEST_F(SpecialCaseListTest, ModuleIsIn) { - Module M("hello", Ctx); - Function *F = makeFunction("foo", M); - GlobalVariable *GV = makeGlobal("bar", "t", M); - - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("# This is a comment.\n" - "\n" - "src:hello\n")); - EXPECT_TRUE(SCL->isIn(M)); - EXPECT_TRUE(SCL->isIn(*F)); - EXPECT_TRUE(SCL->isIn(*GV)); - - SCL.reset(makeSpecialCaseList("src:he*o\n")); - EXPECT_TRUE(SCL->isIn(M)); - EXPECT_TRUE(SCL->isIn(*F)); - EXPECT_TRUE(SCL->isIn(*GV)); - - SCL.reset(makeSpecialCaseList("src:hi\n")); - EXPECT_FALSE(SCL->isIn(M)); - EXPECT_FALSE(SCL->isIn(*F)); - EXPECT_FALSE(SCL->isIn(*GV)); -} - -TEST_F(SpecialCaseListTest, FunctionIsIn) { - Module M("hello", Ctx); - Function *Foo = makeFunction("foo", M); - Function *Bar = makeFunction("bar", M); - - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); - EXPECT_TRUE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - - SCL.reset(makeSpecialCaseList("fun:b*\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_TRUE(SCL->isIn(*Bar)); - - SCL.reset(makeSpecialCaseList("fun:f*\n" - "fun:bar\n")); - EXPECT_TRUE(SCL->isIn(*Foo)); - EXPECT_TRUE(SCL->isIn(*Bar)); - - SCL.reset(makeSpecialCaseList("fun:foo=functional\n")); - EXPECT_TRUE(SCL->isIn(*Foo, "functional")); - StringRef Category; - EXPECT_FALSE(SCL->isIn(*Bar, "functional")); -} - -TEST_F(SpecialCaseListTest, GlobalIsIn) { - Module M("hello", Ctx); - GlobalVariable *Foo = makeGlobal("foo", "t1", M); - GlobalVariable *Bar = makeGlobal("bar", "t2", M); - - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n")); - EXPECT_TRUE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_FALSE(SCL->isIn(*Foo, "init")); - EXPECT_FALSE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("global:foo=init\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_TRUE(SCL->isIn(*Foo, "init")); - EXPECT_FALSE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("global-init:foo\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_TRUE(SCL->isIn(*Foo, "init")); - EXPECT_FALSE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("type:t2=init\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_FALSE(SCL->isIn(*Foo, "init")); - EXPECT_TRUE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_FALSE(SCL->isIn(*Foo, "init")); - EXPECT_TRUE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("src:hello=init\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_TRUE(SCL->isIn(*Foo, "init")); - EXPECT_TRUE(SCL->isIn(*Bar, "init")); - - SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); - EXPECT_FALSE(SCL->isIn(*Foo)); - EXPECT_FALSE(SCL->isIn(*Bar)); - EXPECT_TRUE(SCL->isIn(*Foo, "init")); - EXPECT_TRUE(SCL->isIn(*Bar, "init")); -} - -TEST_F(SpecialCaseListTest, AliasIsIn) { - Module M("hello", Ctx); - Function *Foo = makeFunction("foo", M); - GlobalVariable *Bar = makeGlobal("bar", "t", M); - GlobalAlias *FooAlias = makeAlias("fooalias", Foo); - GlobalAlias *BarAlias = makeAlias("baralias", Bar); - - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias)); - EXPECT_FALSE(SCL->isIn(*BarAlias)); - - SCL.reset(makeSpecialCaseList("global:bar\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias)); - EXPECT_FALSE(SCL->isIn(*BarAlias)); - - SCL.reset(makeSpecialCaseList("global:fooalias\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias)); - EXPECT_FALSE(SCL->isIn(*BarAlias)); - - SCL.reset(makeSpecialCaseList("fun:fooalias\n")); - EXPECT_TRUE(SCL->isIn(*FooAlias)); - EXPECT_FALSE(SCL->isIn(*BarAlias)); - - SCL.reset(makeSpecialCaseList("global:baralias=init\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); - EXPECT_TRUE(SCL->isIn(*BarAlias, "init")); - - SCL.reset(makeSpecialCaseList("type:t=init\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); - EXPECT_TRUE(SCL->isIn(*BarAlias, "init")); - - SCL.reset(makeSpecialCaseList("fun:baralias=init\n")); - EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); - EXPECT_FALSE(SCL->isIn(*BarAlias, "init")); -} - -TEST_F(SpecialCaseListTest, Substring) { - Module M("othello", Ctx); - Function *F = makeFunction("tomfoolery", M); - GlobalVariable *GV = makeGlobal("bartender", "t", M); - GlobalAlias *GA1 = makeAlias("buffoonery", F); - GlobalAlias *GA2 = makeAlias("foobar", GV); - - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" - "fun:foo\n" - "global:bar\n")); - EXPECT_FALSE(SCL->isIn(M)); - EXPECT_FALSE(SCL->isIn(*F)); - EXPECT_FALSE(SCL->isIn(*GV)); - EXPECT_FALSE(SCL->isIn(*GA1)); - EXPECT_FALSE(SCL->isIn(*GA2)); - - SCL.reset(makeSpecialCaseList("fun:*foo*\n")); - EXPECT_TRUE(SCL->isIn(*F)); - EXPECT_TRUE(SCL->isIn(*GA1)); -} - -TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { - std::string Error; - EXPECT_EQ(0, makeSpecialCaseList("badline", Error)); - EXPECT_EQ("Malformed line 1: 'badline'", Error); - EXPECT_EQ(0, makeSpecialCaseList("src:bad[a-", Error)); - EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range", - Error); - EXPECT_EQ(0, makeSpecialCaseList("src:a.c\n" - "fun:fun(a\n", - Error)); - EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced", - Error); - EXPECT_EQ(0, SpecialCaseList::create("unexisting", Error)); - EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':")); -} - -TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("")); - Module M("foo", Ctx); - EXPECT_FALSE(SCL->isIn(M)); -} - -} |