diff options
-rw-r--r-- | lib/Core/Executor.cpp | 37 | ||||
-rw-r--r-- | test/Feature/ExtCallWarnings.c | 26 |
2 files changed, 49 insertions, 14 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 906484c6..b4da6a08 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -198,17 +198,27 @@ cl::opt<ExternalCallPolicy> ExternalCalls( cl::init(ExternalCallPolicy::Concrete), cl::cat(ExtCallsCat)); -cl::opt<bool> SuppressExternalWarnings( - "suppress-external-warnings", - cl::init(false), - cl::desc("Supress warnings about calling external functions."), - cl::cat(ExtCallsCat)); -cl::opt<bool> AllExternalWarnings( - "all-external-warnings", - cl::init(false), - cl::desc("Issue a warning every time an external call is made, " - "as opposed to once per function (default=false)"), +/*** External call warnings options ***/ + +enum class ExtCallWarnings { + None, // Never warn on external calls + OncePerFunction, // Only warn once per function on external calls + All, // Always warn on external calls +}; + +cl::opt<ExtCallWarnings> ExternalCallWarnings( + "external-call-warnings", + cl::desc("Specify when to warn about external calls"), + cl::values( + clEnumValN( + ExtCallWarnings::None, "none", + "Never warn"), + clEnumValN(ExtCallWarnings::OncePerFunction, "once-per-function", + "Warn once per external function (default)"), + clEnumValN(ExternalCallPolicy::All, "all", + "Always warn")), + cl::init(ExtCallWarnings::OncePerFunction), cl::cat(ExtCallsCat)); cl::opt<std::size_t> ExternalPageThreshold( @@ -1323,7 +1333,7 @@ Executor::toConstant(ExecutionState &state, << " to value " << value << " (" << (*(state.pc)).info->file << ":" << (*(state.pc)).info->line << ")"; - if (AllExternalWarnings) + if (ExternalCallWarnings == ExtCallWarnings::All) klee_warning("%s", os.str().c_str()); else klee_warning_once(reason, "%s", os.str().c_str()); @@ -3966,8 +3976,7 @@ void Executor::callExternalFunction(ExecutionState &state, errnoValue->getZExtValue(sizeof(*errno_addr) * 8)); #endif - if (!SuppressExternalWarnings) { - + if (ExternalCallWarnings != ExtCallWarnings::None) { std::string TmpStr; llvm::raw_string_ostream os(TmpStr); os << "calling external: " << callable->getName().str() << "("; @@ -3978,7 +3987,7 @@ void Executor::callExternalFunction(ExecutionState &state, } os << ") at " << state.pc->getSourceLocation(); - if (AllExternalWarnings) + if (ExternalCallWarnings == ExtCallWarnings::All) klee_warning("%s", os.str().c_str()); else klee_warning_once(callable->getValue(), "%s", os.str().c_str()); diff --git a/test/Feature/ExtCallWarnings.c b/test/Feature/ExtCallWarnings.c new file mode 100644 index 00000000..6ee3f371 --- /dev/null +++ b/test/Feature/ExtCallWarnings.c @@ -0,0 +1,26 @@ +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --external-call-warnings=none %t.bc 2>&1 | FileCheck --check-prefix=CHECK-NONE %s + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --external-call-warnings=once-per-function %t.bc 2>&1 | FileCheck --check-prefix=CHECK-ONCE %s + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --external-call-warnings=all %t.bc 2>&1 | FileCheck --check-prefix=CHECK-ALL %s + +#include "klee/klee.h" +#include <stdio.h> +#include <stdlib.h> + +int main() { + return abs(-5) + abs(6); + // CHECK-NONE-NOT: calling external + + // CHECK-ONCE: calling external + // CHECK-ONCE-NOT: calling external + + // CHECK-ALL: calling external + // CHECK-ALL: calling external + // CHECK-ALL-NOT: calling external +} |