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