[PATCH] LWG 2733, LWG 2759 reject bool in gcd and lcm

Jonathan Wakely jwakely@redhat.com
Mon Oct 10 12:17:00 GMT 2016


These DRs are only in Tentatively Ready status, but they're not
controversial so implementing them immediately seems sensible.

The deleted function is sufficient, but the static assertions are more
user-friendly (and are only tested once, not in every recursive call
to __gcd or __lcm).

	* include/experimental/numeric (gcd, lcm): Make bool arguments
	ill-formed.
	* include/std/numeric (gcd, lcm): Likewise.
	* testsuite/26_numerics/gcd/gcd_neg.cc: New test.
	* testsuite/26_numerics/lcm/lcm_neg.cc: New test.

Tested x86_64-linux, committed to trunk.

-------------- next part --------------
commit a785026d8d928a1492daf6919a57d6cda714f714
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Oct 10 11:58:27 2016 +0100

    LWG 2733, LWG 2759 reject bool in gcd and lcm
    
    	* include/experimental/numeric (gcd, lcm): Make bool arguments
    	ill-formed.
    	* include/std/numeric (gcd, lcm): Likewise.
    	* testsuite/26_numerics/gcd/gcd_neg.cc: New test.
    	* testsuite/26_numerics/lcm/lcm_neg.cc: New test.

diff --git a/libstdc++-v3/include/experimental/numeric b/libstdc++-v3/include/experimental/numeric
index 6d1dc21..0ce4bda 100644
--- a/libstdc++-v3/include/experimental/numeric
+++ b/libstdc++-v3/include/experimental/numeric
@@ -57,8 +57,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr common_type_t<_Mn, _Nn>
     gcd(_Mn __m, _Nn __n)
     {
-      static_assert(is_integral<_Mn>::value, "arguments to gcd are integers");
-      static_assert(is_integral<_Nn>::value, "arguments to gcd are integers");
+      static_assert(is_integral<_Mn>::value, "gcd arguments are integers");
+      static_assert(is_integral<_Nn>::value, "gcd arguments are integers");
+      static_assert(!is_same<_Mn, bool>::value, "gcd arguments are not bools");
+      static_assert(!is_same<_Nn, bool>::value, "gcd arguments are not bools");
       return std::__detail::__gcd(__m, __n);
     }
 
@@ -67,8 +69,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr common_type_t<_Mn, _Nn>
     lcm(_Mn __m, _Nn __n)
     {
-      static_assert(is_integral<_Mn>::value, "arguments to lcm are integers");
-      static_assert(is_integral<_Nn>::value, "arguments to lcm are integers");
+      static_assert(is_integral<_Mn>::value, "lcm arguments are integers");
+      static_assert(is_integral<_Nn>::value, "lcm arguments are integers");
+      static_assert(!is_same<_Mn, bool>::value, "lcm arguments are not bools");
+      static_assert(!is_same<_Nn, bool>::value, "lcm arguments are not bools");
       return std::__detail::__lcm(__m, __n);
     }
 
diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index 7b1ab98..4414081 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -96,6 +96,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __abs_integral(_Tp __val)
     { return __val; }
 
+  void __abs_integral(bool) = delete;
+
   template<typename _Mn, typename _Nn>
     constexpr common_type_t<_Mn, _Nn>
     __gcd(_Mn __m, _Nn __n)
@@ -129,8 +131,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr common_type_t<_Mn, _Nn>
     gcd(_Mn __m, _Nn __n)
     {
-      static_assert(is_integral<_Mn>::value, "arguments to gcd are integers");
-      static_assert(is_integral<_Nn>::value, "arguments to gcd are integers");
+      static_assert(is_integral<_Mn>::value, "gcd arguments are integers");
+      static_assert(is_integral<_Nn>::value, "gcd arguments are integers");
+      static_assert(!is_same<_Mn, bool>::value, "gcd arguments are not bools");
+      static_assert(!is_same<_Nn, bool>::value, "gcd arguments are not bools");
       return __detail::__gcd(__m, __n);
     }
 
@@ -140,8 +144,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr common_type_t<_Mn, _Nn>
     lcm(_Mn __m, _Nn __n)
     {
-      static_assert(is_integral<_Mn>::value, "arguments to lcm are integers");
-      static_assert(is_integral<_Nn>::value, "arguments to lcm are integers");
+      static_assert(is_integral<_Mn>::value, "lcm arguments are integers");
+      static_assert(is_integral<_Nn>::value, "lcm arguments are integers");
+      static_assert(!is_same<_Mn, bool>::value, "lcm arguments are not bools");
+      static_assert(!is_same<_Nn, bool>::value, "lcm arguments are not bools");
       return __detail::__lcm(__m, __n);
     }
 
diff --git a/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc b/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
new file mode 100644
index 0000000..231ce8d
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/gcd/gcd_neg.cc
@@ -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-options "-std=gnu++1z" }
+// { dg-do compile { target c++1z } }
+
+#include <numeric>
+
+void
+test01()
+{
+  std::gcd(true, 1);    // { dg-error "from here" }
+  std::gcd(1, true);    // { dg-error "from here" }
+  std::gcd(true, true); // { dg-error "from here" }
+  std::gcd(0.1, 1);     // { dg-error "from here" }
+  std::gcd(1, 0.1);     // { dg-error "from here" }
+  std::gcd(0.1, 0.1);   // { dg-error "from here" }
+}
+
+// { dg-error "integers" "" { target *-*-* } 134 }
+// { dg-error "integers" "" { target *-*-* } 135 }
+// { dg-error "not bools" "" { target *-*-* } 136 }
+// { dg-error "not bools" "" { target *-*-* } 137 }
+// { dg-prune-output "deleted function" }
+// { dg-prune-output "invalid operands" }
diff --git a/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc b/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
new file mode 100644
index 0000000..085ad77
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/lcm/lcm_neg.cc
@@ -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-options "-std=gnu++1z" }
+// { dg-do compile { target c++1z } }
+
+#include <numeric>
+
+void
+test01()
+{
+  std::lcm(true, 1);    // { dg-error "from here" }
+  std::lcm(1, true);    // { dg-error "from here" }
+  std::lcm(true, true); // { dg-error "from here" }
+  std::lcm(0.1, 1);     // { dg-error "from here" }
+  std::lcm(1, 0.1);     // { dg-error "from here" }
+  std::lcm(0.1, 0.1);   // { dg-error "from here" }
+}
+
+// { dg-error "integers" "" { target *-*-* } 147 }
+// { dg-error "integers" "" { target *-*-* } 148 }
+// { dg-error "not bools" "" { target *-*-* } 149 }
+// { dg-error "not bools" "" { target *-*-* } 150 }
+// { dg-prune-output "deleted function" }
+// { dg-prune-output "invalid operands" }


More information about the Gcc-patches mailing list