diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-02-11 23:47:19 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-02-11 23:47:19 +0000 |
commit | ecc2c089fd997a787b3e2817765ca966384b7281 (patch) | |
tree | d71fc9961a76e7381ae7fd75ee5b0a3b5f81ce42 | |
parent | fc1ec361d39c403915c3c3c2c74468451fade20f (diff) | |
download | libcxx-ecc2c089fd997a787b3e2817765ca966384b7281.tar.gz |
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
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@353767 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/CMakeLists.txt | 1 | ||||
-rw-r--r-- | include/fenv.h | 204 | ||||
-rw-r--r-- | include/module.modulemap | 5 | ||||
-rw-r--r-- | test/libcxx/depr/depr.c.headers/fenv.pass.cpp | 19 | ||||
-rw-r--r-- | test/libcxx/double_include.sh.cpp | 1 | ||||
-rw-r--r-- | test/libcxx/include_as_c.sh.cpp | 1 | ||||
-rw-r--r-- | test/std/depr/depr.c.headers/fenv_h.pass.cpp | 22 |
7 files changed, 241 insertions, 12 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 73f7cfc4d..3bd09b329 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -95,6 +95,7 @@ set(files ext/__hash ext/hash_map ext/hash_set + fenv.h filesystem float.h forward_list diff --git a/include/fenv.h b/include/fenv.h new file mode 100644 index 000000000..6c979ac5a --- /dev/null +++ b/include/fenv.h @@ -0,0 +1,204 @@ +// -*- C++ -*- +//===---------------------------- math.h ----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_FENV_H +#define _LIBCPP_FENV_H + + +/* + fenv.h synopsis + +This entire header is C99 / C++0X + +Macros: + + FE_DIVBYZERO + FE_INEXACT + FE_INVALID + FE_OVERFLOW + FE_UNDERFLOW + FE_ALL_EXCEPT + FE_DOWNWARD + FE_TONEAREST + FE_TOWARDZERO + FE_UPWARD + FE_DFL_ENV + +Types: + + fenv_t + fexcept_t + +int feclearexcept(int excepts); +int fegetexceptflag(fexcept_t* flagp, int excepts); +int feraiseexcept(int excepts); +int fesetexceptflag(const fexcept_t* flagp, int excepts); +int fetestexcept(int excepts); +int fegetround(); +int fesetround(int round); +int fegetenv(fenv_t* envp); +int feholdexcept(fenv_t* envp); +int fesetenv(const fenv_t* envp); +int feupdateenv(const fenv_t* envp); + + +*/ + +#include <__config> +#include_next <fenv.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifdef __cplusplus + +extern "C++" { + +#ifdef feclearexcept +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_feclearexcept(int __excepts) { + return feclearexcept(__excepts); +} +#undef feclearexcept +_LIBCPP_INLINE_VISIBILITY +inline int feclearexcept(int __excepts) { + return ::__libcpp_feclearexcept(__excepts); +} +#endif // defined(feclearexcept) + +#ifdef fegetexceptflag +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fegetexceptflag(fexcept_t* __out_ptr, int __excepts) { + return fegetexceptflag(__out_ptr, __excepts); +} +#undef fegetexceptflag +_LIBCPP_INLINE_VISIBILITY +inline int fegetexceptflag(fexcept_t *__out_ptr, int __excepts) { + return ::__libcpp_fegetexceptflag(__out_ptr, __excepts); +} +#endif // defined(fegetexceptflag) + + +#ifdef feraiseexcept +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_feraiseexcept(int __excepts) { + return feraiseexcept(__excepts); +} +#undef feraiseexcept +_LIBCPP_INLINE_VISIBILITY +inline int feraiseexcept(int __excepts) { + return ::__libcpp_feraiseexcept(__excepts); +} +#endif // defined(feraiseexcept) + + +#ifdef fesetexceptflag +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fesetexceptflag(const fexcept_t* __out_ptr, int __excepts) { + return fesetexceptflag(__out_ptr, __excepts); +} +#undef fesetexceptflag +_LIBCPP_INLINE_VISIBILITY +inline int fesetexceptflag(const fexcept_t *__out_ptr, int __excepts) { + return ::__libcpp_fesetexceptflag(__out_ptr, __excepts); +} +#endif // defined(fesetexceptflag) + + +#ifdef fetestexcept +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fetestexcept(int __excepts) { + return fetestexcept(__excepts); +} +#undef fetestexcept +_LIBCPP_INLINE_VISIBILITY +inline int fetestexcept(int __excepts) { + return ::__libcpp_fetestexcept(__excepts); +} +#endif // defined(fetestexcept) + +#ifdef fegetround +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fegetround() { + return fegetround(); +} +#undef fegetround +_LIBCPP_INLINE_VISIBILITY +inline int fegetround() { + return ::__libcpp_fegetround(); +} +#endif // defined(fegetround) + +#ifdef fesetround +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fesetround(int __round) { + return fesetround(__round); +} +#undef fesetround +_LIBCPP_INLINE_VISIBILITY +inline int fesetround(int __round) { + return ::__libcpp_fesetround(__round); +} +#endif // defined(fesetround) + +#ifdef fegetenv +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fegetenv(fenv_t* __envp) { + return fegetenv(__envp); +} +#undef fegetenv +_LIBCPP_INLINE_VISIBILITY +inline int fegetenv(fenv_t* __envp) { + return ::__libcpp_fegetenv(__envp); +} +#endif // defined(fegetenv) + +#ifdef feholdexcept +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_feholdexcept(fenv_t* __envp) { + return feholdexcept(__envp); +} +#undef feholdexcept +_LIBCPP_INLINE_VISIBILITY +inline int feholdexcept(fenv_t* __envp) { + return ::__libcpp_feholdexcept(__envp); +} +#endif // defined(feholdexcept) + + +#ifdef fesetenv +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_fesetenv(const fenv_t* __envp) { + return fesetenv(__envp); +} +#undef fesetenv +_LIBCPP_INLINE_VISIBILITY +inline int fesetenv(const fenv_t* __envp) { + return ::__libcpp_fesetenv(__envp); +} +#endif // defined(fesetenv) + +#ifdef feupdateenv +_LIBCPP_INLINE_VISIBILITY +inline int __libcpp_feupdateenv(const fenv_t* __envp) { + return feupdateenv(__envp); +} +#undef feupdateenv +_LIBCPP_INLINE_VISIBILITY +inline int feupdateenv(const fenv_t* __envp) { + return ::__libcpp_feupdateenv(__envp); +} +#endif // defined(feupdateenv) + +} // extern "C++" + +#endif // defined(__cplusplus) + +#endif // _LIBCPP_FENV_H diff --git a/include/module.modulemap b/include/module.modulemap index 6d88f5211..bbfe90ed5 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -24,7 +24,10 @@ module std [system] { header "errno.h" export * } - // <fenv.h> provided by C library. + module fenv_h { + header "fenv.h" + export * + } // <float.h> provided by compiler or C library. module inttypes_h { header "inttypes.h" diff --git a/test/libcxx/depr/depr.c.headers/fenv.pass.cpp b/test/libcxx/depr/depr.c.headers/fenv.pass.cpp new file mode 100644 index 000000000..9cc7063e8 --- /dev/null +++ b/test/libcxx/depr/depr.c.headers/fenv.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <fenv.h> + +#include <fenv.h> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index a167b0a58..2ee444af5 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -63,6 +63,7 @@ #include <deque> #include <errno.h> #include <exception> +#include <fenv.h> #include <filesystem> #include <float.h> #include <forward_list> diff --git a/test/libcxx/include_as_c.sh.cpp b/test/libcxx/include_as_c.sh.cpp index c056f61ae..67d5e14b3 100644 --- a/test/libcxx/include_as_c.sh.cpp +++ b/test/libcxx/include_as_c.sh.cpp @@ -17,6 +17,7 @@ #include <complex.h> #include <ctype.h> #include <errno.h> +#include <fenv.h> #include <float.h> #include <inttypes.h> #include <limits.h> diff --git a/test/std/depr/depr.c.headers/fenv_h.pass.cpp b/test/std/depr/depr.c.headers/fenv_h.pass.cpp index 3a6f63c3f..6b38f4e6c 100644 --- a/test/std/depr/depr.c.headers/fenv_h.pass.cpp +++ b/test/std/depr/depr.c.headers/fenv_h.pass.cpp @@ -61,17 +61,17 @@ int main(int, char**) { fenv_t fenv = {}; fexcept_t fex = 0; - static_assert((std::is_same<decltype(feclearexcept(0)), int>::value), ""); - static_assert((std::is_same<decltype(fegetexceptflag(&fex, 0)), int>::value), ""); - static_assert((std::is_same<decltype(feraiseexcept(0)), int>::value), ""); - static_assert((std::is_same<decltype(fesetexceptflag(&fex, 0)), int>::value), ""); - static_assert((std::is_same<decltype(fetestexcept(0)), int>::value), ""); - static_assert((std::is_same<decltype(fegetround()), int>::value), ""); - static_assert((std::is_same<decltype(fesetround(0)), int>::value), ""); - static_assert((std::is_same<decltype(fegetenv(&fenv)), int>::value), ""); - static_assert((std::is_same<decltype(feholdexcept(&fenv)), int>::value), ""); - static_assert((std::is_same<decltype(fesetenv(&fenv)), int>::value), ""); - static_assert((std::is_same<decltype(feupdateenv(&fenv)), int>::value), ""); + static_assert((std::is_same<decltype(::feclearexcept(0)), int>::value), ""); + static_assert((std::is_same<decltype(::fegetexceptflag(&fex, 0)), int>::value), ""); + static_assert((std::is_same<decltype(::feraiseexcept(0)), int>::value), ""); + static_assert((std::is_same<decltype(::fesetexceptflag(&fex, 0)), int>::value), ""); + static_assert((std::is_same<decltype(::fetestexcept(0)), int>::value), ""); + static_assert((std::is_same<decltype(::fegetround()), int>::value), ""); + static_assert((std::is_same<decltype(::fesetround(0)), int>::value), ""); + static_assert((std::is_same<decltype(::fegetenv(&fenv)), int>::value), ""); + static_assert((std::is_same<decltype(::feholdexcept(&fenv)), int>::value), ""); + static_assert((std::is_same<decltype(::fesetenv(&fenv)), int>::value), ""); + static_assert((std::is_same<decltype(::feupdateenv(&fenv)), int>::value), ""); return 0; } |