This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[patch, libstdc++] In debug mode, diagnose empty initializer_list in min/max/minmax
- From: Eelis <eelis at eelis dot net>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 23 Feb 2016 22:03:20 +0100
- Subject: [patch, libstdc++] In debug mode, diagnose empty initializer_list in min/max/minmax
- Authentication-results: sourceware.org; auth=none
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.
Thanks,
Eelis
Index: libstdc++-v3/include/debug/formatter.h
===================================================================
--- libstdc++-v3/include/debug/formatter.h (revision 233636)
+++ libstdc++-v3/include/debug/formatter.h (working copy)
@@ -87,6 +87,8 @@
__msg_splice_bad,
__msg_splice_other,
__msg_splice_overlap,
+ // std::initializer_list checks
+ __msg_empty_init_list,
// iterator checks
__msg_init_singular,
__msg_init_copy_singular,
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)
@@ -139,6 +139,8 @@
"attempt to splice an iterator from a different container",
"splice destination %1.name;"
" occurs within source range [%2.name;, %3.name;)",
+ // std::initializer_list checks
+ "%1;(): empty initializer_list",
// iterator checks
"attempt to initialize an iterator that will immediately become singular",
"attempt to copy-construct an iterator from a singular iterator",
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)
@@ -62,6 +62,7 @@
# define __glibcxx_requires_cond(_Cond,_Msg)
# define __glibcxx_requires_valid_range(_First,_Last)
+# define __glibcxx_requires_non_empty_init_list(_List)
# define __glibcxx_requires_sorted(_First,_Last)
# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred)
# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2)
@@ -99,6 +100,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/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/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/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;
+}