From: Louis Dionne Date: Thu, 3 Jun 2021 18:14:57 +0000 (-0400) Subject: [libc++] Implement LWG3435 (constraints on reverse_iterator and move_iterator) X-Git-Tag: llvmorg-14-init~4933 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e4d3a993c2675f46cbe99acd1bf6e6d39d9c1aee;p=platform%2Fupstream%2Fllvm.git [libc++] Implement LWG3435 (constraints on reverse_iterator and move_iterator) --- diff --git a/libcxx/docs/Cxx2bStatusIssuesStatus.csv b/libcxx/docs/Cxx2bStatusIssuesStatus.csv index 2e4f416..1535640 100644 --- a/libcxx/docs/Cxx2bStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2bStatusIssuesStatus.csv @@ -6,7 +6,7 @@ "`3211 `__","``std::tuple<>`` should be trivially constructible","November 2020","","" "`3236 `__","Random access iterator requirements lack limiting relational operators domain to comparing those from the same range","November 2020","","" "`3265 `__","``move_iterator``'s conversions are more broken after P1207","November 2020","Fixed by `LWG3435 `__","" -"`3435 `__","``three_way_comparable_with, reverse_iterator>``","November 2020","","" +"`3435 `__","``three_way_comparable_with, reverse_iterator>``","November 2020","|Complete|","13.0" "`3432 `__","Missing requirement for comparison_category","November 2020","","" "`3447 `__","Deduction guides for ``take_view`` and ``drop_view`` have different constraints","November 2020","","" "`3450 `__","The const overloads of ``take_while_view::begin/end`` are underconstrained","November 2020","","" diff --git a/libcxx/include/iterator b/libcxx/include/iterator index 9d9a553..0661714 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -669,27 +669,53 @@ public: #ifndef _LIBCPP_ABI_NO_ITERATOR_BASES _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reverse_iterator() : __t(), current() {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {} - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reverse_iterator(const reverse_iterator<_Up>& __u) : __t(__u.base()), current(__u.base()) {} - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reverse_iterator& operator=(const reverse_iterator<_Up>& __u) - { __t = current = __u.base(); return *this; } + + template ::value && is_convertible<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + reverse_iterator(const reverse_iterator<_Up>& __u) + : __t(__u.base()), current(__u.base()) + { } + + template ::value && + is_convertible<_Up const&, _Iter>::value && + is_assignable<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { + __t = current = __u.base(); + return *this; + } #else _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reverse_iterator() : current() {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 explicit reverse_iterator(_Iter __x) : current(__x) {} - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reverse_iterator(const reverse_iterator<_Up>& __u) : current(__u.base()) {} - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - reverse_iterator& operator=(const reverse_iterator<_Up>& __u) - { current = __u.base(); return *this; } + + template ::value && is_convertible<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + reverse_iterator(const reverse_iterator<_Up>& __u) + : current(__u.base()) + { } + + template ::value && + is_convertible<_Up const&, _Iter>::value && + is_assignable<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + reverse_iterator& operator=(const reverse_iterator<_Up>& __u) { + current = __u.base(); + return *this; + } #endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return current;} @@ -1217,11 +1243,27 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 move_iterator() : __i() {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 explicit move_iterator(_Iter __x) : __i(__x) {} - template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 - move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} + + template ::value && is_convertible<_Up const&, _Iter>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} + + template ::value && + is_convertible<_Up const&, _Iter>::value && + is_assignable<_Iter&, _Up const&>::value + > > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + move_iterator& operator=(const move_iterator<_Up>& __u) { + __i = __u.base(); + return *this; + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference operator*() const { return static_cast(*__i); } diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp similarity index 50% rename from libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp rename to libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp index 4e60adc..7ef5655 100644 --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/convert.compile.fail.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.convert.LWG3435.verify.cpp @@ -6,37 +6,20 @@ // //===----------------------------------------------------------------------===// -// GCC 5 does not evaluate static assertions dependent on a template parameter. -// UNSUPPORTED: gcc-5 - // // move_iterator // template -// requires HasConstructor -// move_iterator(const move_iterator &u); - -// test requires +// requires !same_as && convertible_to +// move_iterator(const move_iterator &u); #include -template -void -test(U u) -{ - std::move_iterator r2(u); - std::move_iterator r1 = r2; -} - -struct base {}; -struct derived {}; - -int main(int, char**) -{ - derived d; - - test(&d); +struct Base { }; +struct Derived : Base { }; - return 0; +void test() { + std::move_iterator base; + std::move_iterator derived(base); // expected-error {{no matching constructor for initialization of 'std::move_iterator'}} } diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp similarity index 63% rename from libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp rename to libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp index 1dd9813..b141115 100644 --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/iter.compile.fail.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op.const/ctor.iter.explicit.verify.cpp @@ -6,30 +6,18 @@ // //===----------------------------------------------------------------------===// -// GCC 5 does not evaluate static assertions dependent on a template parameter. -// UNSUPPORTED: gcc-5 - // // move_iterator // explicit move_iterator(Iter ); -// test explicit +// test explicitness #include -template -void -test(It i) -{ - std::move_iterator r = i; -} - -int main(int, char**) -{ - char s[] = "123"; - test(s); - - return 0; +int main(int, char**) { + char const* it = ""; + std::move_iterator r = it; // expected-error{{no viable conversion from 'const char *' to 'std::move_iterator'}} + return 0; } diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp new file mode 100644 index 0000000..2bdfadf --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/assign.LWG3435.verify.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// move_iterator + +// template +// requires !same_as && convertible_to && assignable_from +// move_iterator& operator=(const move_iterator& u); + +#include + +struct Base { }; +struct Derived : Base { }; + +void test() { + std::move_iterator base; + std::move_iterator derived; + derived = base; // expected-error {{no viable overloaded '='}} +} diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp deleted file mode 100644 index fafe706..0000000 --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.compile.fail.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// GCC 5 does not evaluate static assertions dependent on a template parameter. -// UNSUPPORTED: gcc-5 - -// - -// move_iterator - -// template -// requires HasAssign -// move_iterator& -// operator=(const move_iterator& u); - -// test requires - -#include - -template -void -test(U u) -{ - const std::move_iterator r2(u); - std::move_iterator r1; - r1 = r2; -} - -struct base {}; -struct derived {}; - -int main(int, char**) -{ - derived d; - test(&d); - - return 0; -} diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp index a847192..9b54414 100644 --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.op=/move_iterator.pass.cpp @@ -29,7 +29,7 @@ test(U u) { const std::move_iterator r2(u); std::move_iterator r1; - std::move_iterator& rr = r1 = r2; + std::move_iterator& rr = (r1 = r2); assert(r1.base() == u); assert(&rr == &r1); } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp new file mode 100644 index 0000000..3b3c7cb --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.LWG3435.verify.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// reverse_iterator + +// template +// requires !same_as && convertible_to && assignable_from +// reverse_iterator& operator=(const reverse_iterator& u); + +#include + +struct Base { }; +struct Derived : Base { }; + +void test() { + std::reverse_iterator base; + std::reverse_iterator derived; + derived = base; // expected-error {{no viable overloaded '='}} +} diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp new file mode 100644 index 0000000..6082809 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// reverse_iterator + +// template +// requires !same_as && convertible_to +// reverse_iterator(const reverse_iterator &); + +#include + +struct Base { }; +struct Derived : Base { }; + +void test() { + std::reverse_iterator base; + std::reverse_iterator derived(base); // expected-error {{no matching constructor for initialization of 'std::reverse_iterator'}} +}