Skip to content

Commit cf39dd4

Browse files
committed
Add fenv.h header
Summary: Some implementations of fenv.h use macros to define the functions they provide. This can cause problems when `std::fegetround()` is spelled in source. This patch adds a `fenv.h` header to libc++ for the sole purpose of turning those macros into real functions. Reviewers: rsmith, mclow.lists, ldionne Reviewed By: rsmith Subscribers: mgorny, christof, libcxx-commits Differential Revision: https://reviews.llvm.org/D57729 llvm-svn: 353767
1 parent 5906a65 commit cf39dd4

File tree

7 files changed

+241
-12
lines changed

7 files changed

+241
-12
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ set(files
9595
ext/__hash
9696
ext/hash_map
9797
ext/hash_set
98+
fenv.h
9899
filesystem
99100
float.h
100101
forward_list

libcxx/include/fenv.h

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// -*- C++ -*-
2+
//===---------------------------- math.h ----------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP_FENV_H
11+
#define _LIBCPP_FENV_H
12+
13+
14+
/*
15+
fenv.h synopsis
16+
17+
This entire header is C99 / C++0X
18+
19+
Macros:
20+
21+
FE_DIVBYZERO
22+
FE_INEXACT
23+
FE_INVALID
24+
FE_OVERFLOW
25+
FE_UNDERFLOW
26+
FE_ALL_EXCEPT
27+
FE_DOWNWARD
28+
FE_TONEAREST
29+
FE_TOWARDZERO
30+
FE_UPWARD
31+
FE_DFL_ENV
32+
33+
Types:
34+
35+
fenv_t
36+
fexcept_t
37+
38+
int feclearexcept(int excepts);
39+
int fegetexceptflag(fexcept_t* flagp, int excepts);
40+
int feraiseexcept(int excepts);
41+
int fesetexceptflag(const fexcept_t* flagp, int excepts);
42+
int fetestexcept(int excepts);
43+
int fegetround();
44+
int fesetround(int round);
45+
int fegetenv(fenv_t* envp);
46+
int feholdexcept(fenv_t* envp);
47+
int fesetenv(const fenv_t* envp);
48+
int feupdateenv(const fenv_t* envp);
49+
50+
51+
*/
52+
53+
#include <__config>
54+
#include_next <fenv.h>
55+
56+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
57+
#pragma GCC system_header
58+
#endif
59+
60+
#ifdef __cplusplus
61+
62+
extern "C++" {
63+
64+
#ifdef feclearexcept
65+
_LIBCPP_INLINE_VISIBILITY
66+
inline int __libcpp_feclearexcept(int __excepts) {
67+
return feclearexcept(__excepts);
68+
}
69+
#undef feclearexcept
70+
_LIBCPP_INLINE_VISIBILITY
71+
inline int feclearexcept(int __excepts) {
72+
return ::__libcpp_feclearexcept(__excepts);
73+
}
74+
#endif // defined(feclearexcept)
75+
76+
#ifdef fegetexceptflag
77+
_LIBCPP_INLINE_VISIBILITY
78+
inline int __libcpp_fegetexceptflag(fexcept_t* __out_ptr, int __excepts) {
79+
return fegetexceptflag(__out_ptr, __excepts);
80+
}
81+
#undef fegetexceptflag
82+
_LIBCPP_INLINE_VISIBILITY
83+
inline int fegetexceptflag(fexcept_t *__out_ptr, int __excepts) {
84+
return ::__libcpp_fegetexceptflag(__out_ptr, __excepts);
85+
}
86+
#endif // defined(fegetexceptflag)
87+
88+
89+
#ifdef feraiseexcept
90+
_LIBCPP_INLINE_VISIBILITY
91+
inline int __libcpp_feraiseexcept(int __excepts) {
92+
return feraiseexcept(__excepts);
93+
}
94+
#undef feraiseexcept
95+
_LIBCPP_INLINE_VISIBILITY
96+
inline int feraiseexcept(int __excepts) {
97+
return ::__libcpp_feraiseexcept(__excepts);
98+
}
99+
#endif // defined(feraiseexcept)
100+
101+
102+
#ifdef fesetexceptflag
103+
_LIBCPP_INLINE_VISIBILITY
104+
inline int __libcpp_fesetexceptflag(const fexcept_t* __out_ptr, int __excepts) {
105+
return fesetexceptflag(__out_ptr, __excepts);
106+
}
107+
#undef fesetexceptflag
108+
_LIBCPP_INLINE_VISIBILITY
109+
inline int fesetexceptflag(const fexcept_t *__out_ptr, int __excepts) {
110+
return ::__libcpp_fesetexceptflag(__out_ptr, __excepts);
111+
}
112+
#endif // defined(fesetexceptflag)
113+
114+
115+
#ifdef fetestexcept
116+
_LIBCPP_INLINE_VISIBILITY
117+
inline int __libcpp_fetestexcept(int __excepts) {
118+
return fetestexcept(__excepts);
119+
}
120+
#undef fetestexcept
121+
_LIBCPP_INLINE_VISIBILITY
122+
inline int fetestexcept(int __excepts) {
123+
return ::__libcpp_fetestexcept(__excepts);
124+
}
125+
#endif // defined(fetestexcept)
126+
127+
#ifdef fegetround
128+
_LIBCPP_INLINE_VISIBILITY
129+
inline int __libcpp_fegetround() {
130+
return fegetround();
131+
}
132+
#undef fegetround
133+
_LIBCPP_INLINE_VISIBILITY
134+
inline int fegetround() {
135+
return ::__libcpp_fegetround();
136+
}
137+
#endif // defined(fegetround)
138+
139+
#ifdef fesetround
140+
_LIBCPP_INLINE_VISIBILITY
141+
inline int __libcpp_fesetround(int __round) {
142+
return fesetround(__round);
143+
}
144+
#undef fesetround
145+
_LIBCPP_INLINE_VISIBILITY
146+
inline int fesetround(int __round) {
147+
return ::__libcpp_fesetround(__round);
148+
}
149+
#endif // defined(fesetround)
150+
151+
#ifdef fegetenv
152+
_LIBCPP_INLINE_VISIBILITY
153+
inline int __libcpp_fegetenv(fenv_t* __envp) {
154+
return fegetenv(__envp);
155+
}
156+
#undef fegetenv
157+
_LIBCPP_INLINE_VISIBILITY
158+
inline int fegetenv(fenv_t* __envp) {
159+
return ::__libcpp_fegetenv(__envp);
160+
}
161+
#endif // defined(fegetenv)
162+
163+
#ifdef feholdexcept
164+
_LIBCPP_INLINE_VISIBILITY
165+
inline int __libcpp_feholdexcept(fenv_t* __envp) {
166+
return feholdexcept(__envp);
167+
}
168+
#undef feholdexcept
169+
_LIBCPP_INLINE_VISIBILITY
170+
inline int feholdexcept(fenv_t* __envp) {
171+
return ::__libcpp_feholdexcept(__envp);
172+
}
173+
#endif // defined(feholdexcept)
174+
175+
176+
#ifdef fesetenv
177+
_LIBCPP_INLINE_VISIBILITY
178+
inline int __libcpp_fesetenv(const fenv_t* __envp) {
179+
return fesetenv(__envp);
180+
}
181+
#undef fesetenv
182+
_LIBCPP_INLINE_VISIBILITY
183+
inline int fesetenv(const fenv_t* __envp) {
184+
return ::__libcpp_fesetenv(__envp);
185+
}
186+
#endif // defined(fesetenv)
187+
188+
#ifdef feupdateenv
189+
_LIBCPP_INLINE_VISIBILITY
190+
inline int __libcpp_feupdateenv(const fenv_t* __envp) {
191+
return feupdateenv(__envp);
192+
}
193+
#undef feupdateenv
194+
_LIBCPP_INLINE_VISIBILITY
195+
inline int feupdateenv(const fenv_t* __envp) {
196+
return ::__libcpp_feupdateenv(__envp);
197+
}
198+
#endif // defined(feupdateenv)
199+
200+
} // extern "C++"
201+
202+
#endif // defined(__cplusplus)
203+
204+
#endif // _LIBCPP_FENV_H

libcxx/include/module.modulemap

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ module std [system] {
2424
header "errno.h"
2525
export *
2626
}
27-
// <fenv.h> provided by C library.
27+
module fenv_h {
28+
header "fenv.h"
29+
export *
30+
}
2831
// <float.h> provided by compiler or C library.
2932
module inttypes_h {
3033
header "inttypes.h"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===----------------------------------------------------------------------===//
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+
// <fenv.h>
10+
11+
#include <fenv.h>
12+
13+
#ifndef _LIBCPP_VERSION
14+
#error _LIBCPP_VERSION not defined
15+
#endif
16+
17+
int main()
18+
{
19+
}

libcxx/test/libcxx/double_include.sh.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include <deque>
6464
#include <errno.h>
6565
#include <exception>
66+
#include <fenv.h>
6667
#include <filesystem>
6768
#include <float.h>
6869
#include <forward_list>

libcxx/test/libcxx/include_as_c.sh.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <complex.h>
1818
#include <ctype.h>
1919
#include <errno.h>
20+
#include <fenv.h>
2021
#include <float.h>
2122
#include <inttypes.h>
2223
#include <limits.h>

libcxx/test/std/depr/depr.c.headers/fenv_h.pass.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,17 @@ int main(int, char**)
6161
{
6262
fenv_t fenv = {};
6363
fexcept_t fex = 0;
64-
static_assert((std::is_same<decltype(feclearexcept(0)), int>::value), "");
65-
static_assert((std::is_same<decltype(fegetexceptflag(&fex, 0)), int>::value), "");
66-
static_assert((std::is_same<decltype(feraiseexcept(0)), int>::value), "");
67-
static_assert((std::is_same<decltype(fesetexceptflag(&fex, 0)), int>::value), "");
68-
static_assert((std::is_same<decltype(fetestexcept(0)), int>::value), "");
69-
static_assert((std::is_same<decltype(fegetround()), int>::value), "");
70-
static_assert((std::is_same<decltype(fesetround(0)), int>::value), "");
71-
static_assert((std::is_same<decltype(fegetenv(&fenv)), int>::value), "");
72-
static_assert((std::is_same<decltype(feholdexcept(&fenv)), int>::value), "");
73-
static_assert((std::is_same<decltype(fesetenv(&fenv)), int>::value), "");
74-
static_assert((std::is_same<decltype(feupdateenv(&fenv)), int>::value), "");
64+
static_assert((std::is_same<decltype(::feclearexcept(0)), int>::value), "");
65+
static_assert((std::is_same<decltype(::fegetexceptflag(&fex, 0)), int>::value), "");
66+
static_assert((std::is_same<decltype(::feraiseexcept(0)), int>::value), "");
67+
static_assert((std::is_same<decltype(::fesetexceptflag(&fex, 0)), int>::value), "");
68+
static_assert((std::is_same<decltype(::fetestexcept(0)), int>::value), "");
69+
static_assert((std::is_same<decltype(::fegetround()), int>::value), "");
70+
static_assert((std::is_same<decltype(::fesetround(0)), int>::value), "");
71+
static_assert((std::is_same<decltype(::fegetenv(&fenv)), int>::value), "");
72+
static_assert((std::is_same<decltype(::feholdexcept(&fenv)), int>::value), "");
73+
static_assert((std::is_same<decltype(::fesetenv(&fenv)), int>::value), "");
74+
static_assert((std::is_same<decltype(::feupdateenv(&fenv)), int>::value), "");
7575

7676
return 0;
7777
}

0 commit comments

Comments
 (0)