diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-05-10 12:25:06 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-05-10 12:25:06 +0100 |
commit | d7187f9ea16a5494d3d7cfd1264a40057fa9a504 (patch) | |
tree | 17e298208a900930d88a077df9aa7e7d5a57a74a /libstdc++-v3 | |
parent | cf68d92c7bb339d89426558cae2ad731ae8f0508 (diff) | |
download | gcc-d7187f9ea16a5494d3d7cfd1264a40057fa9a504.zip gcc-d7187f9ea16a5494d3d7cfd1264a40057fa9a504.tar.gz gcc-d7187f9ea16a5494d3d7cfd1264a40057fa9a504.tar.bz2 |
libstdc++/71005 fix post-increment for filesystem iterators
PR libstdc++/71005
* include/experimental/bits/fs_dir.h (__directory_iterator_proxy):
New type.
(directory_iterator::operator++(int)): Return proxy.
(recursive_directory_iterator::operator++(int)): Likewise.
* testsuite/experimental/filesystem/iterators/directory_iterator.cc:
Test post-increment.
* testsuite/experimental/filesystem/iterators/
recursive_directory_iterator.cc: Likewise.
From-SVN: r236072
Diffstat (limited to 'libstdc++-v3')
4 files changed, 137 insertions, 13 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1cdb7f4..58f6646 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2016-05-10 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/71005 + * include/experimental/bits/fs_dir.h (__directory_iterator_proxy): + New type. + (directory_iterator::operator++(int)): Return proxy. + (recursive_directory_iterator::operator++(int)): Likewise. + * testsuite/experimental/filesystem/iterators/directory_iterator.cc: + Test post-increment. + * testsuite/experimental/filesystem/iterators/ + recursive_directory_iterator.cc: Likewise. + 2016-05-09 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/71004 @@ -20,7 +32,7 @@ * include/experimental/bits/fs_dir.h (recursive_directory_iterator): Initialize scalar member variables in default constructor. * testsuite/experimental/filesystem/iterators/ - recursive_directory_iterator.cc: Teste default construction. + recursive_directory_iterator.cc: Test default construction. 2016-05-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> diff --git a/libstdc++-v3/include/experimental/bits/fs_dir.h b/libstdc++-v3/include/experimental/bits/fs_dir.h index f128cce..5fd41c2 100644 --- a/libstdc++-v3/include/experimental/bits/fs_dir.h +++ b/libstdc++-v3/include/experimental/bits/fs_dir.h @@ -153,8 +153,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 }; struct _Dir; + class directory_iterator; class recursive_directory_iterator; + struct __directory_iterator_proxy + { + const directory_entry& operator*() const noexcept { return _M_entry; } + + private: + friend class directory_iterator; + friend class recursive_directory_iterator; + + explicit + __directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { } + + directory_entry _M_entry; + }; + class directory_iterator { public: @@ -177,7 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 : directory_iterator(__p, directory_options::none, __ec) { } directory_iterator(const path& __p, - directory_options __options, error_code& __ec) noexcept + directory_options __options, + error_code& __ec) noexcept : directory_iterator(__p, __options, &__ec) { } directory_iterator(const directory_iterator& __rhs) = default; @@ -186,19 +202,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ~directory_iterator() = default; - directory_iterator& operator=(const directory_iterator& __rhs) = default; - directory_iterator& operator=(directory_iterator&& __rhs) noexcept = default; + directory_iterator& + operator=(const directory_iterator& __rhs) = default; + + directory_iterator& + operator=(directory_iterator&& __rhs) noexcept = default; const directory_entry& operator*() const; const directory_entry* operator->() const { return &**this; } directory_iterator& operator++(); directory_iterator& increment(error_code& __ec) noexcept; - directory_iterator operator++(int) + __directory_iterator_proxy operator++(int) { - auto __tmp = *this; + __directory_iterator_proxy __pr{**this}; ++*this; - return __tmp; + return __pr; } private: @@ -274,18 +293,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // modifiers recursive_directory_iterator& - operator=(const recursive_directory_iterator& __rhs) noexcept; + operator=(const recursive_directory_iterator& __rhs) noexcept; recursive_directory_iterator& - operator=(recursive_directory_iterator&& __rhs) noexcept; + operator=(recursive_directory_iterator&& __rhs) noexcept; recursive_directory_iterator& operator++(); recursive_directory_iterator& increment(error_code& __ec) noexcept; - recursive_directory_iterator operator++(int) + __directory_iterator_proxy operator++(int) { - auto __tmp = *this; + __directory_iterator_proxy __pr{**this}; ++*this; - return __tmp; + return __pr; } void pop(); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc index 28b948f..ce9f437 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc @@ -70,8 +70,53 @@ test01() remove_all(p, ec); } +void +test02() +{ + bool test __attribute__((unused)) = false; + + std::error_code ec; + const auto p = __gnu_test::nonexistent_path(); + create_directory(p, fs::current_path(), ec); + create_directory_symlink(p, p / "l", ec); + VERIFY( !ec ); + + // Test post-increment (libstdc++/71005) + auto iter = fs::directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter != fs::directory_iterator() ); + const auto entry1 = *iter; + const auto entry2 = *iter++; + VERIFY( entry1 == entry2 ); + VERIFY( entry1.path() == p/"l" ); + VERIFY( iter == fs::directory_iterator() ); + + remove_all(p, ec); +} + +void +test03() +{ + bool test __attribute__((unused)) = false; + + std::error_code ec; + const auto p = __gnu_test::nonexistent_path(); + create_directories(p / "longer_than_small_string_buffer", ec); + VERIFY( !ec ); + + // Test for no reallocation on each dereference (this is a GNU extension) + auto iter = fs::directory_iterator(p, ec); + const auto* s1 = iter->path().c_str(); + const auto* s2 = iter->path().c_str(); + VERIFY( s1 == s2 ); + + remove_all(p, ec); +} + int main() { test01(); + test02(); + test03(); } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc index b5f71be..fb4c31e 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc @@ -102,7 +102,53 @@ test02() { bool test __attribute__((unused)) = false; - // libstdc++71004 + std::error_code ec; + const auto p = __gnu_test::nonexistent_path(); + create_directories(p / "d1/d2", ec); + VERIFY( !ec ); + + // Test post-increment (libstdc++/71005) + auto iter = fs::recursive_directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + const auto entry1 = *iter; + const auto entry2 = *iter++; + VERIFY( entry1 == entry2 ); + VERIFY( entry1.path() == p/"d1" ); + const auto entry3 = *iter; + const auto entry4 = *iter++; + VERIFY( entry3 == entry4 ); + VERIFY( entry3.path() == p/"d1/d2" ); + VERIFY( iter == fs::recursive_directory_iterator() ); + + remove_all(p, ec); +} + +void +test03() +{ + bool test __attribute__((unused)) = false; + + std::error_code ec; + const auto p = __gnu_test::nonexistent_path(); + create_directories(p / "longer_than_small_string_buffer", ec); + VERIFY( !ec ); + + // Test for no reallocation on each dereference (this is a GNU extension) + auto iter = fs::recursive_directory_iterator(p, ec); + const auto* s1 = iter->path().c_str(); + const auto* s2 = iter->path().c_str(); + VERIFY( s1 == s2 ); + + remove_all(p, ec); +} + +void +test04() +{ + bool test __attribute__((unused)) = false; + + // libstdc++/71004 const fs::recursive_directory_iterator it; VERIFY( it == fs::recursive_directory_iterator() ); } @@ -112,4 +158,6 @@ main() { test01(); test02(); + test03(); + test04(); } |