Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libc / test / src / fenv / feholdexcept_test.cpp
blob735c7705ff49c6ad91b7ac90c5a5d6c8cc2ba93f
1 //===-- Unittests for feholdexcept with exceptions enabled ----------------===//
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 //===----------------------------------------------------------------------===//
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"
16 #include <fenv.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)
31 return;
32 #endif // Architectures where exception trapping is not supported
34 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
35 FE_UNDERFLOW};
37 for (int e : excepts) {
38 fenv_t env;
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
54 // this closure.
55 LIBC_NAMESPACE::fputil::set_env(&env);
56 LIBC_NAMESPACE::fputil::raise_except(e);
57 });
59 // Cleanup
60 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
61 ASSERT_EQ(LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT), 0);