Skip to content

Commit b854a23

Browse files
[libc][c23][fenv] Implement fetestexceptflag (#87828)
Provide C23 `fetestexceptflag` function according to 7.6.4.6 in the latest [revision of the C standard](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf) from 2023-04-02. Closes #87565.
1 parent 950bb09 commit b854a23

File tree

19 files changed

+110
-10
lines changed

19 files changed

+110
-10
lines changed

libc/config/baremetal/arm/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS
201201
libc.src.fenv.fesetround
202202
libc.src.fenv.feraiseexcept
203203
libc.src.fenv.fetestexcept
204+
libc.src.fenv.fetestexceptflag
204205
libc.src.fenv.feupdateenv
205206

206207
# math.h entrypoints

libc/config/baremetal/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ set(TARGET_LIBM_ENTRYPOINTS
201201
libc.src.fenv.fesetround
202202
libc.src.fenv.feraiseexcept
203203
libc.src.fenv.fetestexcept
204+
libc.src.fenv.fetestexceptflag
204205
libc.src.fenv.feupdateenv
205206

206207
# math.h entrypoints

libc/config/darwin/arm/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ set(TARGET_LIBM_ENTRYPOINTS
112112
libc.src.fenv.fesetround
113113
libc.src.fenv.feraiseexcept
114114
libc.src.fenv.fetestexcept
115+
libc.src.fenv.fetestexceptflag
115116
libc.src.fenv.feupdateenv
116117

117118
# math.h entrypoints

libc/config/darwin/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ set(TARGET_LIBM_ENTRYPOINTS
106106
# libc.src.fenv.fesetround
107107
# libc.src.fenv.feraiseexcept
108108
# libc.src.fenv.fetestexcept
109+
# libc.src.fenv.fetestexceptflag
109110
# libc.src.fenv.feupdateenv
110111

111112
## Currently disabled for failing tests.

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ set(TARGET_LIBM_ENTRYPOINTS
324324
libc.src.fenv.fesetround
325325
libc.src.fenv.feraiseexcept
326326
libc.src.fenv.fetestexcept
327+
libc.src.fenv.fetestexceptflag
327328
libc.src.fenv.feupdateenv
328329

329330
# math.h entrypoints

libc/config/linux/arm/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ set(TARGET_LIBM_ENTRYPOINTS
192192
libc.src.fenv.fesetround
193193
libc.src.fenv.feraiseexcept
194194
libc.src.fenv.fetestexcept
195+
libc.src.fenv.fetestexceptflag
195196
libc.src.fenv.feupdateenv
196197

197198
# math.h entrypoints

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ set(TARGET_LIBM_ENTRYPOINTS
332332
libc.src.fenv.fesetround
333333
libc.src.fenv.feraiseexcept
334334
libc.src.fenv.fetestexcept
335+
libc.src.fenv.fetestexceptflag
335336
libc.src.fenv.feupdateenv
336337

337338
# math.h entrypoints

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ set(TARGET_LIBM_ENTRYPOINTS
346346
libc.src.fenv.fesetround
347347
libc.src.fenv.feraiseexcept
348348
libc.src.fenv.fetestexcept
349+
libc.src.fenv.fetestexceptflag
349350
libc.src.fenv.feupdateenv
350351

351352
# math.h entrypoints

libc/config/windows/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ set(TARGET_LIBM_ENTRYPOINTS
110110
libc.src.fenv.fesetround
111111
libc.src.fenv.feraiseexcept
112112
libc.src.fenv.fetestexcept
113+
libc.src.fenv.fetestexceptflag
113114
libc.src.fenv.feupdateenv
114115

115116
# math.h entrypoints

libc/docs/c23.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Additions:
2121
* fenv.h
2222

2323
* fesetexcept |check|
24-
* fetestexceptflag
24+
* fetestexceptflag |check|
2525
* fegetmode
2626
* fesetmode
2727
* math.h

libc/docs/fenv.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fenv.h Functions
4242
- |check|
4343
- 7.6.6.3
4444
* - fesetexcept
45-
-
45+
- |check|
4646
- 7.6.4.4
4747
* - fesetexceptflag
4848
- |check|
@@ -57,7 +57,7 @@ fenv.h Functions
5757
- |check|
5858
- 7.6.4.7
5959
* - fetestexceptflag
60-
-
60+
- |check|
6161
- 7.6.4.6
6262
* - feupdateenv
6363
- |check|

libc/spec/stdc.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ def StdC : StandardSpec<"stdc"> {
149149
RetValSpec<IntType>,
150150
[ArgSpec<IntType>]
151151
>,
152+
FunctionSpec<
153+
"fetestexceptflag",
154+
RetValSpec<IntType>,
155+
[ArgSpec<ConstFExceptTPtr>, ArgSpec<IntType>]
156+
>,
152157
FunctionSpec<
153158
"feraiseexcept",
154159
RetValSpec<IntType>,

libc/src/fenv/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ add_entrypoint_object(
5858
-O2
5959
)
6060

61+
add_entrypoint_object(
62+
fetestexceptflag
63+
SRCS
64+
fetestexceptflag.cpp
65+
HDRS
66+
fetestexceptflag.h
67+
DEPENDS
68+
libc.hdr.types.fexcept_t
69+
libc.src.__support.FPUtil.fenv_impl
70+
COMPILE_OPTIONS
71+
-O2
72+
)
73+
6174
add_entrypoint_object(
6275
fegetenv
6376
SRCS

libc/src/fenv/fetestexceptflag.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Implementation of fetestexceptflag function -----------------------===//
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/fetestexceptflag.h"
10+
#include "hdr/types/fexcept_t.h"
11+
#include "src/__support/FPUtil/FEnvImpl.h"
12+
#include "src/__support/common.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
LLVM_LIBC_FUNCTION(int, fetestexceptflag,
17+
(const fexcept_t *flagp, int excepts)) {
18+
static_assert(sizeof(int) >= sizeof(fexcept_t),
19+
"fexcept_t value cannot fit in an int value.");
20+
return *flagp | fputil::test_except(excepts);
21+
}
22+
23+
} // namespace LIBC_NAMESPACE

libc/src/fenv/fetestexceptflag.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for fetestexceptflag --------------*- C++ -*-===//
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+
#ifndef LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H
10+
#define LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H
11+
12+
#include "hdr/types/fexcept_t.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int fetestexceptflag(const fexcept_t *, int excepts);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_FENV_FETESTEXCEPTFLAG_H

libc/test/src/fenv/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ add_libc_unittest(
4848
DEPENDS
4949
libc.src.fenv.fegetexceptflag
5050
libc.src.fenv.fesetexceptflag
51+
libc.src.fenv.fetestexceptflag
5152
libc.src.__support.FPUtil.fenv_impl
5253
)
5354

libc/test/src/fenv/exception_flags_test.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===-- Unittests for fegetexceptflag and fesetexceptflag -----------------===//
1+
//===-- Unittests for fe{get|set|test}exceptflag --------------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -9,11 +9,12 @@
99
#include "hdr/types/fexcept_t.h"
1010
#include "src/fenv/fegetexceptflag.h"
1111
#include "src/fenv/fesetexceptflag.h"
12+
#include "src/fenv/fetestexceptflag.h"
1213

1314
#include "src/__support/FPUtil/FEnvImpl.h"
1415
#include "test/UnitTest/Test.h"
1516

16-
TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) {
17+
TEST(LlvmLibcFenvTest, GetSetTestExceptFlag) {
1718
// We will disable all exceptions to prevent invocation of the exception
1819
// handler.
1920
LIBC_NAMESPACE::fputil::disable_except(FE_ALL_EXCEPT);
@@ -39,19 +40,36 @@ TEST(LlvmLibcFenvTest, GetExceptFlagAndSetExceptFlag) {
3940
ASSERT_EQ(LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT), 0);
4041
ASSERT_NE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
4142

43+
// Exception flags are exactly the flags corresponding to the previously
44+
// raised exception.
45+
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&eflags, FE_ALL_EXCEPT),
46+
LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT));
47+
4248
// Cleanup. We clear all excepts as raising excepts like FE_OVERFLOW
4349
// can also raise FE_INEXACT.
4450
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
4551
}
4652

47-
// Next, we will raise one exception and save the flags.
53+
// Next, we will raise one exception, save the flag and clear all exceptions.
4854
LIBC_NAMESPACE::fputil::raise_except(FE_INVALID);
49-
fexcept_t eflags;
50-
LIBC_NAMESPACE::fegetexceptflag(&eflags, FE_ALL_EXCEPT);
51-
// Clear all exceptions and raise two other exceptions.
55+
fexcept_t invalid_flag;
56+
LIBC_NAMESPACE::fegetexceptflag(&invalid_flag, FE_ALL_EXCEPT);
57+
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&invalid_flag, FE_ALL_EXCEPT),
58+
FE_INVALID);
5259
LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT);
60+
61+
// Raise two other exceptions and verify that they are set.
5362
LIBC_NAMESPACE::fputil::raise_except(FE_OVERFLOW | FE_INEXACT);
63+
fexcept_t overflow_and_inexact_flag;
64+
LIBC_NAMESPACE::fegetexceptflag(&overflow_and_inexact_flag, FE_ALL_EXCEPT);
65+
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag,
66+
FE_ALL_EXCEPT),
67+
FE_OVERFLOW | FE_INEXACT);
68+
ASSERT_EQ(LIBC_NAMESPACE::fetestexceptflag(&overflow_and_inexact_flag,
69+
FE_OVERFLOW | FE_INEXACT),
70+
FE_OVERFLOW | FE_INEXACT);
71+
5472
// When we set the flags and test, we should only see FE_INVALID.
55-
LIBC_NAMESPACE::fesetexceptflag(&eflags, FE_ALL_EXCEPT);
73+
LIBC_NAMESPACE::fesetexceptflag(&invalid_flag, FE_ALL_EXCEPT);
5674
EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT), FE_INVALID);
5775
}

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,16 @@ libc_function(
11451145
],
11461146
)
11471147

1148+
libc_function(
1149+
name = "fetestexceptflag",
1150+
srcs = ["src/fenv/fetestexceptflag.cpp"],
1151+
hdrs = ["src/fenv/fetestexceptflag.h"],
1152+
deps = [
1153+
":__support_common",
1154+
":__support_fputil_fenv_impl",
1155+
],
1156+
)
1157+
11481158
libc_function(
11491159
name = "feclearexcept",
11501160
srcs = ["src/fenv/feclearexcept.cpp"],

utils/bazel/llvm-project-overlay/libc/test/src/fenv/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ libc_test(
7575
libc_function_deps = [
7676
"//libc:fegetexceptflag",
7777
"//libc:fesetexceptflag",
78+
"//libc:fetestexceptflag",
7879
],
7980
deps = [
8081
"//libc:__support_fputil_fenv_impl",

0 commit comments

Comments
 (0)