1 //===-- Unittests for fegetenv and fesetenv -------------------------------===//
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/fegetenv.h"
10 #include "src/fenv/fegetround.h"
11 #include "src/fenv/fesetenv.h"
12 #include "src/fenv/fesetround.h"
13
14 #include "src/__support/FPUtil/FEnvImpl.h"
15 #include "utils/UnitTest/Test.h"
16
17 #include <fenv.h>
18
TEST(LlvmLibcFenvTest,GetEnvAndSetEnv)19 TEST(LlvmLibcFenvTest, GetEnvAndSetEnv) {
20 // We will disable all exceptions to prevent invocation of the exception
21 // handler.
22 __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT);
23
24 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
25 FE_UNDERFLOW};
26
27 for (int e : excepts) {
28 __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
29
30 // Save the cleared environment.
31 fenv_t env;
32 ASSERT_EQ(__llvm_libc::fegetenv(&env), 0);
33
34 __llvm_libc::fputil::raise_except(e);
35 // Make sure that the exception is raised.
36 ASSERT_NE(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
37
38 ASSERT_EQ(__llvm_libc::fesetenv(&env), 0);
39 ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
40 }
41 }
42
TEST(LlvmLibcFenvTest,Set_FE_DFL_ENV)43 TEST(LlvmLibcFenvTest, Set_FE_DFL_ENV) {
44 // We will disable all exceptions to prevent invocation of the exception
45 // handler.
46 __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT);
47
48 int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
49 FE_UNDERFLOW};
50
51 for (int e : excepts) {
52 __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
53
54 // Save the cleared environment.
55 fenv_t env;
56 ASSERT_EQ(__llvm_libc::fegetenv(&env), 0);
57
58 __llvm_libc::fputil::raise_except(e);
59 // Make sure that the exception is raised.
60 ASSERT_NE(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
61
62 ASSERT_EQ(__llvm_libc::fesetenv(FE_DFL_ENV), 0);
63 // Setting the default env should clear all exceptions.
64 ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
65 }
66
67 ASSERT_EQ(__llvm_libc::fesetround(FE_DOWNWARD), 0);
68 ASSERT_EQ(__llvm_libc::fesetenv(FE_DFL_ENV), 0);
69 // Setting the default env should set rounding mode to FE_TONEAREST.
70 int rm = __llvm_libc::fegetround();
71 EXPECT_EQ(rm, FE_TONEAREST);
72 }
73
74 #ifdef _WIN32
TEST(LlvmLibcFenvTest,Windows_Set_Get_Test)75 TEST(LlvmLibcFenvTest, Windows_Set_Get_Test) {
76 // If a valid fenv_t is written, then reading it back out should be identical.
77 fenv_t setEnv = {0x7e00053e, 0x0f00000f};
78 fenv_t getEnv;
79 ASSERT_EQ(__llvm_libc::fesetenv(&setEnv), 0);
80 ASSERT_EQ(__llvm_libc::fegetenv(&getEnv), 0);
81
82 ASSERT_EQ(setEnv._Fe_ctl, getEnv._Fe_ctl);
83 ASSERT_EQ(setEnv._Fe_stat, getEnv._Fe_stat);
84 }
85 #endif
86