aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog102
-rwxr-xr-xlibstdc++-v3/configure2
-rw-r--r--libstdc++-v3/doc/Makefile.am2
-rw-r--r--libstdc++-v3/doc/Makefile.in2
-rw-r--r--libstdc++-v3/include/Makefile.am2
-rw-r--r--libstdc++-v3/include/Makefile.in2
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h4
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h2
-rw-r--r--libstdc++-v3/include/bits/stl_pair.h184
-rw-r--r--libstdc++-v3/include/debug/deque38
-rw-r--r--libstdc++-v3/include/debug/forward_list55
-rw-r--r--libstdc++-v3/include/debug/functions.h81
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h210
-rw-r--r--libstdc++-v3/include/debug/list60
-rw-r--r--libstdc++-v3/include/debug/macros.h25
-rw-r--r--libstdc++-v3/include/debug/map.h11
-rw-r--r--libstdc++-v3/include/debug/multimap.h11
-rw-r--r--libstdc++-v3/include/debug/multiset.h11
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h190
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.tcc50
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.h66
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.tcc16
-rw-r--r--libstdc++-v3/include/debug/set.h11
-rw-r--r--libstdc++-v3/include/debug/stl_iterator.h113
-rw-r--r--libstdc++-v3/include/debug/string49
-rw-r--r--libstdc++-v3/include/debug/unordered_map24
-rw-r--r--libstdc++-v3/include/debug/unordered_set24
-rw-r--r--libstdc++-v3/include/debug/vector35
-rw-r--r--libstdc++-v3/include/experimental/functional2
-rw-r--r--libstdc++-v3/include/std/tuple490
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc108
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/piecewise.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc282
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc47
35 files changed, 2024 insertions, 334 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9e76cc4d27e..f159f786b7d 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,105 @@
+2015-06-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/Makefile.am (stamp-pdf-doxygen): Grep for LaTeX errors in log.
+ * doc/Makefile.in: Regenerate.
+
+ * include/bits/stl_pair.h: Replace class keyword with typename.
+
+2015-06-30 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Implement N4387, "Improving pair and tuple", and LWG 2367.
+
+ * include/bits/stl_pair.h (_ConstructiblePair,
+ _ImplicitlyConvertiblePair, _MoveConstructiblePair,
+ _ImplicitlyMoveConvertiblePair): New.
+ (pair()): Constrain it.
+ (pair(const _T1&, const _T2&), pair(const pair<_U1, _U2>&),
+ pair(_U1&&, const _T2&), pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
+ pair(pair<_U1, _U2>&&)): Make conditionally explicit.
+ * include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
+ (tuple()): Constrain it.
+ (tuple(const _UElements&...), tuple(_UElements&&...),
+ tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&),
+ tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
+ tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
+ tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
+ tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
+ tuple(const pair<_U1, _U2>&), tuple(pair<_U1, _U2>&&),
+ tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
+ tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
+ conditionally explicit.
+ * include/experimental/functional (__boyer_moore_array_base): Name
+ array type explicitly instead of using an empty braced-init-list.
+ * testsuite/20_util/pair/cons/explicit_construct.cc: New.
+ * testsuite/20_util/pair/piecewise.cc: Use piecewise_construct.
+ * testsuite/20_util/pair/requirements/dr2367.cc: New.
+ * testsuite/20_util/tuple/cons/explicit_construct.cc: New.
+ * testsuite/20_util/tuple/requirements/dr2367.cc: New.
+
+2015-06-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * configure: Regenerate.
+
+2015-06-29 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_iterator_base_types.h (_Iter_base): Limit definition
+ to pre-C++11 mode.
+ * include/debug/functions.h
+ (__gnu_debug::__valid_range, __gnu_debug::__base): Move...
+ * include/debug/safe_iterator.h
+ (__gnu_debug::_Sequence_traits): New.
+ (__gnu_debug::__get_distance_from_begin): New.
+ (__gnu_debug::__get_distance_to_end): New.
+ (__gnu_debug::_Safe_iterator<>::_M_valid_range): Expose iterator range
+ distance information. Add optional check_dereferenceable parameter,
+ default true.
+ (__gnu_debug::_Distance_precision, __gnu_debug::__get_distance): Move
+ default definition...
+ (__gnu_debug::__get_distance): New overload for _Safe_iterator.
+ (__gnu_debug::__unsafe): Likewise.
+ * include/debug/helper_functions.h: ...here. New.
+ (__gnu_debug::__unsafe): New helper function to remove safe iterator
+ layer.
+ * include/debug/stl_iterator.h: New. Include latter.
+ * include/bits/stl_iterator.h: Include latter in debug mode.
+ * include/debug/stl_iterator.tcc: Adapt.
+ * include/debug/safe_local_iterator.h (__gnu_debug::__get_distance): Add
+ overload for _Safe_local_iterator.
+ (__gnu_debug::__unsafe): Likewise.
+ * include/debug/safe_local_iterator.tcc: Adapt.
+ * include/debug/macros.h (__glibcxx_check_valid_range2): New.
+ (__glibcxx_check_insert_range): Add _Dist parameter.
+ (__glibcxx_check_insert_range_after): Likewise.
+ (__glibcxx_check_string, __glibcxx_check_string_len): Implement using
+ _GLIBCXX_DEBUG_PEDASSERT.
+ * include/debug/deque (deque<>::assign): Remove iterator debug layer
+ when possible.
+ (deque<>::insert): Likewise.
+ * include/debug/forward_list (__glibcxx_check_valid_fl_range): New.
+ (forward_list<>::splice_after): Use latter.
+ (forward_list<>::assign): Remove iterator debug layer when possible.
+ (forward_list<>::insert_after): Likewise.
+ (__gnu_debug::_Sequence_traits<>): Partial specialization.
+ * include/debug/list (list<>::assign): Remove iterator debug layer when
+ possible.
+ (list<>::insert): Likewise.
+ [__gnu_debug::_Sequence_traits<>]: Partial specialization pre C++11 ABI.
+ * include/debug/map.h (map<>::insert): Remove iterator debug layer when
+ possible.
+ * include/debug/multimap.h (multimap<>::insert): Likewise.
+ * include/debug/set.h (set<>::insert): Likewise.
+ * include/debug/multiset.h (multiset<>::insert): Likewise.
+ * include/debug/string (basic_string<>::append, basic_string<>::assign,
+ basic_string<>::insert, basic_string<>::replace): Likewise.
+ * include/debug/unordered_map
+ (unordered_map<>::insert, unordered_multimap<>::insert): Likewise.
+ * include/debug/unordered_set
+ (unordered_set<>::insert, unordered_multiset<>insert): Likewise.
+ * include/debug/vector
+ (vector<>::assign, vector<>::insert): Likewise.
+ * include/Makefile.am: Add new debug headers.
+ * include/Makefile.in: Regenerate.
+
2015-06-26 Jonathan Wakely <jwakely@redhat.com>
* doc/xml/manual/intro.xml: Document LWG 2108 status.
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 3654b68f281..1b99c06c1ce 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -79216,7 +79216,7 @@ $as_echo_n "checking for sendfile that can copy files... " >&6; }
$as_echo_n "(cached) " >&6
else
case "${target_os}" in
- gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu | solaris*)
+ gnu* | linux* | solaris*)
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
diff --git a/libstdc++-v3/doc/Makefile.am b/libstdc++-v3/doc/Makefile.am
index d6ea2d1648d..d63cf17db8e 100644
--- a/libstdc++-v3/doc/Makefile.am
+++ b/libstdc++-v3/doc/Makefile.am
@@ -257,6 +257,7 @@ stamp-latex-doxygen: ${doxygen_outdir}/latex
# include asking a wizard to enlarge capacity. If this is the case,
# find texmf.cnf and add a zero for pool_size, string_vacancies,
# max_strings, and pool_free values.
+# Errors like "File `foo.sty' not found" mean a TeX package is missing.
stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
-(cd ${doxygen_outdir}/latex && $(MAKE) -i pdf;)
echo "Generating doxygen pdf file...";
@@ -265,6 +266,7 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
echo ":: PDF file is ${api_pdf}"; \
else \
echo "... error"; \
+ grep -F 'LaTeX Error' ${doxygen_outdir}/latex/refman.log; \
exit 12; \
fi
$(STAMP) stamp-pdf-doxygen
diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in
index 4690fad8ac6..798a9a3ae37 100644
--- a/libstdc++-v3/doc/Makefile.in
+++ b/libstdc++-v3/doc/Makefile.in
@@ -891,6 +891,7 @@ stamp-latex-doxygen: ${doxygen_outdir}/latex
# include asking a wizard to enlarge capacity. If this is the case,
# find texmf.cnf and add a zero for pool_size, string_vacancies,
# max_strings, and pool_free values.
+# Errors like "File `foo.sty' not found" mean a TeX package is missing.
stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
-(cd ${doxygen_outdir}/latex && $(MAKE) -i pdf;)
echo "Generating doxygen pdf file...";
@@ -899,6 +900,7 @@ stamp-pdf-doxygen: stamp-latex-doxygen ${doxygen_outdir}/pdf
echo ":: PDF file is ${api_pdf}"; \
else \
echo "... error"; \
+ grep -F 'LaTeX Error' ${doxygen_outdir}/latex/refman.log; \
exit 12; \
fi
$(STAMP) stamp-pdf-doxygen
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 927418ed8b0..05be8ad1b84 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -766,6 +766,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
+ ${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@@ -785,6 +786,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
+ ${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 0674d8ca976..bab83b40018 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1047,6 +1047,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
+ ${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@@ -1066,6 +1067,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
+ ${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 58b9aabf2e6..1060433d0bd 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1246,4 +1246,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
#endif // C++11
+#ifdef _GLIBCXX_DEBUG
+# include <debug/stl_iterator.h>
+#endif
+
#endif
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index 83e6444ab1c..eba9e398be7 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -206,6 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//@}
+#if __cplusplus < 201103L
// If _Iterator has a base returns it otherwise _Iterator is returned
// untouched
template<typename _Iterator, bool _HasBase>
@@ -223,6 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static iterator_type _S_base(_Iterator __it)
{ return __it.base(); }
};
+#endif
#if __cplusplus >= 201103L
template<typename _InIter>
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 490b00565a0..a5a7898f2b7 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -84,6 +84,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<std::size_t...>
struct _Index_tuple;
+
+ // Concept utility functions, reused in conditionally-explicit
+ // constructors.
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ConstructiblePair()
+ {
+ return __and_<is_constructible<_T1, const _U1&>,
+ is_constructible<_T2, const _U2&>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ImplicitlyConvertiblePair()
+ {
+ return __and_<is_convertible<const _U1&, _T1>,
+ is_convertible<const _U2&, _T2>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _MoveConstructiblePair()
+ {
+ return __and_<is_constructible<_T1, _U1&&>,
+ is_constructible<_T2, _U2&&>>::value;
+ }
+
+ template <typename _T1, typename _T2, typename _U1, typename _U2>
+ constexpr bool _ImplicitlyMoveConvertiblePair()
+ {
+ return __and_<is_convertible<_U1&&, _T1>,
+ is_convertible<_U2&&, _T2>>::value;
+ }
+
+
#endif
/**
@@ -92,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @tparam _T1 Type of first object.
* @tparam _T2 Type of second object.
*/
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
struct pair
{
typedef _T1 first_type; /// @c first_type is the first bound type
@@ -105,52 +137,136 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 265. std::pair::pair() effects overly restrictive
/** The default constructor creates @c first and @c second using their
* respective default constructors. */
+#if __cplusplus >= 201103L
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<__and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>>
+ ::value, bool>::type = true>
+#endif
_GLIBCXX_CONSTEXPR pair()
: first(), second() { }
/** Two objects may be passed to a @c pair constructor to be copied. */
- _GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
+#if __cplusplus < 201103L
+ pair(const _T1& __a, const _T2& __b)
+ : first(__a), second(__b) { }
+#else
+ template<typename _U1 = _T1, typename _U2=_T2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
+ template<typename _U1 = _T1, typename _U2=_T2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(const _T1& __a, const _T2& __b)
+ : first(__a), second(__b) { }
+#endif
+
/** There is also a templated copy ctor for the @c pair class itself. */
#if __cplusplus < 201103L
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
#else
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
- constexpr pair(const pair<_U1, _U2>& __p)
+ template<typename _U1, typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const pair<_U1, _U2>& __p)
+ : first(__p.first), second(__p.second) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
constexpr pair(const pair&) = default;
constexpr pair(pair&&) = default;
// DR 811.
- template<class _U1, class = typename
- enable_if<is_convertible<_U1, _T1>::value>::type>
- constexpr pair(_U1&& __x, const _T2& __y)
- : first(std::forward<_U1>(__x)), second(__y) { }
-
- template<class _U2, class = typename
- enable_if<is_convertible<_U2, _T2>::value>::type>
- constexpr pair(const _T1& __x, _U2&& __y)
- : first(__x), second(std::forward<_U2>(__y)) { }
-
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename
+ enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+ && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+ && _ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _T2>(),
+ bool>::type=true>
+ constexpr pair(_U1&& __x, const _T2& __y)
+ : first(std::forward<_U1>(__x)), second(__y) { }
+
+ template<typename _U1, typename
+ enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+ && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+ && (!_ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+ || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _T2>()),
+ bool>::type=false>
+ explicit constexpr pair(_U1&& __x, const _T2& __y)
+ : first(std::forward<_U1>(__x)), second(__y) { }
+
+ template<typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+ && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+ && _ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _T1, _U2>(),
+ bool>::type=true>
+ constexpr pair(const _T1& __x, _U2&& __y)
+ : first(__x), second(std::forward<_U2>(__y)) { }
+
+ template<typename _U2, typename
+ enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+ && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+ && (!_ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+ || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _T1, _U2>()),
+ bool>::type=false>
+ explicit pair(const _T1& __x, _U2&& __y)
+ : first(__x), second(std::forward<_U2>(__y)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=true>
constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
- template<class _U1, class _U2, class = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(_U1&& __x, _U2&& __y)
+ : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
+
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=true>
constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+ && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+ _U1, _U2>(),
+ bool>::type=false>
+ explicit constexpr pair(pair<_U1, _U2>&& __p)
+ : first(std::forward<_U1>(__p.first)),
+ second(std::forward<_U2>(__p.second)) { }
+
template<typename... _Args1, typename... _Args2>
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
@@ -172,7 +288,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair&
operator=(const pair<_U1, _U2>& __p)
{
@@ -181,7 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
- template<class _U1, class _U2>
+ template<typename _U1, typename _U2>
pair&
operator=(pair<_U1, _U2>&& __p)
{
@@ -209,38 +325,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/// Two pairs of the same type are equal iff their members are equal.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first == __y.first && __x.second == __y.second; }
/// <http://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html>
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first < __y.first
|| (!(__y.first < __x.first) && __x.second < __y.second); }
/// Uses @c operator== to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x == __y); }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __y < __x; }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__y < __x); }
/// Uses @c operator< to find the result.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x < __y); }
@@ -249,7 +365,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// See std::pair::swap().
// Note: no std::swap overloads in C++03 mode, this has performance
// implications, see, eg, libstdc++/38466.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline void
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
noexcept(noexcept(__x.swap(__y)))
@@ -270,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 181. make_pair() unintended behavior
#if __cplusplus >= 201103L
// NB: DR 706.
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
constexpr pair<typename __decay_and_strip<_T1>::__type,
typename __decay_and_strip<_T2>::__type>
make_pair(_T1&& __x, _T2&& __y)
@@ -281,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
}
#else
- template<class _T1, class _T2>
+ template<typename _T1, typename _T2>
inline pair<_T1, _T2>
make_pair(_T1 __x, _T2 __y)
{ return pair<_T1, _T2>(__x, __y); }
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index fffc5e4ab63..7d15e33606b 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -169,9 +169,14 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -460,10 +465,16 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base_iterator __res = _Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+ _Base_iterator __res;
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ __res = _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ __res = _Base::insert(__position.base(), __first, __last);
+
this->_M_invalidate_all();
return iterator(__res, this);
}
@@ -473,9 +484,16 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
+
this->_M_invalidate_all();
}
#endif
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 2b42a3f8d29..df35bc29cf5 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -36,6 +36,13 @@
#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+// Special validity check for forward_list ranges.
+#define __glibcxx_check_valid_fl_range(_First,_Last,_Dist) \
+_GLIBCXX_DEBUG_VERIFY(_First._M_valid_range(_Last, _Dist, false), \
+ _M_message(__gnu_debug::__msg_valid_range) \
+ ._M_iterator(_First, #_First) \
+ ._M_iterator(_Last, #_Last))
+
namespace __gnu_debug
{
/// Special iterators swap and invalidation for forward_list because of the
@@ -269,9 +276,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -401,11 +414,19 @@ namespace __debug
insert_after(const_iterator __pos,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range_after(__pos, __first, __last);
- return iterator(_Base::insert_after(__pos.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last)),
- this);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range_after(__pos, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ return
+ {
+ _Base::insert_after(__pos.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last)),
+ this
+ };
+ else
+ return { _Base::insert_after(__pos.base(), __first, __last), this };
}
iterator
@@ -580,9 +601,10 @@ namespace __debug
splice_after(const_iterator __pos, forward_list&& __list,
const_iterator __before, const_iterator __last)
{
+ typename __gnu_debug::_Distance_traits<const_iterator>::__type __dist;
auto __listptr = std::__addressof(__list);
__glibcxx_check_insert_after(__pos);
- __glibcxx_check_valid_range(__before, __last);
+ __glibcxx_check_valid_fl_range(__before, __last, __dist);
_GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(__listptr),
_M_message(__gnu_debug::__msg_splice_other)
._M_sequence(__list, "list")
@@ -801,7 +823,7 @@ namespace __debug
namespace __gnu_debug
{
- template<class _Tp, class _Alloc>
+ template<typename _Tp, typename _Alloc>
struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
{
typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
@@ -820,6 +842,19 @@ namespace __gnu_debug
{ return _S_Is(__it); }
};
+ template<typename _Tp, typename _Alloc>
+ struct _Sequence_traits<std::__debug::forward_list<_Tp, _Alloc> >
+ {
+ typedef typename std::__debug::forward_list<_Tp, _Alloc>::iterator _It;
+
+ static typename _Distance_traits<_It>::__type
+ _S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
+ {
+ return __seq.empty()
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ }
+ };
+
#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index bf60ccc23c6..7f0659f5b25 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -29,11 +29,6 @@
#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
#define _GLIBCXX_DEBUG_FUNCTIONS_H 1
-#include <bits/c++config.h>
-#include <bits/stl_iterator_base_types.h> // for iterator_traits,
- // categories and _Iter_base
-#include <bits/cpp_type_traits.h> // for __is_integer
-
#include <bits/move.h> // for __addressof
#include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L
@@ -41,6 +36,7 @@
// conditional.
#endif
+#include <debug/helper_functions.h>
#include <debug/formatter.h>
namespace __gnu_debug
@@ -85,58 +81,6 @@ namespace __gnu_debug
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
- /** If the distance between two random access iterators is
- * nonnegative, assume the range is valid.
- */
- template<typename _RandomAccessIterator>
- inline bool
- __valid_range_aux2(const _RandomAccessIterator& __first,
- const _RandomAccessIterator& __last,
- std::random_access_iterator_tag)
- { return __last - __first >= 0; }
-
- /** Can't test for a valid range with input iterators, because
- * iteration may be destructive. So we just assume that the range
- * is valid.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range_aux2(const _InputIterator&, const _InputIterator&,
- std::input_iterator_tag)
- { return true; }
-
- /** We say that integral types for a valid range, and defer to other
- * routines to realize what to do with integral types instead of
- * iterators.
- */
- template<typename _Integral>
- inline bool
- __valid_range_aux(const _Integral&, const _Integral&, std::__true_type)
- { return true; }
-
- /** We have iterators, so figure out what kind of iterators that are
- * to see if we can check the range ahead of time.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range_aux(const _InputIterator& __first,
- const _InputIterator& __last, std::__false_type)
- { return __valid_range_aux2(__first, __last,
- std::__iterator_category(__first)); }
-
- /** Don't know what these iterators are, or if they are even
- * iterators (we may get an integral type for InputIterator), so
- * see if they are integral and pass them on to the next phase
- * otherwise.
- */
- template<typename _InputIterator>
- inline bool
- __valid_range(const _InputIterator& __first, const _InputIterator& __last)
- {
- typedef typename std::__is_integer<_InputIterator>::__type _Integral;
- return __valid_range_aux(__first, __last, _Integral());
- }
-
/* Checks that [first, last) is a valid range, and then returns
* __first. This routine is useful when we can't use a separate
* assertion statement because, e.g., we are in a constructor.
@@ -500,29 +444,6 @@ namespace __gnu_debug
return __first == __last;
}
- // Helper struct to detect random access safe iterators.
- template<typename _Iterator>
- struct __is_safe_random_iterator
- {
- enum { __value = 0 };
- typedef std::__false_type __type;
- };
-
- template<typename _Iterator>
- struct _Siter_base
- : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
- { };
-
- /** Helper function to extract base iterator of random access safe iterator
- in order to reduce performance impact of debug mode. Limited to random
- access iterator because it is the only category for which it is possible
- to check for correct iterators order in the __valid_range function
- thanks to the < operator.
- */
- template<typename _Iterator>
- inline typename _Siter_base<_Iterator>::iterator_type
- __base(_Iterator __it)
- { return _Siter_base<_Iterator>::_S_base(__it); }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
new file mode 100644
index 00000000000..a2db00d29cc
--- /dev/null
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -0,0 +1,210 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2003-2015 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 debug/helper_functions.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
+#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
+
+#include <bits/stl_iterator_base_types.h> // for iterator_traits,
+ // categories and _Iter_base
+#include <bits/cpp_type_traits.h> // for __is_integer
+
+#include <bits/stl_pair.h> // for pair
+
+namespace __gnu_debug
+{
+ /** The precision to which we can calculate the distance between
+ * two iterators.
+ */
+ enum _Distance_precision
+ {
+ __dp_none, // Not even an iterator type
+ __dp_equality, //< Can compare iterator equality, only
+ __dp_sign, //< Can determine equality and ordering
+ __dp_exact //< Can determine distance precisely
+ };
+
+ template<typename _Iterator,
+ typename = typename std::__is_integer<_Iterator>::__type>
+ struct _Distance_traits
+ {
+ private:
+ typedef
+ typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
+
+ template<typename _DiffType,
+ typename = typename std::__is_void<_DiffType>::__type>
+ struct _DiffTraits
+ { typedef _DiffType __type; };
+
+ template<typename _DiffType>
+ struct _DiffTraits<_DiffType, std::__true_type>
+ { typedef std::ptrdiff_t __type; };
+
+ typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
+
+ public:
+ typedef std::pair<_DiffType, _Distance_precision> __type;
+ };
+
+ template<typename _Integral>
+ struct _Distance_traits<_Integral, std::__true_type>
+ { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
+
+ /** Determine the distance between two iterators with some known
+ * precision.
+ */
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+ std::random_access_iterator_tag)
+ { return std::make_pair(__rhs - __lhs, __dp_exact); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+ std::input_iterator_tag)
+ {
+ if (__lhs == __rhs)
+ return std::make_pair(0, __dp_exact);
+
+ return std::make_pair(1, __dp_equality);
+ }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
+ { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
+
+ /** We say that integral types for a valid range, and defer to other
+ * routines to realize what to do with integral types instead of
+ * iterators.
+ */
+ template<typename _Integral>
+ inline bool
+ __valid_range_aux(const _Integral&, const _Integral&,
+ typename _Distance_traits<_Integral>::__type& __dist,
+ std::__true_type)
+ {
+ __dist = std::make_pair(0, __dp_none);
+ return true;
+ }
+
+ /** We have iterators, so figure out what kind of iterators that are
+ * to see if we can check the range ahead of time.
+ */
+ template<typename _InputIterator>
+ inline bool
+ __valid_range_aux(const _InputIterator& __first,
+ const _InputIterator& __last,
+ typename _Distance_traits<_InputIterator>::__type& __dist,
+ std::__false_type)
+ {
+ __dist = __get_distance(__first, __last);
+ switch (__dist.second)
+ {
+ case __dp_none:
+ break;
+ case __dp_equality:
+ if (__dist.first == 0)
+ return true;
+ break;
+ case __dp_sign:
+ case __dp_exact:
+ return __dist.first >= 0;
+ }
+
+ return true;
+ }
+
+ /** Don't know what these iterators are, or if they are even
+ * iterators (we may get an integral type for InputIterator), so
+ * see if they are integral and pass them on to the next phase
+ * otherwise.
+ */
+ template<typename _InputIterator>
+ inline bool
+ __valid_range(const _InputIterator& __first, const _InputIterator& __last,
+ typename _Distance_traits<_InputIterator>::__type& __dist)
+ {
+ typedef typename std::__is_integer<_InputIterator>::__type _Integral;
+ return __valid_range_aux(__first, __last, __dist, _Integral());
+ }
+
+ template<typename _InputIterator>
+ inline bool
+ __valid_range(const _InputIterator& __first, const _InputIterator& __last)
+ {
+ typename _Distance_traits<_InputIterator>::__type __dist;
+ return __valid_range(__first, __last, __dist);
+ }
+
+#if __cplusplus < 201103L
+ // Helper struct to detect random access safe iterators.
+ template<typename _Iterator>
+ struct __is_safe_random_iterator
+ {
+ enum { __value = 0 };
+ typedef std::__false_type __type;
+ };
+
+ template<typename _Iterator>
+ struct _Siter_base
+ : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
+ { };
+
+ /** Helper function to extract base iterator of random access safe iterator
+ in order to reduce performance impact of debug mode. Limited to random
+ access iterator because it is the only category for which it is possible
+ to check for correct iterators order in the __valid_range function
+ thanks to the < operator.
+ */
+ template<typename _Iterator>
+ inline typename _Siter_base<_Iterator>::iterator_type
+ __base(_Iterator __it)
+ { return _Siter_base<_Iterator>::_S_base(__it); }
+#else
+ template<typename _Iterator>
+ inline _Iterator
+ __base(_Iterator __it)
+ { return __it; }
+#endif
+
+#if __cplusplus < 201103L
+ template<typename _Iterator>
+ struct _Unsafe_type
+ { typedef _Iterator _Type; };
+#endif
+
+ /* Remove debug mode safe iterator layer, if any. */
+ template<typename _Iterator>
+ inline _Iterator
+ __unsafe(_Iterator __it)
+ { return __it; }
+}
+
+#endif
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index 12ac53c4675..0f3f1a0e241 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -177,9 +177,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
}
@@ -441,11 +447,18 @@ namespace __debug
insert(const_iterator __position, _InputIterator __first,
_InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- return iterator(_Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last)),
- this);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ return
+ {
+ _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last)),
+ this
+ };
+ else
+ return { _Base::insert(__position.base(), __first, __last), this };
}
#else
template<class _InputIterator>
@@ -453,9 +466,14 @@ namespace __debug
insert(iterator __position, _InputIterator __first,
_InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
}
#endif
@@ -795,13 +813,29 @@ namespace __debug
} // namespace __debug
} // namespace std
-#ifndef _GLIBCXX_DEBUG_PEDANTIC
namespace __gnu_debug
{
+#ifndef _GLIBCXX_USE_CXX11_ABI
+ // If not using C++11 list::size() is not in O(1) so we do not use it.
+ template<typename _Tp, typename _Alloc>
+ struct _Sequence_traits<std::__debug::list<_Tp, _Alloc> >
+ {
+ typedef typename std::__debug::list<_Tp, _Alloc>::iterator _It;
+
+ static typename _Distance_traits<_It>::__type
+ _S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
+ {
+ return __seq.empty()
+ ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+ }
+ };
+#endif
+
+#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<std::__debug::list<_Tp, _Alloc> >
{ enum { __value = 1 }; };
-}
#endif
+}
#endif
diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h
index f796e718770..a4c2649c843 100644
--- a/libstdc++-v3/include/debug/macros.h
+++ b/libstdc++-v3/include/debug/macros.h
@@ -56,6 +56,12 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
+#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \
+ _M_message(__gnu_debug::__msg_valid_range) \
+ ._M_iterator(_First, #_First) \
+ ._M_iterator(_Last, #_Last))
+
// Verify that [_First, _Last) forms a non-empty iterator range.
#define __glibcxx_check_non_empty_range(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(_First != _Last, \
@@ -104,8 +110,8 @@ _GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
-#define __glibcxx_check_insert_range(_Position,_First,_Last) \
-__glibcxx_check_valid_range(_First,_Last); \
+#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \
+__glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@@ -123,8 +129,8 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
-#define __glibcxx_check_insert_range_after(_Position,_First,_Last) \
-__glibcxx_check_valid_range(_First,_Last); \
+#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\
+ __glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert_after(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@@ -352,13 +358,8 @@ _GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
._M_sequence(_This, "this"))
-#ifdef _GLIBCXX_DEBUG_PEDANTIC
-# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
-# define __glibcxx_check_string_len(_String,_Len) \
- _GLIBCXX_DEBUG_ASSERT(_String != 0 || _Len == 0)
-#else
-# define __glibcxx_check_string(_String)
-# define __glibcxx_check_string_len(_String,_Len)
-#endif
+#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0)
+#define __glibcxx_check_string_len(_String,_Len) \
+ _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0)
#endif
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index 688fb99d499..9bda8eba1da 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -307,9 +307,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index e2c806131f0..b9b0a74c94e 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -286,9 +286,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h
index b4d738f4bec..f1f6e2c576a 100644
--- a/libstdc++-v3/include/debug/multiset.h
+++ b/libstdc++-v3/include/debug/multiset.h
@@ -271,9 +271,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 9f2dcd1e238..a8bee214e36 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -41,7 +41,7 @@ namespace __gnu_debug
/** Helper struct to deal with sequence offering a before_begin
* iterator.
**/
- template <typename _Sequence>
+ template<typename _Sequence>
struct _BeforeBeginHelper
{
template<typename _Iterator>
@@ -55,38 +55,16 @@ namespace __gnu_debug
{ return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
};
- /** The precision to which we can calculate the distance between
- * two iterators.
- */
- enum _Distance_precision
+ /** Sequence traits giving the size of a container if possible. */
+ template<typename _Sequence>
+ struct _Sequence_traits
{
- __dp_equality, //< Can compare iterator equality, only
- __dp_sign, //< Can determine equality and ordering
- __dp_exact //< Can determine distance precisely
- };
-
- /** Determine the distance between two iterators with some known
- * precision.
- */
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
- std::random_access_iterator_tag)
- { return std::make_pair(__rhs - __lhs, __dp_exact); }
+ typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
- std::forward_iterator_tag)
- { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
-
- template<typename _Iterator>
- inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
- _Distance_precision>
- __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
- { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
+ static typename _DistTraits::__type
+ _S_size(const _Sequence& __seq)
+ { return std::make_pair(__seq.size(), __dp_exact); }
+ };
/** \brief Safe iterator wrapper.
*
@@ -476,7 +454,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
- _M_valid_range(const _Safe_iterator& __rhs) const;
+ _M_valid_range(const _Safe_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist,
+ bool __check_dereferenceable = true) const;
// The sequence this iterator references.
typename
@@ -768,15 +748,157 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
- const _Safe_iterator<_Iterator, _Sequence>& __last)
- { return __first._M_valid_range(__last); }
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __first._M_valid_range(__last, __dist); }
+
+ /** Safe iterators can help to get better distance knowledge. */
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ std::random_access_iterator_tag)
+ { return std::make_pair(__last.base() - __first.base(), __dp_exact); }
+
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_iterator<_Iterator, _Sequence>& __last,
+ std::input_iterator_tag)
+ {
+ typedef typename _Distance_traits<_Iterator>::__type _Diff;
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ if (__first.base() == __last.base())
+ return std::make_pair(0, __dp_exact);
+
+ if (__first._M_is_before_begin())
+ {
+ if (__last._M_is_begin())
+ return std::make_pair(1, __dp_exact);
+
+ return std::make_pair(1, __dp_sign);
+ }
+
+ if (__first._M_is_begin())
+ {
+ if (__last._M_is_before_begin())
+ return std::make_pair(-1, __dp_exact);
+
+ if (__last._M_is_end())
+ return _SeqTraits::_S_size(*__first._M_get_sequence());
+
+ return std::make_pair(1, __dp_sign);
+ }
+
+ if (__first._M_is_end())
+ {
+ if (__last._M_is_before_begin())
+ return std::make_pair(-1, __dp_exact);
+
+ if (__last._M_is_begin())
+ {
+ _Diff __diff = _SeqTraits::_S_size(*__first._M_get_sequence());
+ return std::make_pair(-__diff.first, __diff.second);
+ }
+
+ return std::make_pair(-1, __dp_sign);
+ }
+
+ if (__last._M_is_before_begin() || __last._M_is_begin())
+ return std::make_pair(-1, __dp_sign);
+
+ if (__last._M_is_end())
+ return std::make_pair(1, __dp_sign);
+
+ return std::make_pair(1, __dp_equality);
+ }
+
+ // Get distance from sequence begin to specified iterator.
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance_from_begin(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ {
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ // No need to consider before_begin as this function is only used in
+ // _M_can_advance which won't be used for forward_list iterators.
+ if (__it._M_is_begin())
+ return std::make_pair(0, __dp_exact);
+
+ if (__it._M_is_end())
+ return _SeqTraits::_S_size(*__it._M_get_sequence());
+
+ typename _Distance_traits<_Iterator>::__type __res
+ = __get_distance(__it._M_get_sequence()->_M_base().begin(), __it.base());
+
+ if (__res.second == __dp_equality)
+ return std::make_pair(1, __dp_sign);
+
+ return __res;
+ }
+
+ // Get distance from specified iterator to sequence end.
+ template<typename _Iterator, typename _Sequence>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance_to_end(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ {
+ typedef _Sequence_traits<_Sequence> _SeqTraits;
+
+ // No need to consider before_begin as this function is only used in
+ // _M_can_advance which won't be used for forward_list iterators.
+ if (__it._M_is_begin())
+ return _SeqTraits::_S_size(*__it._M_get_sequence());
+
+ if (__it._M_is_end())
+ return std::make_pair(0, __dp_exact);
+ typename _Distance_traits<_Iterator>::__type __res
+ = __get_distance(__it.base(), __it._M_get_sequence()->_M_base().end());
+
+ if (__res.second == __dp_equality)
+ return std::make_pair(1, __dp_sign);
+
+ return __res;
+ }
+
+#if __cplusplus < 201103L
template<typename _Iterator, typename _Sequence>
struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
: std::__are_same<std::random_access_iterator_tag,
typename std::iterator_traits<_Iterator>::
iterator_category>
{ };
+#else
+ template<typename _Iterator, typename _Sequence>
+ _Iterator
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
+ std::random_access_iterator_tag)
+ { return __it.base(); }
+
+ template<typename _Iterator, typename _Sequence>
+ const _Safe_iterator<_Iterator, _Sequence>&
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
+ std::input_iterator_tag)
+ { return __it; }
+
+ template<typename _Iterator, typename _Sequence>
+ auto
+ __base(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ -> decltype(__base(__it, std::__iterator_category(__it)))
+ { return __base(__it, std::__iterator_category(__it)); }
+#endif
+
+#if __cplusplus < 201103L
+ template<typename _Iterator, typename _Sequence>
+ struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
+ { typedef _Iterator _Type; };
+#endif
+
+ template<typename _Iterator, typename _Sequence>
+ inline _Iterator
+ __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ { return __it.base(); }
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index 47b6f2f1dd3..1ad26e3e07b 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -38,12 +38,14 @@ namespace __gnu_debug
{
if (this->_M_singular())
return false;
+
if (__n == 0)
return true;
+
if (__n < 0)
{
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(_M_get_sequence()->_M_base().begin(), base());
+ __get_distance_from_begin(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@@ -51,7 +53,7 @@ namespace __gnu_debug
else
{
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), _M_get_sequence()->_M_base().end());
+ __get_distance_to_end(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@@ -61,37 +63,31 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_iterator& __rhs) const
+ _M_valid_range(const _Safe_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist,
+ bool __check_dereferenceable) const
{
if (!_M_can_compare(__rhs))
return false;
- /* Determine if we can order the iterators without the help of
- the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
- switch (__dist.second) {
- case __dp_equality:
- if (__dist.first == 0)
- return true;
- break;
-
- case __dp_sign:
- case __dp_exact:
- return __dist.first >= 0;
- }
+ /* Determine iterators order */
+ __dist = __get_distance(*this, __rhs);
+ switch (__dist.second)
+ {
+ case __dp_equality:
+ if (__dist.first == 0)
+ return true;
+ break;
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. Note, for the special case of forward_list,
- * before_begin replaces the role of begin. */
- if (_M_is_beginnest() || __rhs._M_is_end())
- return true;
- if (_M_is_end() || __rhs._M_is_beginnest())
- return false;
+ case __dp_sign:
+ case __dp_exact:
+ // If range is not empty first iterator must be dereferenceable.
+ if (__dist.first > 0)
+ return !__check_dereferenceable || _M_dereferenceable();
+ return __dist.first == 0;
+ }
- // Assume that this is a valid range; we can't check anything else
+ // Assume that this is a valid range; we can't check anything else.
return true;
}
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index dcbe4400cac..350a1d249ed 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -322,7 +322,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
- _M_valid_range(const _Safe_local_iterator& __rhs) const;
+ _M_valid_range(const _Safe_local_iterator& __rhs,
+ std::pair<difference_type,
+ _Distance_precision>& __dist_info) const;
// The sequence this iterator references.
typename
@@ -440,8 +442,66 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
- const _Safe_local_iterator<_Iterator, _Sequence>& __last)
- { return __first._M_valid_range(__last); }
+ const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist_info)
+ { return __first._M_valid_range(__last, __dist_info); }
+
+ /** Safe local iterators need a special method to get distance between each
+ other. */
+ template<typename _Iterator, typename _Sequence>
+ inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
+ _Distance_precision>
+ __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
+ const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+ std::input_iterator_tag)
+ {
+ if (__first.base() == __last.base())
+ return { 0, __dp_exact };
+
+ if (__first._M_is_begin())
+ {
+ if (__last._M_is_end())
+ return
+ {
+ __first._M_get_sequence()->bucket_size(__first.bucket()),
+ __dp_exact
+ };
+
+ return { 1, __dp_sign };
+ }
+
+ if (__first._M_is_end())
+ {
+ if (__last._M_is_begin())
+ return
+ {
+ -__first._M_get_sequence()->bucket_size(__first.bucket()),
+ __dp_exact
+ };
+
+ return { -1, __dp_sign };
+ }
+
+ if (__last._M_is_begin())
+ return { -1, __dp_sign };
+
+ if (__last._M_is_end())
+ return { 1, __dp_sign };
+
+ return { 1, __dp_equality };
+ }
+
+#if __cplusplus < 201103L
+ template<typename _Iterator, typename _Sequence>
+ struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
+ { typedef _Iterator _Type; };
+#endif
+
+ template<typename _Iterator, typename _Sequence>
+ inline _Iterator
+ __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
+ { return __it.base(); }
+
} // namespace __gnu_debug
#include <debug/safe_local_iterator.tcc>
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index 455e4cd5dd7..f846bf78307 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -34,17 +34,18 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_local_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_local_iterator& __rhs) const
+ _M_valid_range(const _Safe_local_iterator& __rhs,
+ std::pair<difference_type, _Distance_precision>& __dist) const
{
if (!_M_can_compare(__rhs))
return false;
+
if (bucket() != __rhs.bucket())
return false;
/* Determine if we can order the iterators without the help of
the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
+ __dist = __get_distance(*this, __rhs);
switch (__dist.second)
{
case __dp_equality:
@@ -57,15 +58,6 @@ namespace __gnu_debug
return __dist.first >= 0;
}
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. */
- if (_M_is_begin() || __rhs._M_is_end())
- return true;
- if (_M_is_end() || __rhs._M_is_begin())
- return false;
-
// Assume that this is a valid range; we can't check anything else
return true;
}
diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h
index c13ee811aaa..1ca6dda9c0e 100644
--- a/libstdc++-v3/include/debug/set.h
+++ b/libstdc++-v3/include/debug/set.h
@@ -280,9 +280,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h
new file mode 100644
index 00000000000..d1e57ea75a0
--- /dev/null
+++ b/libstdc++-v3/include/debug/stl_iterator.h
@@ -0,0 +1,113 @@
+// Debugging support implementation -*- C++ -*-
+
+// Copyright (C) 2015 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 debug/stl_iterator.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_STL_ITERATOR_H
+#define _GLIBCXX_DEBUG_STL_ITERATOR_H 1
+
+#include <debug/helper_functions.h>
+
+namespace __gnu_debug
+{
+ // Help Debug mode to see through reverse_iterator.
+ template<typename _Iterator>
+ inline bool
+ __valid_range(const std::reverse_iterator<_Iterator>& __first,
+ const std::reverse_iterator<_Iterator>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __valid_range(__last.base(), __first.base(), __dist); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const std::reverse_iterator<_Iterator>& __first,
+ const std::reverse_iterator<_Iterator>& __last)
+ { return __get_distance(__last.base(), __first.base()); }
+
+#if __cplusplus < 201103L
+ template<typename _Iterator>
+ struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> >
+ : __is_safe_random_iterator<_Iterator>
+ { };
+
+ template<typename _Iterator>
+ struct _Unsafe_type<std::reverse_iterator<_Iterator> >
+ {
+ typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
+ typedef std::reverse_iterator<_UnsafeType> _Type;
+ };
+
+ template<typename _Iterator>
+ inline std::reverse_iterator<typename _Unsafe_type<_Iterator>::_Type>
+ __unsafe(const std::reverse_iterator<_Iterator>& __it)
+ {
+ typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
+ return std::reverse_iterator<_UnsafeType>(__unsafe(__it.base()));
+ }
+#else
+ template<typename _Iterator>
+ inline auto
+ __base(const std::reverse_iterator<_Iterator>& __it)
+ -> decltype(std::__make_reverse_iterator(__base(__it.base())))
+ { return std::__make_reverse_iterator(__base(__it.base())); }
+
+ template<typename _Iterator>
+ inline auto
+ __unsafe(const std::reverse_iterator<_Iterator>& __it)
+ -> decltype(std::__make_reverse_iterator(__unsafe(__it.base())))
+ { return std::__make_reverse_iterator(__unsafe(__it.base())); }
+#endif
+
+#if __cplusplus >= 201103L
+ // Help Debug mode to see through move_iterator.
+ template<typename _Iterator>
+ inline bool
+ __valid_range(const std::move_iterator<_Iterator>& __first,
+ const std::move_iterator<_Iterator>& __last,
+ typename _Distance_traits<_Iterator>::__type& __dist)
+ { return __valid_range(__first.base(), __last.base(), __dist); }
+
+ template<typename _Iterator>
+ inline typename _Distance_traits<_Iterator>::__type
+ __get_distance(const std::move_iterator<_Iterator>& __first,
+ const std::move_iterator<_Iterator>& __last)
+ { return __get_distance(__first.base(), __last.base()); }
+
+ template<typename _Iterator>
+ inline auto
+ __unsafe(const std::move_iterator<_Iterator>& __it)
+ -> decltype(std::make_move_iterator(__unsafe(__it.base())))
+ { return std::make_move_iterator(__unsafe(__it.base())); }
+
+ template<typename _Iterator>
+ inline auto
+ __base(const std::move_iterator<_Iterator>& __it)
+ -> decltype(std::make_move_iterator(__base(__it.base())))
+ { return std::make_move_iterator(__base(__it.base())); }
+#endif
+}
+
+#endif
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index f068ef04fe8..72ae88e5495 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -380,9 +380,15 @@ namespace __gnu_debug
basic_string&
append(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::append(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::append(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::append(__first, __last);
+
this->_M_invalidate_all();
return *this;
}
@@ -452,9 +458,15 @@ namespace __gnu_debug
basic_string&
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
return *this;
}
@@ -533,9 +545,15 @@ namespace __gnu_debug
void
insert(iterator __p, _InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__p, __first, __last);
- _Base::insert(__p.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range2(__p, __first, __last, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__p.base(), __first, __last);
+
this->_M_invalidate_all();
}
@@ -676,8 +694,17 @@ namespace __gnu_debug
_InputIterator __j1, _InputIterator __j2)
{
__glibcxx_check_erase_range(__i1, __i2);
- __glibcxx_check_valid_range(__j1, __j2);
- _Base::replace(__i1.base(), __i2.base(), __j1, __j2);
+
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__j1, __j2, __dist);
+
+ if (__dist.second >= __dp_sign)
+ _Base::replace(__i1.base(), __i2.base(),
+ __gnu_debug::__unsafe(__j1),
+ __gnu_debug::__unsafe(__j2));
+ else
+ _Base::replace(__i1.base(), __i2.base(), __j1, __j2);
+
this->_M_invalidate_all();
return *this;
}
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 3f46641d678..41e20d7f203 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -364,10 +364,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
@@ -809,10 +815,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index 10a9c270ed0..1e6846140ab 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -355,10 +355,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
@@ -799,10 +805,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
- _Base::insert(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__first, __last);
+
_M_check_rehashed(__bucket_count);
}
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index be679920949..310009756c0 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -244,9 +244,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_valid_range(__first, __last);
- _Base::assign(__gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_valid_range2(__first, __last, __dist);
+
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::assign(__gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::assign(__first, __last);
+
this->_M_invalidate_all();
this->_M_update_guaranteed_capacity();
}
@@ -574,16 +580,21 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::cbegin();
- _Base_iterator __res = _Base::insert(__position.base(),
- __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ _Base_iterator __res;
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ __res = _Base::insert(__position.base(),
+ __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ __res = _Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();
@@ -598,15 +609,19 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
- __glibcxx_check_insert_range(__position, __first, __last);
+ typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
+ __glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::begin();
- _Base::insert(__position.base(), __gnu_debug::__base(__first),
- __gnu_debug::__base(__last));
+ if (__dist.second >= __gnu_debug::__dp_sign)
+ _Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
+ __gnu_debug::__unsafe(__last));
+ else
+ _Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 0472f593df5..c6b9800f7a6 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -124,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _RAIter, typename _Unused>
__boyer_moore_array_base(_RAIter __pat, size_t __patlen,
_Unused&&, _Pred&& __pred)
- : _M_bad_char{ {}, std::move(__pred) }
+ : _M_bad_char{ std::array<_Tp, _Len>{}, std::move(__pred) }
{
std::get<0>(_M_bad_char).fill(__patlen);
if (__patlen > 0)
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0504012cbd1..59b992a4a06 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -457,63 +457,236 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+
+ // Concept utility functions, reused in conditionally-explicit
+ // constructors.
+ template<bool, typename... _Elements>
+ struct _TC
+ {
+ template<typename... _UElements>
+ static constexpr bool _ConstructibleTuple()
+ {
+ return __and_<is_constructible<_Elements, const _UElements&>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyConvertibleTuple()
+ {
+ return __and_<is_convertible<const _UElements&, _Elements>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _MoveConstructibleTuple()
+ {
+ return __and_<is_constructible<_Elements, _UElements&&>...>::value;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyMoveConvertibleTuple()
+ {
+ return __and_<is_convertible<_UElements&&, _Elements>...>::value;
+ }
+ };
+
+ template<typename... _Elements>
+ struct _TC<false, _Elements...>
+ {
+ template<typename... _UElements>
+ static constexpr bool _ConstructibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyConvertibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _MoveConstructibleTuple()
+ {
+ return false;
+ }
+
+ template<typename... _UElements>
+ static constexpr bool _ImplicitlyMoveConvertibleTuple()
+ {
+ return false;
+ }
+ };
+
/// Primary class template, tuple
template<typename... _Elements>
class tuple : public _Tuple_impl<0, _Elements...>
{
typedef _Tuple_impl<0, _Elements...> _Inherited;
+ // Used for constraining the default constructor so
+ // that it becomes dependent on the constraints.
+ template<typename _Dummy>
+ struct _TC2
+ {
+ static constexpr bool _DefaultConstructibleTuple()
+ {
+ return __and_<is_default_constructible<_Elements>...>::value;
+ }
+ };
+
public:
+ template<typename _Dummy = void,
+ typename enable_if<_TC2<_Dummy>::
+ _DefaultConstructibleTuple(),
+ bool>::type = true>
constexpr tuple()
: _Inherited() { }
- explicit
- constexpr tuple(const _Elements&... __elements)
+ // Shortcut for the cases where constructors taking _Elements...
+ // need to be constrained.
+ template<typename _Dummy> using _TCC =
+ _TC<is_same<_Dummy, void>::value,
+ _Elements...>;
+
+ template<typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=true>
+ constexpr tuple(const _Elements&... __elements)
: _Inherited(__elements...) { }
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<_UElements,
- _Elements>...>::value>::type>
- explicit
+ template<typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=false>
+ explicit constexpr tuple(const _Elements&... __elements)
+ : _Inherited(__elements...) { }
+
+ // Shortcut for the cases where constructors taking _UElements...
+ // need to be constrained.
+ template<typename... _UElements> using _TMC =
+ _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+ _Elements...>;
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=true>
constexpr tuple(_UElements&&... __elements)
+ : _Inherited(std::forward<_UElements>(__elements)...) { }
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>()
+ && (sizeof...(_Elements) >= 1),
+ bool>::type=false>
+ explicit constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<const _UElements&,
- _Elements>...>::value>::type>
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=true>
constexpr tuple(const tuple<_UElements...>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
- template<typename... _UElements, typename = typename
- enable_if<__and_<is_convertible<_UElements,
- _Elements>...>::value>::type>
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit constexpr tuple(const tuple<_UElements...>& __in)
+ : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+ { }
+
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
constexpr tuple(tuple<_UElements...>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+ template<typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit constexpr tuple(tuple<_UElements...>&& __in)
+ : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
- template<typename _Alloc>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _Elements&... __elements)
: _Inherited(__tag, __a, __elements...) { }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_Elements...>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_Elements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const _Elements&... __elements)
+ : _Inherited(__tag, __a, __elements...) { }
+
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
_UElements&&... __elements)
: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
{ }
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ _UElements&&... __elements)
+ : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
+ { }
+
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -522,24 +695,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_UElements...>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
{ }
- template<typename _Alloc, typename... _UElements, typename = typename
- enable_if<sizeof...(_UElements)
- == sizeof...(_Elements)>::type>
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _ConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const tuple<_UElements...>& __in)
+ : _Inherited(__tag, __a,
+ static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+ { }
+
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && _TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
tuple<_UElements...>&& __in)
: _Inherited(__tag, __a,
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
{ }
+ template<typename _Alloc, typename... _UElements, typename
+ enable_if<_TMC<_UElements...>::template
+ _MoveConstructibleTuple<_UElements...>()
+ && !_TMC<_UElements...>::template
+ _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+ bool>::type=false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple<_UElements...>&& __in)
+ : _Inherited(__tag, __a,
+ static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
+ { }
+
tuple&
operator=(const tuple& __in)
{
@@ -582,7 +785,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// Explicit specialization, zero-element tuple.
- template<>
+ template<>
class tuple<>
{
public:
@@ -597,65 +800,190 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
public:
+ template <typename _U1 = _T1,
+ typename _U2 = _T2,
+ typename enable_if<__and_<
+ is_default_constructible<_U1>,
+ is_default_constructible<_U2>>
+ ::value, bool>::type = true>
+
constexpr tuple()
: _Inherited() { }
- explicit
- constexpr tuple(const _T1& __a1, const _T2& __a2)
- : _Inherited(__a1, __a2) { }
-
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
- explicit
+ // Shortcut for the cases where constructors taking _T1, _T2
+ // need to be constrained.
+ template<typename _Dummy> using _TCC =
+ _TC<is_same<_Dummy, void>::value, _T1, _T2>;
+
+ template<typename _Dummy = void, typename
+ enable_if<_TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type = true>
+ constexpr tuple(const _T1& __a1, const _T2& __a2)
+ : _Inherited(__a1, __a2) { }
+
+ template<typename _Dummy = void, typename
+ enable_if<_TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+ : _Inherited(__a1, __a2) { }
+
+ // Shortcut for the cases where constructors taking _U1, _U2
+ // need to be constrained.
+ using _TMC = _TC<true, _T1, _T2>;
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(_U1&& __a1, _U2&& __a2)
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+ : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
+
constexpr tuple(const tuple&) = default;
constexpr tuple(tuple&&) = default;
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(const tuple<_U1, _U2>& __in)
: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+ : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(tuple<_U1, _U2>&& __in)
: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<const _U1&, _T1>,
- is_convertible<const _U2&, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+ : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(const pair<_U1, _U2>& __in)
: _Inherited(__in.first, __in.second) { }
- template<typename _U1, typename _U2, typename = typename
- enable_if<__and_<is_convertible<_U1, _T1>,
- is_convertible<_U2, _T2>>::value>::type>
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(const pair<_U1, _U2>& __in)
+ : _Inherited(__in.first, __in.second) { }
+
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
constexpr tuple(pair<_U1, _U2>&& __in)
: _Inherited(std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
+ template<typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit constexpr tuple(pair<_U1, _U2>&& __in)
+ : _Inherited(std::forward<_U1>(__in.first),
+ std::forward<_U2>(__in.second)) { }
+
// Allocator-extended constructors.
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a)
: _Inherited(__tag, __a) { }
- template<typename _Alloc>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && _TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type=true>
+
tuple(allocator_arg_t __tag, const _Alloc& __a,
const _T1& __a1, const _T2& __a2)
: _Inherited(__tag, __a, __a1, __a2) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _Dummy = void,
+ typename enable_if<
+ _TCC<_Dummy>::template
+ _ConstructibleTuple<_T1, _T2>()
+ && !_TCC<_Dummy>::template
+ _ImplicitlyConvertibleTuple<_T1, _T2>(),
+ bool>::type=false>
+
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const _T1& __a1, const _T2& __a2)
+ : _Inherited(__tag, __a, __a1, __a2) { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
: _Inherited(__tag, __a, std::forward<_U1>(__a1),
std::forward<_U2>(__a2)) { }
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ _U1&& __a1, _U2&& __a2)
+ : _Inherited(__tag, __a, std::forward<_U1>(__a1),
+ std::forward<_U2>(__a2)) { }
+
template<typename _Alloc>
tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -664,28 +992,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const tuple<_U1, _U2>& __in)
: _Inherited(__tag, __a,
static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
{ }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const tuple<_U1, _U2>& __in)
+ : _Inherited(__tag, __a,
+ static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
+ { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
{ }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ tuple<_U1, _U2>&& __in)
+ : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
+ { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a,
const pair<_U1, _U2>& __in)
: _Inherited(__tag, __a, __in.first, __in.second) { }
- template<typename _Alloc, typename _U1, typename _U2>
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _ConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ const pair<_U1, _U2>& __in)
+ : _Inherited(__tag, __a, __in.first, __in.second) { }
+
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && _TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = true>
tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
std::forward<_U2>(__in.second)) { }
+ template<typename _Alloc, typename _U1, typename _U2, typename
+ enable_if<_TMC::template
+ _MoveConstructibleTuple<_U1, _U2>()
+ && !_TMC::template
+ _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+ bool>::type = false>
+ explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+ pair<_U1, _U2>&& __in)
+ : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
+ std::forward<_U2>(__in.second)) { }
+
tuple&
operator=(const tuple& __in)
{
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
new file mode 100644
index 00000000000..50edda9151a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -0,0 +1,108 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 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/>.
+
+#include <utility>
+
+struct Explicit
+{
+ Explicit() = default;
+ explicit Explicit(int) {}
+};
+
+std::pair<int, int> f1() {return {1,2};}
+
+std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
+
+std::pair<long, long> f3() {return std::pair<int, int>{1,2};}
+
+std::pair<Explicit, Explicit> f4()
+{
+ return std::pair<int, int>{1,2}; // { dg-error "could not convert" }
+}
+
+std::pair<long, long> f5() {return {1,2};}
+
+std::pair<int, int> v0{1,2};
+
+std::pair<Explicit, Explicit> v1{1,2};
+
+std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "explicit" }
+
+std::pair<Explicit, Explicit> v3{std::pair<int,int>{1,2}};
+
+std::pair<Explicit, Explicit> v4 =
+ std::pair<int,int>{1,2}; // { dg-error "conversion" }
+
+std::pair<char *, char *> v5(0,0);
+
+std::pair<long, long> v6{1,2};
+
+std::pair<long, long> v7 = {1,2};
+
+std::pair<long, long> v8{std::pair<int,int>{1,2}};
+
+std::pair<long, long> v9 = std::pair<int,int>{1,2};
+
+std::pair<Explicit, Explicit> v10{v0};
+
+std::pair<Explicit, Explicit> v11 = v0; // { dg-error "conversion" }
+
+std::pair<long, long> v12{v0};
+
+std::pair<long, long> v13 = v0;
+
+void f6(std::pair<Explicit, Explicit>) {}
+
+void f7(std::pair<long, long>) {}
+
+void test_arg_passing()
+{
+ f6(v0); // { dg-error "could not convert" }
+ f6(v1);
+ f6({1,2}); // { dg-error "explicit" }
+ f6(std::pair<Explicit, Explicit>{});
+ f6(std::pair<int, int>{}); // { dg-error "could not convert" }
+ f7(v0);
+ f7(v6);
+ f7({1,2});
+ f7(std::pair<int, int>{});
+ f7(std::pair<long, long>{});
+}
+
+struct MoveOnly
+{
+ MoveOnly() = default;
+ MoveOnly(MoveOnly&&) {}
+};
+
+struct ExplicitMoveOnly
+{
+ ExplicitMoveOnly() = default;
+ ExplicitMoveOnly(ExplicitMoveOnly&&) {}
+ explicit ExplicitMoveOnly(MoveOnly&&) {}
+};
+
+std::pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}};
+std::pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0};
+
+std::pair<int*, ExplicitMoveOnly> v16 =
+ {0, MoveOnly{}}; // { dg-error "explicit" }
+std::pair<ExplicitMoveOnly, int*> v17 =
+ {MoveOnly{}, 0}; // { dg-error "explicit" }
diff --git a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
index bcdab7d60c7..40ab16b14b9 100644
--- a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
@@ -69,20 +69,20 @@ void test01()
{
bool test __attribute__((unused)) = true;
- std::pair<type_one, type_zero> pp0(std::piecewise_construct_t(),
+ std::pair<type_one, type_zero> pp0(std::piecewise_construct,
std::forward_as_tuple(-3),
std::forward_as_tuple());
VERIFY( pp0.first.get() == -3 );
VERIFY( pp0.second.get() == 757 );
- std::pair<type_one, type_two> pp1(std::piecewise_construct_t(),
+ std::pair<type_one, type_two> pp1(std::piecewise_construct,
std::forward_as_tuple(6),
std::forward_as_tuple(5, 4));
VERIFY( pp1.first.get() == 6 );
VERIFY( pp1.second.get1() == 5 );
VERIFY( pp1.second.get2() == 4 );
- std::pair<type_two, type_two> pp2(std::piecewise_construct_t(),
+ std::pair<type_two, type_two> pp2(std::piecewise_construct,
std::forward_as_tuple(2, 1),
std::forward_as_tuple(-1, -3));
VERIFY( pp2.first.get1() == 2 );
diff --git a/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
new file mode 100644
index 00000000000..603b7c57074
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 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/>.
+
+#include <utility>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+ struct X
+ {
+ X() = delete;
+ };
+
+ typedef std::pair<int, X> P;
+ static_assert(!std::is_constructible<P>::value, "");
+ static_assert(!std::is_default_constructible<P>::value, "");
+}
+
+int main()
+{
+ test_default_constructible();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
new file mode 100644
index 00000000000..114a4906f1f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -0,0 +1,282 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 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/>.
+
+#include <tuple>
+#include <utility>
+#include <memory>
+
+struct Explicit
+{
+ Explicit() = default;
+ explicit Explicit(int) {}
+};
+
+std::tuple<int> f1a() {return {1};}
+std::tuple<int, int> f1b() {return {1,2};}
+std::tuple<int, int, int> f1c() {return {1,2,3};}
+
+std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
+
+std::tuple<long> f3_a() {return std::tuple<int>{1};}
+std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
+std::tuple<long, long, long> f3_c() {return std::tuple<int, int, int>{1,2,3};}
+
+std::tuple<Explicit> f4_a()
+{
+ return std::tuple<int>{1}; // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit> f4_b()
+{
+ return std::tuple<int, int>{1,2}; // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit, Explicit> f4_c()
+{
+ return std::tuple<int, int,int>{1,2,3}; // { dg-error "could not convert" }
+}
+
+std::tuple<long> f5_a() {return {1};}
+std::tuple<long, long> f5_b() {return {1,2};}
+std::tuple<long, long, long> f5_c() {return {1,2,3};}
+
+std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
+std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
+std::tuple<Explicit, Explicit> fp3()
+ {return std::pair<int, int>{1,2}; } // { dg-error "could not convert" }
+
+std::tuple<int> v0_a{1};
+std::tuple<int, int> v0_b{1,2};
+std::tuple<int, int, int> v0_c{1,2,3};
+
+std::tuple<Explicit> v1_a{1};
+std::tuple<Explicit, Explicit> v1_b{1,2};
+std::tuple<Explicit, Explicit, Explicit> v1_c{1,2,3};
+
+std::tuple<Explicit> v2_a = {1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error "explicit" }
+
+std::tuple<Explicit> v3_a{std::tuple<int>{1}};
+std::tuple<Explicit, Explicit> v3_b{std::tuple<int,int>{1,2}};
+std::tuple<Explicit, Explicit, Explicit> v3_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<Explicit, Explicit> v4_a =
+ std::tuple<int>{1}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v4_b =
+ std::tuple<int,int>{1,2}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v4_c =
+ std::tuple<int,int,int>{1,2,3}; // { dg-error "conversion" }
+
+std::tuple<long> v6_a{1};
+std::tuple<long, long> v6_b{1,2};
+std::tuple<long, long, long> v6_c{1,2,3};
+
+std::tuple<long> v7_a = {1};
+std::tuple<long, long> v7_b = {1,2};
+std::tuple<long, long, long> v7_c = {1,2,3};
+
+std::tuple<long> v8_a{std::tuple<int>{1}};
+std::tuple<long, long> v8_b{std::tuple<int,int>{1,2}};
+std::tuple<long, long, long> v8_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<long> v9_a = std::tuple<int>{1};
+std::tuple<long, long> v9_b = std::tuple<int,int>{1,2};
+std::tuple<long, long, long> v9_c = std::tuple<int,int,int>{1,2,3};
+
+std::tuple<Explicit> v10_a{v0_a};
+std::tuple<Explicit, Explicit> v10_b{v0_b};
+std::tuple<Explicit, Explicit, Explicit> v10_c{v0_c};
+
+std::tuple<Explicit> v11_a = v0_a; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v11_b = v0_b; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v11_c
+ = v0_c; // { dg-error "conversion" }
+
+std::tuple<long> v12_a{v0_a};
+std::tuple<long, long> v12_b{v0_b};
+std::tuple<long, long, long> v12_c{v0_c};
+
+std::tuple<long> v13_a = v0_a;
+std::tuple<long, long> v13_b = v0_b;
+std::tuple<long, long, long> v13_c = v0_c;
+
+std::tuple<int, int> v14{std::pair<int, int>{1,2}};
+std::tuple<long, long> v15{std::pair<int, int>{1,2}};
+std::tuple<Explicit, Explicit> v16{std::pair<int, int>{1,2}};
+
+std::tuple<int, int> v17 = std::pair<int, int>{1,2};
+std::tuple<long, long> v18 = std::pair<int, int>{1,2};
+std::tuple<Explicit, Explicit> v19
+ = std::pair<int, int>{1,2}; // { dg-error "conversion" }
+
+std::pair<int, int> v20;
+
+std::tuple<int, int> v21{v20};
+std::tuple<long, long> v22{v20};
+std::tuple<Explicit, Explicit> v23{v20};
+
+std::tuple<int, int> v24 = v20;
+std::tuple<long, long> v25 = v20;
+std::tuple<Explicit, Explicit> v26 = v20; // { dg-error "conversion" }
+
+std::tuple<int> v27_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v27_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v27_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v28_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v28_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+ v28_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v29_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<Explicit, Explicit>
+ v29_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<Explicit, Explicit, Explicit>
+ v29_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<int> v30_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v30_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v30_c
+ = {std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v31_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v31_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+ v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v32_a
+ = {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v32_b
+ = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v32_c
+ = {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error "explicit" }
+
+std::tuple<int, int> v33{std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v34{std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit>
+ v35{std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}};
+
+std::tuple<int, int> v36 = {std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v37 = {std::allocator_arg, std::allocator<int>{},
+ std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit> v38
+= {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // { dg-error "explicit" }
+
+std::tuple<int, int> v39{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v40{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit>
+ v41{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit> v44
+= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
+
+struct DeletedCopy
+{
+ DeletedCopy(int);
+ DeletedCopy(const DeletedCopy&) = delete;
+};
+
+std::tuple<DeletedCopy> v45{42};
+std::tuple<DeletedCopy> v46{std::allocator_arg,
+ std::allocator<DeletedCopy>{}, 42};
+
+struct Sanity
+{
+ int v;
+};
+
+std::tuple<int, Sanity> v47(3, {42});
+std::tuple<int, int, Sanity> v48(3, 4, {42});
+std::tuple<int, Sanity> v49(std::allocator_arg,
+ std::allocator<Sanity>{},
+ 3, {42});
+std::tuple<int, int, Sanity> v50(std::allocator_arg,
+ std::allocator<Sanity>{},
+ 3, 4, {42});
+
+void f6_a(std::tuple<Explicit>) {}
+void f6_b(std::tuple<Explicit, Explicit>) {}
+void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f7_a(std::tuple<long>) {}
+void f7_b(std::tuple<long, long>) {}
+void f7_c(std::tuple<long, long, long>) {}
+
+void test_arg_passing()
+{
+ f6_a(v0_a); // { dg-error "could not convert" }
+ f6_b(v0_b); // { dg-error "could not convert" }
+ f6_c(v0_c); // { dg-error "could not convert" }
+ f6_b(v20); // { dg-error "could not convert" }
+
+ f6_a(v1_a);
+ f6_b(v1_b);
+ f6_c(v1_c);
+
+ f6_a({1}); // { dg-error "explicit" }
+ f6_b({1,2}); // { dg-error "explicit" }
+ f6_c({1,2,3}); // { dg-error "explicit" }
+
+ f6_a(std::tuple<Explicit>{});
+ f6_b(std::tuple<Explicit, Explicit>{});
+ f6_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+ f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
+ f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+ f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+ f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+ f7_a(v0_a);
+ f7_b(v0_b);
+ f7_c(v0_c);
+ f7_b(v20);
+
+ f7_a(v6_a);
+ f7_b(v6_b);
+ f7_c(v6_c);
+
+ f7_a({1});
+ f7_b({1,2});
+ f7_c({1,2,3});
+
+ f7_a(std::tuple<int>{});
+ f7_b(std::tuple<int, int>{});
+ f7_c(std::tuple<int, int, int>{});
+ f7_b(std::pair<int, int>{});
+
+
+ f7_a(std::tuple<long>{});
+ f7_b(std::tuple<long, long>{});
+ f7_c(std::tuple<long, long, long>{});
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
new file mode 100644
index 00000000000..d3b975bd0f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
@@ -0,0 +1,47 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 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/>.
+
+#include <tuple>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+ struct X
+ {
+ X() = delete;
+ };
+
+ typedef std::tuple<int, X> T;
+ static_assert(!std::is_constructible<T>::value, "");
+ static_assert(!std::is_default_constructible<T>::value, "");
+
+ typedef std::tuple<int, int, X> T2;
+ static_assert(!std::is_constructible<T2>::value, "");
+ static_assert(!std::is_default_constructible<T2>::value, "");
+
+
+}
+
+int main()
+{
+ test_default_constructible();
+ return 0;
+}