1 //===-- Unittests for feraiseexcept 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 //===----------------------------------------------------------------------===// 8 9 #include "src/fenv/feclearexcept.h" 10 #include "src/fenv/feraiseexcept.h" 11 #include "src/fenv/fetestexcept.h" 12 13 #include "src/__support/FPUtil/FEnvUtils.h" 14 #include "src/__support/architectures.h" 15 #include "utils/UnitTest/FPExceptMatcher.h" 16 #include "utils/UnitTest/Test.h" 17 18 #include <fenv.h> 19 #include <signal.h> 20 21 // This test enables an exception and verifies that raising that exception 22 // triggers SIGFPE. 23 TEST(LlvmLibcExceptionStatusTest, RaiseAndCrash) { 24 #if defined(LLVM_LIBC_ARCH_AARCH64) 25 // Few aarch64 HW implementations do not trap exceptions. We skip this test 26 // completely on such HW. 27 // 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 __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 33 __llvm_libc::fputil::enable_except(FE_DIVBYZERO); 34 if (__llvm_libc::fputil::get_except() == 0) 35 return; 36 #endif // defined(LLVM_LIBC_ARCH_AARCH64) 37 38 // TODO: Install a floating point exception handler and verify that the 39 // the expected exception was raised. One will have to longjmp back from 40 // that exception handler, so such a testing can be done after we have 41 // longjmp implemented. 42 43 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, 44 FE_UNDERFLOW}; 45 46 // We '|' the individual exception flags instead of using FE_ALL_EXCEPT 47 // as it can include non-standard extensions. Note that we should be able 48 // to compile this file with headers from other libcs as well. 49 constexpr int ALL_EXCEPTS = 50 FE_DIVBYZERO | FE_INVALID | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW; 51 52 for (int e : excepts) { 53 __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 54 __llvm_libc::fputil::enable_except(e); 55 ASSERT_EQ(__llvm_libc::feclearexcept(FE_ALL_EXCEPT), 0); 56 // Raising all exceptions except |e| should not call the 57 // SIGFPE handler. They should set the exception flag though, 58 // so we verify that. Since other exceptions like FE_DIVBYZERO 59 // can raise FE_INEXACT as well, we don't verify the other 60 // exception flags when FE_INEXACT is enabled. 61 if (e != FE_INEXACT) { 62 int others = ALL_EXCEPTS & ~e; 63 ASSERT_EQ(__llvm_libc::feraiseexcept(others), 0); 64 ASSERT_EQ(__llvm_libc::fetestexcept(others), others); 65 } 66 67 ASSERT_RAISES_FP_EXCEPT([=] { 68 // In test frameworks like Fuchsia's zxtest, this translates to 69 // a death test which runs this closure in a different thread. So, 70 // we enable the exception again inside this closure so that the 71 // exception gets enabled for the thread running this closure. 72 __llvm_libc::fputil::enable_except(e); 73 __llvm_libc::feraiseexcept(e); 74 }); 75 76 // Cleanup. 77 __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT); 78 ASSERT_EQ(__llvm_libc::feclearexcept(FE_ALL_EXCEPT), 0); 79 } 80 } 81