diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -92,6 +92,9 @@ // its vtable and typeinfo to libc++ rather than having all other libraries // using that class define their own copies. # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +// Give reverse_iterator one data member of type T, not two. +// Also, in C++14 and later, don't derive iterator types from std::iterator. +# define _LIBCPP_ABI_NO_ITERATOR_BASES // Enable optimized version of __do_get_(un)signed which avoids redundant copies. # define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET // Use the smallest possible integer type to represent the index of the variant. diff --git a/libcxx/include/__memory/raw_storage_iterator.h b/libcxx/include/__memory/raw_storage_iterator.h --- a/libcxx/include/__memory/raw_storage_iterator.h +++ b/libcxx/include/__memory/raw_storage_iterator.h @@ -29,15 +29,23 @@ template class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 raw_storage_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator&> // purposefully not C++03 +#endif { private: _OutputIterator __x_; public: + typedef output_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef raw_storage_iterator& reference; + _LIBCPP_INLINE_VISIBILITY explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {} _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator*() {return *this;} _LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(const _Tp& __element) diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -366,6 +366,7 @@ typedef traits traits_type; typedef basic_ostream ostream_type; + constexpr ostream_iterator() noexcept = default; // C++20 ostream_iterator(ostream_type& s); ostream_iterator(ostream_type& s, const charT* delimiter); ostream_iterator(const ostream_iterator& x); @@ -420,6 +421,7 @@ typedef basic_streambuf streambuf_type; typedef basic_ostream ostream_type; + constexpr ostreambuf_iterator() noexcept = default; // C++20 ostreambuf_iterator(ostream_type& s) noexcept; ostreambuf_iterator(streambuf_type* s) noexcept; ostreambuf_iterator& operator=(charT c); @@ -615,14 +617,18 @@ template class _LIBCPP_TEMPLATE_VIS reverse_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator::iterator_category, typename iterator_traits<_Iter>::value_type, typename iterator_traits<_Iter>::difference_type, typename iterator_traits<_Iter>::pointer, typename iterator_traits<_Iter>::reference> +#endif { private: - /*mutable*/ _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break +#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES + _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break +#endif static_assert(!__is_stashing_iterator<_Iter>::value, "The specified iterator type cannot be used with reverse_iterator; " @@ -632,6 +638,7 @@ _Iter current; public: typedef _Iter iterator_type; + typedef typename iterator_traits<_Iter>::value_type value_type; typedef typename iterator_traits<_Iter>::difference_type difference_type; typedef typename iterator_traits<_Iter>::reference reference; typedef typename iterator_traits<_Iter>::pointer pointer; @@ -644,6 +651,7 @@ bidirectional_iterator_tag> iterator_concept; #endif +#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reverse_iterator() : __t(), current() {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -655,6 +663,20 @@ _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; } +#endif + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return current;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -767,16 +789,23 @@ template class _LIBCPP_TEMPLATE_VIS back_insert_iterator - : public iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif { protected: _Container* container; public: typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 back_insert_iterator& operator=(const typename _Container::value_type& __value_) @@ -800,16 +829,23 @@ template class _LIBCPP_TEMPLATE_VIS front_insert_iterator - : public iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif { protected: _Container* container; public: typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit front_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 front_insert_iterator& operator=(const typename _Container::value_type& __value_) @@ -833,17 +869,24 @@ template class _LIBCPP_TEMPLATE_VIS insert_iterator - : public iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) + : public iterator +#endif { protected: _Container* container; typename _Container::iterator iter; public: typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; +#if _LIBCPP_STD_VER > 17 + typedef ptrdiff_t difference_type; +#else + typedef void difference_type; +#endif + typedef void pointer; + typedef void reference; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, typename _Container::iterator __i) : container(_VSTD::addressof(__x)), iter(__i) {} @@ -869,12 +912,19 @@ template , class _Distance = ptrdiff_t> class _LIBCPP_TEMPLATE_VIS istream_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator +#endif { public: typedef _CharT char_type; typedef _Traits traits_type; typedef basic_istream<_CharT,_Traits> istream_type; + typedef input_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Distance difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; private: istream_type* __in_stream_; _Tp __value_; @@ -930,13 +980,15 @@ template > class _LIBCPP_TEMPLATE_VIS ostream_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator +#endif { public: typedef output_iterator_tag iterator_category; typedef void value_type; #if _LIBCPP_STD_VER > 17 - typedef std::ptrdiff_t difference_type; + typedef ptrdiff_t difference_type; #else typedef void difference_type; #endif @@ -950,6 +1002,9 @@ ostream_type* __out_stream_; const char_type* __delim_; public: +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY ostream_iterator() = default; +#endif _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s) _NOEXCEPT : __out_stream_(_VSTD::addressof(__s)), __delim_(nullptr) {} _LIBCPP_INLINE_VISIBILITY ostream_iterator(ostream_type& __s, const _CharT* __delimiter) _NOEXCEPT @@ -969,11 +1024,18 @@ template class _LIBCPP_TEMPLATE_VIS istreambuf_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator +#endif { public: + typedef input_iterator_tag iterator_category; + typedef _CharT value_type; + typedef typename _Traits::off_type difference_type; + typedef _CharT* pointer; + typedef _CharT reference; typedef _CharT char_type; typedef _Traits traits_type; typedef typename _Traits::int_type int_type; @@ -1039,13 +1101,15 @@ template class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator +#if _LIBCPP_STD_VER <= 11 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES) : public iterator +#endif { public: typedef output_iterator_tag iterator_category; typedef void value_type; #if _LIBCPP_STD_VER > 17 - typedef std::ptrdiff_t difference_type; + typedef ptrdiff_t difference_type; #else typedef void difference_type; #endif @@ -1059,6 +1123,9 @@ private: streambuf_type* __sbuf_; public: +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator() = default; +#endif _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(ostream_type& __s) _NOEXCEPT : __sbuf_(__s.rdbuf()) {} _LIBCPP_INLINE_VISIBILITY ostreambuf_iterator(streambuf_type* __s) _NOEXCEPT diff --git a/libcxx/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/cxx20_iterator_traits.compile.pass.cpp @@ -50,12 +50,12 @@ typename Traits::iterator_concept; }; -template +template constexpr bool testIOIterator() { using Traits = std::iterator_traits; static_assert(std::same_as); static_assert(std::same_as); - static_assert(std::same_as); + static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); static_assert(!has_iterator_concept_v); @@ -200,8 +200,8 @@ #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) static_assert(testWithoutConcept, char, long long, char, char*, std::input_iterator_tag>()); static_assert(testWithoutConcept, int, std::ptrdiff_t, int&&, int*, std::random_access_iterator_tag>()); -static_assert(testIOIterator, std::output_iterator_tag, std::ptrdiff_t>()); -static_assert(testIOIterator, std::output_iterator_tag, std::ptrdiff_t>()); +static_assert(testIOIterator, std::output_iterator_tag>()); +static_assert(testIOIterator, std::output_iterator_tag>()); static_assert(testConstWithoutConcept()); static_assert(testConstWithoutConcept()); #endif // !_LIBCPP_HAS_NO_LOCALIZATION diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/types.pass.cpp @@ -48,7 +48,11 @@ q.test(); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); +#else + static_assert((std::is_same::value), ""); +#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/types.pass.cpp @@ -49,7 +49,11 @@ q.test(); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); +#else + static_assert((std::is_same::value), ""); +#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/insert.iterator/types.pass.cpp @@ -52,7 +52,11 @@ q.test(); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); +#else + static_assert((std::is_same::value), ""); +#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/iterator_concept_conformance.compile.pass.cpp @@ -19,8 +19,8 @@ using iterator = std::ostream_iterator; static_assert(!std::indirectly_readable); static_assert(std::indirectly_writable); -static_assert(!std::weakly_incrementable); -static_assert(!std::input_or_output_iterator); +static_assert(std::weakly_incrementable); +static_assert(std::input_or_output_iterator); static_assert(!std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::input_iterator); diff --git a/libcxx/test/std/iterators/stream.iterators/ostream.iterator/ostream.iterator.cons.des/default.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/ostream.iterator.cons.des/default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/stream.iterators/ostream.iterator/ostream.iterator.cons.des/default.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// class ostream_iterator + +// constexpr ostream_iterator() noexcept = default; + +#include +#include // char_traits + +#include "test_macros.h" + +struct MyTraits : std::char_traits { + MyTraits(); // This should not be called. +}; + +constexpr bool test_constexpr() +{ + std::ostream_iterator it; + (void)it; + std::ostream_iterator wit; + (void)wit; + return true; +} + +int main(int, char**) +{ + ASSERT_NOEXCEPT(std::ostream_iterator()); + ASSERT_NOEXCEPT(std::ostream_iterator()); + + test_constexpr(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/iterator_concept_conformance.compile.pass.cpp @@ -20,8 +20,8 @@ using iterator = std::ostreambuf_iterator; static_assert(!std::indirectly_readable); static_assert(std::indirectly_writable); -static_assert(!std::weakly_incrementable); -static_assert(!std::input_or_output_iterator); +static_assert(std::weakly_incrementable); +static_assert(std::input_or_output_iterator); static_assert(!std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::input_iterator); diff --git a/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/ostreambuf.iter.cons/default.pass.cpp b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/ostreambuf.iter.cons/default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/stream.iterators/ostreambuf.iterator/ostreambuf.iter.cons/default.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// class ostreambuf_iterator + +// constexpr ostreambuf_iterator() noexcept = default; + +#include + +#include "test_macros.h" + +constexpr bool test_constexpr() +{ + std::ostreambuf_iterator it; + (void)it; + std::ostreambuf_iterator wit; + (void)wit; + return true; +} + +int main(int, char**) +{ + ASSERT_NOEXCEPT(std::ostreambuf_iterator()); + ASSERT_NOEXCEPT(std::ostreambuf_iterator()); + + test_constexpr(); + static_assert(test_constexpr()); + + return 0; +}