Commit d7187f9e by Jonathan Wakely Committed by Jonathan Wakely

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
parent cf68d92c
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> 2016-05-09 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/71004 PR libstdc++/71004
...@@ -20,7 +32,7 @@ ...@@ -20,7 +32,7 @@
* include/experimental/bits/fs_dir.h (recursive_directory_iterator): * include/experimental/bits/fs_dir.h (recursive_directory_iterator):
Initialize scalar member variables in default constructor. Initialize scalar member variables in default constructor.
* testsuite/experimental/filesystem/iterators/ * 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> 2016-05-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
......
...@@ -153,8 +153,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -153,8 +153,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}; };
struct _Dir; struct _Dir;
class directory_iterator;
class recursive_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 class directory_iterator
{ {
public: public:
...@@ -177,7 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -177,7 +192,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
: directory_iterator(__p, directory_options::none, __ec) { } : directory_iterator(__p, directory_options::none, __ec) { }
directory_iterator(const path& __p, 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(__p, __options, &__ec) { }
directory_iterator(const directory_iterator& __rhs) = default; directory_iterator(const directory_iterator& __rhs) = default;
...@@ -186,19 +202,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -186,19 +202,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
~directory_iterator() = default; ~directory_iterator() = default;
directory_iterator& operator=(const directory_iterator& __rhs) = default; directory_iterator&
directory_iterator& operator=(directory_iterator&& __rhs) noexcept = default; operator=(const directory_iterator& __rhs) = default;
directory_iterator&
operator=(directory_iterator&& __rhs) noexcept = default;
const directory_entry& operator*() const; const directory_entry& operator*() const;
const directory_entry* operator->() const { return &**this; } const directory_entry* operator->() const { return &**this; }
directory_iterator& operator++(); directory_iterator& operator++();
directory_iterator& increment(error_code& __ec) noexcept; 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; ++*this;
return __tmp; return __pr;
} }
private: private:
...@@ -281,11 +300,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -281,11 +300,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
recursive_directory_iterator& operator++(); recursive_directory_iterator& operator++();
recursive_directory_iterator& increment(error_code& __ec) noexcept; 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; ++*this;
return __tmp; return __pr;
} }
void pop(); void pop();
......
...@@ -70,8 +70,53 @@ test01() ...@@ -70,8 +70,53 @@ test01()
remove_all(p, ec); 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 int
main() main()
{ {
test01(); test01();
test02();
test03();
} }
...@@ -102,7 +102,53 @@ test02() ...@@ -102,7 +102,53 @@ test02()
{ {
bool test __attribute__((unused)) = false; 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; const fs::recursive_directory_iterator it;
VERIFY( it == fs::recursive_directory_iterator() ); VERIFY( it == fs::recursive_directory_iterator() );
} }
...@@ -112,4 +158,6 @@ main() ...@@ -112,4 +158,6 @@ main()
{ {
test01(); test01();
test02(); test02();
test03();
test04();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment