From: Jonathan Wakely Date: Wed, 19 Feb 2020 17:04:07 +0000 (+0000) Subject: libstdc++: subrange converting constructor should disallow slicing (LWG 3282) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=77f5310f0205714538668b88fbf1de44f1f435be;p=gcc.git libstdc++: subrange converting constructor should disallow slicing (LWG 3282) * include/std/ranges (__detail::__convertible_to_non_slicing): New helper concept. (__detail::__pair_like_convertible_to): Remove. (__detail::__pair_like_convertible_from): Add requirements for non-slicing conversions. (subrange): Constrain constructors with __convertible_to_non_slicing. Remove constructors from pair-like types. Add new deduction guide. * testsuite/std/ranges/subrange/lwg3282_neg.cc: New test. --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 689bee8c2a9..6e22536680f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,14 @@ 2020-02-19 Jonathan Wakely + * include/std/ranges (__detail::__convertible_to_non_slicing): New + helper concept. + (__detail::__pair_like_convertible_to): Remove. + (__detail::__pair_like_convertible_from): Add requirements for + non-slicing conversions. + (subrange): Constrain constructors with __convertible_to_non_slicing. + Remove constructors from pair-like types. Add new deduction guide. + * testsuite/std/ranges/subrange/lwg3282_neg.cc: New test. + * include/bits/iterator_concepts.h (iter_move): Add declaration to prevent unqualified lookup finding a suitable declaration (LWG 3247). diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b0806750a08..b348ba2cfcb 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -214,6 +214,12 @@ namespace ranges namespace __detail { + template + concept __convertible_to_non_slicing = convertible_to<_From, _To> + && !(is_pointer_v> && is_pointer_v> + && __not_same_as>, + remove_pointer_t>>); + template concept __pair_like = !is_reference_v<_Tp> && requires(_Tp __t) @@ -226,19 +232,12 @@ namespace ranges { get<1>(__t) } -> convertible_to&>; }; - template - concept __pair_like_convertible_to - = !range<_Tp> && __pair_like> - && requires(_Tp&& __t) - { - { get<0>(std::forward<_Tp>(__t)) } -> convertible_to<_Up>; - { get<1>(std::forward<_Tp>(__t)) } -> convertible_to<_Vp>; - }; - template concept __pair_like_convertible_from = !range<_Tp> && __pair_like<_Tp> - && constructible_from<_Tp, _Up, _Vp>; + && constructible_from<_Tp, _Up, _Vp> + && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>> + && convertible_to<_Vp, tuple_element_t<1, _Tp>>; template concept __iterator_sentinel_pair @@ -277,12 +276,13 @@ namespace ranges subrange() = default; constexpr - subrange(_It __i, _Sent __s) requires (!_S_store_size) + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) + requires (!_S_store_size) : _M_begin(std::move(__i)), _M_end(__s) { } constexpr - subrange(_It __i, _Sent __s, + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, __detail::__make_unsigned_like_t> __n) requires (_Kind == subrange_kind::sized) : _M_begin(std::move(__i)), _M_end(__s) @@ -295,7 +295,7 @@ namespace ranges template<__detail::__not_same_as _Rng> requires borrowed_range<_Rng> - && convertible_to, _It> + && __detail::__convertible_to_non_slicing, _It> && convertible_to, _Sent> constexpr subrange(_Rng&& __r) requires (!_S_store_size || sized_range<_Rng>) @@ -306,7 +306,7 @@ namespace ranges } template - requires convertible_to, _It> + requires __detail::__convertible_to_non_slicing, _It> && convertible_to, _Sent> constexpr subrange(_Rng&& __r, @@ -315,23 +315,6 @@ namespace ranges : subrange{ranges::begin(__r), ranges::end(__r), __n} { } - template<__detail::__not_same_as _PairLike> - requires __detail::__pair_like_convertible_to<_PairLike, _It, _Sent> - constexpr - subrange(_PairLike&& __r) requires (!_S_store_size) - : subrange{std::get<0>(std::forward<_PairLike>(__r)), - std::get<1>(std::forward<_PairLike>(__r))} - { } - - template<__detail::__pair_like_convertible_to<_It, _Sent> _PairLike> - constexpr - subrange(_PairLike&& __r, - __detail::__make_unsigned_like_t> __n) - requires (_Kind == subrange_kind::sized) - : subrange{std::get<0>(std::forward<_PairLike>(__r)), - std::get<1>(std::forward<_PairLike>(__r)), __n} - { } - template<__detail::__not_same_as _PairLike> requires __detail::__pair_like_convertible_from<_PairLike, const _It&, const _Sent&> @@ -402,6 +385,9 @@ namespace ranges } }; + template _Sent> + subrange(_It, _Sent) -> subrange<_It, _Sent>; + template _Sent> subrange(_It, _Sent, __detail::__make_unsigned_like_t>) diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/lwg3282_neg.cc b/libstdc++-v3/testsuite/std/ranges/subrange/lwg3282_neg.cc new file mode 100644 index 00000000000..5c2f1de45ad --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/subrange/lwg3282_neg.cc @@ -0,0 +1,31 @@ +// Copyright (C) 2020 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +using std::ranges::subrange; + +// LWG 3282. subrange converting constructor should disallow derived to base +// conversions + +struct Base {}; +struct Derived : Base {}; +subrange sd; +subrange sb = sd; // { dg-error "conversion" }