about summary refs log tree commit diff homepage
path: root/test/CXX/symex/libc++/dynamic_cast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/symex/libc++/dynamic_cast.cpp')
-rw-r--r--test/CXX/symex/libc++/dynamic_cast.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/test/CXX/symex/libc++/dynamic_cast.cpp b/test/CXX/symex/libc++/dynamic_cast.cpp
new file mode 100644
index 00000000..53e5bc69
--- /dev/null
+++ b/test/CXX/symex/libc++/dynamic_cast.cpp
@@ -0,0 +1,50 @@
+// RUN: sh %S/compile_with_libcxx.sh "%llvmgxx" "%s" "%S" "%t" "%klee" "%libcxx_include"
+
+// Copied from 'http://en.cppreference.com/w/cpp/language/dynamic_cast'
+
+struct V {
+    virtual void f() {};  // must be polymorphic to use runtime-checked dynamic_cast
+};
+struct A : virtual V {};
+struct B : virtual V {
+  B(V* v, A* a) {
+    // casts during construction (see the call in the constructor of D below)
+    dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
+    dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
+  }
+};
+struct D : A, B {
+    D() : B((A*)this, this) { }
+};
+
+struct Base {
+    virtual ~Base() {}
+};
+
+struct Derived: Base {
+    virtual void name() {}
+};
+
+int main()
+{
+    D d; // the most derived object
+    A& a = d; // upcast, dynamic_cast may be used, but unnecessary
+    D& new_d = dynamic_cast<D&>(a); // downcast
+    B& new_b = dynamic_cast<B&>(a); // sidecast
+
+
+    Base* b1 = new Base;
+    if(Derived* d = dynamic_cast<Derived*>(b1))
+    {
+        d->name(); // safe to call
+    }
+
+    Base* b2 = new Derived;
+    if(Derived* d = dynamic_cast<Derived*>(b2))
+    {
+        d->name(); // safe to call
+    }
+
+    delete b1;
+    delete b2;
+}