Subject: Re: bug#43579: g++ does not provide std::fegetround

From: Andreas Enge <[email-masked]>
Date: Fri, 2 Oct 2020 20:06:21 +0200

Hello,

On Thu, Oct 01, 2020 at 09:39:35PM -0500, Brett Gilio wrote:
> >> The following test file round.cpp does not compile with our g++-10.2.0:
> >> #include <cfenv>
> >> int main () {
> >>    return std::fegetround ();
> >> }
> >
> > Could you provide detailed steps to reproduce it?

well, just put these lines into a file called "round.cpp" (as attached),
and then
   gcc round.cpp
produces
round.cpp: In function 'int main()':
round.cpp:3:16: error: 'fegetround' is not a member of 'std'; did you mean 'fegetround'?
    3 |    return std::fegetround ();
      |                ^~~~~~~~~~
In file included from /home/andreas/.guix-profile/include/c++/fenv.h:36,
                 from /home/andreas/.guix-profile/include/c++/cfenv:41,
                 from round.cpp:1:
/home/andreas/.guix-profile/include/fenv.h:104:12: note: 'fegetround' declared here
  104 | extern int fegetround (void) __THROW __attribute_pure__;
      |            ^~~~~~~~~~

On Thu, Oct 01, 2020 at 09:39:35PM -0500, Brett Gilio wrote:
> I believe `std::fegetround` was introduced in C++11, are you using the
> appropriate flag?

And then you can use any of
   gcc --std=c++17 round.cpp
   gcc --std=c++14 round.cpp
   gcc --std=c++11 round.cpp
with the same outcome.

The issue
   https://github.com/fplll/fplll/issues/444
I referenced in my bug report provides more discussion; the outcome was that
it is a bug in Guix. I will try to summarise it in the following to make this
bug report self-contained; all file and directory names are relative to
`guix build gcc-toolchain`.

include/c++/cfenv does this around line 41:
#if _GLIBCXX_HAVE_FENV_H
# include <fenv.h>
#endif

include/c++/fenv.h has this in line 34:
#include <bits/c++config.h>

include/c++/x86_64-unknown-linux-gnu/bits/c++config.h has this around line 28:
/* Define if C99 functions in <fenv.h> should be imported in <tr1/cfenv> in
   namespace std::tr1. */
/* #undef _GLIBCXX_USE_C99_FENV_TR1 */

And back to include/c++/fenv.h from line 41 on:
#if _GLIBCXX_USE_C99_FENV_TR1
#undef feclearexcept
#undef fegetexceptflag
#undef feraiseexcept
#undef fesetexceptflag
#undef fetestexcept
#undef fegetround
#undef fesetround
...
namespace std
{
...
  using ::fegetround;
  using ::fesetround;
...
}
#endif // _GLIBCXX_USE_C99_FENV_TR1

The difference to the Opensuse headers is that in bits/c++config.h,
they define _GLIBCXX_USE_C99_FENV_TR1, which, as I understand it,
removes the fe* functions from the global namespace to put them back into
the std:: namespace.

This should happen somewhere in a configure phase inside the gcc build, but
I do not know how to obtain the config.log file easily (short of adding a
phase "(const #f)" to the build recipe and doing a "guix build -K").

Andreas