This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch, libstdc++] In debug mode, diagnose empty initializer_list in min/max/minmax


On 2016-02-23 23:39, Jonathan Wakely wrote:
On 23/02/16 22:03 +0100, Eelis wrote:
The std::min, std::max, and std::minmax overloads that take a std::initializer_list all require that the list is not empty. The attached patch adds debug mode checks for this.

Nice, thanks for the patch.

Hi Jonathan,

Thanks for the review! Updated patch attached.

I couldn't find precedent in the libstdc++ testsuite of tests that test __glibcxx_assert assertions, so I put these under {min,max,minmax}/assert/, analogous to {min,max,minmax}/debug/. Is that ok?

Otherwise this looks good, but will have to wait until after the GCC 6 release now.

No hurry at all. :)

Cheers,

Eelis
Index: libstdc++-v3/include/debug/formatter.h
===================================================================
--- libstdc++-v3/include/debug/formatter.h	(revision 233636)
+++ libstdc++-v3/include/debug/formatter.h	(working copy)
@@ -127,7 +127,8 @@
     // others
     __msg_equal_allocs,
     __msg_insert_range_from_self,
-    __msg_irreflexive_ordering
+    __msg_irreflexive_ordering,
+    __msg_empty_init_list
   };
 
   class _Error_formatter
Index: libstdc++-v3/src/c++11/debug.cc
===================================================================
--- libstdc++-v3/src/c++11/debug.cc	(revision 233636)
+++ libstdc++-v3/src/c++11/debug.cc	(working copy)
@@ -188,7 +188,8 @@
     "allocators must be equal",
     "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
     " container",
-    "comparison doesn't meet irreflexive requirements, assert(!(a < a))"
+    "comparison doesn't meet irreflexive requirements, assert(!(a < a))",
+    "%1;(): empty initializer_list"
   };
 
   void
Index: libstdc++-v3/include/debug/macros.h
===================================================================
--- libstdc++-v3/include/debug/macros.h	(revision 233636)
+++ libstdc++-v3/include/debug/macros.h	(working copy)
@@ -69,6 +69,12 @@
 		      ._M_iterator(_First, #_First)			\
 		      ._M_iterator(_Last, #_Last))
 
+// Verify that the initializer_list is non-empty.
+#define __glibcxx_check_non_empty_init_list(_List)			\
+_GLIBCXX_DEBUG_VERIFY(_List.size() != 0,				\
+		      _M_message(__gnu_debug::__msg_empty_init_list)	\
+		      ._M_string(__func__))
+
 /** Verify that we can insert into *this with the iterator _Position.
  *  Insertion into a container at a specific position requires that
  *  the iterator be nonsingular, either dereferenceable or past-the-end,
Index: libstdc++-v3/include/debug/debug.h
===================================================================
--- libstdc++-v3/include/debug/debug.h	(revision 233636)
+++ libstdc++-v3/include/debug/debug.h	(working copy)
@@ -87,9 +87,13 @@
 // Verify that the container is nonempty
 # define __glibcxx_requires_nonempty() \
   __glibcxx_assert(! this->empty())
+// Verify that the initializer_list is non-empty.
+# define __glibcxx_requires_non_empty_init_list(_List) \
+  __glibcxx_assert(_List.size() != 0)
 #else
 # define __glibcxx_requires_non_empty_range(_First,_Last)
 # define __glibcxx_requires_nonempty()
+# define __glibcxx_requires_non_empty_init_list(_List)
 #endif
 
 #else
@@ -99,6 +103,8 @@
 # define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg)
 # define __glibcxx_requires_valid_range(_First,_Last)	\
   __glibcxx_check_valid_range(_First,_Last)
+# define __glibcxx_requires_non_empty_init_list(_List)	\
+  __glibcxx_check_non_empty_init_list(_List)
 # define __glibcxx_requires_non_empty_range(_First,_Last)	\
   __glibcxx_check_non_empty_range(_First,_Last)
 # define __glibcxx_requires_sorted(_First,_Last)	\
Index: libstdc++-v3/include/bits/stl_algo.h
===================================================================
--- libstdc++-v3/include/bits/stl_algo.h	(revision 233636)
+++ libstdc++-v3/include/bits/stl_algo.h	(working copy)
@@ -3452,25 +3452,37 @@
     _GLIBCXX14_CONSTEXPR
     inline _Tp
     min(initializer_list<_Tp> __l)
-    { return *std::min_element(__l.begin(), __l.end()); }
+    {
+      __glibcxx_requires_non_empty_init_list(__l);
+      return *std::min_element(__l.begin(), __l.end());
+    }
 
   template<typename _Tp, typename _Compare>
     _GLIBCXX14_CONSTEXPR
     inline _Tp
     min(initializer_list<_Tp> __l, _Compare __comp)
-    { return *std::min_element(__l.begin(), __l.end(), __comp); }
+    {
+      __glibcxx_requires_non_empty_init_list(__l);
+      return *std::min_element(__l.begin(), __l.end(), __comp);
+    }
 
   template<typename _Tp>
     _GLIBCXX14_CONSTEXPR
     inline _Tp
     max(initializer_list<_Tp> __l)
-    { return *std::max_element(__l.begin(), __l.end()); }
+    {
+      __glibcxx_requires_non_empty_init_list(__l);
+      return *std::max_element(__l.begin(), __l.end());
+    }
 
   template<typename _Tp, typename _Compare>
     _GLIBCXX14_CONSTEXPR
     inline _Tp
     max(initializer_list<_Tp> __l, _Compare __comp)
-    { return *std::max_element(__l.begin(), __l.end(), __comp); }
+    {
+      __glibcxx_requires_non_empty_init_list(__l);
+      return *std::max_element(__l.begin(), __l.end(), __comp);
+    }
 
   template<typename _Tp>
     _GLIBCXX14_CONSTEXPR
@@ -3477,6 +3489,7 @@
     inline pair<_Tp, _Tp>
     minmax(initializer_list<_Tp> __l)
     {
+      __glibcxx_requires_non_empty_init_list(__l);
       pair<const _Tp*, const _Tp*> __p =
 	std::minmax_element(__l.begin(), __l.end());
       return std::make_pair(*__p.first, *__p.second);
@@ -3487,6 +3500,7 @@
     inline pair<_Tp, _Tp>
     minmax(initializer_list<_Tp> __l, _Compare __comp)
     {
+      __glibcxx_requires_non_empty_init_list(__l);
       pair<const _Tp*, const _Tp*> __p =
 	std::minmax_element(__l.begin(), __l.end(), __comp);
       return std::make_pair(*__p.first, *__p.second);
Index: libstdc++-v3/testsuite/25_algorithms/max/assert/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/max/assert/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/max/assert/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_ASSERTIONS
+
+#include <algorithm>
+
+void test01()
+{
+  std::max<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/25_algorithms/max/debug/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/max/debug/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/max/debug/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_DEBUG
+
+#include <algorithm>
+
+void test01()
+{
+  std::max<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/25_algorithms/min/assert/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/min/assert/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/min/assert/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_ASSERTIONS
+
+#include <algorithm>
+
+void test01()
+{
+  std::min<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/25_algorithms/min/debug/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/min/debug/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/min/debug/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_DEBUG
+
+#include <algorithm>
+
+void test01()
+{
+  std::min<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/25_algorithms/minmax/assert/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/minmax/assert/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/minmax/assert/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_ASSERTIONS
+
+#include <algorithm>
+
+void test01()
+{
+  std::minmax<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: libstdc++-v3/testsuite/25_algorithms/minmax/debug/empty_neg.cc
===================================================================
--- libstdc++-v3/testsuite/25_algorithms/minmax/debug/empty_neg.cc	(revision 0)
+++ libstdc++-v3/testsuite/25_algorithms/minmax/debug/empty_neg.cc	(working copy)
@@ -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-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#define _GLIBCXX_DEBUG
+
+#include <algorithm>
+
+void test01()
+{
+  std::minmax<int>({}); // error: empty initializer_list
+}
+
+int main()
+{
+  test01();
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]