summaryrefslogtreecommitdiff
path: root/unittests/Support/Casting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Support/Casting.cpp')
-rw-r--r--unittests/Support/Casting.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp
index e6c35fc21eb7d..9a818f6bdebde 100644
--- a/unittests/Support/Casting.cpp
+++ b/unittests/Support/Casting.cpp
@@ -40,6 +40,14 @@ struct foo {
}*/
};
+struct base {
+ virtual ~base() {}
+};
+
+struct derived : public base {
+ static bool classof(const base *B) { return true; }
+};
+
template <> struct isa_impl<foo, bar> {
static inline bool doit(const bar &Val) {
dbgs() << "Classof: " << &Val << "\n";
@@ -47,6 +55,10 @@ template <> struct isa_impl<foo, bar> {
}
};
+template <typename T> struct isa_impl<foo, T> {
+ static inline bool doit(const T &Val) { return false; }
+};
+
foo *bar::baz() {
return cast<foo>(this);
}
@@ -123,6 +135,13 @@ TEST(CastingTest, cast) {
// EXPECT_EQ(F7, null_foo);
foo *F8 = B1.baz();
EXPECT_NE(F8, null_foo);
+
+ std::unique_ptr<const bar> BP(B2);
+ auto FP = cast<foo>(std::move(BP));
+ static_assert(std::is_same<std::unique_ptr<const foo>, decltype(FP)>::value,
+ "Incorrect deduced return type!");
+ EXPECT_NE(FP.get(), null_foo);
+ FP.release();
}
TEST(CastingTest, cast_or_null) {
@@ -136,6 +155,10 @@ TEST(CastingTest, cast_or_null) {
EXPECT_EQ(F14, null_foo);
foo *F15 = B1.caz();
EXPECT_NE(F15, null_foo);
+
+ std::unique_ptr<const bar> BP(fub());
+ auto FP = cast_or_null<foo>(std::move(BP));
+ EXPECT_EQ(FP.get(), null_foo);
}
TEST(CastingTest, dyn_cast) {
@@ -165,6 +188,58 @@ TEST(CastingTest, dyn_cast_or_null) {
EXPECT_NE(F5, null_foo);
}
+std::unique_ptr<derived> newd() { return llvm::make_unique<derived>(); }
+std::unique_ptr<base> newb() { return llvm::make_unique<derived>(); }
+
+TEST(CastingTest, unique_dyn_cast) {
+ derived *OrigD = nullptr;
+ auto D = llvm::make_unique<derived>();
+ OrigD = D.get();
+
+ // Converting from D to itself is valid, it should return a new unique_ptr
+ // and the old one should become nullptr.
+ auto NewD = unique_dyn_cast<derived>(D);
+ ASSERT_EQ(OrigD, NewD.get());
+ ASSERT_EQ(nullptr, D);
+
+ // Converting from D to B is valid, B should have a value and D should be
+ // nullptr.
+ auto B = unique_dyn_cast<base>(NewD);
+ ASSERT_EQ(OrigD, B.get());
+ ASSERT_EQ(nullptr, NewD);
+
+ // Converting from B to itself is valid, it should return a new unique_ptr
+ // and the old one should become nullptr.
+ auto NewB = unique_dyn_cast<base>(B);
+ ASSERT_EQ(OrigD, NewB.get());
+ ASSERT_EQ(nullptr, B);
+
+ // Converting from B to D is valid, D should have a value and B should be
+ // nullptr;
+ D = unique_dyn_cast<derived>(NewB);
+ ASSERT_EQ(OrigD, D.get());
+ ASSERT_EQ(nullptr, NewB);
+
+ // Converting between unrelated types should fail. The original value should
+ // remain unchanged and it should return nullptr.
+ auto F = unique_dyn_cast<foo>(D);
+ ASSERT_EQ(nullptr, F);
+ ASSERT_EQ(OrigD, D.get());
+
+ // All of the above should also hold for temporaries.
+ auto D2 = unique_dyn_cast<derived>(newd());
+ EXPECT_NE(nullptr, D2);
+
+ auto B2 = unique_dyn_cast<derived>(newb());
+ EXPECT_NE(nullptr, B2);
+
+ auto B3 = unique_dyn_cast<base>(newb());
+ EXPECT_NE(nullptr, B3);
+
+ auto F2 = unique_dyn_cast<foo>(newb());
+ EXPECT_EQ(nullptr, F2);
+}
+
// These lines are errors...
//foo *F20 = cast<foo>(B2); // Yields const foo*
//foo &F21 = cast<foo>(B3); // Yields const foo&