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