llvm/unittests/ADT/PointerSumTypeTest.cpp
Chandler Carruth 560cdb12b5 [ADT] Add a sum type abstraction for pointer-like types.
This is a much more general and powerful form of PointerUnion. It
provides a reasonably complete sum type (from type theory) for
pointer-like types. It has several significant advantages over the
existing PointerUnion infrastructure:

1) It allows more than two pointer types to participate without awkward
   nesting structures.
2) It directly exposes the tag so that it is convenient to write
   switches over the possible members.
3) It can re-use the same type for multiple tag values, something that
   has been worked around by either abusing PointerIntPair or defining
   nonce types and doing unsafe pointer casting.
4) It supports customization of the PointerLikeTypeTraits used for
   specific member types. This means it could (in theory) be used even
   with types that are over-aligned on allocation to expose larger
   numbers of bits to the tag.

All in all, I think it is at least complimentary to the existing
infrastructure, and a strict improvement for some use cases.

Differential Revision: http://reviews.llvm.org/D15843

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@257282 91177308-0d34-0410-b5e6-96231b3b80d8
2016-01-10 08:48:23 +00:00

114 lines
3.1 KiB
C++

//===- llvm/unittest/ADT/PointerSumTypeTest.cpp ---------------------------===//
//
// 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/PointerSumType.h"
using namespace llvm;
namespace {
struct PointerSumTypeTest : public testing::Test {
enum Kinds { Float, Int1, Int2 };
float f;
int i1, i2;
typedef PointerSumType<Kinds, PointerSumTypeMember<Float, float *>,
PointerSumTypeMember<Int1, int *>,
PointerSumTypeMember<Int2, int *>>
SumType;
SumType a, b, c, n;
PointerSumTypeTest()
: f(3.14f), i1(42), i2(-1), a(SumType::create<Float>(&f)),
b(SumType::create<Int1>(&i1)), c(SumType::create<Int2>(&i2)), n() {}
};
TEST_F(PointerSumTypeTest, NullTest) {
EXPECT_TRUE(a);
EXPECT_TRUE(b);
EXPECT_TRUE(c);
EXPECT_FALSE(n);
}
TEST_F(PointerSumTypeTest, GetTag) {
EXPECT_EQ(Float, a.getTag());
EXPECT_EQ(Int1, b.getTag());
EXPECT_EQ(Int2, c.getTag());
EXPECT_EQ((Kinds)0, n.getTag());
}
TEST_F(PointerSumTypeTest, Is) {
EXPECT_TRUE(a.is<Float>());
EXPECT_FALSE(a.is<Int1>());
EXPECT_FALSE(a.is<Int2>());
EXPECT_FALSE(b.is<Float>());
EXPECT_TRUE(b.is<Int1>());
EXPECT_FALSE(b.is<Int2>());
EXPECT_FALSE(c.is<Float>());
EXPECT_FALSE(c.is<Int1>());
EXPECT_TRUE(c.is<Int2>());
}
TEST_F(PointerSumTypeTest, Get) {
EXPECT_EQ(&f, a.get<Float>());
EXPECT_EQ(nullptr, a.get<Int1>());
EXPECT_EQ(nullptr, a.get<Int2>());
EXPECT_EQ(nullptr, b.get<Float>());
EXPECT_EQ(&i1, b.get<Int1>());
EXPECT_EQ(nullptr, b.get<Int2>());
EXPECT_EQ(nullptr, c.get<Float>());
EXPECT_EQ(nullptr, c.get<Int1>());
EXPECT_EQ(&i2, c.get<Int2>());
// Note that we can use .get even on a null sum type. It just always produces
// a null pointer, even if one of the discriminants is null.
EXPECT_EQ(nullptr, n.get<Float>());
EXPECT_EQ(nullptr, n.get<Int1>());
EXPECT_EQ(nullptr, n.get<Int2>());
}
TEST_F(PointerSumTypeTest, Cast) {
EXPECT_EQ(&f, a.cast<Float>());
EXPECT_EQ(&i1, b.cast<Int1>());
EXPECT_EQ(&i2, c.cast<Int2>());
}
TEST_F(PointerSumTypeTest, Assignment) {
b = SumType::create<Int2>(&i2);
EXPECT_EQ(nullptr, b.get<Float>());
EXPECT_EQ(nullptr, b.get<Int1>());
EXPECT_EQ(&i2, b.get<Int2>());
b = SumType::create<Int2>(&i1);
EXPECT_EQ(nullptr, b.get<Float>());
EXPECT_EQ(nullptr, b.get<Int1>());
EXPECT_EQ(&i1, b.get<Int2>());
float Local = 1.616f;
b = SumType::create<Float>(&Local);
EXPECT_EQ(&Local, b.get<Float>());
EXPECT_EQ(nullptr, b.get<Int1>());
EXPECT_EQ(nullptr, b.get<Int2>());
n = SumType::create<Int1>(&i2);
EXPECT_TRUE(n);
EXPECT_EQ(nullptr, n.get<Float>());
EXPECT_EQ(&i2, n.get<Int1>());
EXPECT_EQ(nullptr, n.get<Int2>());
n = SumType::create<Float>(nullptr);
EXPECT_FALSE(n);
EXPECT_EQ(nullptr, n.get<Float>());
EXPECT_EQ(nullptr, n.get<Int1>());
EXPECT_EQ(nullptr, n.get<Int2>());
}
} // end anonymous namespace