Modify

Ticket #11756 (reopened Patches)

Opened 15 months ago

Last modified 3 weeks ago

boost.Test: non standards compliant use of FE_* macros (unable to compile boost test library on FPU-less arches)

Reported by: bartosz.krasinski@… Owned by: renficiaud
Milestone: Boost 1.63.0 Component: test
Version: Boost 1.59.0 Severity: Problem
Keywords: Cc:

Description

In file included from ./boost/test/unit_test_monitor.hpp:18:0,

from ./boost/test/impl/unit_test_monitor.ipp:20, from libs/test/src/unit_test_monitor.cpp:16:

./boost/test/execution_monitor.hpp:492:27: error: 'FE_DIVBYZERO' was not declared in this scope ./boost/test/execution_monitor.hpp:493:27: error: 'FE_INEXACT' was not declared in this scope ./boost/test/execution_monitor.hpp:494:27: error: 'FE_INVALID' was not declared in this scope ./boost/test/execution_monitor.hpp:495:27: error: 'FE_OVERFLOW' was not declared in this scope ./boost/test/execution_monitor.hpp:496:27: error: 'FE_UNDERFLOW' was not declared in this scope ./boost/test/execution_monitor.hpp:498:27: error: 'FE_ALL_EXCEPT' was not declared in this scope

these constants are not defined in fenv.h version 1.58 was compiled successfully

bartek@homesrv:~/builds/boost_1_59_0$ mips-openwrt-linux-g++ -v Reading specs from /work/openwrt-sdk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/../lib/gcc/mips-openwrt-linux-uclibc/4.6.3/specs COLLECT_GCC=mips-openwrt-linux-g++ COLLECT_LTO_WRAPPER=/work/openwrt-sdk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/../libexec/gcc/mips-openwrt-linux-uclibc/4.6.3/lto-wrapper Target: mips-openwrt-linux-uclibc Configured with: /work/openwrt/build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.02/configure --prefix=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2 --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=mips-openwrt-linux-uclibc --with-gnu-ld --enable-target-optspace --disable-libgomp --disable-libmudflap --disable-multilib --disable-nls --with-host-libstdcxx=-lstdc++ --with-float=soft --with-gmp=/work/openwrt/staging_dir/host --with-mpfr=/work/openwrt/staging_dir/host --disable-decimal-float --with-mips-plt --with-mpc=/work/openwrt/staging_dir/host --disable-libssp --disable-cxa_atexit --with-headers=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/include --enable-languages=c,c++ --enable-shared --enable-threads --with-slibdir=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib --enable-lto --with-libelf=/work/openwrt/staging_dir/host --disable-tls Thread model: posix gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02)

Attachments

0001-config-BOOST_NO_FENV_H.patch Download (3.6 KB) - added by André Draszik <git@…> 5 months ago.
gcc: #define BOOST_NO_FENV_H on FPU-less arches
0001-execution_monitor-fix-soft-float-issues.patch Download (4.3 KB) - added by André Draszik <git@…> 5 months ago.
fix FE_* usage in test (based on previous comment)
0001-execution_monitor-fix-soft-float-issues.2.patch Download (6.1 KB) - added by André Draszik <git@…> 5 months ago.
fix FE_* usage in test (updated again based on johnmaddock's tips)

Change History

comment:1 Changed 15 months ago by viboes

  • Owner set to rogeeff
  • Component changed from None to test

comment:2 Changed 13 months ago by joerg.krause@…

Same with Buildroot, e.g.  http://autobuild.buildroot.net/results/28d/28db2fc2d6bffeb7c842fbcce2eeaf89ae5f8b01/build-end.log.

The problem is, that some architectures, currently do not implement FE_DIVBYZERO, even though they have <fenv.h> and feenableexcept().

comment:3 Changed 13 months ago by renficiaud

I do not have access to those platforms. Do you know by chance if those "deficiencies" are described in the boost.config project?

http://www.boost.org/doc/libs/1_60_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_c__03_defects

especially the macro

BOOST_NO_FENV_H

comment:4 Changed 13 months ago by bartosz.krasinski@…

Hi

here is search result:

bartek@homesrv:~/builds/boost_1_59_0$ grep -rnw . -e "BOOST_NO_FENV_H" ./libs/config/test/all/Jamfile.v2:394:test-suite "BOOST_NO_FENV_H" : ./libs/config/test/config_info.cpp:1073: PRINT_MACRO(BOOST_NO_FENV_H); ./libs/config/test/boost_no_fenv_h.ipp:9:// MACRO: BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_pass.cpp:9:// Test file for macro BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_pass.cpp:11:// BOOST_NO_FENV_H should be defined. ./libs/config/test/no_fenv_h_pass.cpp:23:#ifndef BOOST_NO_FENV_H ./libs/config/test/config_test.cpp:380:#ifndef BOOST_NO_FENV_H ./libs/config/test/config_test.cpp:1611: std::cerr << "Failed test for BOOST_NO_FENV_H at: " << FILE << ":" << LINE << std::endl; ./libs/config/test/no_fenv_h_fail.cpp:9:// Test file for macro BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_fail.cpp:11:// BOOST_NO_FENV_H should not be defined. ./libs/config/test/no_fenv_h_fail.cpp:23:#ifdef BOOST_NO_FENV_H ./libs/config/doc/html/boost_config/boost_macro_reference.html:293: <code class="computeroutput"><span class="identifier">BOOST_NO_FENV_H</span></code> ./libs/config/doc/macro_reference.qbk:74:[[`BOOST_NO_FENV_H`][Platform, Standard library][

./boost/math/tools/config.hpp:339:#if ((defined(linux) && !defined(UCLIBC) && !defined(BOOST_MATH_HAVE_FIXED_GLIBC))
defined(QNX) defined(IBMCPP)) && !defined(BOOST_NO_FENV_H)

./boost/test/execution_monitor.hpp:63:#if !defined(BOOST_NO_FENV_H)

./boost/test/execution_monitor.hpp:489:#elif defined(BOOST_NO_FENV_H)
defined(BOOST_CLANG)

./boost/test/impl/execution_monitor.ipp:1382:#elif defined(GLIBC) && defined(USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H) ./boost/test/impl/execution_monitor.ipp:1419:#elif defined(GLIBC) && defined(USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H) ./boost/detail/fenv.hpp:10:#if defined(BOOST_NO_FENV_H) ./boost/config/platform/cygwin.hpp:43:#define BOOST_NO_FENV_H ./boost/config/compiler/intel.hpp:497:# define BOOST_NO_FENV_H ./boost/config/compiler/visualc.hpp:47:# define BOOST_NO_FENV_H

when i added mentioned macro: BOOST_NO_FENV_H to the boost/config/user.hpp header then i successfully built following libraries (in comparision to the previous build - without this macro):

libbost_unit_test_framework.a libbost_test_exec_monitor.a libbost_prge_xec_monitor.a

of course for openwrt-linux-mips platform

thanks for clue

comment:5 Changed 13 months ago by renficiaud

Thank you for your feedback,

Boost.Test relies on Boost.Config for the proper configuration of the BOOST_NO_FENV_H macro. From your message, it looks like this macro is not properly defined for your platform openwrt-linux-mips, and if you define it manually, Boost.Test properly compiles.

Have I understood properly?

comment:6 Changed 13 months ago by bartosz.krasinski@…

Yes, exactly

It is because, i guess, first of all i build bootstrap in x86_64.

./bootstrap.sh

next i build boost for x86_64 and x86 platforms (debian)

./b2 link=static variant=release --prefix=/work/libextern/boost-x86 address-model=32 cxxflags=-fPIC install

once again, thanks bartek

./b2 link=static variant=release --prefix=/work/libextern/boost-x64 address-model=64 cxxflags=-fPIC install

finally i create boost.config.jam file, in which i place:

using gcc : mips : "mips-openwrt-linux-g++" ;

and i build boost for mips:

./b2 toolset=gcc-mips link=static variant=release --prefix=/work/libextern/boost-mips cxxflags=-fPIC --user-config=user.config.jam install

maybe I missed something that boost build system did not recognized correctly mips platform but now i will add manually mentioned macro and it is enough for me.

comment:7 Changed 13 months ago by renficiaud

I will transfer the issue to Boost.Config then. Thanks

comment:8 Changed 13 months ago by renficiaud

  • Owner changed from rogeeff to johnmaddock
  • Component changed from test to config

comment:9 Changed 13 months ago by joerg.krause@…

Boost detects a fenv.h system header and assumes it defines FE_DIVBYZERO and friends. The involved toolchains does have this system header, but they do not define these macros, e.g. the mipsel toolchain from Buildroot (fenv.h includes tr1/cfenv):

/** @file tr1/cfenv
 *  This is a TR1 C++ Library header. 
 */

#ifndef _GLIBCXX_TR1_CFENV
#define _GLIBCXX_TR1_CFENV 1

#pragma GCC system_header

#include <bits/c++config.h>

#if _GLIBCXX_HAVE_FENV_H
# include <fenv.h>
#endif

#ifdef _GLIBCXX_USE_C99_FENV_TR1

#undef feclearexcept
#undef fegetexceptflag
#undef feraiseexcept
#undef fesetexceptflag
#undef fetestexcept
#undef fegetround
#undef fesetround
#undef fegetenv
#undef feholdexcept
#undef fesetenv
#undef feupdateenv

namespace std _GLIBCXX_VISIBILITY(default)
{
namespace tr1
{
  // types
  using ::fenv_t;
  using ::fexcept_t;

  // functions
  using ::feclearexcept;
  using ::fegetexceptflag;
  using ::feraiseexcept;
  using ::fesetexceptflag;
  using ::fetestexcept;

  using ::fegetround;
  using ::fesetround;

  using ::fegetenv;
  using ::feholdexcept;
  using ::fesetenv;
  using ::feupdateenv;
}
}

#endif // _GLIBCXX_USE_C99_FENV_TR1

#endif // _GLIBCXX_TR1_CFENV

Changed 5 months ago by André Draszik <git@…>

gcc: #define BOOST_NO_FENV_H on FPU-less arches

comment:10 Changed 5 months ago by André Draszik <git@…>

  • Summary changed from Unable to compile boost test library on openwrt - mips to boost.Config doesn't detect FPU-less arches (Unable to compile boost test library on FPU-less arches)

comment:11 Changed 5 months ago by André Draszik <git@…>

  • Type changed from Support Requests to Patches

comment:12 Changed 5 months ago by johnmaddock

  • Owner changed from johnmaddock to rogeeff
  • Component changed from config to test

Sorry to ping this back to Boost.Test, but I believe this is a misunderstanding of how fenv.h works. The key point is:

A fully standards conforming fenv.h does not have to define any FE_* macros, and if it does define them, then it defines macros only for the FP exceptions it actually supports.

So correct usage requires a triple check:

1) Check BOOST_NO_FENV_H to see if the header is supported.

2) Include the header and then check FE_ALL_EXCEPT to see if any FP exceptions are supported.

3) Before using the individual FE_* macros, you need to check for their existence too as not all may be supported.

And finally.... the standard also permits other FE_* macros if there are exceptions supported other than the standard set. There's no standard way to tell what these might be, but their presence can be inferred by checking FE_ALL_EXCEPT against the bitwise or of the other FE_* macros.

Changed 5 months ago by André Draszik <git@…>

fix FE_* usage in test (based on previous comment)

comment:13 Changed 5 months ago by André Draszik <git@…>

  • Summary changed from boost.Config doesn't detect FPU-less arches (Unable to compile boost test library on FPU-less arches) to boost.Test: non standards compliant use of FE_* macros (unable to compile boost test library on FPU-less arches)

comment:14 Changed 5 months ago by johnmaddock

That doesn't quite get it: if fenv.h is available, but FE_DIVBYZERO is unset then BOOST_FPE_DIVBYZERO is also left unset (for example), where as it should be set to a stub value I guess (1 or 0).... except a quick grep of the source suggests these are unused anyway? Which just leaves BOOST_FPE_ALL which definitely needs to be in #if...#else block, so I suggest something more like:

#ifdef FE_DIVBYZERO
    BOOST_FPE_DIVBYZERO = FE_DIVBYZERO,
#else
    BOOST_FPE_DIVBYZERO = 0,
#endif
#ifdef FE_INEXACT
    BOOST_FPE_INEXACT   = FE_INEXACT,
#else
    BOOST_FPE_INEXACT   = 0,
#endif
#ifdef FE_INVALID
    BOOST_FPE_INVALID   = FE_INVALID,
#else
    BOOST_FPE_INVALID   = 0,
#endif
#ifdef FE_OVERFLOW
    BOOST_FPE_OVERFLOW  = FE_OVERFLOW,
#else
    BOOST_FPE_OVERFLOW  = 0,
#endif
#ifdef FE_UNDERFLOW
    BOOST_FPE_UNDERFLOW = FE_UNDERFLOW,
#else
    BOOST_FPE_UNDERFLOW = 0,
#endif
#ifdef FE_ALL_EXCEPT
    BOOST_FPE_ALL       = FE_ALL_EXCEPT,
#else
    BOOST_FPE_ALL       = 1,
#endif

comment:15 Changed 5 months ago by André Draszik <git@…>

Based on your previous comment:

Include the header and then check FE_ALL_EXCEPT to see if any FP exceptions are supported

I understood that if fenv.h is available, then FE_ALL_EXCEPT can have *any* value. In my case, it is defined, but it's defined to 0, since no exceptions are supported. Hence I had a check for this. This is now gone, and with this version BOOST_FPE_ALL would be == 0, too.

Hence I think it should be checking

#ifdef FE_ALL_EXCEPT && (FE_ALL_EXCEPT != 0)

BOOST_FPE_ALL = FE_ALL_EXCEPT,

#else

BOOST_FPE_ALL = 1,

#endif

instead ?

comment:16 Changed 5 months ago by André Draszik <git@…>

On the other hand, does it really make sense to set BOOST_FPE_ALL to 1 if exceptions are not supported in the implementation? Wouldn't this be better?

#ifdef FE_ALL_EXCEPT
    BOOST_FPE_ALL       = FE_ALL_EXCEPT,
#else
    BOOST_FPE_ALL       = 0,
#endif

comment:17 Changed 5 months ago by johnmaddock

Yes it does make more sense for BOOST_FPE_ALL to be 0 in that case - I just followed existing practice for the case where there is no fenv.h as I wasn't sure what effect a zero value might have in the code's assumptions. I think the library authors will have to figure that one out.

Changed 5 months ago by André Draszik <git@…>

fix FE_* usage in test (updated again based on johnmaddock's tips)

comment:18 Changed 5 months ago by André Draszik <git@…>

Thanks!

I've had another look and I think this is a good version now. This works well for me on my target device as well as on my host machine.

comment:19 Changed 4 months ago by renficiaud

  • Owner changed from rogeeff to renficiaud
  • Milestone changed from To Be Determined to Boost 1.63.0

comment:20 Changed 3 months ago by renficiaud

I am looking at this right now, and it is running fine on branch origin/topic/11756-floatingpoint-exception-macros. However, I am just thinking:

  • In case fenv.h is not found, does it mean that floating point exception is just not supported?
  • Does this mean the same as FE_ALL_EXCEPT not defined?

I am just thinking of making this distinction together with the use of BOOST_FPE_OFF.

I also would like to have a better coverage of this. On your platform, what happens when you divide by 0 with and without your patch applied?

Thanks,

comment:21 Changed 3 months ago by André Draszik <git@…>

Thanks. I can't really answer your questions regarding missing fenv.h / FE_ALL_EXCEPT and BOOST_FPE_OFF. A standards compliant env should provide both, but of course FE_ALL_EXCEPT may be 0.

 http://pubs.opengroup.org/onlinepubs/009695399/basedefs/fenv.h.html  http://en.cppreference.com/w/cpp/numeric/fenv/FE_exceptions

I am not an expert on boost so I need some more information on what you want me to test please. Without my patch it doesn't compile on my platform.

comment:22 Changed 3 months ago by renficiaud

In develop, merged at rev cbbacca13083eaacd9c2d197524540ff9e37bade

comment:23 Changed 3 months ago by renficiaud

  • Status changed from new to assigned

comment:24 Changed 3 months ago by renficiaud

Merged to master (rev cd74a43a784bff0d9c4768fa26f5f1f2b1359014)

comment:25 Changed 6 weeks ago by renficiaud

  • Status changed from assigned to closed
  • Resolution set to fixed

comment:26 Changed 3 weeks ago by smetz

Hi, this modification generates a buid error for Intel compilers (version 11.0 in my case).

Indeed, for Intel compilers BOOST_NO_FENV_H is set as true, and compiler will not find fe* functions in execution_monitor.ipp lines 1382 and 1422.

comment:27 Changed 3 weeks ago by renficiaud

  • Status changed from closed to reopened
  • Resolution fixed deleted

comment:28 follow-up: ↓ 30 Changed 3 weeks ago by renficiaud

Hi smetz,

Is this visible now on the regression board? I have no access to neither the Intel nor the "FPU-less" machines.

comment:29 Changed 3 weeks ago by smetz

It doesn't appear in the regression board for the moment. This regression appeared in the boost 1.63 version.

comment:30 in reply to: ↑ 28 Changed 3 weeks ago by anonymous

Maybe you just have to come back on some modifications:

in boost/test/impl/execution_monitor.ipp lines 1378 and 1418, change:

#elif defined(__GLIBC__) && defined(__USE_GNU)

by

#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)

This works on my side with the Intel compiler. But I'm not sure that this will not introduce a new regression for the CLang compiler, I don't know if CLang support floatingpoint exceptions.

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as reopened
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.