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