xref: /llvm-project/libc/test/UnitTest/FPExceptMatcher.cpp (revision 9426fdd4cbd6812b69c218b865f184cb25342be4)
1af1315c2SSiva Chandra Reddy //===-- FPExceptMatchers.cpp ----------------------------------------------===//
2af1315c2SSiva Chandra Reddy //
3af1315c2SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4af1315c2SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5af1315c2SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6af1315c2SSiva Chandra Reddy //
7af1315c2SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8af1315c2SSiva Chandra Reddy 
9af1315c2SSiva Chandra Reddy #include "FPExceptMatcher.h"
10af1315c2SSiva Chandra Reddy 
115ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
120efb376cSNick Desaulniers #include "test/UnitTest/ExecuteFunction.h" // FunctionCaller
13d2be9826SRoland McGrath #include "test/UnitTest/Test.h"
14d2be9826SRoland McGrath 
1575bbf4ddSJob Henandez Lara #include "hdr/types/fenv_t.h"
1675bbf4ddSJob Henandez Lara #include "src/__support/FPUtil/FEnvImpl.h"
17af1315c2SSiva Chandra Reddy #include <setjmp.h>
18af1315c2SSiva Chandra Reddy #include <signal.h>
19af1315c2SSiva Chandra Reddy 
20d2be9826SRoland McGrath #if LIBC_TEST_HAS_MATCHERS()
21d2be9826SRoland McGrath 
225ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
23af1315c2SSiva Chandra Reddy namespace testing {
24af1315c2SSiva Chandra Reddy 
25af1315c2SSiva Chandra Reddy #if defined(_WIN32)
26af1315c2SSiva Chandra Reddy #define sigjmp_buf jmp_buf
27af1315c2SSiva Chandra Reddy #define sigsetjmp(buf, save) setjmp(buf)
28af1315c2SSiva Chandra Reddy #define siglongjmp(buf, val) longjmp(buf, val)
29af1315c2SSiva Chandra Reddy #endif
30af1315c2SSiva Chandra Reddy 
31af1315c2SSiva Chandra Reddy static thread_local sigjmp_buf jumpBuffer;
32af1315c2SSiva Chandra Reddy static thread_local bool caughtExcept;
33af1315c2SSiva Chandra Reddy 
34af1315c2SSiva Chandra Reddy static void sigfpeHandler(int sig) {
35af1315c2SSiva Chandra Reddy   caughtExcept = true;
36af1315c2SSiva Chandra Reddy   siglongjmp(jumpBuffer, -1);
37af1315c2SSiva Chandra Reddy }
38af1315c2SSiva Chandra Reddy 
39af1315c2SSiva Chandra Reddy FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
400efb376cSNick Desaulniers   sighandler_t oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
41af1315c2SSiva Chandra Reddy 
42af1315c2SSiva Chandra Reddy   caughtExcept = false;
43af1315c2SSiva Chandra Reddy   fenv_t oldEnv;
4475bbf4ddSJob Henandez Lara   fputil::get_env(&oldEnv);
45af1315c2SSiva Chandra Reddy   if (sigsetjmp(jumpBuffer, 1) == 0)
460efb376cSNick Desaulniers     func->call();
47*9426fdd4SNick Desaulniers   delete func;
48af1315c2SSiva Chandra Reddy   // We restore the previous floating point environment after
49af1315c2SSiva Chandra Reddy   // the call to the function which can potentially raise SIGFPE.
5075bbf4ddSJob Henandez Lara   fputil::set_env(&oldEnv);
51af1315c2SSiva Chandra Reddy   signal(SIGFPE, oldSIGFPEHandler);
52af1315c2SSiva Chandra Reddy   exceptionRaised = caughtExcept;
53af1315c2SSiva Chandra Reddy }
54af1315c2SSiva Chandra Reddy 
55af1315c2SSiva Chandra Reddy } // namespace testing
565ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
57d2be9826SRoland McGrath 
58d2be9826SRoland McGrath #endif // LIBC_TEST_HAS_MATCHERS()
59