xref: /aosp_15_r20/external/llvm-libc/test/UnitTest/FPExceptMatcher.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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 Worker static 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 Worker FPExceptMatcher::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