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 <fenv.h> 12 #include <memory> 13 #include <setjmp.h> 14 #include <signal.h> 15 16 namespace __llvm_libc { 17 namespace fputil { 18 namespace testing { 19 20 #if defined(_WIN32) 21 #define sigjmp_buf jmp_buf 22 #define sigsetjmp(buf, save) setjmp(buf) 23 #define siglongjmp(buf, val) longjmp(buf, val) 24 #endif 25 26 static thread_local sigjmp_buf jumpBuffer; 27 static thread_local bool caughtExcept; 28 sigfpeHandler(int sig)29static void sigfpeHandler(int sig) { 30 caughtExcept = true; 31 siglongjmp(jumpBuffer, -1); 32 } 33 FPExceptMatcher(FunctionCaller * func)34FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) { 35 auto oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler); 36 std::unique_ptr<FunctionCaller> funcUP(func); 37 38 caughtExcept = false; 39 fenv_t oldEnv; 40 fegetenv(&oldEnv); 41 if (sigsetjmp(jumpBuffer, 1) == 0) 42 funcUP->call(); 43 // We restore the previous floating point environment after 44 // the call to the function which can potentially raise SIGFPE. 45 fesetenv(&oldEnv); 46 signal(SIGFPE, oldSIGFPEHandler); 47 exceptionRaised = caughtExcept; 48 } 49 50 } // namespace testing 51 } // namespace fputil 52 } // namespace __llvm_libc 53