(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 [EMAIL PROTECTED]:/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.
------- Additional Comments From lminder at gmx dot net  2005-01-07 23:06 
-------
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

-- 
           Summary: std::isnan<>() is broken on FreeBSD
           Product: gcc
           Version: 4.0.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: lminder at gmx dot net
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i386-unknown-freebsd5.3
  GCC host triplet: i386-unknown-freebsd5.3
GCC target triplet: i386-unknown-freebsd5.3


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19322

Reply via email to