From: Jonathan Wakely Date: Mon, 30 Jul 2018 17:13:05 +0000 (+0100) Subject: PR libstdc++/86734 make reverse_iterator::operator-> more robust X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a64ede727f78b423591995428fbc5a6ac4e72cb0;p=gcc.git PR libstdc++/86734 make reverse_iterator::operator-> more robust Implement the proposed resolution from LWG 1052, which also resolves DR 2118 by avoiding taking the address in the first place. PR libstdc++/86734 * include/bits/stl_iterator.h (reverse_iterator::operator->): Call _S_to_pointer (LWG 1052, LWG 2118). (reverse_iterator::_S_to_pointer): Define overloaded helper functions. * testsuite/24_iterators/reverse_iterator/dr1052.cc: New test. * testsuite/24_iterators/reverse_iterator/dr2188.cc: New test. From-SVN: r263074 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b1653f16a6a..6298f7eab23 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2018-07-30 Jonathan Wakely + PR libstdc++/86734 + * include/bits/stl_iterator.h (reverse_iterator::operator->): Call + _S_to_pointer (LWG 1052, LWG 2118). + (reverse_iterator::_S_to_pointer): Define overloaded helper functions. + * testsuite/24_iterators/reverse_iterator/dr1052.cc: New test. + * testsuite/24_iterators/reverse_iterator/dr2188.cc: New test. + * libsupc++/new_opa.cc (operator new(size_t, align_val_t)): Add workaround for aligned_alloc bug on AIX. * testsuite/18_support/new_aligned.cc: New test. diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 0d5f20bc2c6..8562f879c16 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -122,6 +122,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ // _GLIBCXX_RESOLVE_LIB_DEFECTS // 235 No specification of default ctor for reverse_iterator + // 1012. reverse_iterator default ctor should value initialize _GLIBCXX17_CONSTEXPR reverse_iterator() : current() { } @@ -182,7 +183,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ _GLIBCXX17_CONSTEXPR pointer operator->() const - { return &(operator*()); } + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1052. operator-> should also support smart pointers + _Iterator __tmp = current; + --__tmp; + return _S_to_pointer(__tmp); + } /** * @return @c *this @@ -286,6 +293,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX17_CONSTEXPR reference operator[](difference_type __n) const { return *(*this + __n); } + + private: + template + static _GLIBCXX17_CONSTEXPR _Tp* + _S_to_pointer(_Tp* __p) + { return __p; } + + template + static _GLIBCXX17_CONSTEXPR pointer + _S_to_pointer(_Tp __t) + { return __t.operator->(); } }; //@{ diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr1052.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr1052.cc new file mode 100644 index 00000000000..2704010a083 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr1052.cc @@ -0,0 +1,82 @@ +// Copyright (C) 2018 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-do run { target c++11 } } + +// PR libstdc++/86734 +// LWG 1052. reverse_iterator::operator-> should also support smart pointers +// LWG 2775. reverse_iterator is does not compile for fancy pointers + +#include +#include + +void +test01() +{ + // Example 1 from LWG 1052 + + struct X { int m; }; + + static X x; + + struct IterX { + typedef std::bidirectional_iterator_tag iterator_category; + typedef X& reference; + struct pointer + { + pointer(X& v) : value(v) {} + X& value; + X* operator->() const {return &value;} + }; + typedef std::ptrdiff_t difference_type; + typedef X value_type; + // additional iterator requirements not important for this issue + + reference operator*() const { return x; } + pointer operator->() const { return pointer(x); } + IterX& operator--() {return *this;} + + }; + + std::reverse_iterator ix; + VERIFY( &ix->m == &(*ix).m ); +} + +void +test02() +{ + // Example 2 from LWG 1052 + + struct P { + P() : first(10), second(20.0) { } + int first; + double second; + }; + P op; + std::reverse_iterator ri(&op + 1); + VERIFY( ri->first == 10 ); +} + +// N.B. Example 3 from LWG 1052 isn't expected to work, +// because a caching iterator like IterX is not a forward iterator. + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr2188.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr2188.cc new file mode 100644 index 00000000000..047334ddf24 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/dr2188.cc @@ -0,0 +1,47 @@ +// Copyright (C) 2018 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-do run { target c++11 } } + +// PR libstdc++/86734 + +#include +#include + +void +test01() +{ + // LWG DR 2188 + // Reverse iterator does not fully support targets that overload operator& + struct X { + int val; + int* operator&() { return &val; } + const int* operator&() const { return &val; } + }; + + X x[2] = { {1}, {2} }; + std::reverse_iterator rev(x+2); + VERIFY( rev->val == 2 ); + ++rev; + VERIFY( rev->val == 1 ); +} + +int +main() +{ + test01(); +}