1 //===-- Unittests for feholdexcept with exceptions enabled ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "hdr/types/fenv_t.h"
10 #include "src/fenv/feholdexcept.h"
12 #include "src/__support/FPUtil/FEnvImpl.h"
13 #include "src/__support/macros/properties/architectures.h"
14 #include "test/UnitTest/FEnvSafeTest.h"
15 #include "test/UnitTest/FPExceptMatcher.h"
16 #include "test/UnitTest/Test.h"
20 using LlvmLibcFEnvTest
= LIBC_NAMESPACE::testing::FEnvSafeTest
;
22 TEST_F(LlvmLibcFEnvTest
, RaiseAndCrash
) {
23 #if defined(LIBC_TARGET_ARCH_IS_ANY_ARM) || \
24 defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
25 // Few Arm HW implementations do not trap exceptions. We skip this test
26 // completely on such HW.
28 // Whether HW supports trapping exceptions or not is deduced by enabling an
29 // exception and reading back to see if the exception got enabled. If the
30 // exception did not get enabled, then it means that the HW does not support
31 // trapping exceptions.
32 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT
);
33 LIBC_NAMESPACE::fputil::enable_except(FE_DIVBYZERO
);
34 if (LIBC_NAMESPACE::fputil::get_except() == 0)
36 #endif // Architectures where exception trapping is not supported
38 int excepts
[] = {FE_DIVBYZERO
, FE_INVALID
, FE_INEXACT
, FE_OVERFLOW
,
41 for (int e
: excepts
) {
43 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT
);
44 LIBC_NAMESPACE::fputil::enable_except(e
);
45 ASSERT_EQ(LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT
), 0);
46 ASSERT_EQ(LIBC_NAMESPACE::feholdexcept(&env
), 0);
47 // feholdexcept should disable all excepts so raising an exception
48 // should not crash/invoke the exception handler.
49 ASSERT_EQ(LIBC_NAMESPACE::fputil::raise_except(e
), 0);
51 ASSERT_RAISES_FP_EXCEPT([=] {
52 // When we put back the saved env, which has the exception enabled, it
53 // should crash with SIGFPE. Note that we set the old environment
54 // back inside this closure because in some test frameworks like Fuchsia's
55 // zxtest, this test translates to a death test in which this closure is
56 // run in a different thread. So, we set the old environment inside
57 // this closure so that the exception gets enabled for the thread running
59 LIBC_NAMESPACE::fputil::set_env(&env
);
60 LIBC_NAMESPACE::fputil::raise_except(e
);
64 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT
);
65 ASSERT_EQ(LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT
), 0);