summaryrefslogtreecommitdiff
path: root/libc/test/src/fenv/exception_status_test.cpp
blob: c81dae65b5c27d3cb9ab3bee982fdfe48ad003ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//===-- Unittests for feclearexcept, feraiseexcept and fetestexpect -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/fenv/feclearexcept.h"
#include "src/fenv/feraiseexcept.h"
#include "src/fenv/fetestexcept.h"

#include "src/__support/FPUtil/FEnvUtils.h"
#include "utils/UnitTest/Test.h"

#include <fenv.h>

TEST(LlvmLibcExceptionStatusTest, RaiseAndTest) {
  // This test raises a set of exceptions and checks that the exception
  // status flags are updated. The intention is really not to invoke the
  // exception handler. Hence, we will disable all exceptions at the
  // beginning.
  __llvm_libc::fputil::disableExcept(FE_ALL_EXCEPT);

  int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
                   FE_UNDERFLOW};

  constexpr int allExcepts =
      FE_DIVBYZERO | FE_INVALID | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW;

  for (int e : excepts) {
    int r = __llvm_libc::feraiseexcept(e);
    ASSERT_EQ(r, 0);
    int s = __llvm_libc::fetestexcept(e);
    ASSERT_EQ(s, e);

    r = __llvm_libc::feclearexcept(e);
    ASSERT_EQ(r, 0);
    s = __llvm_libc::fetestexcept(e);
    ASSERT_EQ(s, 0);
  }

  for (int e1 : excepts) {
    for (int e2 : excepts) {
      int e = e1 | e2;
      int r = __llvm_libc::feraiseexcept(e);
      ASSERT_EQ(r, 0);
      int s = __llvm_libc::fetestexcept(e);
      ASSERT_EQ(s, e);

      r = __llvm_libc::feclearexcept(e);
      ASSERT_EQ(r, 0);
      s = __llvm_libc::fetestexcept(e);
      ASSERT_EQ(s, 0);
    }
  }

  for (int e1 : excepts) {
    for (int e2 : excepts) {
      for (int e3 : excepts) {
        int e = e1 | e2 | e3;
        int r = __llvm_libc::feraiseexcept(e);
        ASSERT_EQ(r, 0);
        int s = __llvm_libc::fetestexcept(e);
        ASSERT_EQ(s, e);

        r = __llvm_libc::feclearexcept(e);
        ASSERT_EQ(r, 0);
        s = __llvm_libc::fetestexcept(e);
        ASSERT_EQ(s, 0);
      }
    }
  }

  for (int e1 : excepts) {
    for (int e2 : excepts) {
      for (int e3 : excepts) {
        for (int e4 : excepts) {
          int e = e1 | e2 | e3 | e4;
          int r = __llvm_libc::feraiseexcept(e);
          ASSERT_EQ(r, 0);
          int s = __llvm_libc::fetestexcept(e);
          ASSERT_EQ(s, e);

          r = __llvm_libc::feclearexcept(e);
          ASSERT_EQ(r, 0);
          s = __llvm_libc::fetestexcept(e);
          ASSERT_EQ(s, 0);
        }
      }
    }
  }

  for (int e1 : excepts) {
    for (int e2 : excepts) {
      for (int e3 : excepts) {
        for (int e4 : excepts) {
          for (int e5 : excepts) {
            int e = e1 | e2 | e3 | e4 | e5;
            int r = __llvm_libc::feraiseexcept(e);
            ASSERT_EQ(r, 0);
            int s = __llvm_libc::fetestexcept(e);
            ASSERT_EQ(s, e);

            r = __llvm_libc::feclearexcept(e);
            ASSERT_EQ(r, 0);
            s = __llvm_libc::fetestexcept(e);
            ASSERT_EQ(s, 0);
          }
        }
      }
    }
  }

  int r = __llvm_libc::feraiseexcept(allExcepts);
  ASSERT_EQ(r, 0);
  int s = __llvm_libc::fetestexcept(allExcepts);
  ASSERT_EQ(s, allExcepts);
}