xref: /aosp_15_r20/external/llvm-libc/test/UnitTest/FPExceptMatcher.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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)34 static void sigfpeHandler(int sig) {
35   caughtExcept = true;
36   siglongjmp(jumpBuffer, -1);
37 }
38 
FPExceptMatcher(FunctionCaller * func)39 FPExceptMatcher::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