Bug 19322 - std::isnan<>() is broken on FreeBSD
Summary: std::isnan<>() is broken on FreeBSD
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.0.0
: P3 normal
Target Milestone: 4.0.0
Assignee: Paolo Carlini
URL:
Keywords:
: 20919 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-01-07 23:06 UTC by lminder
Modified: 2005-04-09 19:32 UTC (History)
4 users (show)

See Also:
Host: i386-unknown-freebsd5.3
Target: i386-unknown-freebsd5.3
Build: i386-unknown-freebsd5.3
Known to work:
Known to fail:
Last reconfirmed: 2005-01-13 10:41:09


Attachments
As tested on x86-linux (591 bytes, patch)
2005-01-13 10:43 UTC, Paolo Carlini
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description lminder 2005-01-07 23:06:57 UTC

(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.
Comment 1 lminder 2005-01-07 23:06:57 UTC
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
Comment 2 Paolo Carlini 2005-01-13 10:41:09 UTC
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.
Comment 3 Paolo Carlini 2005-01-13 10:43:06 UTC
Created attachment 7949 [details]
As tested on x86-linux
Comment 4 Gabriel Dos Reis 2005-01-13 13:27:11 UTC
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
Comment 5 lminder 2005-01-13 18:22:35 UTC
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
Comment 6 Paolo Carlini 2005-01-13 18:27:23 UTC
> 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.
Comment 7 Paolo Carlini 2005-01-14 01:05:02 UTC
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...
Comment 8 Gabriel Dos Reis 2005-01-14 03:18:54 UTC
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
Comment 9 GCC Commits 2005-01-16 09:59:24 UTC
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

Comment 10 Paolo Carlini 2005-01-16 10:02:45 UTC
Fixed.
Comment 11 Andrew Pinski 2005-04-09 19:32:42 UTC
*** Bug 20919 has been marked as a duplicate of this bug. ***