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 //===----------------------------------------------------------------------===// 8 9 #include "src/fenv/feholdexcept.h" 10 11 #include "src/__support/FPUtil/FEnvUtils.h" 12 #include "src/__support/FPUtil/FPExceptMatcher.h" 13 #include "utils/UnitTest/Test.h" 14 15 #include <fenv.h> 16 17 TEST(LlvmLibcFEnvTest, RaiseAndCrash) { 18 #ifdef __aarch64__ 19 // Few aarch64 HW implementations do not trap exceptions. We skip this test 20 // completely on such HW. 21 // 22 // Whether HW supports trapping exceptions or not is deduced by enabling an 23 // exception and reading back to see if the exception got enabled. If the 24 // exception did not get enabled, then it means that the HW does not support 25 // trapping exceptions. 26 __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); 27 __llvm_libc::fputil::enableExcept(FE_DIVBYZERO); 28 if (__llvm_libc::fputil::getExcept() == 0) 29 return; 30 #endif 31 32 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW, 33 FE_UNDERFLOW}; 34 35 for (int e : excepts) { 36 fenv_t env; 37 __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); 38 __llvm_libc::fputil::enableExcept(e); 39 ASSERT_EQ(__llvm_libc::fputil::clearExcept(FE_ALL_EXCEPT), 0); 40 ASSERT_EQ(__llvm_libc::feholdexcept(&env), 0); 41 // feholdexcept should disable all excepts so raising an exception 42 // should not crash/invoke the exception handler. 43 ASSERT_EQ(__llvm_libc::fputil::raiseExcept(e), 0); 44 45 ASSERT_RAISES_FP_EXCEPT([=] { 46 // When we put back the saved env, which has the exception enabled, it 47 // should crash with SIGFPE. Note that we set the old environment 48 // back inside this closure because in some test frameworks like Fuchsia's 49 // zxtest, this test translates to a death test in which this closure is 50 // run in a different thread. So, we set the old environment inside 51 // this closure so that the exception gets enabled for the thread running 52 // this closure. 53 __llvm_libc::fputil::setEnv(&env); 54 __llvm_libc::fputil::raiseExcept(e); 55 }); 56 57 // Cleanup 58 __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT); 59 ASSERT_EQ(__llvm_libc::fputil::clearExcept(FE_ALL_EXCEPT), 0); 60 } 61 } 62