#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();
fesetenv(&oldEnv);
signal(SIGFPE, oldSIGFPEHandler);
exceptionRaised = caughtExcept;
}
}
}
}