analyzer: fix i18n issues in symbolic out-of-bounds [PR106626]
[platform/upstream/gcc.git] / libstdc++-v3 / include / tr1 / cmath
index 21bdee8..384f116 100644 (file)
@@ -1,7 +1,6 @@
 // TR1 cmath -*- C++ -*-
 
-// Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
-// Free Software Foundation, Inc.
+// Copyright (C) 2006-2022 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
@@ -32,6 +31,8 @@
 
 #pragma GCC system_header
 
+#include <bits/requires_hosted.h> // TR1
+
 #include <cmath>
 
 #ifdef _GLIBCXX_USE_C99_MATH_TR1
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
-namespace tr1
-{
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+namespace tr1
+{
 #if _GLIBCXX_USE_C99_MATH_TR1
 
+  // Using declarations to bring names from libc's <math.h> into std::tr1.
+
   // types
   using ::double_t;
   using ::float_t;
@@ -417,9 +420,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if _GLIBCXX_USE_C99_MATH_TR1
 
-  /// Additional overloads [8.16.4].
+  /** Additional overloads [8.16.4].
+   *  @{
+   */
+
+  // For functions defined in C++03 the additional overloads are already
+  // declared in <cmath> so we can just re-declare them in std::tr1.
+
   using std::acos;
+  using std::asin;
+  using std::atan;
+  using std::atan2;
+  using std::ceil;
+  using std::cos;
+  using std::cosh;
+  using std::exp;
+  using std::floor;
+  using std::fmod;
+  using std::frexp;
+  using std::ldexp;
+  using std::log;
+  using std::log10;
+  using std::sin;
+  using std::sinh;
+  using std::sqrt;
+  using std::tan;
+  using std::tanh;
 
+#if __cplusplus >= 201103L
+
+  // Since C++11, <cmath> defines additional overloads for these functions
+  // in namespace std.
+
+  using std::acosh;
+  using std::asinh;
+  using std::atanh;
+  using std::cbrt;
+  using std::copysign;
+  using std::erf;
+  using std::erfc;
+  using std::exp2;
+  using std::expm1;
+  using std::fdim;
+  using std::fma;
+  using std::fmax;
+  using std::fmin;
+  using std::hypot;
+  using std::ilogb;
+  using std::lgamma;
+  using std::llrint;
+  using std::llround;
+  using std::log1p;
+  using std::log2;
+  using std::logb;
+  using std::lrint;
+  using std::lround;
+  using std::nan;
+  using std::nearbyint;
+  using std::nextafter;
+  using std::nexttoward;
+  using std::remainder;
+  using std::remquo;
+  using std::rint;
+  using std::round;
+  using std::scalbln;
+  using std::scalbn;
+  using std::tgamma;
+  using std::trunc;
+
+#else // __cplusplus < 201103L
+
+  // In C++03 we need to provide the additional overloads.
+
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   acosh(float __x)
   { return __builtin_acoshf(__x); }
@@ -427,17 +500,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   acosh(long double __x)
   { return __builtin_acoshl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     acosh(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return acosh(__type(__x));
-    }
-
-  using std::asin;
+    { return __builtin_acosh(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   asinh(float __x)
   { return __builtin_asinhf(__x); }
@@ -445,18 +516,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   asinh(long double __x)
   { return __builtin_asinhl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     asinh(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return asinh(__type(__x));
-    }
-
-  using std::atan;
-  using std::atan2;
+    { return __builtin_asinh(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   atanh(float __x)
   { return __builtin_atanhf(__x); }
@@ -464,15 +532,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   atanh(long double __x)
   { return __builtin_atanhl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     atanh(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return atanh(__type(__x));
-    }
+    { return __builtin_atanh(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   cbrt(float __x)
   { return __builtin_cbrtf(__x); }
@@ -480,17 +548,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   cbrt(long double __x)
   { return __builtin_cbrtl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     cbrt(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return cbrt(__type(__x));
-    }
-
-  using std::ceil;
+    { return __builtin_cbrt(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   copysign(float __x, float __y)
   { return __builtin_copysignf(__x, __y); }
@@ -498,6 +564,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   copysign(long double __x, long double __y)
   { return __builtin_copysignl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -507,9 +574,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return copysign(__type(__x), __type(__y));
     }
 
-  using std::cos;
-  using std::cosh;  
-
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   erf(float __x)
   { return __builtin_erff(__x); }
@@ -517,15 +582,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   erf(long double __x)
   { return __builtin_erfl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     erf(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return erf(__type(__x));
-    }
+    { return __builtin_erf(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   erfc(float __x)
   { return __builtin_erfcf(__x); }
@@ -533,17 +598,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   erfc(long double __x)
   { return __builtin_erfcl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     erfc(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return erfc(__type(__x));
-    }
-
-  using std::exp;
+    { return __builtin_erfc(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   exp2(float __x)
   { return __builtin_exp2f(__x); }
@@ -551,15 +614,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   exp2(long double __x)
   { return __builtin_exp2l(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     exp2(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return exp2(__type(__x));
-    }
+    { return __builtin_exp2(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   expm1(float __x)
   { return __builtin_expm1f(__x); }
@@ -567,34 +630,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   expm1(long double __x)
   { return __builtin_expm1l(__x); }
-
-  template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
-    expm1(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return expm1(__type(__x));
-    }
-
-  // Note: we deal with fabs in a special way, because an using std::fabs
-  // would bring in also the overloads for complex types, which in C++0x
-  // mode have a different return type.
-  using ::fabs;
-
-  inline float
-  fabs(float __x)
-  { return __builtin_fabsf(__x); }
-
-  inline long double
-  fabs(long double __x)
-  { return __builtin_fabsl(__x); }
+#endif
 
   template<typename _Tp>
     inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
                                           double>::__type
-    fabs(_Tp __x)
-    { return __builtin_fabs(__x); }
+    expm1(_Tp __x)
+    { return __builtin_expm1(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   fdim(float __x, float __y)
   { return __builtin_fdimf(__x, __y); }
@@ -602,6 +646,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   fdim(long double __x, long double __y)
   { return __builtin_fdiml(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -611,8 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return fdim(__type(__x), __type(__y));
     }
 
-  using std::floor;
-
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   fma(float __x, float __y, float __z)
   { return __builtin_fmaf(__x, __y, __z); }
@@ -620,6 +664,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   fma(long double __x, long double __y, long double __z)
   { return __builtin_fmal(__x, __y, __z); }
+#endif
 
   template<typename _Tp, typename _Up, typename _Vp>
     inline typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
@@ -629,6 +674,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return fma(__type(__x), __type(__y), __type(__z));
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   fmax(float __x, float __y)
   { return __builtin_fmaxf(__x, __y); }
@@ -636,6 +682,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   fmax(long double __x, long double __y)
   { return __builtin_fmaxl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -645,6 +692,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return fmax(__type(__x), __type(__y));
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   fmin(float __x, float __y)
   { return __builtin_fminf(__x, __y); }
@@ -652,6 +700,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   fmin(long double __x, long double __y)
   { return __builtin_fminl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -661,9 +710,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return fmin(__type(__x), __type(__y));
     }
 
-  using std::fmod;
-  using std::frexp;
-
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   hypot(float __x, float __y)
   { return __builtin_hypotf(__x, __y); }
@@ -671,15 +718,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   hypot(long double __x, long double __y)
   { return __builtin_hypotl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
-    hypot(_Tp __x, _Up __y)
+    hypot(_Tp __y, _Up __x)
     {
       typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
-      return hypot(__type(__x), __type(__y));
+      return hypot(__type(__y), __type(__x));
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline int
   ilogb(float __x)
   { return __builtin_ilogbf(__x); }
@@ -687,17 +736,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline int
   ilogb(long double __x)
   { return __builtin_ilogbl(__x); }
+#endif
 
   template<typename _Tp>
-    inline int
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          int>::__type
     ilogb(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return ilogb(__type(__x));
-    }
-
-  using std::ldexp;
+    { return __builtin_ilogb(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   lgamma(float __x)
   { return __builtin_lgammaf(__x); }
@@ -705,15 +752,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   lgamma(long double __x)
   { return __builtin_lgammal(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     lgamma(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return lgamma(__type(__x));
-    }
+    { return __builtin_lgamma(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline long long
   llrint(float __x)
   { return __builtin_llrintf(__x); }
@@ -721,15 +768,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long long
   llrint(long double __x)
   { return __builtin_llrintl(__x); }
+#endif
 
   template<typename _Tp>
-    inline long long
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          long long>::__type
     llrint(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return llrint(__type(__x));
-    }
+    { return __builtin_llrint(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline long long
   llround(float __x)
   { return __builtin_llroundf(__x); }
@@ -737,18 +784,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long long
   llround(long double __x)
   { return __builtin_llroundl(__x); }
+#endif
 
   template<typename _Tp>
-    inline long long
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          long long>::__type
     llround(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return llround(__type(__x));
-    }
-
-  using std::log;
-  using std::log10;
+    { return __builtin_llround(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   log1p(float __x)
   { return __builtin_log1pf(__x); }
@@ -756,16 +800,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   log1p(long double __x)
   { return __builtin_log1pl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     log1p(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return log1p(__type(__x));
-    }
+    { return __builtin_log1p(__x); }
 
   // DR 568.
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   log2(float __x)
   { return __builtin_log2f(__x); }
@@ -773,15 +817,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   log2(long double __x)
   { return __builtin_log2l(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     log2(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return log2(__type(__x));
-    }
+    { return __builtin_log2(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   logb(float __x)
   { return __builtin_logbf(__x); }
@@ -789,15 +833,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   logb(long double __x)
   { return __builtin_logbl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     logb(_Tp __x)
     {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return logb(__type(__x));
+      return __builtin_logb(__x);
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline long
   lrint(float __x)
   { return __builtin_lrintf(__x); }
@@ -805,15 +851,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long
   lrint(long double __x)
   { return __builtin_lrintl(__x); }
+#endif
 
   template<typename _Tp>
-    inline long
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          long>::__type
     lrint(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return lrint(__type(__x));
-    }
+    { return __builtin_lrint(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline long
   lround(float __x)
   { return __builtin_lroundf(__x); }
@@ -821,15 +867,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long
   lround(long double __x)
   { return __builtin_lroundl(__x); }
+#endif
 
   template<typename _Tp>
-    inline long
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          long>::__type
     lround(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return lround(__type(__x));
-    }
+    { return __builtin_lround(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   nearbyint(float __x)
   { return __builtin_nearbyintf(__x); }
@@ -837,15 +883,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   nearbyint(long double __x)
   { return __builtin_nearbyintl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     nearbyint(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return nearbyint(__type(__x));
-    }
+    { return __builtin_nearbyint(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   nextafter(float __x, float __y)
   { return __builtin_nextafterf(__x, __y); }
@@ -853,6 +899,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   nextafter(long double __x, long double __y)
   { return __builtin_nextafterl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -862,6 +909,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return nextafter(__type(__x), __type(__y));
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   nexttoward(float __x, long double __y)
   { return __builtin_nexttowardf(__x, __y); }
@@ -869,19 +917,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   nexttoward(long double __x, long double __y)
   { return __builtin_nexttowardl(__x, __y); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     nexttoward(_Tp __x, long double __y)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return nexttoward(__type(__x), __y);
-    }
-
-  // DR 550. What should the return type of pow(float,int) be?
-  // NB: C++0x and TR1 != C++03.
-  //   using std::pow;
+    { return __builtin_nexttoward(__x, __y); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   remainder(float __x, float __y)
   { return __builtin_remainderf(__x, __y); }
@@ -889,6 +933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   remainder(long double __x, long double __y)
   { return __builtin_remainderl(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -898,6 +943,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return remainder(__type(__x), __type(__y));
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   remquo(float __x, float __y, int* __pquo)
   { return __builtin_remquof(__x, __y, __pquo); }
@@ -905,6 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   remquo(long double __x, long double __y, int* __pquo)
   { return __builtin_remquol(__x, __y, __pquo); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -914,6 +961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return remquo(__type(__x), __type(__y), __pquo);
     }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   rint(float __x)
   { return __builtin_rintf(__x); }
@@ -921,15 +969,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   rint(long double __x)
   { return __builtin_rintl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     rint(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return rint(__type(__x));
-    }
+    { return __builtin_rint(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   round(float __x)
   { return __builtin_roundf(__x); }
@@ -937,15 +985,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   round(long double __x)
   { return __builtin_roundl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     round(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return round(__type(__x));
-    }
+    { return __builtin_round(__x); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   scalbln(float __x, long __ex)
   { return __builtin_scalblnf(__x, __ex); }
@@ -953,15 +1001,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   scalbln(long double __x, long __ex)
   { return __builtin_scalblnl(__x, __ex); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     scalbln(_Tp __x, long __ex)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return scalbln(__type(__x), __ex);
-    }
+    { return __builtin_scalbln(__x, __ex); }
  
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   scalbn(float __x, int __ex)
   { return __builtin_scalbnf(__x, __ex); }
@@ -969,21 +1017,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   scalbn(long double __x, int __ex)
   { return __builtin_scalbnl(__x, __ex); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     scalbn(_Tp __x, int __ex)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return scalbn(__type(__x), __ex);
-    }
-
-  using std::sin;
-  using std::sinh;
-  using std::sqrt;
-  using std::tan;
-  using std::tanh;
+    { return __builtin_scalbn(__x, __ex); }
 
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   tgamma(float __x)
   { return __builtin_tgammaf(__x); }
@@ -991,15 +1033,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   tgamma(long double __x)
   { return __builtin_tgammal(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     tgamma(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return tgamma(__type(__x));
-    }
+    { return __builtin_tgamma(__x); }
  
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   trunc(float __x)
   { return __builtin_truncf(__x); }
@@ -1007,32 +1049,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   trunc(long double __x)
   { return __builtin_truncl(__x); }
+#endif
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type 
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
+                                          double>::__type
     trunc(_Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
-      return trunc(__type(__x));
-    }
+    { return __builtin_trunc(__x); }
 
-#endif
-_GLIBCXX_END_NAMESPACE_VERSION
-}
-}
+#endif // __cplusplus < 201103L
 
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-namespace tr1
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  /// @}
 
-  // DR 550. What should the return type of pow(float,int) be?
-  // NB: C++0x and TR1 != C++03.
-  inline double
-  pow(double __x, double __y)
-  { return std::pow(__x, __y); }
+#endif /* _GLIBCXX_USE_C99_MATH_TR1 */
 
+  // DR 550. What should the return type of pow(float,int) be?
+  // NB: C++11 and TR1 != C++03.
+
+  // We cannot do "using std::pow;" because that would bring in unwanted
+  // pow(*, int) overloads in C++03, with the wrong return type. Instead we
+  // define all the necessary overloads, but the std::tr1::pow(double, double)
+  // overload cannot be provided here, because <tr1/math.h> would add it to
+  // the global namespace where it would clash with ::pow(double,double) from
+  // libc (revealed by the fix of PR c++/54537).
+  // The solution is to forward std::tr1::pow(double,double) to
+  // std::pow(double,double) via the function template below. See
+  // the discussion about this issue here:
+  // http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01278.html
+
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
   inline float
   pow(float __x, float __y)
   { return std::pow(__x, __y); }
@@ -1040,6 +1085,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline long double
   pow(long double __x, long double __y)
   { return std::pow(__x, __y); }
+#endif
 
   template<typename _Tp, typename _Up>
     inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
@@ -1049,9 +1095,147 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::pow(__type(__x), __type(__y));
     }
 
+#if __cplusplus >= 201103L
+  // We also deal with fabs in a special way, because "using std::fabs;"
+  // could bring in C++11's std::fabs<T>(const std::complex<T>&) with a
+  // different return type from std::tr1::fabs<T>(const std::complex<T>&).
+  // We define the necessary overloads, except std::tr1::fabs(double) which
+  // could clash with ::fabs(double) from libc.
+  // The function template handles double as well as integers, forwarding
+  // to std::fabs.
+
+#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
+  inline float
+  fabs(float __x)
+  { return __builtin_fabsf(__x); }
+
+  inline long double
+  fabs(long double __x)
+  { return __builtin_fabsl(__x); }
+#endif
+#endif
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__promote<_Tp>::__type
+    fabs(_Tp __x)
+    { return std::fabs(__x); }
+
+#else  // ! C++11
+
+  // For C++03 just use std::fabs as there is no overload for std::complex<>.
+  using std::fabs;
+
+#endif // C++11
+
+} // namespace tr1
 _GLIBCXX_END_NAMESPACE_VERSION
-}
-}
+} // namespace std
+
+/**
+ * @defgroup tr1_math_spec_func TR1 Mathematical Special Functions
+ * @ingroup numerics
+ *
+ * A collection of advanced mathematical special functions.
+ */
+
+#if _GLIBCXX_USE_STD_SPEC_FUNCS
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace tr1
+{
+  using std::assoc_laguerref;
+  using std::assoc_laguerrel;
+  using std::assoc_laguerre;
+
+  using std::assoc_legendref;
+  using std::assoc_legendrel;
+  using std::assoc_legendre;
+
+  using std::betaf;
+  using std::betal;
+  using std::beta;
+
+  using std::comp_ellint_1f;
+  using std::comp_ellint_1l;
+  using std::comp_ellint_1;
+
+  using std::comp_ellint_2f;
+  using std::comp_ellint_2l;
+  using std::comp_ellint_2;
+
+  using std::comp_ellint_3f;
+  using std::comp_ellint_3l;
+  using std::comp_ellint_3;
+
+  using std::cyl_bessel_if;
+  using std::cyl_bessel_il;
+  using std::cyl_bessel_i;
+
+  using std::cyl_bessel_jf;
+  using std::cyl_bessel_jl;
+  using std::cyl_bessel_j;
+
+  using std::cyl_bessel_kf;
+  using std::cyl_bessel_kl;
+  using std::cyl_bessel_k;
+
+  using std::cyl_neumannf;
+  using std::cyl_neumannl;
+  using std::cyl_neumann;
+
+  using std::ellint_1f;
+  using std::ellint_1l;
+  using std::ellint_1;
+
+  using std::ellint_2f;
+  using std::ellint_2l;
+  using std::ellint_2;
+
+  using std::ellint_3f;
+  using std::ellint_3l;
+  using std::ellint_3;
+
+  using std::expintf;
+  using std::expintl;
+  using std::expint;
+
+  using std::hermitef;
+  using std::hermitel;
+  using std::hermite;
+
+  using std::laguerref;
+  using std::laguerrel;
+  using std::laguerre;
+
+  using std::legendref;
+  using std::legendrel;
+  using std::legendre;
+
+  using std::riemann_zetaf;
+  using std::riemann_zetal;
+  using std::riemann_zeta;
+
+  using std::sph_besself;
+  using std::sph_bessell;
+  using std::sph_bessel;
+
+  using std::sph_legendref;
+  using std::sph_legendrel;
+  using std::sph_legendre;
+
+  using std::sph_neumannf;
+  using std::sph_neumannl;
+  using std::sph_neumann;
+
+} // namespace tr1
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#else // ! _GLIBCXX_USE_STD_SPEC_FUNCS
 
 #include <bits/stl_algobase.h>
 #include <limits>
@@ -1062,7 +1246,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
 #include <tr1/beta_function.tcc>
 #include <tr1/ell_integral.tcc>
 #include <tr1/exp_integral.tcc>
-#include <tr1/hypergeometric.tcc>
 #include <tr1/legendre_function.tcc>
 #include <tr1/modified_bessel_func.tcc>
 #include <tr1/poly_hermite.tcc>
@@ -1071,16 +1254,11 @@ _GLIBCXX_END_NAMESPACE_VERSION
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
-namespace tr1
-{
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  /**
-   * @defgroup tr1_math_spec_func Mathematical Special Functions
-   * @ingroup numerics
-   *
-   * A collection of advanced mathematical special functions.
-   * @{
+namespace tr1
+  {
+  /** @addtogroup tr1_math_spec_func
+   *  @{
    */
 
   inline float
@@ -1188,23 +1366,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   inline float
-  conf_hypergf(float __a, float __c, float __x)
-  { return __detail::__conf_hyperg<float>(__a, __c, __x); }
-
-  inline long double
-  conf_hypergl(long double __a, long double __c, long double __x)
-  { return __detail::__conf_hyperg<long double>(__a, __c, __x); }
-
-  ///  5.2.1.7  Confluent hypergeometric functions.
-  template<typename _Tpa, typename _Tpc, typename _Tp>
-    inline typename __gnu_cxx::__promote_3<_Tpa, _Tpc, _Tp>::__type
-    conf_hyperg(_Tpa __a, _Tpc __c, _Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote_3<_Tpa, _Tpc, _Tp>::__type __type;
-      return __detail::__conf_hyperg<__type>(__a, __c, __x);
-    }
-
-  inline float
   cyl_bessel_if(float __nu, float __x)
   { return __detail::__cyl_bessel_i<float>(__nu, __x); }
 
@@ -1358,23 +1519,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   inline float
-  hypergf(float __a, float __b, float __c, float __x)
-  { return __detail::__hyperg<float>(__a, __b, __c, __x); }
-
-  inline long double
-  hypergl(long double __a, long double __b, long double __c, long double __x)
-  { return __detail::__hyperg<long double>(__a, __b, __c, __x); }
-
-  ///  5.2.1.17  Hypergeometric functions.
-  template<typename _Tpa, typename _Tpb, typename _Tpc, typename _Tp>
-    inline typename __gnu_cxx::__promote_4<_Tpa, _Tpb, _Tpc, _Tp>::__type
-    hyperg(_Tpa __a, _Tpb __b, _Tpc __c, _Tp __x)
-    {
-      typedef typename __gnu_cxx::__promote_4<_Tpa, _Tpb, _Tpc, _Tp>::__type __type;
-      return __detail::__hyperg<__type>(__a, __b, __c, __x);
-    }
-
-  inline float
   laguerref(unsigned int __n, float __x)
   { return __detail::__laguerre<float>(__n, __x); }
 
@@ -1476,9 +1620,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __detail::__sph_neumann<__type>(__n, __x);
     }
 
-  /* @} */ // tr1_math_spec_func
+  /// @} tr1_math_spec_func
+
+} // namespace tr1
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // _GLIBCXX_USE_STD_SPEC_FUNCS
+
+#if _GLIBCXX_USE_STD_SPEC_FUNCS && !defined(__STRICT_ANSI__)
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace tr1
+{
+  using __gnu_cxx::conf_hypergf;
+  using __gnu_cxx::conf_hypergl;
+  using __gnu_cxx::conf_hyperg;
+
+  using __gnu_cxx::hypergf;
+  using __gnu_cxx::hypergl;
+  using __gnu_cxx::hyperg;
+} // namespace tr1
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#else // ! (_GLIBCXX_USE_STD_SPEC_FUNCS && !defined(__STRICT_ANSI__))
+
+#include <bits/stl_algobase.h>
+#include <limits>
+#include <tr1/type_traits>
+
+#include <tr1/hypergeometric.tcc>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace tr1
+{
+  /** @addtogroup tr1_math_spec_func
+   *  @{
+   */
+
+  inline float
+  conf_hypergf(float __a, float __c, float __x)
+  { return __detail::__conf_hyperg<float>(__a, __c, __x); }
+
+  inline long double
+  conf_hypergl(long double __a, long double __c, long double __x)
+  { return __detail::__conf_hyperg<long double>(__a, __c, __x); }
+
+  ///  5.2.1.7  Confluent hypergeometric functions.
+  template<typename _Tpa, typename _Tpc, typename _Tp>
+    inline typename __gnu_cxx::__promote_3<_Tpa, _Tpc, _Tp>::__type
+    conf_hyperg(_Tpa __a, _Tpc __c, _Tp __x)
+    {
+      typedef typename __gnu_cxx::__promote_3<_Tpa, _Tpc, _Tp>::__type __type;
+      return __detail::__conf_hyperg<__type>(__a, __c, __x);
+    }
+
+  inline float
+  hypergf(float __a, float __b, float __c, float __x)
+  { return __detail::__hyperg<float>(__a, __b, __c, __x); }
+
+  inline long double
+  hypergl(long double __a, long double __b, long double __c, long double __x)
+  { return __detail::__hyperg<long double>(__a, __b, __c, __x); }
+
+  ///  5.2.1.17  Hypergeometric functions.
+  template<typename _Tpa, typename _Tpb, typename _Tpc, typename _Tp>
+    inline typename __gnu_cxx::__promote_4<_Tpa, _Tpb, _Tpc, _Tp>::__type
+    hyperg(_Tpa __a, _Tpb __b, _Tpc __c, _Tp __x)
+    {
+      typedef typename __gnu_cxx::__promote_4<_Tpa, _Tpb, _Tpc, _Tp>::__type __type;
+      return __detail::__hyperg<__type>(__a, __b, __c, __x);
+    }
+
+  /// @} tr1_math_spec_func
+
+} // namespace tr1
+
 _GLIBCXX_END_NAMESPACE_VERSION
-}
-}
+} // namespace std
+#endif // _GLIBCXX_USE_STD_SPEC_FUNCS && !defined(__STRICT_ANSI__)
 
 #endif // _GLIBCXX_TR1_CMATH