diff options
Diffstat (limited to 'unittests/Support')
-rw-r--r-- | unittests/Support/AllocatorTest.cpp | 143 | ||||
-rw-r--r-- | unittests/Support/CommandLineTest.cpp | 60 | ||||
-rw-r--r-- | unittests/Support/ConstantRangeTest.cpp | 351 | ||||
-rw-r--r-- | unittests/Support/MathExtrasTest.cpp | 2 | ||||
-rw-r--r-- | unittests/Support/RegexTest.cpp | 65 | ||||
-rw-r--r-- | unittests/Support/TypeBuilderTest.cpp | 281 | ||||
-rw-r--r-- | unittests/Support/ValueHandleTest.cpp | 118 | ||||
-rw-r--r-- | unittests/Support/raw_ostream_test.cpp | 45 |
8 files changed, 918 insertions, 147 deletions
diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp new file mode 100644 index 0000000..2a01f3a --- /dev/null +++ b/unittests/Support/AllocatorTest.cpp @@ -0,0 +1,143 @@ +//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator 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/Allocator.h" + +#include "gtest/gtest.h" +#include <cstdlib> + +using namespace llvm; + +namespace { + +TEST(AllocatorTest, Basics) { + BumpPtrAllocator Alloc; + int *a = (int*)Alloc.Allocate(sizeof(int), 0); + int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); + int *c = (int*)Alloc.Allocate(sizeof(int), 0); + *a = 1; + b[0] = 2; + b[9] = 2; + *c = 3; + EXPECT_EQ(1, *a); + EXPECT_EQ(2, b[0]); + EXPECT_EQ(2, b[9]); + EXPECT_EQ(3, *c); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Allocate enough bytes to create three slabs. +TEST(AllocatorTest, ThreeSlabs) { + BumpPtrAllocator Alloc(4096, 4096); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(3U, Alloc.GetNumSlabs()); +} + +// Allocate enough bytes to create two slabs, reset the allocator, and do it +// again. +TEST(AllocatorTest, TestReset) { + BumpPtrAllocator Alloc(4096, 4096); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); + Alloc.Reset(); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + Alloc.Allocate(3000, 0); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); +} + +// Test some allocations at varying alignments. +TEST(AllocatorTest, TestAlignment) { + BumpPtrAllocator Alloc; + uintptr_t a; + a = (uintptr_t)Alloc.Allocate(1, 2); + EXPECT_EQ(0U, a & 1); + a = (uintptr_t)Alloc.Allocate(1, 4); + EXPECT_EQ(0U, a & 3); + a = (uintptr_t)Alloc.Allocate(1, 8); + EXPECT_EQ(0U, a & 7); + a = (uintptr_t)Alloc.Allocate(1, 16); + EXPECT_EQ(0U, a & 15); + a = (uintptr_t)Alloc.Allocate(1, 32); + EXPECT_EQ(0U, a & 31); + a = (uintptr_t)Alloc.Allocate(1, 64); + EXPECT_EQ(0U, a & 63); + a = (uintptr_t)Alloc.Allocate(1, 128); + EXPECT_EQ(0U, a & 127); +} + +// 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); + + // Fill the slab right up until the end pointer. + Alloc.Allocate(4096 - sizeof(MemSlab), 0); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); + + // If we dont't allocate a new slab, then we will have overflowed. + Alloc.Allocate(1, 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; + +public: + virtual ~MockSlabAllocator() { } + + virtual MemSlab *Allocate(size_t Size) { + // 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; + + // Hold a pointer to the base so we can free the whole malloced block. + ((void**)Slab)[-1] = MemBase; + + LastSlab = Slab; + return Slab; + } + + virtual void Deallocate(MemSlab *Slab) { + free(((void**)Slab)[-1]); + } + + MemSlab *GetLastSlab() { + return LastSlab; + } +}; + +// 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); +} + +} // anonymous namespace diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp new file mode 100644 index 0000000..72fa24a --- /dev/null +++ b/unittests/Support/CommandLineTest.cpp @@ -0,0 +1,60 @@ +//===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine 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/CommandLine.h" +#include "llvm/Config/config.h" + +#include "gtest/gtest.h" + +#include <string> +#include <stdlib.h> + +using namespace llvm; + +namespace { + +class TempEnvVar { + public: + TempEnvVar(const char *name, const char *value) + : name(name) { + const char *old_value = getenv(name); + EXPECT_EQ(NULL, old_value) << old_value; +#if HAVE_SETENV + setenv(name, value, true); +#else +# define SKIP_ENVIRONMENT_TESTS +#endif + } + + ~TempEnvVar() { +#if HAVE_SETENV + // Assume setenv and unsetenv come together. + unsetenv(name); +#endif + } + + private: + const char *const name; +}; + +#ifndef SKIP_ENVIRONMENT_TESTS + +const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS"; + +cl::opt<std::string> EnvironmentTestOption("env-test-opt"); +TEST(CommandLineTest, ParseEnvironment) { + TempEnvVar TEV(test_env_var, "-env-test-opt=hello"); + EXPECT_EQ("", EnvironmentTestOption); + cl::ParseEnvironmentOptions("CommandLineTest", test_env_var); + EXPECT_EQ("hello", EnvironmentTestOption); +} + +#endif // SKIP_ENVIRONMENT_TESTS + +} // anonymous namespace diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp new file mode 100644 index 0000000..6b8d01d --- /dev/null +++ b/unittests/Support/ConstantRangeTest.cpp @@ -0,0 +1,351 @@ +//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange 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/ConstantRange.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class ConstantRangeTest : public ::testing::Test { +protected: + static ConstantRange Full; + static ConstantRange Empty; + static ConstantRange One; + static ConstantRange Some; + static ConstantRange Wrap; +}; + +ConstantRange ConstantRangeTest::Full(16); +ConstantRange ConstantRangeTest::Empty(16, false); +ConstantRange ConstantRangeTest::One(APInt(16, 0xa)); +ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa)); +ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa)); + +TEST_F(ConstantRangeTest, Basics) { + EXPECT_TRUE(Full.isFullSet()); + EXPECT_FALSE(Full.isEmptySet()); + EXPECT_FALSE(Full.isWrappedSet()); + EXPECT_TRUE(Full.contains(APInt(16, 0x0))); + EXPECT_TRUE(Full.contains(APInt(16, 0x9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xa))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Empty.isFullSet()); + EXPECT_TRUE(Empty.isEmptySet()); + EXPECT_FALSE(Empty.isWrappedSet()); + EXPECT_FALSE(Empty.contains(APInt(16, 0x0))); + EXPECT_FALSE(Empty.contains(APInt(16, 0x9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xa))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(One.isFullSet()); + EXPECT_FALSE(One.isEmptySet()); + EXPECT_FALSE(One.isWrappedSet()); + EXPECT_FALSE(One.contains(APInt(16, 0x0))); + EXPECT_FALSE(One.contains(APInt(16, 0x9))); + EXPECT_TRUE(One.contains(APInt(16, 0xa))); + EXPECT_FALSE(One.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(One.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Some.isFullSet()); + EXPECT_FALSE(Some.isEmptySet()); + EXPECT_FALSE(Some.isWrappedSet()); + EXPECT_FALSE(Some.contains(APInt(16, 0x0))); + EXPECT_FALSE(Some.contains(APInt(16, 0x9))); + EXPECT_TRUE(Some.contains(APInt(16, 0xa))); + EXPECT_TRUE(Some.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Some.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Wrap.isFullSet()); + EXPECT_FALSE(Wrap.isEmptySet()); + EXPECT_TRUE(Wrap.isWrappedSet()); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x0))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x9))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xa))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa))); +} + +TEST_F(ConstantRangeTest, Equality) { + EXPECT_EQ(Full, Full); + EXPECT_EQ(Empty, Empty); + EXPECT_EQ(One, One); + EXPECT_EQ(Some, Some); + EXPECT_EQ(Wrap, Wrap); + EXPECT_NE(Full, Empty); + EXPECT_NE(Full, One); + EXPECT_NE(Full, Some); + EXPECT_NE(Full, Wrap); + EXPECT_NE(Empty, One); + EXPECT_NE(Empty, Some); + EXPECT_NE(Empty, Wrap); + EXPECT_NE(One, Some); + EXPECT_NE(One, Wrap); + EXPECT_NE(Some, Wrap); +} + +TEST_F(ConstantRangeTest, SingleElement) { + EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL)); + EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL)); + + EXPECT_FALSE(Full.isSingleElement()); + EXPECT_FALSE(Empty.isSingleElement()); + EXPECT_TRUE(One.isSingleElement()); + EXPECT_FALSE(Some.isSingleElement()); + EXPECT_FALSE(Wrap.isSingleElement()); +} + +TEST_F(ConstantRangeTest, GetSetSize) { + EXPECT_EQ(Full.getSetSize(), APInt(16, 0)); + EXPECT_EQ(Empty.getSetSize(), APInt(16, 0)); + EXPECT_EQ(One.getSetSize(), APInt(16, 1)); + EXPECT_EQ(Some.getSetSize(), APInt(16, 0xaa0)); + EXPECT_EQ(Wrap.getSetSize(), APInt(16, 0x10000 - 0xaa0)); +} + +TEST_F(ConstantRangeTest, GetMinsAndMaxes) { + EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX)); + EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX)); + + EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0)); + EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0)); + + EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX)); + EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX)); + + EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + + // Found by Klee + EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(), + APInt(4, 7)); +} + +TEST_F(ConstantRangeTest, Trunc) { + ConstantRange TFull = Full.truncate(10); + ConstantRange TEmpty = Empty.truncate(10); + ConstantRange TOne = One.truncate(10); + ConstantRange TSome = Some.truncate(10); + ConstantRange TWrap = Wrap.truncate(10); + EXPECT_TRUE(TFull.isFullSet()); + EXPECT_TRUE(TEmpty.isEmptySet()); + EXPECT_EQ(TOne, ConstantRange(APInt(One.getLower()).trunc(10), + APInt(One.getUpper()).trunc(10))); + EXPECT_TRUE(TSome.isFullSet()); +} + +TEST_F(ConstantRangeTest, ZExt) { + ConstantRange ZFull = Full.zeroExtend(20); + ConstantRange ZEmpty = Empty.zeroExtend(20); + ConstantRange ZOne = One.zeroExtend(20); + ConstantRange ZSome = Some.zeroExtend(20); + ConstantRange ZWrap = Wrap.zeroExtend(20); + EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + EXPECT_TRUE(ZEmpty.isEmptySet()); + EXPECT_EQ(ZOne, ConstantRange(APInt(One.getLower()).zext(20), + APInt(One.getUpper()).zext(20))); + EXPECT_EQ(ZSome, ConstantRange(APInt(Some.getLower()).zext(20), + APInt(Some.getUpper()).zext(20))); + EXPECT_EQ(ZWrap, ConstantRange(APInt(Wrap.getLower()).zext(20), + APInt(Wrap.getUpper()).zext(20))); +} + +TEST_F(ConstantRangeTest, SExt) { + ConstantRange SFull = Full.signExtend(20); + ConstantRange SEmpty = Empty.signExtend(20); + ConstantRange SOne = One.signExtend(20); + ConstantRange SSome = Some.signExtend(20); + ConstantRange SWrap = Wrap.signExtend(20); + EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + EXPECT_TRUE(SEmpty.isEmptySet()); + EXPECT_EQ(SOne, ConstantRange(APInt(One.getLower()).sext(20), + APInt(One.getUpper()).sext(20))); + EXPECT_EQ(SSome, ConstantRange(APInt(Some.getLower()).sext(20), + APInt(Some.getUpper()).sext(20))); + EXPECT_EQ(SWrap, ConstantRange(APInt(Wrap.getLower()).sext(20), + APInt(Wrap.getUpper()).sext(20))); +} + +TEST_F(ConstantRangeTest, IntersectWith) { + EXPECT_EQ(Empty.intersectWith(Full), Empty); + EXPECT_EQ(Empty.intersectWith(Empty), Empty); + EXPECT_EQ(Empty.intersectWith(One), Empty); + EXPECT_EQ(Empty.intersectWith(Some), Empty); + EXPECT_EQ(Empty.intersectWith(Wrap), Empty); + EXPECT_EQ(Full.intersectWith(Full), Full); + EXPECT_EQ(Some.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One)); + + // Klee generated testcase from PR4545. + // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like + // 01..4.6789ABCDEF where the dots represent values not in the intersection. + ConstantRange LHS(APInt(16, 4), APInt(16, 2)); + ConstantRange RHS(APInt(16, 6), APInt(16, 5)); + EXPECT_TRUE(LHS.intersectWith(RHS) == LHS); +} + +TEST_F(ConstantRangeTest, UnionWith) { + EXPECT_EQ(Wrap.unionWith(One), + ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb))); + EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One)); + EXPECT_EQ(Empty.unionWith(Empty), Empty); + EXPECT_EQ(Full.unionWith(Full), Full); + EXPECT_EQ(Some.unionWith(Wrap), Full); + + // PR4545 + EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith( + ConstantRange(APInt(16, 0), APInt(16, 8))), + ConstantRange(APInt(16, 14), APInt(16, 8))); + EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith( + ConstantRange(APInt(16, 4), APInt(16, 0))), + ConstantRange(16)); + EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith( + ConstantRange(APInt(16, 2), APInt(16, 1))), + ConstantRange(16)); +} + +TEST_F(ConstantRangeTest, SubtractAPInt) { + EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); + EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty); + EXPECT_EQ(Some.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Wrap.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Add) { + EXPECT_EQ(Full.add(APInt(16, 4)), Full); + EXPECT_EQ(Full.add(Full), Full); + EXPECT_EQ(Full.add(Empty), Empty); + EXPECT_EQ(Full.add(One), Full); + EXPECT_EQ(Full.add(Some), Full); + EXPECT_EQ(Full.add(Wrap), Full); + EXPECT_EQ(Empty.add(Empty), Empty); + EXPECT_EQ(Empty.add(One), Empty); + EXPECT_EQ(Empty.add(Some), Empty); + EXPECT_EQ(Empty.add(Wrap), Empty); + EXPECT_EQ(Empty.add(APInt(16, 4)), Empty); + EXPECT_EQ(Some.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe), APInt(16, 0xaae))); + EXPECT_EQ(Wrap.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xaae), APInt(16, 0xe))); + EXPECT_EQ(One.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe))); +} + +TEST_F(ConstantRangeTest, Multiply) { + EXPECT_EQ(Full.multiply(Full), Full); + EXPECT_EQ(Full.multiply(Empty), Empty); + EXPECT_EQ(Full.multiply(One), Full); + EXPECT_EQ(Full.multiply(Some), Full); + EXPECT_EQ(Full.multiply(Wrap), Full); + EXPECT_EQ(Empty.multiply(Empty), Empty); + EXPECT_EQ(Empty.multiply(One), Empty); + EXPECT_EQ(Empty.multiply(Some), Empty); + EXPECT_EQ(Empty.multiply(Wrap), Empty); + EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xa + 1))); + EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xaa9 + 1))); + EXPECT_EQ(One.multiply(Wrap), Full); + EXPECT_EQ(Some.multiply(Some), Full); + EXPECT_EQ(Some.multiply(Wrap), Full); + EXPECT_EQ(Wrap.multiply(Wrap), Full); + + // http://llvm.org/PR4545 + EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply( + ConstantRange(APInt(4, 6), APInt(4, 2))), + ConstantRange(4, /*isFullSet=*/true)); +} + +TEST_F(ConstantRangeTest, UMax) { + EXPECT_EQ(Full.umax(Full), Full); + EXPECT_EQ(Full.umax(Empty), Empty); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Full.umax(Wrap), Full); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Empty.umax(Empty), Empty); + EXPECT_EQ(Empty.umax(Some), Empty); + EXPECT_EQ(Empty.umax(Wrap), Empty); + EXPECT_EQ(Empty.umax(One), Empty); + EXPECT_EQ(Some.umax(Some), Some); + EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Some.umax(One), Some); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.umax(Wrap), Full); + EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(One.umax(One), One); +} + +TEST_F(ConstantRangeTest, SMax) { + EXPECT_EQ(Full.smax(Full), Full); + EXPECT_EQ(Full.smax(Empty), Empty); + EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Full.smax(Wrap), Full); + EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Empty.smax(Empty), Empty); + EXPECT_EQ(Empty.smax(Some), Empty); + EXPECT_EQ(Empty.smax(Wrap), Empty); + EXPECT_EQ(Empty.smax(One), Empty); + EXPECT_EQ(Some.smax(Some), Some); + EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(Some.smax(One), Some); + EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(One.smax(One), One); +} + +TEST_F(ConstantRangeTest, UDiv) { + EXPECT_EQ(Full.udiv(Full), Full); + EXPECT_EQ(Full.udiv(Empty), Empty); + EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Wrap), Full); + EXPECT_EQ(Empty.udiv(Empty), Empty); + EXPECT_EQ(Empty.udiv(One), Empty); + EXPECT_EQ(Empty.udiv(Some), Empty); + EXPECT_EQ(Empty.udiv(Wrap), Empty); + EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1))); + EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2))); + EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111))); + EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.udiv(Wrap), Full); +} + +} // anonymous namespace diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index 1f19468..3db1f77 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/MathExtrasTest.cpp - math utils tests --------===// +//===- unittests/Support/MathExtrasTest.cpp - math utils tests ------------===// // // The LLVM Compiler Infrastructure // diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp new file mode 100644 index 0000000..44c7e55 --- /dev/null +++ b/unittests/Support/RegexTest.cpp @@ -0,0 +1,65 @@ +//===- llvm/unittest/Support/RegexTest.cpp - Regex 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/Regex.h" +#include "llvm/ADT/SmallVector.h" +#include <cstring> + +using namespace llvm; +namespace { + +class RegexTest : public ::testing::Test { +}; + +TEST_F(RegexTest, Basics) { + Regex r1("^[0-9]+$"); + EXPECT_TRUE(r1.match("916")); + EXPECT_TRUE(r1.match("9")); + EXPECT_FALSE(r1.match("9a")); + + SmallVector<StringRef, 1> Matches; + Regex r2("[0-9]+"); + EXPECT_TRUE(r2.match("aa216b", &Matches)); + EXPECT_EQ(1u, Matches.size()); + EXPECT_EQ("216", Matches[0].str()); + + Regex r3("[0-9]+([a-f])?:([0-9]+)"); + EXPECT_TRUE(r3.match("9a:513b", &Matches)); + EXPECT_EQ(3u, Matches.size()); + EXPECT_EQ("9a:513", Matches[0].str()); + EXPECT_EQ("a", Matches[1].str()); + EXPECT_EQ("513", Matches[2].str()); + + EXPECT_TRUE(r3.match("9:513b", &Matches)); + EXPECT_EQ(3u, Matches.size()); + EXPECT_EQ("9:513", Matches[0].str()); + EXPECT_EQ("", Matches[1].str()); + EXPECT_EQ("513", Matches[2].str()); + + Regex r4("a[^b]+b"); + std::string String="axxb"; + String[2] = '\0'; + EXPECT_FALSE(r4.match("abb")); + EXPECT_TRUE(r4.match(String, &Matches)); + EXPECT_EQ(1u, Matches.size()); + EXPECT_EQ(String, Matches[0].str()); + + + std::string NulPattern="X[0-9]+X([a-f])?:([0-9]+)"; + String="YX99a:513b"; + NulPattern[7] = '\0'; + Regex r5(NulPattern); + EXPECT_FALSE(r5.match(String)); + EXPECT_FALSE(r5.match("X9")); + String[3]='\0'; + EXPECT_TRUE(r5.match(String)); +} + +} diff --git a/unittests/Support/TypeBuilderTest.cpp b/unittests/Support/TypeBuilderTest.cpp index 425ee6b..a5c5e67 100644 --- a/unittests/Support/TypeBuilderTest.cpp +++ b/unittests/Support/TypeBuilderTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/TypeBuilder.h" +#include "llvm/LLVMContext.h" #include "gtest/gtest.h" @@ -16,134 +17,146 @@ using namespace llvm; namespace { TEST(TypeBuilderTest, Void) { - EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, true>::get())); - EXPECT_EQ(Type::VoidTy, (TypeBuilder<void, false>::get())); + EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, false>::get(getGlobalContext()))); // Special case for C compatibility: - EXPECT_EQ(PointerType::getUnqual(Type::Int8Ty), - (TypeBuilder<void*, false>::get())); + EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()), + (TypeBuilder<void*, false>::get(getGlobalContext()))); } 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())); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<uint8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<int16_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<uint16_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<int32_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<uint32_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<int64_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<uint64_t, false>::get(getGlobalContext()))); + + EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(size_t) * CHAR_BIT), + (TypeBuilder<size_t, false>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(ptrdiff_t) * CHAR_BIT), + (TypeBuilder<ptrdiff_t, false>::get(getGlobalContext()))); } 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())); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, true>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, false>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, true>::get(getGlobalContext()))); + EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, false>::get(getGlobalContext()))); } TEST(TypeBuilderTest, Float) { - EXPECT_EQ(Type::FloatTy, (TypeBuilder<float, false>::get())); - EXPECT_EQ(Type::DoubleTy, (TypeBuilder<double, false>::get())); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<float, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<double, false>::get(getGlobalContext()))); // 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())); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, false>::get(getGlobalContext()))); } 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())); + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<int8_t**, false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<int8_t[7], false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<int8_t[], false>::get(getGlobalContext()))); + + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<types::i<8>**, false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<types::i<8>[7], false>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<types::i<8>[], false>::get(getGlobalContext()))); + + EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())), + (TypeBuilder<types::i<8>**, true>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7), + (TypeBuilder<types::i<8>[7], true>::get(getGlobalContext()))); + EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0), + (TypeBuilder<types::i<8>[], true>::get(getGlobalContext()))); + + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile int8_t, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile int8_t, false>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const types::i<8>, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile types::i<8>, false>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile types::i<8>, false>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const types::i<8>, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<volatile types::i<8>, true>::get(getGlobalContext()))); + EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), + (TypeBuilder<const volatile types::i<8>, true>::get(getGlobalContext()))); + + EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()), + (TypeBuilder<const volatile int8_t*const volatile, false>::get(getGlobalContext()))); } 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), + EXPECT_EQ(FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false), + (TypeBuilder<void(), true>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<int32_t*, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(const int32_t*), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(const int32_t*, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char*, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(int32_t*, char*, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*, char), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), + (TypeBuilder<int8_t(int32_t*, char*, char, ...), false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), + (TypeBuilder<int8_t(int32_t*, void*, char, char), false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), 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), + false>::get(getGlobalContext()))); + params.push_back(TypeBuilder<char, false>::get(getGlobalContext())); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false), (TypeBuilder<int8_t(int32_t*, void*, char, char, char), - false>::get())); - EXPECT_EQ(FunctionType::get(Type::Int8Ty, params, true), + false>::get(getGlobalContext()))); + EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true), (TypeBuilder<int8_t(int32_t*, char*, char, char, char, ...), - false>::get())); + false>::get(getGlobalContext()))); +} + +TEST(TypeBuilderTest, Context) { + // We used to cache TypeBuilder results in static local variables. This + // produced the same type for different contexts, which of course broke + // things. + LLVMContext context1; + EXPECT_EQ(&context1, + &(TypeBuilder<types::i<1>, true>::get(context1))->getContext()); + LLVMContext context2; + EXPECT_EQ(&context2, + &(TypeBuilder<types::i<1>, true>::get(context2))->getContext()); } class MyType { @@ -163,14 +176,14 @@ class MyPortableType { namespace llvm { template<bool cross> class TypeBuilder<MyType, cross> { public: - static const StructType *get() { + static const StructType *get(LLVMContext &Context) { // 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); + std::vector<const Type*> st; + st.push_back(TypeBuilder<int, cross>::get(Context)); + st.push_back(TypeBuilder<int*, cross>::get(Context)); + st.push_back(TypeBuilder<void*[], cross>::get(Context)); + static const StructType *const result = StructType::get(Context, st); return result; } @@ -186,14 +199,14 @@ public: template<bool cross> class TypeBuilder<MyPortableType, cross> { public: - static const StructType *get() { + static const StructType *get(LLVMContext &Context) { // 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); + std::vector<const Type*> st; + st.push_back(TypeBuilder<types::i<32>, cross>::get(Context)); + st.push_back(TypeBuilder<types::i<32>*, cross>::get(Context)); + st.push_back(TypeBuilder<types::i<8>*[], cross>::get(Context)); + static const StructType *const result = StructType::get(Context, st); return result; } @@ -210,24 +223,24 @@ public: namespace { TEST(TypeBuilderTest, Extensions) { - EXPECT_EQ(PointerType::getUnqual(StructType::get( - TypeBuilder<int, false>::get(), - TypeBuilder<int*, false>::get(), - TypeBuilder<void*[], false>::get(), + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<int, false>::get(getGlobalContext()), + TypeBuilder<int*, false>::get(getGlobalContext()), + TypeBuilder<void*[], false>::get(getGlobalContext()), 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(), + (TypeBuilder<MyType*, false>::get(getGlobalContext()))); + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<types::i<32>, false>::get(getGlobalContext()), + TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), + TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), 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(), + (TypeBuilder<MyPortableType*, false>::get(getGlobalContext()))); + EXPECT_EQ(PointerType::getUnqual(StructType::get(getGlobalContext(), + TypeBuilder<types::i<32>, false>::get(getGlobalContext()), + TypeBuilder<types::i<32>*, false>::get(getGlobalContext()), + TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()), NULL)), - (TypeBuilder<MyPortableType*, true>::get())); + (TypeBuilder<MyPortableType*, true>::get(getGlobalContext()))); } } // anonymous namespace diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp index 336e7d9..c89a7af 100644 --- a/unittests/Support/ValueHandleTest.cpp +++ b/unittests/Support/ValueHandleTest.cpp @@ -11,6 +11,7 @@ #include "llvm/Constants.h" #include "llvm/Instructions.h" +#include "llvm/ADT/OwningPtr.h" #include "gtest/gtest.h" @@ -25,8 +26,9 @@ protected: Constant *ConstantV; std::auto_ptr<BitCastInst> BitcastV; - ValueHandle() : ConstantV(ConstantInt::get(Type::Int32Ty, 0)), - BitcastV(new BitCastInst(ConstantV, Type::Int32Ty)) { + ValueHandle() : + ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), + BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { } }; @@ -44,8 +46,8 @@ TEST_F(ValueHandle, WeakVH_BasicOperation) { // 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()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); } TEST_F(ValueHandle, WeakVH_Comparisons) { @@ -119,6 +121,13 @@ TEST_F(ValueHandle, AssertingVH_BasicOperation) { EXPECT_FALSE((*AVH).mayWriteToMemory()); } +TEST_F(ValueHandle, AssertingVH_Const) { + const CastInst *ConstBitcast = BitcastV.get(); + AssertingVH<const CastInst> AVH(ConstBitcast); + const CastInst *implicit_to_exact_type = AVH; + implicit_to_exact_type = implicit_to_exact_type; // Avoid warning. +} + TEST_F(ValueHandle, AssertingVH_Comparisons) { AssertingVH<Value> BitcastAVH(BitcastV.get()); AssertingVH<Value> ConstantAVH(ConstantV); @@ -192,8 +201,8 @@ TEST_F(ValueHandle, CallbackVH_BasicOperation) { // 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()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); } TEST_F(ValueHandle, CallbackVH_Comparisons) { @@ -284,14 +293,17 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { public: int DeletedCalls; Value *AURWArgument; + LLVMContext *Context; - RecoveringVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} RecoveringVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} private: virtual void deleted() { - getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::Int32Ty)); + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); setValPtr(NULL); } virtual void allUsesReplacedWith(Value *new_value) { @@ -307,11 +319,93 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { RecoveringVH RVH; RVH = BitcastV.get(); std::auto_ptr<BinaryOperator> BitcastUser( - BinaryOperator::CreateAdd(RVH, Constant::getNullValue(Type::Int32Ty))); + BinaryOperator::CreateAdd(RVH, + Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); 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)); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), + BitcastUser->getOperand(0)); +} + +TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { + // When a CallbackVH modifies other ValueHandles in its callbacks, + // that shouldn't interfere with non-modified ValueHandles receiving + // their appropriate callbacks. + // + // We create the active CallbackVH in the middle of a palindromic + // arrangement of other VHs so that the bad behavior would be + // triggered in whichever order callbacks run. + + class DestroyingVH : public CallbackVH { + public: + OwningPtr<WeakVH> ToClear[2]; + DestroyingVH(Value *V) { + ToClear[0].reset(new WeakVH(V)); + setValPtr(V); + ToClear[1].reset(new WeakVH(V)); + } + virtual void deleted() { + ToClear[0].reset(); + ToClear[1].reset(); + CallbackVH::deleted(); + } + virtual void allUsesReplacedWith(Value *) { + ToClear[0].reset(); + ToClear[1].reset(); + } + }; + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2)); + } + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV.reset(); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1)); + EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2)); + } +} + +TEST_F(ValueHandle, AssertingVHCheckedLast) { + // If a CallbackVH exists to clear out a group of AssertingVHs on + // Value deletion, the CallbackVH should get a chance to do so + // before the AssertingVHs assert. + + class ClearingVH : public CallbackVH { + public: + AssertingVH<Value> *ToClear[2]; + ClearingVH(Value *V, + AssertingVH<Value> &A0, AssertingVH<Value> &A1) + : CallbackVH(V) { + ToClear[0] = &A0; + ToClear[1] = &A1; + } + + virtual void deleted() { + *ToClear[0] = 0; + *ToClear[1] = 0; + CallbackVH::deleted(); + } + }; + + AssertingVH<Value> A1, A2; + A1 = BitcastV.get(); + ClearingVH C(BitcastV.get(), A1, A2); + A2 = BitcastV.get(); + // C.deleted() should run first, clearing the two AssertingVHs, + // which should prevent them from asserting. + BitcastV.reset(); } } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index feb0152..bd2e95c 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "gtest/gtest.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -20,6 +22,23 @@ template<typename T> std::string printToString(const T &Value) { return res; } +/// printToString - Print the given value to a stream which only has \arg +/// BytesLeftInBuffer bytes left in the buffer. This is useful for testing edge +/// cases in the buffer handling logic. +template<typename T> std::string printToString(const T &Value, + unsigned BytesLeftInBuffer) { + // FIXME: This is relying on internal knowledge of how raw_ostream works to + // get the buffer position right. + SmallString<256> SVec; + assert(BytesLeftInBuffer < 256 && "Invalid buffer count!"); + llvm::raw_svector_ostream OS(SVec); + unsigned StartIndex = 256 - BytesLeftInBuffer; + for (unsigned i = 0; i != StartIndex; ++i) + OS << '?'; + OS << Value; + return OS.str().substr(StartIndex); +} + template<typename T> std::string printToStringUnbuffered(const T &Value) { std::string res; llvm::raw_string_ostream OS(res); @@ -53,6 +72,10 @@ TEST(raw_ostreamTest, Types_Buffered) { EXPECT_EQ("0x0", printToString((void*) 0)); EXPECT_EQ("0xbeef", printToString((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef)); + + // Min and max. + EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX)); + EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN)); } TEST(raw_ostreamTest, Types_Unbuffered) { @@ -80,6 +103,28 @@ TEST(raw_ostreamTest, Types_Unbuffered) { EXPECT_EQ("0x0", printToStringUnbuffered((void*) 0)); EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef)); EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef)); + + // Min and max. + EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX)); + EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN)); +} + +TEST(raw_ostreamTest, BufferEdge) { + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 1)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 2)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 3)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 4)); + EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 10)); +} + +TEST(raw_ostreamTest, TinyBuffer) { + std::string Str; + raw_string_ostream OS(Str); + OS.SetBufferSize(1); + OS << "hello"; + OS << 1; + OS << 'w' << 'o' << 'r' << 'l' << 'd'; + EXPECT_EQ("hello1world", OS.str()); } } |