forked from OSchip/llvm-project
53 lines
1.4 KiB
C++
53 lines
1.4 KiB
C++
|
//===-- FPExceptMatchers.cpp ----------------------------------------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "FPExceptMatcher.h"
|
||
|
|
||
|
#include <fenv.h>
|
||
|
#include <memory>
|
||
|
#include <setjmp.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
namespace __llvm_libc {
|
||
|
namespace fputil {
|
||
|
namespace testing {
|
||
|
|
||
|
#if defined(_WIN32)
|
||
|
#define sigjmp_buf jmp_buf
|
||
|
#define sigsetjmp(buf, save) setjmp(buf)
|
||
|
#define siglongjmp(buf, val) longjmp(buf, val)
|
||
|
#endif
|
||
|
|
||
|
static thread_local sigjmp_buf jumpBuffer;
|
||
|
static thread_local bool caughtExcept;
|
||
|
|
||
|
static void sigfpeHandler(int sig) {
|
||
|
caughtExcept = true;
|
||
|
siglongjmp(jumpBuffer, -1);
|
||
|
}
|
||
|
|
||
|
FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
|
||
|
auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
|
||
|
std::unique_ptr<FunctionCaller> funcUP(func);
|
||
|
|
||
|
caughtExcept = false;
|
||
|
fenv_t oldEnv;
|
||
|
fegetenv(&oldEnv);
|
||
|
if (sigsetjmp(jumpBuffer, 1) == 0)
|
||
|
funcUP->call();
|
||
|
// We restore the previous floating point environment after
|
||
|
// the call to the function which can potentially raise SIGFPE.
|
||
|
fesetenv(&oldEnv);
|
||
|
signal(SIGFPE, oldSIGFPEHandler);
|
||
|
exceptionRaised = caughtExcept;
|
||
|
}
|
||
|
|
||
|
} // namespace testing
|
||
|
} // namespace fputil
|
||
|
} // namespace __llvm_libc
|