From nobody@FreeBSD.org  Fri Mar 17 03:26:27 2006
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 07A6E16A400
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 17 Mar 2006 03:26:27 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id C8F2643D45
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 17 Mar 2006 03:26:26 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k2H3QQsX005772
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 17 Mar 2006 03:26:26 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id k2H3QQkD005768;
	Fri, 17 Mar 2006 03:26:26 GMT
	(envelope-from nobody)
Message-Id: <200603170326.k2H3QQkD005768@www.freebsd.org>
Date: Fri, 17 Mar 2006 03:26:26 GMT
From: Tom Russo <tvrusso@sandia.gov>
To: freebsd-gnats-submit@FreeBSD.org
Subject: std::isnan()/std::isinf() are not identical to isnan() and isinf()
X-Send-Pr-Version: www-2.3

>Number:         94583
>Category:       kern
>Synopsis:       [libm] std::isnan()/std::isinf() are not identical to isnan() and isinf()
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 17 03:30:16 GMT 2006
>Closed-Date:    Sun Apr 12 15:30:38 UTC 2009
>Last-Modified:  Sun Apr 12 15:30:38 UTC 2009
>Originator:     Tom Russo
>Release:        FreeBSD 5.4 STABLE
>Organization:
Sandia National Laboratories
>Environment:
FreeBSD xxxxxxx.xxxxxx.xxx 5.4-STABLE FreeBSD 5.4-STABLE #1: Thu Oct 20 02:35:11 MDT 2005     root@:/usr/obj/usr/src/sys/WINSTON  i386

>Description:
Discovered that a C++ program that was written to use "std::isnan()" and "std::isinf()" entered an infinite loop with 100% processor activity upon encountering either of these calls.

The attached test program, which was originally written to use "using namespace std;" and no "std::" namespace specification on isnan/isinf worked just fine.  Upon adding the namespace specification to isnan and/or isinf, even the test program hung immediately.

While writing the "how to repeat" part of this problem report I discovered that if I specify any optimization level other than -O2 the code segfaults rather than entering an infinite loop.

>How-To-Repeat:
Compile the following test program:

#include <iostream>
#include <cmath>


int main(void) 

{
  double finite = 1.0e-100;
  double infinity = 1.0/0.0;
  double nan = sqrt(-1.0);
  double minusinfinity = -1.0/0.0;

  std::cout << std::endl << "finite = " << finite << std::endl;
  std::cout << "isinf() = " << isinf(finite) << std::endl;
  std::cout << "isnan() = " << isnan(finite) << std::endl;
  std::cout << "isinf() = " << std::isinf(finite) << std::endl;
  std::cout << "isnan() = " << std::isnan(finite) << std::endl;

  return 0;
}

using g++ 3.4:

g++ -O2 -g -o bugreport bugreport.cpp

Run the resulting executable.

Compiling with -O0 or -O1 results in a segfault instead.

>Fix:

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->analyzed 
State-Changed-By: das 
State-Changed-When: Thu Jan 4 01:16:40 UTC 2007 
State-Changed-Why:  
This appears to be a regression in glibstdc++ 3.4, or our configuration 
of it.  Here's the problem.  In our math.h, isnan() is defined as a macro 
as follows: 

#define isnan(x)                                         
((sizeof (x) == sizeof (float)) ? isnanf(x)          
: (sizeof (x) == sizeof (double)) ? isnan(x)         
: __isnanl(x)) 

This is as suggested in the C99 standard.  Then 
src/contrib/libstdc++/include/c_std/std_cmath.h 
plays a little game to move isnan() out of the 
global namespace: 

namespace __gnu_cxx 
{ 
[...] 
template<typename _Tp> 
inline int 
__capture_isnan(_Tp __f) { return isnan(__f); } 
[...] 
} 
[...] 
#undef isnan 
[...] 
namespace __gnu_cxx 
[...] 
template<typename _Tp> 
inline int 
isnan(_Tp __f) { return __capture_isnan(__f); } 
[...] 
} 

The trouble with this is that once the macro is expanded, 
the call to isnan() within __capture_isnan() simply refers 
to the symbol isnan() within the __gnu_cxx namespace, which 
is a function that refers back to __capture_isnan(), and 
the result is an infinite loop. 

The following workaround (along with corresponding changes for 
isinf()) fixes the problem, but I don't understand the internals 
of libstdc++ well enough to know if it's the best solution. 

template<typename _Tp> 
inline int 
__capture_isnan(_Tp __f) { using ::isnan; return isnan(__f); } 
^^^^^^^^^^^^^^ 
I'm forwarding this to kan@ to take a look at.  This might 
need to be taken to the GNU people, rather than fixed locally, 
or there may be a better fix.  I brought up some similar 
issues regarding isnan() in C++ with them in early 2003. 
As I recall, Loren and someone with Red Hat were very helpful, 
but Gaby's combative attitude resulted in lots of wasted time, 
and ultimately nothing got fixed.  I'd rather not deal with 
that again if I can avoid it. 8) 


Responsible-Changed-From-To: freebsd-bugs->kan 
Responsible-Changed-By: das 
Responsible-Changed-When: Thu Jan 4 01:16:40 UTC 2007 
Responsible-Changed-Why:  


http://www.freebsd.org/cgi/query-pr.cgi?pr=94583 
Responsible-Changed-From-To: kan->freebsd-bugs 
Responsible-Changed-By: kan 
Responsible-Changed-When: Fri Nov 23 17:02:58 UTC 2007 
Responsible-Changed-Why:  
I am not doing anything related to GCC anymore. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=94583 
State-Changed-From-To: analyzed->closed 
State-Changed-By: das 
State-Changed-When: Sun Apr 12 15:30:00 UTC 2009 
State-Changed-Why:  
This seems to be fixed in 7-STABLE and 8-CURRENT, presumably by 
the import of gcc 4.x. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=94583 
>Unformatted:
