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
21namespace LIBC_NAMESPACE {
22namespace 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
30static thread_local sigjmp_buf jumpBuffer;
31static thread_local bool caughtExcept;
32
33static void sigfpeHandler(int sig) {
34 caughtExcept = true;
35 siglongjmp(env: jumpBuffer, val: -1);
36}
37
38FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
39 auto oldSIGFPEHandler = signal(SIGFPE, handler: &sigfpeHandler);
40 std::unique_ptr<FunctionCaller> funcUP(func);
41
42 caughtExcept = false;
43 fenv_t oldEnv;
44 fputil::get_env(envp: &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, handler: oldSIGFPEHandler);
51 exceptionRaised = caughtExcept;
52}
53
54} // namespace testing
55} // namespace LIBC_NAMESPACE
56
57#endif // LIBC_TEST_HAS_MATCHERS()
58

source code of libc/test/UnitTest/FPExceptMatcher.cpp