Implement LWG 2192 and LWG 2294 for std::abs
authorJonathan Wakely <jwakely@redhat.com>
Fri, 30 Sep 2016 16:07:43 +0000 (17:07 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 30 Sep 2016 16:07:43 +0000 (17:07 +0100)
* doc/xml/manual/intro.xml: Document LWG 2192 changes.
* doc/html/*: Regenerate.
* include/Makefile.am: Add bits/std_abs.h.
* include/Makefile.in: Regenerate.
* include/bits/std_abs.h: New header defining all required overloads
of std::abs in one place (LWG 2294).
* include/c_global/cmath (abs(double), abs(float), abs(long double)):
Move to bits/std_abs.h.
(abs<_Tp>(_Tp)): Remove.
* include/c_global/cstdlib (abs(long), abs(long long), abs(__int<N>)):
Move to bits/std_abs.h.
* testsuite/26_numerics/headers/cmath/dr2192.cc: New test.
* testsuite/26_numerics/headers/cmath/dr2192_neg.cc: New test.
* testsuite/26_numerics/headers/cstdlib/dr2192.cc: New test.
* testsuite/26_numerics/headers/cstdlib/dr2192_neg.cc: New test.

From-SVN: r240660

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/bits/std_abs.h [new file with mode: 0644]
libstdc++-v3/include/c_global/cmath
libstdc++-v3/include/c_global/cstdlib
libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192_neg.cc [new file with mode: 0644]

index 0bd62c549b83734dd273b9c00e6a93a98a6b7883..f73e62e4789d5f7bbeeea25bb227aea6b7f60f1b 100644 (file)
@@ -1,5 +1,21 @@
 2016-09-30  Jonathan Wakely  <jwakely@redhat.com>
 
+       * doc/xml/manual/intro.xml: Document LWG 2192 changes.
+       * doc/html/*: Regenerate.
+       * include/Makefile.am: Add bits/std_abs.h.
+       * include/Makefile.in: Regenerate.
+       * include/bits/std_abs.h: New header defining all required overloads
+       of std::abs in one place (LWG 2294).
+       * include/c_global/cmath (abs(double), abs(float), abs(long double)):
+       Move to bits/std_abs.h.
+       (abs<_Tp>(_Tp)): Remove.
+       * include/c_global/cstdlib (abs(long), abs(long long), abs(__int<N>)):
+       Move to bits/std_abs.h.
+       * testsuite/26_numerics/headers/cmath/dr2192.cc: New test.
+       * testsuite/26_numerics/headers/cmath/dr2192_neg.cc: New test.
+       * testsuite/26_numerics/headers/cstdlib/dr2192.cc: New test.
+       * testsuite/26_numerics/headers/cstdlib/dr2192_neg.cc: New test.
+
        PR libstdc++/77801
        * include/experimental/numeric: Include <numeric>.
        (__abs): Define.
index de2ad5f1182b41ef10a1ab756139b62c6c87db9c..8469c6efa4aaa7a759fef163410ecad5de2e3a80 100644 (file)
     </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2187" target="_top">2187</a>:
        <span class="emphasis"><em><code class="code">vector&lt;bool&gt;</code> is missing <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions</em></span>
     </span></dt><dd><p>Add <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions.
+    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2192" target="_top">2192</a>:
+       <span class="emphasis"><em>Validity and return type of <code class="code">std::abs(0u)</code> is unclear</em></span>
+    </span></dt><dd><p>Move all declarations to a common header and remove the
+    generic <code class="code">abs</code> which accepted unsigned arguments.
     </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2196" target="_top">2196</a>:
        <span class="emphasis"><em>Specification of <code class="code">is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</em></span>
     </span></dt><dd><p>Use the referenceable type concept.
index 238ab241080ea756341b884f452d46da02969fef..47478513666c05a9be17635e4e5c97ebf7e499a7 100644 (file)
@@ -940,6 +940,13 @@ requirements of the license of GCC.
     <listitem><para>Add <code>emplace</code> and <code>emplace_back</code> member functions.
     </para></listitem></varlistentry>
 
+    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2192">2192</link>:
+       <emphasis>Validity and return type of <code>std::abs(0u)</code> is unclear</emphasis>
+    </term>
+    <listitem><para>Move all declarations to a common header and remove the
+    generic <code>abs</code> which accepted unsigned arguments.
+    </para></listitem></varlistentry>
+
     <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2196">2196</link>:
        <emphasis>Specification of <code>is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</emphasis>
     </term>
index 778225899c3948cefaf9c75caf842a79c31f9166..4e63fbb438bf0ae333c4d93eb40e55b6798f1cb1 100644 (file)
@@ -159,6 +159,7 @@ bits_headers = \
        ${bits_srcdir}/shared_ptr_base.h \
        ${bits_srcdir}/slice_array.h \
        ${bits_srcdir}/sstream.tcc \
+       ${bits_srcdir}/std_abs.h \
        ${bits_srcdir}/std_mutex.h \
        ${bits_srcdir}/stl_algo.h \
        ${bits_srcdir}/stl_algobase.h \
index 4e2b9e4f6763d4512d67a48ab0b70dd6c7584484..8b788b551c417b5b21aff48ba3827356d8a068cc 100644 (file)
@@ -450,6 +450,7 @@ bits_headers = \
        ${bits_srcdir}/shared_ptr_base.h \
        ${bits_srcdir}/slice_array.h \
        ${bits_srcdir}/sstream.tcc \
+       ${bits_srcdir}/std_abs.h \
        ${bits_srcdir}/std_mutex.h \
        ${bits_srcdir}/stl_algo.h \
        ${bits_srcdir}/stl_algobase.h \
diff --git a/libstdc++-v3/include/bits/std_abs.h b/libstdc++-v3/include/bits/std_abs.h
new file mode 100644 (file)
index 0000000..ab0f980
--- /dev/null
@@ -0,0 +1,107 @@
+// -*- C++ -*- C library enhancements header.
+
+// Copyright (C) 2016 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 3, 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/bits/std_abs.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{cmath, cstdlib}
+ */
+
+#ifndef _GLIBCXX_BITS_STD_ABS_H
+#define _GLIBCXX_BITS_STD_ABS_H
+
+#pragma GCC system_header
+
+#include <bits/c++config.h>
+
+#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+#include_next <stdlib.h>
+#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO
+# include_next <math.h>
+#endif
+#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+
+#undef abs
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  using ::abs;
+
+#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO
+  inline long
+  abs(long __i) { return __builtin_labs(__i); }
+#endif
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+  inline long long
+  abs(long long __x) { return __builtin_llabs (__x); }
+#endif
+
+// _GLIBCXX_RESOLVE_LIB_DEFECTS
+// 2192. Validity and return type of std::abs(0u) is unclear
+// 2294. <cstdlib> should declare abs(double)
+
+#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
+  inline _GLIBCXX_CONSTEXPR double
+  abs(double __x)
+  { return __builtin_fabs(__x); }
+
+  inline _GLIBCXX_CONSTEXPR float
+  abs(float __x)
+  { return __builtin_fabsf(__x); }
+
+  inline _GLIBCXX_CONSTEXPR long double
+  abs(long double __x)
+  { return __builtin_fabsl(__x); }
+#endif
+
+#if defined(__GLIBCXX_TYPE_INT_N_0)
+  inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0
+  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_1)
+  inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1
+  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_2)
+  inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2
+  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+#if defined(__GLIBCXX_TYPE_INT_N_3)
+  inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3
+  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
+#endif
+
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+  inline _GLIBCXX_CONSTEXPR
+  __float128
+  abs(__float128 __x)
+  { return __x < 0 ? -__x : __x; }
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // _GLIBCXX_BITS_STD_ABS_H
index 0e7c4ada6993c4593c368ffd92b6e0031ef8474b..24ce811adf29c8118794e7edee7ec7e627c9d3d3 100644 (file)
 #define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
 #include_next <math.h>
 #undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+#include <bits/std_abs.h>
 
 #ifndef _GLIBCXX_CMATH
 #define _GLIBCXX_CMATH 1
 
 // Get rid of those macros defined in <math.h> in lieu of real functions.
-#undef abs
 #undef div
 #undef acos
 #undef asin
@@ -80,29 +80,6 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
-  inline _GLIBCXX_CONSTEXPR double
-  abs(double __x)
-  { return __builtin_fabs(__x); }
-#endif
-
-#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
-  inline _GLIBCXX_CONSTEXPR float
-  abs(float __x)
-  { return __builtin_fabsf(__x); }
-
-  inline _GLIBCXX_CONSTEXPR long double
-  abs(long double __x)
-  { return __builtin_fabsl(__x); }
-#endif
-
-  template<typename _Tp>
-    inline _GLIBCXX_CONSTEXPR
-    typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
-                                    double>::__type
-    abs(_Tp __x)
-    { return __builtin_fabs(__x); }
-
   using ::acos;
 
 #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
index 1ba5fb7f03ad509d7663ad610c250a72789b02a3..15733dfb75bbfd08b5c9631e7d45ae2ef36166ba 100644 (file)
@@ -74,10 +74,10 @@ namespace std
 #define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
 #include_next <stdlib.h>
 #undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+#include <bits/std_abs.h>
 
 // Get rid of those macros defined in <stdlib.h> in lieu of real functions.
 #undef abort
-#undef abs
 #undef atexit
 #if __cplusplus >= 201103L
 # ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT
@@ -125,7 +125,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   using ::ldiv_t;
 
   using ::abort;
-  using ::abs;
   using ::atexit;
 #if __cplusplus >= 201103L
 # ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT
@@ -168,35 +167,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif // _GLIBCXX_USE_WCHAR_T
 
 #ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO
-  inline long
-  abs(long __i) { return __builtin_labs(__i); }
-
   inline ldiv_t
   div(long __i, long __j) { return ldiv(__i, __j); }
 #endif
 
-#ifdef _GLIBCXX_USE_LONG_LONG
-  inline long long
-  abs(long long __x) { return __builtin_llabs (__x); }
-#endif
-
-#if defined(__GLIBCXX_TYPE_INT_N_0)
-  inline __GLIBCXX_TYPE_INT_N_0
-  abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_1)
-  inline __GLIBCXX_TYPE_INT_N_1
-  abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_2)
-  inline __GLIBCXX_TYPE_INT_N_2
-  abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
-#endif
-#if defined(__GLIBCXX_TYPE_INT_N_3)
-  inline __GLIBCXX_TYPE_INT_N_3
-  abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
-#endif
-
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192.cc
new file mode 100644 (file)
index 0000000..b8d13cd
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 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 3, 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 COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+// NB: Don't include any other headers in this file.
+// LWG 2192 requires <cmath> to declare overloads for integral types.
+#include <cmath>
+
+template<typename, typename> struct is_same { enum { value = 0 }; };
+template<typename T> struct is_same<T, T> { enum { value = 1 }; };
+
+template<typename T, typename U = T>
+  constexpr bool check(T val) {
+    return is_same<decltype(std::abs(val)), U>::value;
+  }
+
+// Unsigned arguments that promote to int are valid:
+static_assert( check<short, int>(1), "abs((short)1) returns int" );
+static_assert( check<unsigned short, int>(1),
+              "abs((unsigned short)1) returns int" );
+
+static_assert( check(1),        "abs(1) returns int" );
+static_assert( check(1l),       "abs(1l) returns long" );
+static_assert( check(1ll),      "abs(1ll) returns long long" );
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/dr2192_neg.cc
new file mode 100644 (file)
index 0000000..bda980a
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 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 3, 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 COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+// NB: Don't include any other headers in this file.
+// LWG 2192 requires abs to be ill-formed for unsigned arguments.
+#include <cmath>
+
+void test()
+{
+  std::abs(0u);                 // { dg-error "ambiguous" }
+  std::abs(0lu);                // { dg-error "ambiguous" }
+  std::abs(0llu);               // { dg-error "ambiguous" }
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192.cc b/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192.cc
new file mode 100644 (file)
index 0000000..312e907
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright (C) 2016 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 3, 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 COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+// NB: Don't include any other headers in this file.
+// LWG 2192 requires <cstdlib> to declare overloads for floating point types.
+#include <cstdlib>
+
+template<typename, typename> struct is_same { enum { value = 0 }; };
+template<typename T> struct is_same<T, T> { enum { value = 1 }; };
+
+template<typename T>
+  constexpr bool check(T val) {
+    return is_same<decltype(std::abs(val)), T>::value;
+  }
+
+static_assert( check(1.f), "abs(1.f) returns float" );
+static_assert( check(1.),  "abs(1.) returns double" );
+static_assert( check(1.l), "abs(1.l) returns long double" );
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/dr2192_neg.cc
new file mode 100644 (file)
index 0000000..9f0046f
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 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 3, 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 COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+// NB: Don't include any other headers in this file.
+// LWG 2192 requires abs to be ill-formed for unsigned arguments.
+#include <cstdlib>
+
+void test()
+{
+  std::abs(0u);                 // { dg-error "ambiguous" }
+  std::abs(0lu);                // { dg-error "ambiguous" }
+  std::abs(0llu);               // { dg-error "ambiguous" }
+}