(Link to original mail: http://gcc.gnu.org/ml/libstdc++/2005-01/msg00059.html) On FreeBSD 5.3, if I run the following test program (compiled w/ system gcc, which is 3.4.2; or a hand-compiled current CVS snapshot): #include <iostream> #include <cmath> int main(void) { std::cout << std::isnan(3.0) << '\n'; return 0; } I get a segfault: lorinder$ g++ x.cc lorinder$ ./a.out Segmentation fault (core dumped) There is no problem on Linux. The segfault happens as well if I add -D_GLIBCXX_USE_C99_MATH. The problem is that __gnu_cxx::isnan<>() calls __gnu_cxx::__capture_isnan<>(), which in turn recursively calls __gnu_cxx::isnan<>(). Indeed, FreeBSD's math.h contains the following snippet: #define isnan(x) \ ((sizeof (x) == sizeof (float)) ? isnanf(x) \ : (sizeof (x) == sizeof (double)) ? isnan(x) \ : __isnanl(x)) So, isnan() is both a macro and a function taking a double. If my understanding is correct, __capture_isnan() calls __gnu_cxx::isnan() instead of ::isnan(). I am well aware that std::isnan() is probably not strictly standard C++ (since isnan is new in C99), but I'd consider it a quality of implementation issue to have it working if it is available. Environment: System: FreeBSD lorenzdesktop 5.3-RELEASE-p1 FreeBSD 5.3-RELEASE-p1 #3: Sat Dec 11 12:45:33 CET 2004 lorinder@lorenzdesktop:/usr/obj/usr/src/sys/MYKERNEL i386 FreeBSD 5.3, i386 (athlon-xp), system libc, and libstdc++. host: i386-unknown-freebsd5.3 build: i386-unknown-freebsd5.3 target: i386-unknown-freebsd5.3 configured with: ../gcc/configure --enable-languages=c,c++,objc --disable-shared --program-suffix=-exp How-To-Repeat: Compile the aforementioned testprogram on FreeBSD 5.3.
Fix: A possibility which fixes the problem for me is to define std::isnan<>() and friends directly in std:: instead of definining them in __gnu_cxx:: and then "importing" them to std::. (On the other hand, there is probably a reason why things aren't done that way to begin with.) Below a hack to <cmath> which fixes the problem for me. (I haven't run the test suite over it or anything, so this might well break other stuff). --- /usr/include/c++/3.4/cmath.orig Fri Oct 29 03:08:48 2004 +++ /usr/include/c++/3.4/cmath Fri Jan 7 04:35:22 2005 @@ -515,61 +515,64 @@ #if _GLIBCXX_USE_C99_MATH #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC -namespace __gnu_cxx +namespace std { template<typename _Tp> int - fpclassify(_Tp __f) { return __capture_fpclassify(__f); } + fpclassify(_Tp __f) { return __gnu_cxx::__capture_fpclassify(__f); } template<typename _Tp> int - isfinite(_Tp __f) { return __capture_isfinite(__f); } + isfinite(_Tp __f) { return __gnu_cxx::__capture_isfinite(__f); } template<typename _Tp> int - isinf(_Tp __f) { return __capture_isinf(__f); } + isinf(_Tp __f) { return __gnu_cxx::__capture_isinf(__f); } template<typename _Tp> int - isnan(_Tp __f) { return __capture_isnan(__f); } + isnan(_Tp __f) { return __gnu_cxx::__capture_isnan(__f); } template<typename _Tp> int - isnormal(_Tp __f) { return __capture_isnormal(__f); } + isnormal(_Tp __f) { return __gnu_cxx::__capture_isnormal(__f); } template<typename _Tp> int - signbit(_Tp __f) { return __capture_signbit(__f); } + signbit(_Tp __f) { return __gnu_cxx::__capture_signbit(__f); } template<typename _Tp> int - isgreater(_Tp __f1, _Tp __f2) { return __capture_isgreater(__f1, __f2); } + isgreater(_Tp __f1, _Tp __f2) { + return __gnu_cxx::__capture_isgreater(__f1, __f2); } template<typename _Tp> int isgreaterequal(_Tp __f1, _Tp __f2) - { return __capture_isgreaterequal(__f1, __f2); } + { return __gnu_cxx::__capture_isgreaterequal(__f1, __f2); } template<typename _Tp> int - isless(_Tp __f1, _Tp __f2) { return __capture_isless(__f1, __f2); } + isless(_Tp __f1, _Tp __f2) { return + __gnu_cxx::__capture_isless(__f1, __f2); } template<typename _Tp> int islessequal(_Tp __f1, _Tp __f2) - { return __capture_islessequal(__f1, __f2); } + { return __gnu_cxx::__capture_islessequal(__f1, __f2); } template<typename _Tp> int islessgreater(_Tp __f1, _Tp __f2) - { return __capture_islessgreater(__f1, __f2); } + { return __gnu_cxx::__capture_islessgreater(__f1, __f2); } template<typename _Tp> int isunordered(_Tp __f1, _Tp __f2) - { return __capture_isunordered(__f1, __f2); } + { return __gnu_cxx::__capture_isunordered(__f1, __f2); } } +/* namespace std { using __gnu_cxx::fpclassify; @@ -585,6 +588,7 @@ using __gnu_cxx::islessgreater; using __gnu_cxx::isunordered; } +*/ #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ #endif
Gaby, can you spot something fundamentally wrong in the proposed patch? I'm testing the slightly tweaked attached version on x86-linux and everything seems still ok: I would suggest Lorenz regtesting it on freebsd or at least checking that 26_numerics/cmath/c_math_dynamic.cc does not regress there.
Created attachment 7949 [details] As tested on x86-linux
Subject: Re: std::isnan<>() is broken on FreeBSD "pcarlini at suse dot de" <gcc-bugzilla@gcc.gnu.org> writes: | Gaby, can you spot something fundamentally wrong in the proposed patch? I'm | testing the slightly tweaked attached version on x86-linux and everything seems | still ok: I would suggest Lorenz regtesting it on freebsd or at least checking | that 26_numerics/cmath/c_math_dynamic.cc does not regress there. I think the patch is OK -- modulo testing on different targets, especially *BSD, linux and another non-glibc system (solaris for example). thanks. -- Gaby
Subject: Re: std::isnan<>() is broken on FreeBSD gdr at integrable-solutions dot net wrote: > I think the patch is OK -- modulo testing on different targets, > especially > *BSD, linux and another non-glibc system (solaris for example). Ok, I'll try to regtest the patch later today on FreeBSD (I'll have to RTFM first on how exactly this is done). I'll report back. I don't have access to a solaris box at the moment. --Lorenz
> Ok, I'll try to regtest the patch later today on FreeBSD (I'll have to > RTFM first on how exactly this is done). I'll report back. Thanks. If it's the first time, probably you have to install DejaGnu and Expect. Have a look to: http://gcc.gnu.org/install/test.html I'm taking care of Solaris testing.
Eric Botcazou reported privately that the patch doesn't introduce regressions on SPARC/Solaris 2.5.1, 2.6, 7, 8 and 9, both mainline and 3.4. Thanks Eric! As soon as we have FreeBSD results, we can go ahead...
Subject: Re: std::isnan<>() is broken on FreeBSD "pcarlini at suse dot de" <gcc-bugzilla@gcc.gnu.org> writes: | Eric Botcazou reported privately that the patch doesn't introduce regressions | on SPARC/Solaris 2.5.1, 2.6, 7, 8 and 9, both mainline and 3.4. Thanks Eric! | | As soon as we have FreeBSD results, we can go ahead... Thanks! -- Gaby
Subject: Bug 19322 CVSROOT: /cvs/gcc Module name: gcc Changes by: paolo@gcc.gnu.org 2005-01-16 09:59:07 Modified files: libstdc++-v3 : ChangeLog libstdc++-v3/include/c_std: std_cmath.h Added files: libstdc++-v3/testsuite/26_numerics/cmath: 19322.cc Log message: 2005-01-16 Lorenz Minder <lminder@gmx.net> Paolo Carlini <pcarlini@suse.de> PR libstdc++/19322 * include/c_std/std_cmath.h: Define the C99 classification facilities directly inside namespace std:. * testsuite/26_numerics/cmath/19322.cc: New. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.2856&r2=1.2857 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/c_std/std_cmath.h.diff?cvsroot=gcc&r1=1.15&r2=1.16 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/testsuite/26_numerics/cmath/19322.cc.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed.
*** Bug 20919 has been marked as a duplicate of this bug. ***