about summary refs log tree commit diff homepage
path: root/test/CXX/symex/libc++/throwing_exception_destructor.cpp
blob: 02d7cdb920e0746cf18c33fab02001f977aaf4c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Testcase for proper handling of exception destructors that throw.
// REQUIRES: uclibc
// REQUIRES: libcxx
// REQUIRES: eh-cxx
// 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");
}