PATCH: libstdc++/7680 (related to RFC posted last week)

Loren James Rittle rittle@latour.rsch.comm.mot.com
Sat Apr 12 09:25:00 GMT 2003


While looking over tweaks for the patch to mirror system header
visibility (work stalled since the FreeBSD 5 reference machines were
broken this week), I looked at libstdc++/7680 again (related problem,
but my efforts last Friday didn't cover it).  That PR is against
FreeBSD in particular but I seem to recall similar issues on some
other ports.  How much trouble am I in if I apply this patch? ;-)

(This one only covers C99 float transcendentals since that is the
sticky issue for FreeBSD on the PR of interest and that is all I can
test on FreeBSD 4, another patch could cover C99 long double
transcendentals and most of my other cases of the first patch I posted
last week regarding C99 support for FreeBSD 5.  Most of the other
things that system vendors might like to optionally hide, which are
keyed off macros, and that we might like to use, fall into this camp
and are supported by this technique.)

Note: C++ allows one to redeclare a function as long as it matches
precisely, where precisely has a precise but not obvious definition.
It is a hard error if it doesn't match precisely.  More importantly,
since at least 3.2, g++ now groks, e.g.  (perhaps it didn't the last
time someone looked at this technique):

	extern "C" { float xxxx (float); }
	namespace yyyy { extern "C" float xxxx (float); using ::xxxx; }

General portability would cause me to ignore this C standardize:

       7.1.4  Use of library functions

       [#2] Provided  that  a  library  function  can  be  declared
       without  reference  to  any  type defined in a header, it is
       also permissible to declare the function and use it  without
       including its associated header.

However, it is (a) key to my new technique; (b) likely to hold true
for C89 and esp. C99 ABI points that adhere to the above constraints;
and (c) in any event, I have designed a completely flexible way to
use/check this on a per-port basis; thus we just enable it where we
can for added robustness (_CHECK) or wish to (_DYNAMIC).

Ports that define neither of:
_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK
_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC
see only an extra level of namespace monkeying (well, since all this
is for internal library implementation, no one really sees it).

Ports that define _GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK to be 1
get a check which ensures that the system headers are consistent with
our requirements (I assume below that only ports expected to have
clean system headers would throw the switch, but negating it by
default would be interesting as well IMHO).  Ports may define
_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC to map to 0 only when
macros are exposing proper support from system headers (note the
negative logic system which removes the crazy !define(X) || X construct).

The number of gcc switches and standard-dictated macros that affect
this space is probably enumerable, yet an autoconf-based solution
seems elusive.  If this technique is OK by fellow library maintainers,
then I shall redo all my outstanding work from last week into this
form.  I will also look for discard PRs that might benefit from this
technique.  I can at least work with a primary port maintainer to help
them improve the situation they see in this area once the infrastructure
is in place.

(BTW, spot checked, full testing over weekend now that reference
FreeBSD machines operational again.  Yup, the new test case fails
without the patch and passes with the patch.)

Regards,
Loren

	libstdc++/7680
	* include/c_std/std_cmath.h (__gnu_cxx_private): New namespace.
	Populate it with multiple legal ways to obtain the C99 float
	transcendentals.  Use them instead of direct global reference.
	* docs/html/17_intro/porting.texi
	(_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK): New macro.
	(_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC): New macro.
	* config/os/bsd/freebsd/os_defines.h
	(_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK): New macro.
	(_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC): New macro.
	* testsuite/26_numerics/c_math_dynamic.cc: New file.

Index: include/c_std/std_cmath.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/c_std/std_cmath.h,v
retrieving revision 1.6
diff -c -r1.6 std_cmath.h
*** include/c_std/std_cmath.h	21 Jun 2002 20:20:48 -0000	1.6
--- include/c_std/std_cmath.h	12 Apr 2003 07:37:17 -0000
***************
*** 1,6 ****
  // -*- C++ -*- C forwarding header.
  
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
  // Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
--- 1,6 ----
  // -*- C++ -*- C forwarding header.
  
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
  // Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
***************
*** 76,81 ****
--- 76,127 ----
  #undef tan
  #undef tanh
  
+ // ...and in the darkness bind them...
+ namespace __gnu_cxx_private
+ {
+ #if _GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK || \
+     _GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC
+   extern "C" float (acosf)(float);
+   extern "C" float (asinf)(float);
+   extern "C" float (atanf)(float);
+   extern "C" float (atan2f)(float, float);
+   extern "C" float (ceilf)(float);
+   extern "C" float (coshf)(float);
+   extern "C" float (expf)(float);
+   extern "C" float (floorf)(float);
+   extern "C" float (fmodf)(float, float);
+   extern "C" float (frexpf)(float, int*);
+   extern "C" float (ldexpf)(float, int);
+   extern "C" float (logf)(float);
+   extern "C" float (log10f)(float);
+   extern "C" float (modff)(float, float*);
+   extern "C" float (powf)(float, float);
+   extern "C" float (sinhf)(float);
+   extern "C" float (tanf)(float);
+   extern "C" float (tanhf)(float);
+ #endif
+ #if !(_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC)
+   using ::acosf;
+   using ::asinf;
+   using ::atanf;
+   using ::atan2f;
+   using ::ceilf;
+   using ::coshf;
+   using ::expf;
+   using ::floorf;
+   using ::fmodf;
+   using ::frexpf;
+   using ::ldexpf;
+   using ::logf;
+   using ::log10f;
+   using ::modff;
+   using ::powf;
+   using ::sinhf;
+   using ::tanf;
+   using ::tanhf;
+ #endif
+ }
+ 
  namespace std 
  {
    // Forward declaration of a helper function.  This really should be
***************
*** 96,102 ****
  
  #if _GLIBCPP_HAVE_ACOSF
    inline float 
!   acos(float __x) { return ::acosf(__x); }
  #else
    inline float 
    acos(float __x) { return ::acos(static_cast<double>(__x)); }
--- 142,148 ----
  
  #if _GLIBCPP_HAVE_ACOSF
    inline float 
!   acos(float __x) { return __gnu_cxx_private::acosf(__x); }
  #else
    inline float 
    acos(float __x) { return ::acos(static_cast<double>(__x)); }
***************
*** 116,122 ****
  
  #if _GLIBCPP_HAVE_ASINF
    inline float 
!   asin(float __x) { return ::asinf(__x); }
  #else
    inline float 
    asin(float __x) { return ::asin(static_cast<double>(__x)); }
--- 162,168 ----
  
  #if _GLIBCPP_HAVE_ASINF
    inline float 
!   asin(float __x) { return __gnu_cxx_private::asinf(__x); }
  #else
    inline float 
    asin(float __x) { return ::asin(static_cast<double>(__x)); }
***************
*** 134,140 ****
  
  #if _GLIBCPP_HAVE_ATANF
    inline float 
!   atan(float __x) { return ::atanf(__x); }
  #else
    inline float 
    atan(float __x) { return ::atan(static_cast<double>(__x)); }
--- 180,186 ----
  
  #if _GLIBCPP_HAVE_ATANF
    inline float 
!   atan(float __x) { return __gnu_cxx_private::atanf(__x); }
  #else
    inline float 
    atan(float __x) { return ::atan(static_cast<double>(__x)); }
***************
*** 152,158 ****
  
  #if _GLIBCPP_HAVE_ATAN2F
    inline float 
!   atan2(float __y, float __x) { return ::atan2f(__y, __x); }
  #else
    inline float 
    atan2(float __y, float __x)
--- 198,204 ----
  
  #if _GLIBCPP_HAVE_ATAN2F
    inline float 
!   atan2(float __y, float __x) { return __gnu_cxx_private::atan2f(__y, __x); }
  #else
    inline float 
    atan2(float __y, float __x)
***************
*** 172,178 ****
  
  #if _GLIBCPP_HAVE_CEILF
    inline float 
!   ceil(float __x) { return ::ceilf(__x); }
  #else
    inline float 
    ceil(float __x) { return ::ceil(static_cast<double>(__x)); }
--- 218,224 ----
  
  #if _GLIBCPP_HAVE_CEILF
    inline float 
!   ceil(float __x) { return __gnu_cxx_private::ceilf(__x); }
  #else
    inline float 
    ceil(float __x) { return ::ceil(static_cast<double>(__x)); }
***************
*** 200,206 ****
  
  #if _GLIBCPP_HAVE_COSHF
    inline float 
!   cosh(float __x) { return ::coshf(__x); }
  #else
    inline float 
    cosh(float __x) { return ::cosh(static_cast<double>(__x)); }
--- 246,252 ----
  
  #if _GLIBCPP_HAVE_COSHF
    inline float 
!   cosh(float __x) { return __gnu_cxx_private::coshf(__x); }
  #else
    inline float 
    cosh(float __x) { return ::cosh(static_cast<double>(__x)); }
***************
*** 218,224 ****
  
  #if _GLIBCPP_HAVE_EXPF
    inline float 
!   exp(float __x) { return ::expf(__x); }
  #else
    inline float 
    exp(float __x) { return ::exp(static_cast<double>(__x)); }
--- 264,270 ----
  
  #if _GLIBCPP_HAVE_EXPF
    inline float 
!   exp(float __x) { return __gnu_cxx_private::expf(__x); }
  #else
    inline float 
    exp(float __x) { return ::exp(static_cast<double>(__x)); }
***************
*** 246,252 ****
  
  #if _GLIBCPP_HAVE_FLOORF
    inline float 
!   floor(float __x) { return ::floorf(__x); }
  #else
    inline float 
    floor(float __x) { return ::floor(static_cast<double>(__x)); }
--- 292,298 ----
  
  #if _GLIBCPP_HAVE_FLOORF
    inline float 
!   floor(float __x) { return __gnu_cxx_private::floorf(__x); }
  #else
    inline float 
    floor(float __x) { return ::floor(static_cast<double>(__x)); }
***************
*** 264,270 ****
  
  #if _GLIBCPP_HAVE_FMODF
    inline float 
!   fmod(float __x, float __y) { return ::fmodf(__x, __y); }
  #else
    inline float 
    fmod(float __x, float __y)
--- 310,316 ----
  
  #if _GLIBCPP_HAVE_FMODF
    inline float 
!   fmod(float __x, float __y) { return __gnu_cxx_private::fmodf(__x, __y); }
  #else
    inline float 
    fmod(float __x, float __y)
***************
*** 284,290 ****
  
  #if _GLIBCPP_HAVE_FREXPF
    inline float 
!   frexp(float __x, int* __exp) { return ::frexpf(__x, __exp); }
  #else
    inline float 
    frexp(float __x, int* __exp) { return ::frexp(__x, __exp); }
--- 330,336 ----
  
  #if _GLIBCPP_HAVE_FREXPF
    inline float 
!   frexp(float __x, int* __exp) { return __gnu_cxx_private::frexpf(__x, __exp); }
  #else
    inline float 
    frexp(float __x, int* __exp) { return ::frexp(__x, __exp); }
***************
*** 303,309 ****
  
  #if _GLIBCPP_HAVE_LDEXPF
    inline float 
!   ldexp(float __x, int __exp) { return ::ldexpf(__x, __exp); }
  #else
    inline float 
    ldexp(float __x, int __exp)
--- 349,355 ----
  
  #if _GLIBCPP_HAVE_LDEXPF
    inline float 
!   ldexp(float __x, int __exp) { return __gnu_cxx_private::ldexpf(__x, __exp); }
  #else
    inline float 
    ldexp(float __x, int __exp)
***************
*** 323,329 ****
  
  #if _GLIBCPP_HAVE_LOGF
    inline float 
!   log(float __x) { return ::logf(__x); }
  #else
    inline float log(float __x)
    { return ::log(static_cast<double>(__x)); }
--- 369,375 ----
  
  #if _GLIBCPP_HAVE_LOGF
    inline float 
!   log(float __x) { return __gnu_cxx_private::logf(__x); }
  #else
    inline float log(float __x)
    { return ::log(static_cast<double>(__x)); }
***************
*** 341,347 ****
  
  #if _GLIBCPP_HAVE_LOG10F
    inline float 
!   log10(float __x) { return ::log10f(__x); }
  #else
    inline float 
    log10(float __x) { return ::log10(static_cast<double>(__x)); }
--- 387,393 ----
  
  #if _GLIBCPP_HAVE_LOG10F
    inline float 
!   log10(float __x) { return __gnu_cxx_private::log10f(__x); }
  #else
    inline float 
    log10(float __x) { return ::log10(static_cast<double>(__x)); }
***************
*** 359,365 ****
  
  #if _GLIBCPP_HAVE_MODFF
    inline float 
!   modf(float __x, float* __iptr) { return ::modff(__x, __iptr); }
  #else
    inline float 
    modf(float __x, float* __iptr)
--- 405,411 ----
  
  #if _GLIBCPP_HAVE_MODFF
    inline float 
!   modf(float __x, float* __iptr) { return __gnu_cxx_private::modff(__x, __iptr); }
  #else
    inline float 
    modf(float __x, float* __iptr)
***************
*** 398,404 ****
  
  #if _GLIBCPP_HAVE_POWF
    inline float 
!   pow(float __x, float __y) { return ::powf(__x, __y); }
  #else
    inline float 
    pow(float __x, float __y)
--- 444,450 ----
  
  #if _GLIBCPP_HAVE_POWF
    inline float 
!   pow(float __x, float __y) { return __gnu_cxx_private::powf(__x, __y); }
  #else
    inline float 
    pow(float __x, float __y)
***************
*** 440,446 ****
  
  #if _GLIBCPP_HAVE_SINHF
    inline float 
!   sinh(float __x) { return ::sinhf(__x); }
  #else
    inline float 
    sinh(float __x) { return ::sinh(static_cast<double>(__x)); }
--- 486,492 ----
  
  #if _GLIBCPP_HAVE_SINHF
    inline float 
!   sinh(float __x) { return __gnu_cxx_private::sinhf(__x); }
  #else
    inline float 
    sinh(float __x) { return ::sinh(static_cast<double>(__x)); }
***************
*** 468,474 ****
  
  #if _GLIBCPP_HAVE_TANF
    inline float 
!   tan(float __x) { return ::tanf(__x); }
  #else
    inline float 
    tan(float __x) { return ::tan(static_cast<double>(__x)); }
--- 514,520 ----
  
  #if _GLIBCPP_HAVE_TANF
    inline float 
!   tan(float __x) { return __gnu_cxx_private::tanf(__x); }
  #else
    inline float 
    tan(float __x) { return ::tan(static_cast<double>(__x)); }
***************
*** 486,492 ****
  
  #if _GLIBCPP_HAVE_TANHF
    inline float 
!   tanh(float __x) { return ::tanhf(__x); }
  #else
    inline float 
    tanh(float __x) { return ::tanh(static_cast<double>(__x)); }
--- 532,538 ----
  
  #if _GLIBCPP_HAVE_TANHF
    inline float 
!   tanh(float __x) { return __gnu_cxx_private::tanhf(__x); }
  #else
    inline float 
    tanh(float __x) { return ::tanh(static_cast<double>(__x)); }
Index: docs/html/17_intro/porting.texi
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/docs/html/17_intro/porting.texi,v
retrieving revision 1.9
diff -c -r1.9 porting.texi
*** docs/html/17_intro/porting.texi	4 Feb 2003 01:27:52 -0000	1.9
--- docs/html/17_intro/porting.texi	12 Apr 2003 08:47:00 -0000
***************
*** 150,160 ****
  target.  It will not work to simply define these macros in
  @file{os_defines.h}.
  
! At this time, there is one libstdc++-v3-specific macro which may be
  defined.  @code{_G_USING_THUNKS} may be defined to 0 to express that the
  port doesn't use thunks (although it is unclear that this is still
  useful since libio support isn't currently working and the g++ v3 ABI
  invalidates the assumption that some ports don't use thunks).
  
  Finally, you should bracket the entire file in an include-guard, like
  this:
--- 150,170 ----
  target.  It will not work to simply define these macros in
  @file{os_defines.h}.
  
! At this time, there are a few libstdc++-v3-specific macro which may be
  defined.  @code{_G_USING_THUNKS} may be defined to 0 to express that the
  port doesn't use thunks (although it is unclear that this is still
  useful since libio support isn't currently working and the g++ v3 ABI
  invalidates the assumption that some ports don't use thunks).
+ 
+ @code{_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK} may be defined
+ to 1 to check the related set of function declarations found in system
+ headers against versions found in the library headers derived from
+ the standard.
+ 
+ @code{_GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC} may be defined
+ to an expression that yields 0 if and only if the system headers
+ are exposing proper support for the related set of functions.  If defined,
+ it must be 0 while bootstrapping the compiler/rebuilding the library.
  
  Finally, you should bracket the entire file in an include-guard, like
  this:
Index: config/os/bsd/freebsd/os_defines.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/os/bsd/freebsd/os_defines.h,v
retrieving revision 1.2
diff -r1.2 os_defines.h
36a37,39
> #define _GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_CHECK 1
> #define _GLIBCPP_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC defined _XOPEN_SOURCE
> 
Index: testsuite/26_numerics/c_math_dynamic.cc
===================================================================
RCS file: testsuite/26_numerics/c_math_dynamic.cc
diff -N testsuite/26_numerics/c_math_dynamic.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/26_numerics/c_math_dynamic.cc	12 Apr 2003 08:39:27 -0000
***************
*** 0 ****
--- 1,58 ----
+ // Inspired by libstdc++/7680 & 26_numerics/c_math.cc, 2003-04-12 ljr
+ 
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction.  Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License.  This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+ 
+ // { dg-do link }
+ // { dg-options "-D_XOPEN_SOURCE" { target *-*-freebsd* } }
+ 
+ #include <cmath>
+ 
+ int
+ test01()
+ {
+   float a = 1.f;
+   float b;
+   std::modf(a, &b);
+   return 0;
+ }
+ 
+ int
+ test02 ()
+ {
+   float a = 0.0f;
+   float b = std::acos(b);
+   return 0;
+ }
+ 
+ int
+ main()
+ {
+   test01();
+   test02();
+   return 0;
+ }



More information about the Libstdc++ mailing list