diff options
Diffstat (limited to 'libstdc++-v3')
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; +} |