summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorSean Silva <silvas@purdue.edu>2012-10-11 23:30:40 +0000
committerSean Silva <silvas@purdue.edu>2012-10-11 23:30:40 +0000
commit8b8fa7b2f403ae2f342413239c4151e075022c97 (patch)
tree70dca59e93c6b45c7a55b1e328c89fe332e36d77 /unittests
parent8ac1995456d6938b68f232995f49c86369dd121d (diff)
downloadllvm-8b8fa7b2f403ae2f342413239c4151e075022c97.tar.gz
llvm-8b8fa7b2f403ae2f342413239c4151e075022c97.tar.bz2
llvm-8b8fa7b2f403ae2f342413239c4151e075022c97.tar.xz
Casting.h: Automatically handle isa<Base>(Derived).
Additionally, all such cases are handled with no dynamic check. All `classof()` of the form class Foo { [...] static bool classof(const Bar *) { return true; } [...] } where Foo is an ancestor of Bar are no longer necessary. Don't write them! Note: The exact test is `is_base_of<Foo, Bar>`, which is non-strict, so that Foo is considered an ancestor of itself. This leads to the following rule of thumb for LLVM-style RTTI: The argument type of `classof()` should be a strict ancestor. For more information about implementing LLVM-style RTTI, see docs/HowToSetUpLLVMStyleRTTI.rst git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165765 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/Support/Casting.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp
index dc0205f325..ad564aa366 100644
--- a/unittests/Support/Casting.cpp
+++ b/unittests/Support/Casting.cpp
@@ -153,3 +153,54 @@ const bar *B2 = &B;
} // anonymous namespace
bar *llvm::fub() { return 0; }
+
+namespace {
+namespace inferred_upcasting {
+// This test case verifies correct behavior of inferred upcasts when the
+// types are statically known to be OK to upcast. This is the case when,
+// for example, Derived inherits from Base, and we do `isa<Base>(Derived)`.
+
+// Note: This test will actually fail to compile without inferred
+// upcasting.
+
+class Base {
+public:
+ // No classof. We are testing that the upcast is inferred.
+ Base() {}
+};
+
+class Derived : public Base {
+public:
+ Derived() {}
+};
+
+// Even with no explicit classof() in Base, we should still be able to cast
+// Derived to its base class.
+TEST(CastingTest, UpcastIsInferred) {
+ Derived D;
+ EXPECT_TRUE(isa<Base>(D));
+ Base *BP = dyn_cast<Base>(&D);
+ EXPECT_TRUE(BP != NULL);
+}
+
+
+// This test verifies that the inferred upcast takes precedence over an
+// explicitly written one. This is important because it verifies that the
+// dynamic check gets optimized away.
+class UseInferredUpcast {
+public:
+ int Dummy;
+ static bool classof(const UseInferredUpcast *) {
+ return false;
+ }
+};
+
+TEST(CastingTest, InferredUpcastTakesPrecedence) {
+ UseInferredUpcast UIU;
+ // Since the explicit classof() returns false, this will fail if the
+ // explicit one is used.
+ EXPECT_TRUE(isa<UseInferredUpcast>(&UIU));
+}
+
+} // end namespace inferred_upcasting
+} // end anonymous namespace