xref: /llvm-project/libc/test/src/fenv/enabled_exceptions_test.cpp (revision 837dab96d6f5bece79fd58d28ea2e6f7c0912493)
1ab3cbe4bSSiva Chandra Reddy //===-- Unittests for feraiseexcept with exceptions enabled ---------------===//
2ab3cbe4bSSiva Chandra Reddy //
3ab3cbe4bSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ab3cbe4bSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5ab3cbe4bSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ab3cbe4bSSiva Chandra Reddy //
7ab3cbe4bSSiva Chandra Reddy //===----------------------------------------------------------------------===//
8ab3cbe4bSSiva Chandra Reddy 
9ab3cbe4bSSiva Chandra Reddy #include "src/fenv/feclearexcept.h"
10ab3cbe4bSSiva Chandra Reddy #include "src/fenv/feraiseexcept.h"
11ab3cbe4bSSiva Chandra Reddy #include "src/fenv/fetestexcept.h"
12ab3cbe4bSSiva Chandra Reddy 
1376ec69a9STue Ly #include "src/__support/FPUtil/FEnvImpl.h"
14f100ec25SGuillaume Chatelet #include "src/__support/macros/properties/architectures.h"
15*837dab96SRoland McGrath #include "test/UnitTest/FEnvSafeTest.h"
16af1315c2SSiva Chandra Reddy #include "test/UnitTest/FPExceptMatcher.h"
17af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
18ab3cbe4bSSiva Chandra Reddy 
1949561181SJob Henandez Lara #include "hdr/fenv_macros.h"
20ab3cbe4bSSiva Chandra Reddy #include <signal.h>
21ab3cbe4bSSiva Chandra Reddy 
22*837dab96SRoland McGrath #include "excepts.h"
23*837dab96SRoland McGrath 
24*837dab96SRoland McGrath using LlvmLibcExceptionStatusTest = LIBC_NAMESPACE::testing::FEnvSafeTest;
25*837dab96SRoland McGrath 
26ab3cbe4bSSiva Chandra Reddy // This test enables an exception and verifies that raising that exception
27ab3cbe4bSSiva Chandra Reddy // triggers SIGFPE.
TEST_F(LlvmLibcExceptionStatusTest,RaiseAndCrash)28*837dab96SRoland McGrath TEST_F(LlvmLibcExceptionStatusTest, RaiseAndCrash) {
29e3087c4bSMikhail R. Gadelha #if defined(LIBC_TARGET_ARCH_IS_ANY_ARM) ||                                    \
30e3087c4bSMikhail R. Gadelha     defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)
31ae8e1b8fSSiva Chandra Reddy   // Few Arm HW implementations do not trap exceptions. We skip this test
32c5cfbe40SSiva Chandra Reddy   // completely on such HW.
33c5cfbe40SSiva Chandra Reddy   //
34c5cfbe40SSiva Chandra Reddy   // Whether HW supports trapping exceptions or not is deduced by enabling an
35c5cfbe40SSiva Chandra Reddy   // exception and reading back to see if the exception got enabled. If the
36c5cfbe40SSiva Chandra Reddy   // exception did not get enabled, then it means that the HW does not support
37c5cfbe40SSiva Chandra Reddy   // trapping exceptions.
38b6bc9d72SGuillaume Chatelet   LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
39b6bc9d72SGuillaume Chatelet   LIBC_NAMESPACE::fputil::enable_except(FE_DIVBYZERO);
40b6bc9d72SGuillaume Chatelet   if (LIBC_NAMESPACE::fputil::get_except() == 0)
41c5cfbe40SSiva Chandra Reddy     return;
426f8dfeeeSSiva Chandra #endif // Architectures where exception trapping is not supported
43c5cfbe40SSiva Chandra Reddy 
44ab3cbe4bSSiva Chandra Reddy   // TODO: Install a floating point exception handler and verify that the
45ab3cbe4bSSiva Chandra Reddy   // the expected exception was raised. One will have to longjmp back from
46ab3cbe4bSSiva Chandra Reddy   // that exception handler, so such a testing can be done after we have
47ab3cbe4bSSiva Chandra Reddy   // longjmp implemented.
48ab3cbe4bSSiva Chandra Reddy 
49*837dab96SRoland McGrath   for (int e : EXCEPTS) {
50b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
51b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::fputil::enable_except(e);
52b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::feclearexcept(FE_ALL_EXCEPT), 0);
53ab3cbe4bSSiva Chandra Reddy     // Raising all exceptions except |e| should not call the
54ab3cbe4bSSiva Chandra Reddy     // SIGFPE handler. They should set the exception flag though,
55ff384700SSiva Chandra Reddy     // so we verify that. Since other exceptions like FE_DIVBYZERO
56ff384700SSiva Chandra Reddy     // can raise FE_INEXACT as well, we don't verify the other
57ff384700SSiva Chandra Reddy     // exception flags when FE_INEXACT is enabled.
58ff384700SSiva Chandra Reddy     if (e != FE_INEXACT) {
5925226f3eSMichael Jones       int others = ALL_EXCEPTS & ~e;
60b6bc9d72SGuillaume Chatelet       ASSERT_EQ(LIBC_NAMESPACE::feraiseexcept(others), 0);
61b6bc9d72SGuillaume Chatelet       ASSERT_EQ(LIBC_NAMESPACE::fetestexcept(others), others);
62ff384700SSiva Chandra Reddy     }
63ab3cbe4bSSiva Chandra Reddy 
64c24c18bbSSiva Chandra Reddy     ASSERT_RAISES_FP_EXCEPT([=] {
65c24c18bbSSiva Chandra Reddy       // In test frameworks like Fuchsia's zxtest, this translates to
66c24c18bbSSiva Chandra Reddy       // a death test which runs this closure in a different thread. So,
67c24c18bbSSiva Chandra Reddy       // we enable the exception again inside this closure so that the
68c24c18bbSSiva Chandra Reddy       // exception gets enabled for the thread running this closure.
69b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::fputil::enable_except(e);
70b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::feraiseexcept(e);
71c24c18bbSSiva Chandra Reddy     });
72c24c18bbSSiva Chandra Reddy 
73c24c18bbSSiva Chandra Reddy     // Cleanup.
74b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
75b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::feclearexcept(FE_ALL_EXCEPT), 0);
76ab3cbe4bSSiva Chandra Reddy   }
77ab3cbe4bSSiva Chandra Reddy }
78