about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Core/ExecutionState.cpp2
-rw-r--r--lib/Core/ExecutionState.h9
-rw-r--r--lib/Core/Executor.cpp25
-rw-r--r--lib/Core/SpecialFunctionHandler.cpp9
-rw-r--r--runtime/klee-eh-cxx/klee_eh_cxx.cpp9
-rw-r--r--test/CXX/symex/basic_c++/templates.cpp2
-rw-r--r--test/CXX/symex/libc++/simple_exception.cpp7
7 files changed, 39 insertions, 24 deletions
diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp
index 9004d706..62376db6 100644
--- a/lib/Core/ExecutionState.cpp
+++ b/lib/Core/ExecutionState.cpp
@@ -107,7 +107,7 @@ ExecutionState::ExecutionState(const ExecutionState& state):
     steppedInstructions(state.steppedInstructions),
     instsSinceCovNew(state.instsSinceCovNew),
     unwindingInformation(state.unwindingInformation
-                             ? state.unwindingInformation->cloned()
+                             ? state.unwindingInformation->clone()
                              : nullptr),
     coveredNew(state.coveredNew),
     forkDisabled(state.forkDisabled) {
diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h
index b3560caf..f91790d5 100644
--- a/lib/Core/ExecutionState.h
+++ b/lib/Core/ExecutionState.h
@@ -65,7 +65,8 @@ struct StackFrame {
 };
 
 /// Contains information related to unwinding (Itanium ABI/2-Phase unwinding)
-struct UnwindingInformation {
+class UnwindingInformation {
+public:
   enum class Kind {
     SearchPhase, // first phase
     CleanupPhase // second phase
@@ -84,7 +85,7 @@ public:
       : kind(k), exceptionObject(exceptionObject) {}
   virtual ~UnwindingInformation() = default;
 
-  virtual std::unique_ptr<UnwindingInformation> cloned() const = 0;
+  virtual std::unique_ptr<UnwindingInformation> clone() const = 0;
 };
 
 struct SearchPhaseUnwindingInformation : public UnwindingInformation {
@@ -101,7 +102,7 @@ struct SearchPhaseUnwindingInformation : public UnwindingInformation {
                              UnwindingInformation::Kind::SearchPhase),
         unwindingProgress(unwindingProgress) {}
 
-  std::unique_ptr<UnwindingInformation> cloned() const {
+  std::unique_ptr<UnwindingInformation> clone() const {
     return std::make_unique<SearchPhaseUnwindingInformation>(*this);
   }
 
@@ -132,7 +133,7 @@ struct CleanupPhaseUnwindingInformation : public UnwindingInformation {
         selectorValue(selectorValue),
         catchingStackIndex(catchingStackIndex) {}
 
-  std::unique_ptr<UnwindingInformation> cloned() const {
+  std::unique_ptr<UnwindingInformation> clone() const {
     return std::make_unique<CleanupPhaseUnwindingInformation>(*this);
   }
 
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 64dcee43..2e6f9c89 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -1632,6 +1632,8 @@ void Executor::unwindToNextLandingpad(ExecutionState &state) {
 }
 
 ref<klee::ConstantExpr> Executor::getEhTypeidFor(ref<Expr> type_info) {
+  // FIXME: Handling getEhTypeidFor is non-deterministic and depends on the
+  //        order states have been processed and executed.
   auto eh_type_iterator =
       std::find(std::begin(eh_typeids), std::end(eh_typeids), type_info);
   if (eh_type_iterator == std::end(eh_typeids)) {
@@ -1998,8 +2000,6 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
     Instruction *caller = kcaller ? kcaller->inst : 0;
     bool isVoidReturn = (ri->getNumOperands() == 0);
     ref<Expr> result = ConstantExpr::alloc(0, Expr::Bool);
-    bool isReturnFromPersonalityFn =
-        ri->getFunction()->getName() == "_klee_eh_cxx_personality";
     
     if (!isVoidReturn) {
       result = eval(ki, 0, state).value;
@@ -2021,7 +2021,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
         ++state.pc;
       }
 
-      if (isReturnFromPersonalityFn) {
+      if (ri->getFunction()->getName() == "_klee_eh_cxx_personality") {
         assert(dyn_cast<ConstantExpr>(result) &&
                "result from personality fn must be a concrete value");
 
@@ -3158,15 +3158,22 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
     }
 
     ref<Expr> arg = eval(ki, 0, state).value;
-    ref<Expr> expPtr = ExtractExpr::create(arg, 0, Expr::Int64);
-    ref<Expr> selector = ExtractExpr::create(arg, Expr::Int64, Expr::Int32);
+    ref<Expr> exceptionPointer = ExtractExpr::create(arg, 0, Expr::Int64);
+    ref<Expr> selectorValue =
+        ExtractExpr::create(arg, Expr::Int64, Expr::Int32);
 
-    if (!Expr::createIsZero(selector)->isTrue()) {
-      llvm::errs() << "resume-instruction called with non-0 selector value '"
-                   << selector << "'\n";
+    if (!dyn_cast<ConstantExpr>(exceptionPointer) ||
+        !dyn_cast<ConstantExpr>(selectorValue)) {
+      terminateStateOnExecError(
+          state, "resume-instruction called with non constant expression");
+      break;
+    }
+
+    if (!Expr::createIsZero(selectorValue)->isTrue()) {
+      klee_warning("resume-instruction called with non-0 selector value");
     }
 
-    if (!EqExpr::create(expPtr, cui->exceptionObject)->isTrue()) {
+    if (!EqExpr::create(exceptionPointer, cui->exceptionObject)->isTrue()) {
       terminateStateOnExecError(
           state, "resume-instruction called with unexpected exception pointer");
       break;
diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp
index 7144e235..6d54eb22 100644
--- a/lib/Core/SpecialFunctionHandler.cpp
+++ b/lib/Core/SpecialFunctionHandler.cpp
@@ -460,13 +460,8 @@ void SpecialFunctionHandler::handleMemalign(ExecutionState &state,
 void SpecialFunctionHandler::handleEhUnwindRaiseExceptionImpl(
     ExecutionState &state, KInstruction *target,
     std::vector<ref<Expr>> &arguments) {
-  if (arguments.size() != 1) {
-    executor.terminateStateOnExecError(
-        state, "Internal Error: Incorrect number of arguments to "
-               "_klee_eh_Unwind_RaiseException_impl, "
-               "should not happen");
-    return;
-  }
+  assert(arguments.size() == 1 &&
+         "invalid number of arguments to _klee_eh_Unwind_RaiseException_impl");
 
   ref<ConstantExpr> exceptionObject = dyn_cast<ConstantExpr>(arguments[0]);
   if (!exceptionObject.get()) {
diff --git a/runtime/klee-eh-cxx/klee_eh_cxx.cpp b/runtime/klee-eh-cxx/klee_eh_cxx.cpp
index 5dec6050..9d86bef4 100644
--- a/runtime/klee-eh-cxx/klee_eh_cxx.cpp
+++ b/runtime/klee-eh-cxx/klee_eh_cxx.cpp
@@ -1,3 +1,12 @@
+//===-- klee_eh_cxx.cpp----------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
 #include <cassert>
 #include <cstdint>
 #include <cstdio>
diff --git a/test/CXX/symex/basic_c++/templates.cpp b/test/CXX/symex/basic_c++/templates.cpp
index c5abb983..b248af42 100644
--- a/test/CXX/symex/basic_c++/templates.cpp
+++ b/test/CXX/symex/basic_c++/templates.cpp
@@ -1,7 +1,7 @@
 // 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
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=uclibc %t.bc 2>&1
 
 #include <cassert>
 
diff --git a/test/CXX/symex/libc++/simple_exception.cpp b/test/CXX/symex/libc++/simple_exception.cpp
index 4d7d2c92..0196e1eb 100644
--- a/test/CXX/symex/libc++/simple_exception.cpp
+++ b/test/CXX/symex/libc++/simple_exception.cpp
@@ -6,15 +6,18 @@
 // 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 <cstdio>
 #include <stdexcept>
 
 int main(int argc, char **args) {
   try {
     throw std::runtime_error("foo");
   } catch (const std::runtime_error &ex) {
+    std::puts(ex.what());
+    // CHECK: foo
   }
 }
+
+// CHECK: KLEE: done: completed paths = 1