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
This commit is contained in:
Eric Fiselier 2019-02-11 23:47:19 +00:00
parent 5906a6591c
commit cf39dd44b8
7 changed files with 241 additions and 12 deletions

View File

@ -95,6 +95,7 @@ set(files
ext/__hash
ext/hash_map
ext/hash_set
fenv.h
filesystem
float.h
forward_list

204
libcxx/include/fenv.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -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()
{
}

View File

@ -63,6 +63,7 @@
#include <deque>
#include <errno.h>
#include <exception>
#include <fenv.h>
#include <filesystem>
#include <float.h>
#include <forward_list>

View File

@ -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>

View File

@ -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;
}