68 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/types/fenv_t.h"10#include "src/fenv/feholdexcept.h"11 12#include "src/__support/FPUtil/FEnvImpl.h"13#include "src/__support/macros/properties/architectures.h"14#include "test/UnitTest/FEnvSafeTest.h"15#include "test/UnitTest/FPExceptMatcher.h"16#include "test/UnitTest/Test.h"17 18#include "excepts.h"19 20using LlvmLibcFEnvTest = LIBC_NAMESPACE::testing::FEnvSafeTest;21 22TEST_F(LlvmLibcFEnvTest, RaiseAndCrash) {23#if defined(LIBC_TARGET_ARCH_IS_ANY_ARM) || \24 defined(LIBC_TARGET_ARCH_IS_ANY_RISCV)25 // Few Arm HW implementations do not trap exceptions. We skip this test26 // completely on such HW.27 //28 // Whether HW supports trapping exceptions or not is deduced by enabling an29 // exception and reading back to see if the exception got enabled. If the30 // exception did not get enabled, then it means that the HW does not support31 // trapping exceptions.32 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);33 LIBC_NAMESPACE::fputil::enable_except(FE_DIVBYZERO);34 if (LIBC_NAMESPACE::fputil::get_except() == 0)35 return;36#endif // Architectures where exception trapping is not supported37 38 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,39 FE_UNDERFLOW};40 41 for (int e : excepts) {42 fenv_t env;43 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);44 LIBC_NAMESPACE::fputil::enable_except(e);45 ASSERT_EQ(LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT), 0);46 ASSERT_EQ(LIBC_NAMESPACE::feholdexcept(&env), 0);47 // feholdexcept should disable all excepts so raising an exception48 // should not crash/invoke the exception handler.49 ASSERT_EQ(LIBC_NAMESPACE::fputil::raise_except(e), 0);50 51 ASSERT_RAISES_FP_EXCEPT([=] {52 // When we put back the saved env, which has the exception enabled, it53 // should crash with SIGFPE. Note that we set the old environment54 // back inside this closure because in some test frameworks like Fuchsia's55 // zxtest, this test translates to a death test in which this closure is56 // run in a different thread. So, we set the old environment inside57 // this closure so that the exception gets enabled for the thread running58 // this closure.59 LIBC_NAMESPACE::fputil::set_env(&env);60 LIBC_NAMESPACE::fputil::raise_except(e);61 });62 63 // Cleanup64 LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);65 ASSERT_EQ(LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT), 0);66 }67}68