diff options
Diffstat (limited to 'unittests/Support')
-rw-r--r-- | unittests/Support/Makefile | 15 | ||||
-rw-r--r-- | unittests/Support/MathExtrasTest.cpp | 104 | ||||
-rw-r--r-- | unittests/Support/TypeBuilderTest.cpp | 233 | ||||
-rw-r--r-- | unittests/Support/ValueHandleTest.cpp | 317 | ||||
-rw-r--r-- | unittests/Support/raw_ostream_test.cpp | 85 |
5 files changed, 754 insertions, 0 deletions
diff --git a/unittests/Support/Makefile b/unittests/Support/Makefile new file mode 100644 index 0000000..815bdd2 --- /dev/null +++ b/unittests/Support/Makefile @@ -0,0 +1,15 @@ +##===- unittests/ADT/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 = Support +LINK_COMPONENTS := core support + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp new file mode 100644 index 0000000..1f19468 --- /dev/null +++ b/unittests/Support/MathExtrasTest.cpp @@ -0,0 +1,104 @@ +//===- llvm/unittest/Support/MathExtrasTest.cpp - math utils 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/MathExtras.h" + +using namespace llvm; + +namespace { + +TEST(MathExtras, isPowerOf2_32) { + EXPECT_TRUE(isPowerOf2_32(1 << 6)); + EXPECT_TRUE(isPowerOf2_32(1 << 12)); + EXPECT_FALSE(isPowerOf2_32((1 << 19) + 3)); + EXPECT_FALSE(isPowerOf2_32(0xABCDEF0)); +} + +TEST(MathExtras, isPowerOf2_64) { + EXPECT_TRUE(isPowerOf2_64(1LL << 46)); + EXPECT_TRUE(isPowerOf2_64(1LL << 12)); + EXPECT_FALSE(isPowerOf2_64((1LL << 53) + 3)); + EXPECT_FALSE(isPowerOf2_64(0xABCDEF0ABCDEF0LL)); +} + +TEST(MathExtras, ByteSwap_32) { + EXPECT_EQ(0x44332211u, ByteSwap_32(0x11223344)); + EXPECT_EQ(0xDDCCBBAAu, ByteSwap_32(0xAABBCCDD)); +} + +TEST(MathExtras, ByteSwap_64) { + EXPECT_EQ(0x8877665544332211ULL, ByteSwap_64(0x1122334455667788LL)); + EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL)); +} + +TEST(MathExtras, CountLeadingZeros_32) { + EXPECT_EQ(8u, CountLeadingZeros_32(0x00F000FF)); + EXPECT_EQ(8u, CountLeadingZeros_32(0x00F12345)); + for (unsigned i = 0; i <= 30; ++i) { + EXPECT_EQ(31 - i, CountLeadingZeros_32(1 << i)); + } +} + +TEST(MathExtras, CountLeadingZeros_64) { + EXPECT_EQ(8u, CountLeadingZeros_64(0x00F1234500F12345LL)); + EXPECT_EQ(1u, CountLeadingZeros_64(1LL << 62)); + for (unsigned i = 0; i <= 62; ++i) { + EXPECT_EQ(63 - i, CountLeadingZeros_64(1LL << i)); + } +} + +TEST(MathExtras, CountLeadingOnes_32) { + for (int i = 30; i >= 0; --i) { + // Start with all ones and unset some bit. + EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + } +} + +TEST(MathExtras, CountLeadingOnes_64) { + for (int i = 62; i >= 0; --i) { + // Start with all ones and unset some bit. + EXPECT_EQ(63u - i, CountLeadingOnes_64(0xFFFFFFFFFFFFFFFFLL ^ (1LL << i))); + } + for (int i = 30; i >= 0; --i) { + // Start with all ones and unset some bit. + EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + } +} + +TEST(MathExtras, FloatBits) { + static const float kValue = 5632.34; + EXPECT_FLOAT_EQ(kValue, BitsToFloat(FloatToBits(kValue))); +} + +TEST(MathExtras, DoubleBits) { + static const double kValue = 87987234.983498; + EXPECT_FLOAT_EQ(kValue, BitsToDouble(DoubleToBits(kValue))); +} + +TEST(MathExtras, MinAlign) { + EXPECT_EQ(1u, MinAlign(2, 3)); + EXPECT_EQ(2u, MinAlign(2, 4)); + EXPECT_EQ(1u, MinAlign(17, 64)); + EXPECT_EQ(256u, MinAlign(256, 512)); +} + +TEST(MathExtras, NextPowerOf2) { + EXPECT_EQ(4u, NextPowerOf2(3)); + EXPECT_EQ(16u, NextPowerOf2(15)); + EXPECT_EQ(256u, NextPowerOf2(128)); +} + +TEST(MathExtras, RoundUpToAlignment) { + EXPECT_EQ(8u, RoundUpToAlignment(5, 8)); + EXPECT_EQ(24u, RoundUpToAlignment(17, 8)); + EXPECT_EQ(0u, RoundUpToAlignment(~0LL, 8)); +} + +} diff --git a/unittests/Support/TypeBuilderTest.cpp b/unittests/Support/TypeBuilderTest.cpp new file mode 100644 index 0000000..425ee6b --- /dev/null +++ b/unittests/Support/TypeBuilderTest.cpp @@ -0,0 +1,233 @@ +//===- llvm/unittest/Support/TypeBuilderTest.cpp - TypeBuilder 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/TypeBuilder.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(TypeBuilderTest, Void) { + EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, true>::get())); + EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, false>::get())); + // Special case for C compatibility: + EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), + (TypeBuilder<void*, false>::get())); +} + +TEST(TypeBuilderTest, HostIntegers) { + EXPECT_EQ(Type::Int8Ty, (TypeBuilder<int8_t, false>::get())); + EXPECT_EQ(Type::Int8Ty, (TypeBuilder<uint8_t, false>::get())); + EXPECT_EQ(Type::Int16Ty, (TypeBuilder<int16_t, false>::get())); + EXPECT_EQ(Type::Int16Ty, (TypeBuilder<uint16_t, false>::get())); + EXPECT_EQ(Type::Int32Ty, (TypeBuilder<int32_t, false>::get())); + EXPECT_EQ(Type::Int32Ty, (TypeBuilder<uint32_t, false>::get())); + EXPECT_EQ(Type::Int64Ty, (TypeBuilder<int64_t, false>::get())); + EXPECT_EQ(Type::Int64Ty, (TypeBuilder<uint64_t, false>::get())); + + EXPECT_EQ(IntegerType::get(sizeof(size_t) * CHAR_BIT), + (TypeBuilder<size_t, false>::get())); + EXPECT_EQ(IntegerType::get(sizeof(ptrdiff_t) * CHAR_BIT), + (TypeBuilder<ptrdiff_t, false>::get())); +} + +TEST(TypeBuilderTest, CrossCompilableIntegers) { + EXPECT_EQ(IntegerType::get(1), (TypeBuilder<types::i<1>, true>::get())); + EXPECT_EQ(IntegerType::get(1), (TypeBuilder<types::i<1>, false>::get())); + EXPECT_EQ(IntegerType::get(72), (TypeBuilder<types::i<72>, true>::get())); + EXPECT_EQ(IntegerType::get(72), (TypeBuilder<types::i<72>, false>::get())); +} + +TEST(TypeBuilderTest, Float) { + EXPECT_EQ(Type::FloatTy, (TypeBuilder<float, false>::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder<double, false>::get())); + // long double isn't supported yet. + EXPECT_EQ(Type::FloatTy, (TypeBuilder<types::ieee_float, true>::get())); + EXPECT_EQ(Type::FloatTy, (TypeBuilder<types::ieee_float, false>::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder<types::ieee_double, true>::get())); + EXPECT_EQ(Type::DoubleTy, (TypeBuilder<types::ieee_double, false>::get())); + EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder<types::x86_fp80, true>::get())); + EXPECT_EQ(Type::X86_FP80Ty, (TypeBuilder<types::x86_fp80, false>::get())); + EXPECT_EQ(Type::FP128Ty, (TypeBuilder<types::fp128, true>::get())); + EXPECT_EQ(Type::FP128Ty, (TypeBuilder<types::fp128, false>::get())); + EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder<types::ppc_fp128, true>::get())); + EXPECT_EQ(Type::PPC_FP128Ty, (TypeBuilder<types::ppc_fp128, false>::get())); +} + +TEST(TypeBuilderTest, Derived) { + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder<int8_t**, false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder<int8_t[7], false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder<int8_t[], false>::get())); + + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder<types::i<8>**, false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder<types::i<8>[7], false>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder<types::i<8>[], false>::get())); + + EXPECT_EQ(PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)), + (TypeBuilder<types::i<8>**, true>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 7), + (TypeBuilder<types::i<8>[7], true>::get())); + EXPECT_EQ(ArrayType::get(Type::Int8Ty, 0), + (TypeBuilder<types::i<8>[], true>::get())); + + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const int8_t, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<volatile int8_t, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const volatile int8_t, false>::get())); + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const types::i<8>, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<volatile types::i<8>, false>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const volatile types::i<8>, false>::get())); + + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const types::i<8>, true>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<volatile types::i<8>, true>::get())); + EXPECT_EQ(Type::Int8Ty, + (TypeBuilder<const volatile types::i<8>, true>::get())); + + EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), + (TypeBuilder<const volatile int8_t*const volatile, false>::get())); +} + +TEST(TypeBuilderTest, Functions) { + std::vector<const Type*> params; + EXPECT_EQ(FunctionType::get(Type::VoidTy, params, false), + (TypeBuilder<void(), true>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(...), false>::get())); + params.push_back(TypeBuilder<int32_t*, false>::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder<int8_t(const int32_t*), false>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(const int32_t*, ...), false>::get())); + params.push_back(TypeBuilder<char*, false>::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder<int8_t(int32_t*, void*), false>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(int32_t*, char*, ...), false>::get())); + params.push_back(TypeBuilder<char, false>::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder<int8_t(int32_t*, void*, char), false>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(int32_t*, char*, char, ...), false>::get())); + params.push_back(TypeBuilder<char, false>::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder<int8_t(int32_t*, void*, char, char), false>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(int32_t*, char*, char, char, ...), + false>::get())); + params.push_back(TypeBuilder<char, false>::get()); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, false), + (TypeBuilder<int8_t(int32_t*, void*, char, char, char), + false>::get())); + EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + (TypeBuilder<int8_t(int32_t*, char*, char, char, char, ...), + false>::get())); +} + +class MyType { + int a; + int *b; + void *array[1]; +}; + +class MyPortableType { + int32_t a; + int32_t *b; + void *array[1]; +}; + +} // anonymous namespace + +namespace llvm { +template<bool cross> class TypeBuilder<MyType, cross> { +public: + static const StructType *get() { + // Using the static result variable ensures that the type is + // only looked up once. + static const StructType *const result = StructType::get( + TypeBuilder<int, cross>::get(), + TypeBuilder<int*, cross>::get(), + TypeBuilder<void*[], cross>::get(), + NULL); + return result; + } + + // You may find this a convenient place to put some constants + // to help with getelementptr. They don't have any effect on + // the operation of TypeBuilder. + enum Fields { + FIELD_A, + FIELD_B, + FIELD_ARRAY + }; +}; + +template<bool cross> class TypeBuilder<MyPortableType, cross> { +public: + static const StructType *get() { + // Using the static result variable ensures that the type is + // only looked up once. + static const StructType *const result = StructType::get( + TypeBuilder<types::i<32>, cross>::get(), + TypeBuilder<types::i<32>*, cross>::get(), + TypeBuilder<types::i<8>*[], cross>::get(), + NULL); + return result; + } + + // You may find this a convenient place to put some constants + // to help with getelementptr. They don't have any effect on + // the operation of TypeBuilder. + enum Fields { + FIELD_A, + FIELD_B, + FIELD_ARRAY + }; +}; +} // namespace llvm +namespace { + +TEST(TypeBuilderTest, Extensions) { + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder<int, false>::get(), + TypeBuilder<int*, false>::get(), + TypeBuilder<void*[], false>::get(), + NULL)), + (TypeBuilder<MyType*, false>::get())); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder<types::i<32>, false>::get(), + TypeBuilder<types::i<32>*, false>::get(), + TypeBuilder<types::i<8>*[], false>::get(), + NULL)), + (TypeBuilder<MyPortableType*, false>::get())); + EXPECT_EQ(PointerType::getUnqual(StructType::get( + TypeBuilder<types::i<32>, false>::get(), + TypeBuilder<types::i<32>*, false>::get(), + TypeBuilder<types::i<8>*[], false>::get(), + NULL)), + (TypeBuilder<MyPortableType*, true>::get())); +} + +} // anonymous namespace diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp new file mode 100644 index 0000000..336e7d9 --- /dev/null +++ b/unittests/Support/ValueHandleTest.cpp @@ -0,0 +1,317 @@ +//===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle 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/ValueHandle.h" + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +#include "gtest/gtest.h" + +#include <memory> + +using namespace llvm; + +namespace { + +class ValueHandle : public testing::Test { +protected: + Constant *ConstantV; + std::auto_ptr<BitCastInst> BitcastV; + + ValueHandle() : ConstantV(ConstantInt::get(Type::Int32Ty, 0)), + BitcastV(new BitCastInst(ConstantV, Type::Int32Ty)) { + } +}; + +class ConcreteCallbackVH : public CallbackVH { +public: + ConcreteCallbackVH() : CallbackVH() {} + ConcreteCallbackVH(Value *V) : CallbackVH(V) {} +}; + +TEST_F(ValueHandle, WeakVH_BasicOperation) { + WeakVH WVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), WVH); + WVH = ConstantV; + EXPECT_EQ(ConstantV, WVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::Int32Ty, WVH->getType()); + EXPECT_EQ(Type::Int32Ty, (*WVH).getType()); +} + +TEST_F(ValueHandle, WeakVH_Comparisons) { + WeakVH BitcastWVH(BitcastV.get()); + WeakVH ConstantWVH(ConstantV); + + EXPECT_TRUE(BitcastWVH == BitcastWVH); + EXPECT_TRUE(BitcastV.get() == BitcastWVH); + EXPECT_TRUE(BitcastWVH == BitcastV.get()); + EXPECT_FALSE(BitcastWVH == ConstantWVH); + + EXPECT_TRUE(BitcastWVH != ConstantWVH); + EXPECT_TRUE(BitcastV.get() != ConstantWVH); + EXPECT_TRUE(BitcastWVH != ConstantV); + EXPECT_FALSE(BitcastWVH != BitcastWVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); +} + +TEST_F(ValueHandle, WeakVH_FollowsRAUW) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, WVH); + EXPECT_EQ(ConstantV, WVH_Copy); + EXPECT_EQ(ConstantV, WVH_Recreated); +} + +TEST_F(ValueHandle, WeakVH_NullOnDeletion) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV.reset(); + Value *null_value = NULL; + EXPECT_EQ(null_value, WVH); + EXPECT_EQ(null_value, WVH_Copy); + EXPECT_EQ(null_value, WVH_Recreated); +} + + +TEST_F(ValueHandle, AssertingVH_BasicOperation) { + AssertingVH<CastInst> AVH(BitcastV.get()); + CastInst *implicit_to_exact_type = AVH; + implicit_to_exact_type = implicit_to_exact_type; // Avoid warning. + + AssertingVH<Value> GenericAVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), GenericAVH); + GenericAVH = ConstantV; + EXPECT_EQ(ConstantV, GenericAVH); + + // Make sure I can call a method on the underlying CastInst. It + // doesn't matter which method. + EXPECT_FALSE(AVH->mayWriteToMemory()); + EXPECT_FALSE((*AVH).mayWriteToMemory()); +} + +TEST_F(ValueHandle, AssertingVH_Comparisons) { + AssertingVH<Value> BitcastAVH(BitcastV.get()); + AssertingVH<Value> ConstantAVH(ConstantV); + + EXPECT_TRUE(BitcastAVH == BitcastAVH); + EXPECT_TRUE(BitcastV.get() == BitcastAVH); + EXPECT_TRUE(BitcastAVH == BitcastV.get()); + EXPECT_FALSE(BitcastAVH == ConstantAVH); + + EXPECT_TRUE(BitcastAVH != ConstantAVH); + EXPECT_TRUE(BitcastV.get() != ConstantAVH); + EXPECT_TRUE(BitcastAVH != ConstantV); + EXPECT_FALSE(BitcastAVH != BitcastAVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); +} + +TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { + AssertingVH<Value> AVH(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(BitcastV.get(), AVH); +} + +#ifdef NDEBUG + +TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { + EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>)); +} + +#else // !NDEBUG + +#ifdef GTEST_HAS_DEATH_TEST + +TEST_F(ValueHandle, AssertingVH_Asserts) { + AssertingVH<Value> AVH(BitcastV.get()); + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + AssertingVH<Value> Copy(AVH); + AVH = NULL; + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + Copy = NULL; + BitcastV.reset(); +} + +#endif // GTEST_HAS_DEATH_TEST + +#endif // NDEBUG + +TEST_F(ValueHandle, CallbackVH_BasicOperation) { + ConcreteCallbackVH CVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), CVH); + CVH = ConstantV; + EXPECT_EQ(ConstantV, CVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::Int32Ty, CVH->getType()); + EXPECT_EQ(Type::Int32Ty, (*CVH).getType()); +} + +TEST_F(ValueHandle, CallbackVH_Comparisons) { + ConcreteCallbackVH BitcastCVH(BitcastV.get()); + ConcreteCallbackVH ConstantCVH(ConstantV); + + EXPECT_TRUE(BitcastCVH == BitcastCVH); + EXPECT_TRUE(BitcastV.get() == BitcastCVH); + EXPECT_TRUE(BitcastCVH == BitcastV.get()); + EXPECT_FALSE(BitcastCVH == ConstantCVH); + + EXPECT_TRUE(BitcastCVH != ConstantCVH); + EXPECT_TRUE(BitcastV.get() != ConstantCVH); + EXPECT_TRUE(BitcastCVH != ConstantV); + EXPECT_FALSE(BitcastCVH != BitcastCVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + int AURWCalls; + + RecordingVH() : DeletedCalls(0), AURWCalls(0) {} + RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *) { AURWCalls++; } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); + BitcastV.reset(); + EXPECT_EQ(1, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + + RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecordingVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *new_value) { + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(NULL, RVH.AURWArgument); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(ConstantV, RVH.AURWArgument); +} + +TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { + class RecoveringVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecoveringVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + + private: + virtual void deleted() { + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::Int32Ty)); + setValPtr(NULL); + } + virtual void allUsesReplacedWith(Value *new_value) { + ASSERT_TRUE(NULL != getValPtr()); + EXPECT_EQ(1U, getValPtr()->getNumUses()); + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + // Normally, if a value has uses, deleting it will crash. However, we can use + // a CallbackVH to remove the uses before the check for no uses. + RecoveringVH RVH; + RVH = BitcastV.get(); + std::auto_ptr<BinaryOperator> BitcastUser( + BinaryOperator::CreateAdd(RVH, Constant::getNullValue(Type::Int32Ty))); + EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); + BitcastV.reset(); // Would crash without the ValueHandler. + EXPECT_EQ(Constant::getNullValue(Type::Int32Ty), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::Int32Ty), BitcastUser->getOperand(0)); +} + +} diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp new file mode 100644 index 0000000..feb0152 --- /dev/null +++ b/unittests/Support/raw_ostream_test.cpp @@ -0,0 +1,85 @@ +//===- llvm/unittest/Support/raw_ostream_test.cpp - raw_ostream 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/raw_ostream.h" + +using namespace llvm; + +namespace { + +template<typename T> std::string printToString(const T &Value) { + std::string res; + llvm::raw_string_ostream(res) << Value; + return res; +} + +template<typename T> std::string printToStringUnbuffered(const T &Value) { + std::string res; + llvm::raw_string_ostream OS(res); + OS.SetUnbuffered(); + OS << Value; + return res; +} + +TEST(raw_ostreamTest, Types_Buffered) { + // Char + EXPECT_EQ("c", printToString('c')); + + // String + EXPECT_EQ("hello", printToString("hello")); + EXPECT_EQ("hello", printToString(std::string("hello"))); + + // Int + EXPECT_EQ("0", printToString(0)); + EXPECT_EQ("2425", printToString(2425)); + EXPECT_EQ("-2425", printToString(-2425)); + + // Long long + EXPECT_EQ("0", printToString(0LL)); + EXPECT_EQ("257257257235709", printToString(257257257235709LL)); + EXPECT_EQ("-257257257235709", printToString(-257257257235709LL)); + + // Double + EXPECT_EQ("1.100000e+00", printToString(1.1)); + + // void* + EXPECT_EQ("0x0", printToString((void*) 0)); + EXPECT_EQ("0xbeef", printToString((void*) 0xbeef)); + EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef)); +} + +TEST(raw_ostreamTest, Types_Unbuffered) { + // Char + EXPECT_EQ("c", printToStringUnbuffered('c')); + + // String + EXPECT_EQ("hello", printToStringUnbuffered("hello")); + EXPECT_EQ("hello", printToStringUnbuffered(std::string("hello"))); + + // Int + EXPECT_EQ("0", printToStringUnbuffered(0)); + EXPECT_EQ("2425", printToStringUnbuffered(2425)); + EXPECT_EQ("-2425", printToStringUnbuffered(-2425)); + + // Long long + EXPECT_EQ("0", printToStringUnbuffered(0LL)); + EXPECT_EQ("257257257235709", printToStringUnbuffered(257257257235709LL)); + EXPECT_EQ("-257257257235709", printToStringUnbuffered(-257257257235709LL)); + + // Double + EXPECT_EQ("1.100000e+00", printToStringUnbuffered(1.1)); + + // void* + EXPECT_EQ("0x0", printToStringUnbuffered((void*) 0)); + EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef)); + EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef)); +} + +} |