diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-11-24 03:13:02 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-11-24 03:13:02 +0000 |
commit | 403011848502577344a222633918496fa03f32d4 (patch) | |
tree | 53da2c91c823c5aae270237cc1e35b1126b0e362 /llvm/unittests/Support/Casting.cpp | |
parent | ba6d83e64b1923ccf56c843fdbb0fee11c45c5aa (diff) | |
download | bcm5719-llvm-403011848502577344a222633918496fa03f32d4.tar.gz bcm5719-llvm-403011848502577344a222633918496fa03f32d4.zip |
Support: Add *cast_or_null<> for pointer wrappers
Fill in omission of `cast_or_null<>` and `dyn_cast_or_null<>` for types
that wrap pointers (e.g., smart pointers).
Type traits need to be slightly stricter than for `cast<>` and
`dyn_cast<>` to resolve ambiguities with simple types.
There didn't seem to be any unit tests for pointer wrappers, so I tested
`isa<>`, `cast<>`, and `dyn_cast<>` while I was in there.
This only supports pointer wrappers with a conversion to `bool` to check
for null. If in the future it's useful to support wrappers without such
a conversion, it should be a straightforward incremental step to use the
`simplify_type` machinery for the null check. In that case, the unit
tests should be updated to remove the `operator bool()` from the
`pointer_wrappers::PTy`.
llvm-svn: 222644
Diffstat (limited to 'llvm/unittests/Support/Casting.cpp')
-rw-r--r-- | llvm/unittests/Support/Casting.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/llvm/unittests/Support/Casting.cpp b/llvm/unittests/Support/Casting.cpp index 88c7d19aa46..3218189eeab 100644 --- a/llvm/unittests/Support/Casting.cpp +++ b/llvm/unittests/Support/Casting.cpp @@ -232,3 +232,99 @@ namespace TemporaryCast { struct pod {}; IllegalCast *testIllegalCast() { return cast<foo>(pod()); } } + +namespace { +namespace pointer_wrappers { + +struct Base { + bool IsDerived; + Base(bool IsDerived = false) : IsDerived(IsDerived) {} +}; + +struct Derived : Base { + Derived() : Base(true) {} + static bool classof(const Base *B) { return B->IsDerived; } +}; + +class PTy { + Base *B; +public: + PTy(Base *B) : B(B) {} + LLVM_EXPLICIT operator bool() const { return get(); } + Base *get() const { return B; } +}; + +} // end namespace pointer_wrappers +} // end namespace + +namespace llvm { + +template <> struct simplify_type<pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) { + return P.get(); + } +}; +template <> struct simplify_type<const pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) { + return P.get(); + } +}; + +} // end namespace llvm + +namespace { +namespace pointer_wrappers { + +// Some objects. +pointer_wrappers::Base B; +pointer_wrappers::Derived D; + +// Mutable "smart" pointers. +pointer_wrappers::PTy MN(nullptr); +pointer_wrappers::PTy MB(&B); +pointer_wrappers::PTy MD(&D); + +// Const "smart" pointers. +const pointer_wrappers::PTy CN(nullptr); +const pointer_wrappers::PTy CB(&B); +const pointer_wrappers::PTy CD(&D); + +TEST(CastingTest, smart_isa) { + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB)); + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD)); +} + +TEST(CastingTest, smart_cast) { + EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_cast_or_null) { + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast) { + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast_or_null) { + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +} // end namespace pointer_wrappers +} // end namespace |