|  | //===-- 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 "test/UnitTest/Test.h" | 
|  |  | 
|  | #include "hdr/types/fenv_t.h" | 
|  | #include "src/__support/FPUtil/FEnvImpl.h" | 
|  | #include <memory> | 
|  | #include <setjmp.h> | 
|  | #include <signal.h> | 
|  |  | 
|  | #if LIBC_TEST_HAS_MATCHERS() | 
|  |  | 
|  | namespace LIBC_NAMESPACE { | 
|  | 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; | 
|  | fputil::get_env(&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. | 
|  | fputil::set_env(&oldEnv); | 
|  | signal(SIGFPE, oldSIGFPEHandler); | 
|  | exceptionRaised = caughtExcept; | 
|  | } | 
|  |  | 
|  | } // namespace testing | 
|  | } // namespace LIBC_NAMESPACE | 
|  |  | 
|  | #endif // LIBC_TEST_HAS_MATCHERS() |