about summary refs log tree commit diff homepage
path: root/test
diff options
context:
space:
mode:
authorFelix Rath <felix.rath@comsys.rwth-aachen.de>2020-05-22 14:09:10 +0200
committerMartinNowack <2443641+MartinNowack@users.noreply.github.com>2020-10-12 11:19:24 +0100
commitc09306ffd894f95be195723327d5b17dca73ebd1 (patch)
tree592773383280012bce8856b28503ab61de0deb98 /test
parentd920e049fa955877f772188fdc58cab1b31aabc9 (diff)
downloadklee-c09306ffd894f95be195723327d5b17dca73ebd1.tar.gz
Implemented support for C++ Exceptions
We implement the Itanium ABI unwinding base-API, and leave the
C++-specific parts to libcxxabi.

Co-authored-by: Lukas Wölfer <lukas.woelfer@rwth-aachen.de>
Diffstat (limited to 'test')
-rw-r--r--test/CXX/symex/basic_c++/diamond.cpp45
-rw-r--r--test/CXX/symex/basic_c++/inheritance.cpp35
-rw-r--r--test/CXX/symex/basic_c++/lambda.cpp20
-rw-r--r--test/CXX/symex/basic_c++/namespace.cpp18
-rw-r--r--test/CXX/symex/basic_c++/reinterpret_cast.cpp26
-rw-r--r--test/CXX/symex/basic_c++/simple.cpp33
-rw-r--r--test/CXX/symex/basic_c++/templates.cpp28
-rw-r--r--test/CXX/symex/basic_c++/virtual.cpp35
-rw-r--r--test/CXX/symex/libc++/atexit.cpp19
-rw-r--r--test/CXX/symex/libc++/can_catch_test.cpp88
-rw-r--r--test/CXX/symex/libc++/catch_recover.cpp26
-rw-r--r--test/CXX/symex/libc++/catch_with_adjusted_exception_pointer.cpp37
-rw-r--r--test/CXX/symex/libc++/cout.cpp4
-rw-r--r--test/CXX/symex/libc++/cout_sym.cpp16
-rw-r--r--test/CXX/symex/libc++/dynamic_cast.cpp56
-rw-r--r--test/CXX/symex/libc++/exception.cpp33
-rw-r--r--test/CXX/symex/libc++/exception_inheritance.cpp78
-rw-r--r--test/CXX/symex/libc++/general_catch.cpp60
-rw-r--r--test/CXX/symex/libc++/landingpad.cpp53
-rw-r--r--test/CXX/symex/libc++/multi_throw.cpp47
-rw-r--r--test/CXX/symex/libc++/multi_unwind.cpp70
-rw-r--r--test/CXX/symex/libc++/nested.cpp26
-rw-r--r--test/CXX/symex/libc++/nested_fail.cpp26
-rw-r--r--test/CXX/symex/libc++/rethrow.cpp35
-rw-r--r--test/CXX/symex/libc++/simple_exception.cpp19
-rw-r--r--test/CXX/symex/libc++/simple_exception_fail.cpp13
-rw-r--r--test/CXX/symex/libc++/symbolic_exception.cpp29
-rw-r--r--test/CXX/symex/libc++/throw_specifiers.cpp35
-rw-r--r--test/CXX/symex/libc++/throwing_exception_destructor.cpp45
-rw-r--r--test/CXX/symex/libc++/uncaught_exception.cpp13
-rw-r--r--test/CXX/symex/libc++/vector.cpp5
31 files changed, 1024 insertions, 49 deletions
diff --git a/test/CXX/symex/basic_c++/diamond.cpp b/test/CXX/symex/basic_c++/diamond.cpp
new file mode 100644
index 00000000..479a9090
--- /dev/null
+++ b/test/CXX/symex/basic_c++/diamond.cpp
@@ -0,0 +1,45 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+struct A {
+  int a;
+  A() {
+    printf("A constructor\n");
+  }
+};
+
+struct B : virtual A {
+  int b;
+  B() {
+    printf("B constructor\n");
+  }
+};
+
+struct C : virtual A {
+  int c;
+  C() {
+    printf("C constructor\n");
+  }
+};
+
+struct D : B, C {
+  int d;
+};
+
+int main(int argc, char **args) {
+  D x;
+  // CHECK: A constructor
+  // CHECK: B constructor
+  // CHECK: C constructor
+
+  x.a = 7;
+  B *y = &x;
+  printf("B::a = %d\n", y->a);
+  // CHECK: B::a = 7
+
+  return 0;
+}
diff --git a/test/CXX/symex/basic_c++/inheritance.cpp b/test/CXX/symex/basic_c++/inheritance.cpp
new file mode 100644
index 00000000..88a0d150
--- /dev/null
+++ b/test/CXX/symex/basic_c++/inheritance.cpp
@@ -0,0 +1,35 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+class Testclass {
+public:
+  Testclass() {
+    printf("Testclass constructor\n");
+  }
+  int a() {
+    return 1;
+  }
+};
+class Derivedclass : public Testclass {
+public:
+  Derivedclass() {
+    printf("Derivedclass constructor\n");
+  }
+  int b() {
+    return 2;
+  }
+};
+
+int main(int argc, char **args) {
+  Derivedclass x;
+  // CHECK: Testclass constructor
+  // CHECK: Derivedclass constructor
+
+  printf("%d / %d", x.a(), x.b());
+  // CHECK: 1 / 2
+
+  return x.a() + x.b();
+}
diff --git a/test/CXX/symex/basic_c++/lambda.cpp b/test/CXX/symex/basic_c++/lambda.cpp
new file mode 100644
index 00000000..e7f8f971
--- /dev/null
+++ b/test/CXX/symex/basic_c++/lambda.cpp
@@ -0,0 +1,20 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+int main(int argc, char **args) {
+  int x = 0;
+  auto y = [&](int h) { return x + h; };
+  auto z = [=](int h) { return x + h; };
+  x = 1;
+
+  printf("y(0) == %d\n", y(0));
+  // CHECK: y(0) == 1
+  printf("z(0) == %d\n", z(0));
+  // CHECK: z(0) == 0
+
+  return 0;
+}
diff --git a/test/CXX/symex/basic_c++/namespace.cpp b/test/CXX/symex/basic_c++/namespace.cpp
new file mode 100644
index 00000000..939e9bcd
--- /dev/null
+++ b/test/CXX/symex/basic_c++/namespace.cpp
@@ -0,0 +1,18 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+namespace test {
+int a() {
+  return 2;
+}
+} // namespace test
+
+int main(int argc, char **args) {
+  printf("test::a() == %d\n", test::a());
+  //CHECK: test::a() == 2
+  return 0;
+}
diff --git a/test/CXX/symex/basic_c++/reinterpret_cast.cpp b/test/CXX/symex/basic_c++/reinterpret_cast.cpp
new file mode 100644
index 00000000..6883226b
--- /dev/null
+++ b/test/CXX/symex/basic_c++/reinterpret_cast.cpp
@@ -0,0 +1,26 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+int main(int argc, char **args) {
+  unsigned int *x = new unsigned int(0);
+  char *y = reinterpret_cast<char *>(x);
+
+  printf("address(x) == %p\n", x);
+  printf("address(y) == %p\n", y);
+  // CHECK: address(x) == [[POINTER_X:0x[a-fA-F0-9]+]]
+  // CHECK: address(y) == [[POINTER_X]]
+
+  printf("first x == 0x%08X\n", *x);
+  // CHECK: first x == 0x00000000
+  y[3] = 0xAB;
+  y[1] = 0x78;
+  printf("second x == 0x%08X\n", *x);
+  // CHECK: second x == 0xAB007800
+
+  delete x;
+  return 0;
+}
diff --git a/test/CXX/symex/basic_c++/simple.cpp b/test/CXX/symex/basic_c++/simple.cpp
new file mode 100644
index 00000000..f66dbd1e
--- /dev/null
+++ b/test/CXX/symex/basic_c++/simple.cpp
@@ -0,0 +1,33 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+// CHECK: KLEE: done: completed paths = 5
+
+#include "klee/klee.h"
+
+class Test {
+  int x;
+
+public:
+  Test(int _x) : x(_x) {}
+
+  int test() {
+    if (x % 2 == 0)
+      return 0;
+    if (x % 3 == 0)
+      return 1;
+    if (x % 5 == 0)
+      return 2;
+    if (x % 7 == 0)
+      return 3;
+    return 4;
+  }
+};
+
+int main(int argc, char **args) {
+  Test a(klee_int("Test"));
+
+  return a.test();
+}
diff --git a/test/CXX/symex/basic_c++/templates.cpp b/test/CXX/symex/basic_c++/templates.cpp
new file mode 100644
index 00000000..c5abb983
--- /dev/null
+++ b/test/CXX/symex/basic_c++/templates.cpp
@@ -0,0 +1,28 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc %t.bc 2>&1
+
+#include <cassert>
+
+template <typename X, typename Y>
+X multiply(X a, Y b) {
+  return a * b;
+}
+
+template <int A>
+int add(int summand) {
+  return A + summand;
+}
+
+int main(int argc, char **args) {
+  assert(add<7>(3) == 10);
+
+  assert(multiply(7, 3) == 21);
+
+  // Check if the float arguments are handled correctly
+  assert(multiply(7.1f, 3) > 21);
+  assert(multiply(3, 7.1f) == 21);
+
+  return 0;
+}
diff --git a/test/CXX/symex/basic_c++/virtual.cpp b/test/CXX/symex/basic_c++/virtual.cpp
new file mode 100644
index 00000000..b4850992
--- /dev/null
+++ b/test/CXX/symex/basic_c++/virtual.cpp
@@ -0,0 +1,35 @@
+// REQUIRES: uclibc
+// RUN: %clangxx %s -emit-llvm %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc %t.bc 2>&1
+
+#include <cassert>
+
+class Testclass {
+public:
+  virtual int vtl() {
+    return 1;
+  }
+};
+
+class Derivedclass : public Testclass {
+};
+
+class Overridingclass : public Derivedclass {
+public:
+  int vtl() override {
+    return 2;
+  }
+};
+
+int main(int argc, char **args) {
+  Testclass x;
+  Derivedclass y;
+  Overridingclass z;
+
+  assert(x.vtl() == 1);
+  assert(y.vtl() == 1);
+  assert(z.vtl() == 2);
+
+  return 0;
+}
diff --git a/test/CXX/symex/libc++/atexit.cpp b/test/CXX/symex/libc++/atexit.cpp
index 03b559ae..fa8df475 100644
--- a/test/CXX/symex/libc++/atexit.cpp
+++ b/test/CXX/symex/libc++/atexit.cpp
@@ -1,19 +1,20 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
 // REQUIRES: libcxx
 // REQUIRES: uclibc
 // RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
 // RUN: rm -rf %t.klee-out
-// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc | FileCheck %s
-//
-// CHECK: Returning from main
-// CHECK: atexit_1
-// CHECK: atexit_2
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
 
-#include <iostream>
 #include <cstdlib>
+#include <iostream>
 
-int main(int argc, char** args){
-  auto atexithandler2 = std::atexit([](){std::cout << "atexit_2" << std::endl;});
-  auto atexithandler1 = std::atexit([](){std::cout << "atexit_1" << std::endl;});
+int main(int argc, char **args) {
+  auto atexithandler2 = std::atexit([]() { std::cout << "atexit_2" << std::endl; });
+  auto atexithandler1 = std::atexit([]() { std::cout << "atexit_1" << std::endl; });
   std::cout << "Returning from main" << std::endl;
+  // CHECK: Returning from main
   return 0;
+  // CHECK: atexit_1
+  // CHECK: atexit_2
 }
diff --git a/test/CXX/symex/libc++/can_catch_test.cpp b/test/CXX/symex/libc++/can_catch_test.cpp
new file mode 100644
index 00000000..9d3a2d23
--- /dev/null
+++ b/test/CXX/symex/libc++/can_catch_test.cpp
@@ -0,0 +1,88 @@
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libcxx --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+#include <typeinfo>
+
+extern bool _klee_eh_can_catch(const void *catcher, const void *exception);
+
+class other {};
+class yet_another {};
+class ya_derived : private yet_another {};
+
+class TestClass {
+public:
+  const char *classname = "TestClass";
+
+  TestClass() { printf("%s: Normal constructor called\n", classname); }
+  TestClass(const TestClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  TestClass(TestClass &&other) {
+    printf("%s: Move constructor called\n", classname);
+  }
+  TestClass &operator=(const TestClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  virtual ~TestClass() { printf("%s: Destructor called\n", classname); }
+};
+
+class DerivedClass : public TestClass {
+public:
+  const char *classname = "DerivedClass";
+
+  DerivedClass() { printf("%s: Normal constructor called\n", classname); }
+  DerivedClass(const DerivedClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  DerivedClass(DerivedClass &&other) {
+    printf("%s: Move constructor called\n", classname);
+  }
+  DerivedClass &operator=(const DerivedClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  ~DerivedClass() { printf("%s: Destructor called\n", classname); }
+};
+
+class SecondDerivedClass : public DerivedClass, other, yet_another {
+public:
+  const char *classname = "SecondDerivedClass";
+
+  SecondDerivedClass() { printf("%s: Normal constructor called\n", classname); }
+  SecondDerivedClass(const SecondDerivedClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  SecondDerivedClass(SecondDerivedClass &&other) {
+    printf("%s: Move constructor called\n", classname);
+  }
+  SecondDerivedClass &operator=(const SecondDerivedClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  ~SecondDerivedClass() { printf("%s: Destructor called\n", classname); }
+};
+
+int main(int argc, char **args) {
+  try {
+    try {
+      throw SecondDerivedClass();
+    } catch (SecondDerivedClass &p) {
+      puts("DerivedClass caught\n");
+      // CHECK: DerivedClass caught
+      throw;
+    }
+  } catch (TestClass &tc) {
+    puts("TestClass caught\n");
+    // CHECK: TestClass caught
+  } catch (int) {
+  } catch (int *) {
+  } catch (ya_derived &) {
+  }
+
+  return 0;
+}
diff --git a/test/CXX/symex/libc++/catch_recover.cpp b/test/CXX/symex/libc++/catch_recover.cpp
new file mode 100644
index 00000000..44362b25
--- /dev/null
+++ b/test/CXX/symex/libc++/catch_recover.cpp
@@ -0,0 +1,26 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+#include <stdexcept>
+
+int main(int argc, char **args) {
+  try {
+    throw std::runtime_error("foo");
+  } catch (const std::runtime_error &ex) {
+    printf("In first catch\n");
+    // CHECK-DAG: In first catch
+  }
+  try {
+    throw std::runtime_error("bar");
+  } catch (const std::runtime_error &ex) {
+    printf("In second catch\n");
+    // CHECK-DAG: In second catch
+  }
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 1
diff --git a/test/CXX/symex/libc++/catch_with_adjusted_exception_pointer.cpp b/test/CXX/symex/libc++/catch_with_adjusted_exception_pointer.cpp
new file mode 100644
index 00000000..bfb69be4
--- /dev/null
+++ b/test/CXX/symex/libc++/catch_with_adjusted_exception_pointer.cpp
@@ -0,0 +1,37 @@
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libcxx --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <iostream>
+
+class Base {
+public:
+  int base_int = 42;
+  virtual void print() {
+    std::cout << "Base\n";
+  }
+};
+
+class Derived : public Base {
+public:
+  virtual void print() {
+    std::cout << "Derived\n";
+  }
+};
+
+int main() {
+  Base *bd = new Derived();
+  // CHECK: Derived
+  bd->print();
+
+  try {
+    throw bd;
+  } catch (Base *b) {
+    // CHECK: Derived
+    b->print();
+    // CHECK: 42
+    std::cout << b->base_int << "\n";
+  }
+}
diff --git a/test/CXX/symex/libc++/cout.cpp b/test/CXX/symex/libc++/cout.cpp
index 0f3c338a..62cd0406 100644
--- a/test/CXX/symex/libc++/cout.cpp
+++ b/test/CXX/symex/libc++/cout.cpp
@@ -1,8 +1,10 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
 // REQUIRES: libcxx
 // REQUIRES: uclibc
 // RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
 // RUN: rm -rf %t.klee-out
-// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
 
 // CHECK-DAG: cout
 // CHECK-DAG: cerr
diff --git a/test/CXX/symex/libc++/cout_sym.cpp b/test/CXX/symex/libc++/cout_sym.cpp
index 8bf81122..177c3ed7 100644
--- a/test/CXX/symex/libc++/cout_sym.cpp
+++ b/test/CXX/symex/libc++/cout_sym.cpp
@@ -1,22 +1,22 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
 // REQUIRES: libcxx
 // REQUIRES: uclibc
 // RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
 // RUN: rm -rf %t.klee-out
-// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc | FileCheck %s
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
 
-// CHECK-DAG: greater
-// CHECK-DAG: lower
-
-
-#include <iostream>
 #include "klee/klee.h"
+#include <iostream>
 
-int main(int argc, char** args){
+int main(int argc, char **args) {
   int x = klee_int("x");
-  if (x > 0){
+  if (x > 0) {
     std::cout << "greater: " << x << std::endl;
+    // CHECK-DAG: greater
   } else {
     std::cout << "lower: " << x << std::endl;
+    // CHECK-DAG: lower
   }
   return 0;
 }
diff --git a/test/CXX/symex/libc++/dynamic_cast.cpp b/test/CXX/symex/libc++/dynamic_cast.cpp
index c2d8b528..a2fc8b82 100644
--- a/test/CXX/symex/libc++/dynamic_cast.cpp
+++ b/test/CXX/symex/libc++/dynamic_cast.cpp
@@ -1,54 +1,52 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
 // REQUIRES: libcxx
 // REQUIRES: uclibc
 // RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
 // RUN: rm -rf %t.klee-out
-// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc
-//
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc
+
 // 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
+  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) {
+  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
+    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) { }
+  D() : B((A *)this, this) {}
 };
 
 struct Base {
-    virtual ~Base() {}
+  virtual ~Base() {}
 };
 
-struct Derived: Base {
-    virtual void name() {}
+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
-
+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 *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
-    }
+  Base *b2 = new Derived;
+  if (Derived *d = dynamic_cast<Derived *>(b2)) {
+    d->name(); // safe to call
+  }
 
-    delete b1;
-    delete b2;
+  delete b1;
+  delete b2;
 }
diff --git a/test/CXX/symex/libc++/exception.cpp b/test/CXX/symex/libc++/exception.cpp
new file mode 100644
index 00000000..b46d474e
--- /dev/null
+++ b/test/CXX/symex/libc++/exception.cpp
@@ -0,0 +1,33 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cstdio>
+
+int main(int argc, char **args) {
+  int x = klee_int("Test");
+
+  try {
+    if (x % 2 == 0) {
+      printf("Normal return\n");
+      // CHECK-DAG: Normal return
+      return 0;
+    }
+    throw x;
+  } catch (int b) {
+    if (b % 3 == 0) {
+      printf("First exceptional return\n");
+      // CHECK-DAG: First exceptional return
+      return 2;
+    }
+    printf("Second exceptional return\n");
+    // CHECK-DAG: Second exceptional return
+    return 3;
+  }
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 3
diff --git a/test/CXX/symex/libc++/exception_inheritance.cpp b/test/CXX/symex/libc++/exception_inheritance.cpp
new file mode 100644
index 00000000..4e42fbb7
--- /dev/null
+++ b/test/CXX/symex/libc++/exception_inheritance.cpp
@@ -0,0 +1,78 @@
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libcxx --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+class TestClass {
+public:
+  const char *classname = "TestClass";
+
+  TestClass() {
+    printf("%s: Normal constructor called\n", classname);
+  }
+  TestClass(const TestClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  TestClass(TestClass &&other) { printf("%s: Move constructor called\n", classname); }
+  TestClass &operator=(const TestClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  virtual ~TestClass() { printf("%s: Destructor called\n", classname); }
+};
+
+class DerivedClass : public TestClass {
+public:
+  const char *classname = "DerivedClass";
+
+  DerivedClass() {
+    printf("%s: Normal constructor called\n", classname);
+  }
+  DerivedClass(const DerivedClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  DerivedClass(DerivedClass &&other) { printf("%s: Move constructor called\n", classname); }
+  DerivedClass &operator=(const DerivedClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  ~DerivedClass() { printf("%s: Destructor called\n", classname); }
+};
+
+class SecondDerivedClass : public DerivedClass {
+public:
+  const char *classname = "SecondDerivedClass";
+
+  SecondDerivedClass() {
+    printf("%s: Normal constructor called\n", classname);
+  }
+  SecondDerivedClass(const SecondDerivedClass &other) {
+    printf("%s: Copy constructor called\n", classname);
+  }
+  SecondDerivedClass(SecondDerivedClass &&other) { printf("%s: Move constructor called\n", classname); }
+  SecondDerivedClass &operator=(const SecondDerivedClass &&other) {
+    printf("%s: Assignment constructor called\n", classname);
+    return *this;
+  }
+  ~SecondDerivedClass() { printf("%s: Destructor called\n", classname); }
+};
+
+int main(int argc, char **args) {
+  try {
+    try {
+      throw SecondDerivedClass();
+    } catch (DerivedClass &p) {
+      puts("DerivedClass caught\n");
+      // CHECK: DerivedClass caught
+      throw;
+    }
+  } catch (TestClass &tc) {
+    puts("TestClass caught\n");
+    // CHECK: TestClass caught
+  }
+
+  return 0;
+}
diff --git a/test/CXX/symex/libc++/general_catch.cpp b/test/CXX/symex/libc++/general_catch.cpp
new file mode 100644
index 00000000..ee7f9983
--- /dev/null
+++ b/test/CXX/symex/libc++/general_catch.cpp
@@ -0,0 +1,60 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cassert>
+#include <cstdio>
+
+struct CustomStruct {
+  int a;
+};
+
+int thrower(int x) {
+  if (x == 0) {
+    CustomStruct p;
+    throw p;
+  } else if (x == 1) {
+    throw 7;
+  } else if (x == 2) {
+    throw new CustomStruct();
+  } else {
+    throw &thrower;
+  }
+}
+
+int catcher(int x) {
+  try {
+    thrower(x);
+  } catch (int ex) {
+    printf("Caught int\n");
+    // CHECK-DAG: Caught int
+    return 1;
+  } catch (CustomStruct ex) {
+    printf("Caught normal CustomStruct\n");
+    // CHECK-DAG: Caught normal CustomStruct
+    return 2;
+  } catch (CustomStruct *ex) {
+    printf("Caught pointer CustomStruct\n");
+    // CHECK-DAG: Caught pointer CustomStruct
+    return 3;
+  } catch (...) {
+    printf("Caught general exception\n");
+    // CHECK-DAG: Caught general exception
+    return 4;
+  }
+  // Unreachable instruction
+  assert(0);
+  return 0;
+}
+
+int main(int argc, char **args) {
+  int x = klee_int("x");
+  int res = catcher(x);
+  return res;
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 4
diff --git a/test/CXX/symex/libc++/landingpad.cpp b/test/CXX/symex/libc++/landingpad.cpp
new file mode 100644
index 00000000..21e55536
--- /dev/null
+++ b/test/CXX/symex/libc++/landingpad.cpp
@@ -0,0 +1,53 @@
+// Testcase for proper handling of
+// c++ type, constructors and destructors.
+// Based on: https://gcc.gnu.org/wiki/Dwarf2EHNewbiesHowto
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libcxx --libc=uclibc  %t.bc | FileCheck %s
+// Expect the following output:
+// CHECK: Throwing 1...
+// CHECK: A() 1
+// CHECK: A(const A&) 2
+// CHECK: Caught.
+// CHECK: ~A() 2
+// CHECK: ~A() 1
+// CHECK: c == 2, d == 2
+
+#include <stdio.h>
+
+int c, d;
+
+struct A {
+  int i;
+  A() {
+    i = ++c;
+    printf("A() %d\n", i);
+  }
+  A(const A &) {
+    i = ++c;
+    printf("A(const A&) %d\n", i);
+  }
+  ~A() {
+    printf("~A() %d\n", i);
+    ++d;
+  }
+};
+
+void f() {
+  printf("Throwing 1...\n");
+  throw A();
+}
+
+int main() {
+  c = 0;
+  d = 0;
+  try {
+    f();
+  } catch (A) {
+    printf("Caught.\n");
+  }
+  printf("c == %d, d == %d\n", c, d);
+  return c != d;
+}
diff --git a/test/CXX/symex/libc++/multi_throw.cpp b/test/CXX/symex/libc++/multi_throw.cpp
new file mode 100644
index 00000000..be07bc17
--- /dev/null
+++ b/test/CXX/symex/libc++/multi_throw.cpp
@@ -0,0 +1,47 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cstdio>
+
+static void x(int a) {
+  if (a == 7) {
+    throw static_cast<float>(a);
+  }
+}
+
+struct ThrowingDestructor {
+  int p = 0;
+  ~ThrowingDestructor() {
+    try {
+      x(p);
+    } catch (float ex) {
+      printf("Caught float in ThrowingDestructor()\n");
+      // CHECK-DAG: Caught float in ThrowingDestructor()
+    }
+  }
+};
+
+static void y(int a) {
+  ThrowingDestructor p;
+  p.p = klee_int("struct_int");
+  try {
+    if (a == 7) {
+      throw a;
+    }
+  } catch (int ex) {
+    printf("Caught int in y()\n");
+    // CHECK-DAG: Caught int in y()
+  }
+}
+
+int main(int argc, char **args) {
+  y(klee_int("fun_int"));
+  return 0;
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 4
diff --git a/test/CXX/symex/libc++/multi_unwind.cpp b/test/CXX/symex/libc++/multi_unwind.cpp
new file mode 100644
index 00000000..98bae1dc
--- /dev/null
+++ b/test/CXX/symex/libc++/multi_unwind.cpp
@@ -0,0 +1,70 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cassert>
+#include <cstdio>
+
+struct CustomStruct {
+  int a;
+};
+
+int thrower(int x) {
+  if (x == 0) {
+    CustomStruct p;
+    throw p;
+  } else if (x == 1) {
+    throw 7;
+  } else {
+    throw new CustomStruct();
+  }
+}
+int rethrower(int x) {
+  thrower(x);
+  return 7;
+}
+
+int failed_catch(int x) {
+  try {
+    rethrower(x);
+  } catch (char *ex) {
+    // Don't catch wrong type
+    assert(0);
+  }
+  // rethrower always throws, cannot reach this instruction
+  assert(0);
+  return 0;
+}
+
+int catcher(int x) {
+  try {
+    failed_catch(x);
+  } catch (int ex) {
+    printf("Caught int\n");
+    // CHECK-DAG: Caught int
+    return 1;
+  } catch (CustomStruct ex) {
+    printf("Caught normal CustomStruct\n");
+    // CHECK-DAG: Caught normal CustomStruct
+    return 2;
+  } catch (CustomStruct *ex) {
+    printf("Caught pointer CustomStruct\n");
+    // CHECK-DAG: Caught pointer CustomStruct
+    return 3;
+  }
+  // Unreachable instruction
+  assert(0);
+  return 0;
+}
+
+int main(int argc, char **args) {
+  int x = klee_int("x");
+  int res = catcher(x);
+  return res;
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 3
diff --git a/test/CXX/symex/libc++/nested.cpp b/test/CXX/symex/libc++/nested.cpp
new file mode 100644
index 00000000..b85d6759
--- /dev/null
+++ b/test/CXX/symex/libc++/nested.cpp
@@ -0,0 +1,26 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+int main(int argc, char **args) {
+  try {
+    try {
+      char *p = new char[8];
+      throw p;
+    } catch (char *ex) {
+      int i = 7;
+      throw i;
+    }
+  } catch (int ex) {
+    printf("Reached outer catch with i = %d\n", ex);
+    // CHECK-DAG: Reached outer catch with i = 7
+  }
+  return 0;
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 1
diff --git a/test/CXX/symex/libc++/nested_fail.cpp b/test/CXX/symex/libc++/nested_fail.cpp
new file mode 100644
index 00000000..919434f1
--- /dev/null
+++ b/test/CXX/symex/libc++/nested_fail.cpp
@@ -0,0 +1,26 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cstdio>
+
+int main(int argc, char **args) {
+  try {
+    try {
+      char *p = new char[8];
+      throw p;
+    } catch (int ex) {
+      printf("Landed in wrong inner catch\n");
+      // CHECK-NOT: Landed in wrong inner catch
+    }
+  } catch (int ex) {
+    printf("Landed in wrong outer catch\n");
+    // CHECK-NOT: Landed in wrong outer catch
+  }
+  return 0;
+}
+// CHECK: terminating with uncaught exception of type char*
diff --git a/test/CXX/symex/libc++/rethrow.cpp b/test/CXX/symex/libc++/rethrow.cpp
new file mode 100644
index 00000000..d6a0954d
--- /dev/null
+++ b/test/CXX/symex/libc++/rethrow.cpp
@@ -0,0 +1,35 @@
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libcxx --libc=uclibc %t.bc 2>&1 | FileCheck %s
+
+#include <cstdio>
+
+class TestClass {
+public:
+  virtual ~TestClass() {}
+};
+
+class DerivedClass : public TestClass {
+};
+
+class SecondDerivedClass : public DerivedClass {
+};
+
+int main(int argc, char **args) {
+  try {
+    try {
+      throw SecondDerivedClass();
+    } catch (DerivedClass &p) {
+      puts("DerivedClass caught\n");
+      // CHECK: DerivedClass caught
+      throw;
+    }
+  } catch (TestClass &tc) {
+    puts("TestClass caught\n");
+    // CHECK: TestClass caught
+  }
+
+  return 0;
+}
diff --git a/test/CXX/symex/libc++/simple_exception.cpp b/test/CXX/symex/libc++/simple_exception.cpp
new file mode 100644
index 00000000..af002253
--- /dev/null
+++ b/test/CXX/symex/libc++/simple_exception.cpp
@@ -0,0 +1,19 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+// CHECK: KLEE: done: completed paths = 1
+
+#include "klee/klee.h"
+
+#include <stdexcept>
+
+int main(int argc, char **args) {
+  try {
+    throw std::runtime_error("foo");
+  } catch (const std::runtime_error &ex) {
+  }
+}
diff --git a/test/CXX/symex/libc++/simple_exception_fail.cpp b/test/CXX/symex/libc++/simple_exception_fail.cpp
new file mode 100644
index 00000000..d4a30b25
--- /dev/null
+++ b/test/CXX/symex/libc++/simple_exception_fail.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include <stdexcept>
+
+int main(int argc, char **args) {
+  throw std::runtime_error("foo");
+}
+// CHECK: terminating with uncaught exception of type std::runtime_error: foo
\ No newline at end of file
diff --git a/test/CXX/symex/libc++/symbolic_exception.cpp b/test/CXX/symex/libc++/symbolic_exception.cpp
new file mode 100644
index 00000000..49d432a8
--- /dev/null
+++ b/test/CXX/symex/libc++/symbolic_exception.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+#include "klee/klee.h"
+#include <cstdio>
+
+int main(int argc, char **args) {
+  try {
+    throw klee_int("x");
+  } catch (int ex) {
+    if (ex > 7) {
+      puts("ex > 7");
+      // CHECK-DAG: ex > 7
+    } else if (ex < 2) {
+      puts("ex < 2");
+      // CHECK-DAG: ex < 2
+    } else {
+      puts("2 <= ex <= 7");
+      // CHECK-DAG: 2 <= ex <= 7
+    }
+  }
+  return 0;
+}
+
+// CHECK-DAG: KLEE: done: completed paths = 3
diff --git a/test/CXX/symex/libc++/throw_specifiers.cpp b/test/CXX/symex/libc++/throw_specifiers.cpp
new file mode 100644
index 00000000..5a7955fb
--- /dev/null
+++ b/test/CXX/symex/libc++/throw_specifiers.cpp
@@ -0,0 +1,35 @@
+// Testcase for proper handling of
+// throw specifications on functions
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libcxx --libc=uclibc  %t.bc | FileCheck %s
+
+#include <stdio.h>
+
+namespace {
+void throw_expected() throw(int) {
+  throw 5;
+}
+
+void throw_unexpected() throw(int, double) {
+  throw "unexpected string";
+}
+} // namespace
+
+int main() {
+  try {
+    throw_expected();
+  } catch (int i) {
+    puts("caught expected int");
+    // CHECK: caught expected int
+  }
+
+  try {
+    throw_unexpected();
+  } catch (char const *s) {
+    puts("caught unexpected string");
+    // CHECK-NOT: caught unexpected string
+  }
+}
diff --git a/test/CXX/symex/libc++/throwing_exception_destructor.cpp b/test/CXX/symex/libc++/throwing_exception_destructor.cpp
new file mode 100644
index 00000000..d24a15b0
--- /dev/null
+++ b/test/CXX/symex/libc++/throwing_exception_destructor.cpp
@@ -0,0 +1,45 @@
+// Testcase for proper handling of exception destructors that throw.
+// REQUIRES: uclibc
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm -O0 -std=c++11 -c -I "%libcxx_include" -g -nostdinc++ -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libcxx --libc=uclibc --exit-on-error  %t.bc
+
+#include <cassert>
+#include <cstdlib>
+#include <exception>
+
+bool destructor_throw = false;
+bool test_catch = false;
+bool int_catch = false;
+
+struct Test {
+  ~Test() noexcept(false) {
+    destructor_throw = true;
+    throw 5;
+  }
+};
+
+int main() {
+  // For some reason, printing to stdout in this test did not work when running
+  // with FileCheck. I tried puts, printf and std::cout, using fflush(stdout)
+  // and std::endl as well, but the output would only be there when not piping
+  // to FileCheck. Therefore we use a terminate handler here, which will just
+  // do the checks instead of printing strings and using FileCheck.
+  std::set_terminate([]() {
+    assert(destructor_throw && test_catch && !int_catch);
+    std::exit(0);
+  });
+
+  try {
+    try {
+      throw Test();
+    } catch (Test &t) {
+      test_catch = true;
+    }
+  } catch (int i) {
+    int_catch = true;
+  }
+
+  assert(false && "should call terminate due to an uncaught exception");
+}
diff --git a/test/CXX/symex/libc++/uncaught_exception.cpp b/test/CXX/symex/libc++/uncaught_exception.cpp
new file mode 100644
index 00000000..4e8f90f5
--- /dev/null
+++ b/test/CXX/symex/libc++/uncaught_exception.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
+// REQUIRES: libcxx
+// RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
+
+int main() {
+  throw 7;
+}
+
+// CHECK: KLEE: ERROR:
+// CHECK: KLEE: done: completed paths = 1
diff --git a/test/CXX/symex/libc++/vector.cpp b/test/CXX/symex/libc++/vector.cpp
index 32afecd2..6f69ad65 100644
--- a/test/CXX/symex/libc++/vector.cpp
+++ b/test/CXX/symex/libc++/vector.cpp
@@ -1,10 +1,10 @@
+// REQUIRES: not-msan
+// Disabling msan because it times out on CI
 // REQUIRES: libcxx
 // REQUIRES: uclibc
 // RUN: %clangxx %s -emit-llvm %O0opt -c -std=c++11 -I "%libcxx_include" -g -nostdinc++ -o %t1.bc
 // RUN: rm -rf %t.klee-out
 // RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc --libcxx %t1.bc 2>&1 | FileCheck %s
-//
-// CHECK: KLEE: done: completed paths = 1
 
 #include "klee/klee.h"
 #include <vector>
@@ -14,3 +14,4 @@ int main(int argc, char **args) {
   a.push_back(klee_int("Test"));
   return a.at(0);
 }
+// CHECK: KLEE: done: completed paths = 1