1*71db0c75SAndroid Build Coastguard Worker //===-- FPExceptMatchers.cpp ----------------------------------------------===// 2*71db0c75SAndroid Build Coastguard Worker // 3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*71db0c75SAndroid Build Coastguard Worker // 7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*71db0c75SAndroid Build Coastguard Worker 9*71db0c75SAndroid Build Coastguard Worker #include "FPExceptMatcher.h" 10*71db0c75SAndroid Build Coastguard Worker 11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h" 12*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h" 13*71db0c75SAndroid Build Coastguard Worker 14*71db0c75SAndroid Build Coastguard Worker #include "hdr/types/fenv_t.h" 15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FEnvImpl.h" 16*71db0c75SAndroid Build Coastguard Worker #include <memory> 17*71db0c75SAndroid Build Coastguard Worker #include <setjmp.h> 18*71db0c75SAndroid Build Coastguard Worker #include <signal.h> 19*71db0c75SAndroid Build Coastguard Worker 20*71db0c75SAndroid Build Coastguard Worker #if LIBC_TEST_HAS_MATCHERS() 21*71db0c75SAndroid Build Coastguard Worker 22*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL { 23*71db0c75SAndroid Build Coastguard Worker namespace testing { 24*71db0c75SAndroid Build Coastguard Worker 25*71db0c75SAndroid Build Coastguard Worker #if defined(_WIN32) 26*71db0c75SAndroid Build Coastguard Worker #define sigjmp_buf jmp_buf 27*71db0c75SAndroid Build Coastguard Worker #define sigsetjmp(buf, save) setjmp(buf) 28*71db0c75SAndroid Build Coastguard Worker #define siglongjmp(buf, val) longjmp(buf, val) 29*71db0c75SAndroid Build Coastguard Worker #endif 30*71db0c75SAndroid Build Coastguard Worker 31*71db0c75SAndroid Build Coastguard Worker static thread_local sigjmp_buf jumpBuffer; 32*71db0c75SAndroid Build Coastguard Worker static thread_local bool caughtExcept; 33*71db0c75SAndroid Build Coastguard Worker sigfpeHandler(int sig)34*71db0c75SAndroid Build Coastguard Workerstatic void sigfpeHandler(int sig) { 35*71db0c75SAndroid Build Coastguard Worker caughtExcept = true; 36*71db0c75SAndroid Build Coastguard Worker siglongjmp(jumpBuffer, -1); 37*71db0c75SAndroid Build Coastguard Worker } 38*71db0c75SAndroid Build Coastguard Worker FPExceptMatcher(FunctionCaller * func)39*71db0c75SAndroid Build Coastguard WorkerFPExceptMatcher::FPExceptMatcher(FunctionCaller *func) { 40*71db0c75SAndroid Build Coastguard Worker auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler); 41*71db0c75SAndroid Build Coastguard Worker std::unique_ptr<FunctionCaller> funcUP(func); 42*71db0c75SAndroid Build Coastguard Worker 43*71db0c75SAndroid Build Coastguard Worker caughtExcept = false; 44*71db0c75SAndroid Build Coastguard Worker fenv_t oldEnv; 45*71db0c75SAndroid Build Coastguard Worker fputil::get_env(&oldEnv); 46*71db0c75SAndroid Build Coastguard Worker if (sigsetjmp(jumpBuffer, 1) == 0) 47*71db0c75SAndroid Build Coastguard Worker funcUP->call(); 48*71db0c75SAndroid Build Coastguard Worker // We restore the previous floating point environment after 49*71db0c75SAndroid Build Coastguard Worker // the call to the function which can potentially raise SIGFPE. 50*71db0c75SAndroid Build Coastguard Worker fputil::set_env(&oldEnv); 51*71db0c75SAndroid Build Coastguard Worker signal(SIGFPE, oldSIGFPEHandler); 52*71db0c75SAndroid Build Coastguard Worker exceptionRaised = caughtExcept; 53*71db0c75SAndroid Build Coastguard Worker } 54*71db0c75SAndroid Build Coastguard Worker 55*71db0c75SAndroid Build Coastguard Worker } // namespace testing 56*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL 57*71db0c75SAndroid Build Coastguard Worker 58*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_TEST_HAS_MATCHERS() 59