diff options
Diffstat (limited to 'libstdc++-v3')
17 files changed, 639 insertions, 69 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cbe0fc5daa8..8db45525a7d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,88 @@ +2018-01-15 Jonathan Wakely <jwakely@redhat.com> + + * python/libstdcxx/v6/printers.py (register_type_printers): Remove + printer for experimental::any. Fix printers for experimental::optional + and experimental::basic_string_view. + + Backport from mainline + 2018-01-04 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/83626 + * src/filesystem/ops.cc (remove(const path&, error_code&))): Do not + return an error for non-existent paths. Remove unnecessary + symlink_status call. + (remove_all(const path&)): Fix type of result variable. + (remove_all(const path&, error_code&))): Use non-throwing increment + for directory iterator. Do not return an error for non-existent paths. + * testsuite/experimental/filesystem/operations/remove.cc: New test. + * testsuite/experimental/filesystem/operations/remove_all.cc: Fix + expected results for non-existent paths. + +2018-01-05 Jonathan Wakely <jwakely@redhat.com> + + Backport from mainline + 2017-11-14 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/locale_conv.h (wbuffer_convert::_M_conv_get): Fix typo. + * testsuite/22_locale/conversions/buffer/3.cc: New test. + + Backport from mainline + 2017-10-19 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/experimental/filesystem/iterators/ + recursive_directory_iterator.cc: Ensure that error_code arguments are + cleared when required. + * testsuite/experimental/filesystem/operations/create_directory.cc: + Remove redundant check. + * testsuite/experimental/filesystem/operations/temp_directory_path.cc: + Ensure that error_code argument is cleared when required. + + Backport from mainline + 2017-12-27 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/83600 + * include/bits/regex.h (match_results::end()): Return valid iterator + when not ready. + * testsuite/28_regex/match_results/ctors/char/default.cc: Check that + unready objects are empty and have equal begin and end iterators. + * testsuite/28_regex/match_results/ctors/wchar_t/default.cc: Likewise. + + Backport from mainline + 2017-12-27 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/83598 + * include/bits/regex.h (basic_regex): Don't modify flags passed to + constructors. + * testsuite/28_regex/basic_regex/ctors/83598.cc: New test. + + Backport from mainline + 2017-12-14 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/83279 + * src/filesystem/std-ops.cc (do_copy_file): Handle sendfile not + copying entire file. + + Backport from mainline + 2018-01-04 Jonathan Wakely <jwakely@redhat.com> + + * include/experimental/fs_ops.h (exists(const path&, error_code&))): + Only check status_known once. + + Backport from mainline + 2017-10-25 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/79283 + * src/filesystem/ops.cc (read_symlink): Handle st_size being zero. + +2017-12-14 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/59568 + * include/std/complex (operator>>): Only use putback if a character + was successfully extracted and only set the value if a number was + successfully extracted. + * testsuite/26_numerics/complex/inserters_extractors/char/59568.cc: + New test. + 2017-11-11 John David Anglin <danglin@gcc.gnu.org> Backport from mainline diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h index 9667374840b..06376e9cd19 100644 --- a/libstdc++-v3/include/bits/locale_conv.h +++ b/libstdc++-v3/include/bits/locale_conv.h @@ -431,7 +431,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 streamsize __nbytes = sizeof(_M_get_buf) - _M_unconv; __nbytes = std::min(__nbytes, _M_buf->in_avail()); if (__nbytes < 1) - __nbytes == 1; + __nbytes = 1; __nbytes = _M_buf->sgetn(_M_get_buf + _M_unconv, __nbytes); if (__nbytes < 1) return false; diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h index 983bdef3871..cf7aa3ee4bf 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -1751,7 +1751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ const_iterator end() const - { return _Base_type::end() - 3; } + { return _Base_type::end() - (empty() ? 0 : 3); } /** * @brief Gets an iterator to one-past-the-end of the collection. diff --git a/libstdc++-v3/include/experimental/bits/fs_ops.h b/libstdc++-v3/include/experimental/bits/fs_ops.h index 62a9826d6e5..7b30a30138e 100644 --- a/libstdc++-v3/include/experimental/bits/fs_ops.h +++ b/libstdc++-v3/include/experimental/bits/fs_ops.h @@ -131,8 +131,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __s = status(__p, __ec); if (status_known(__s)) - __ec.clear(); - return exists(__s); + { + __ec.clear(); + return __s.type() != file_type::not_found; + } + return false; } uintmax_t file_size(const path& __p); diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 8f9703a59c8..1225c6bc44e 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -493,7 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) { _Tp __re_x, __im_x; - _CharT __ch; + _CharT __ch = _CharT(); __is >> __ch; if (__ch == '(') { @@ -511,11 +511,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else __is.setstate(ios_base::failbit); } - else + else if (__is) { __is.putback(__ch); - __is >> __re_x; - __x = __re_x; + if (__is >> __re_x) + __x = __re_x; + else + __is.setstate(ios_base::failbit); } return __is; } diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 040715a9073..ec3feafc5de 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -1154,7 +1154,7 @@ class TemplateTypePrinter(object): Recognizes type names that match a regular expression. Replaces them with a formatted string which can use replacement field {N} to refer to the \N subgroup of the regex match. - Type printers are recusively applied to the subgroups. + Type printers are recursively applied to the subgroups. This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >" and replacing it with "std::vector<{1}>", omitting the template argument @@ -1335,10 +1335,10 @@ def register_type_printers(obj): # strip the "fundamentals_v1" inline namespace from these types add_one_template_type_printer(obj, 'optional<T>', 'experimental::fundamentals_v1::optional<(.*)>', - 'experimental::optional<\\1>') + 'experimental::optional<{1}>') add_one_template_type_printer(obj, 'basic_string_view<C>', 'experimental::fundamentals_v1::basic_string_view<(.*), std::char_traits<\\1> >', - 'experimental::basic_string_view<\\1>') + 'experimental::basic_string_view<{1}>') def register_libstdcxx_printers (obj): "Register libstdc++ pretty-printers with objfile Obj." diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 0dcb1b410fc..d4bd5207b63 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -443,48 +443,68 @@ namespace return false; } + size_t count = from_st->st_size; #ifdef _GLIBCXX_USE_SENDFILE off_t offset = 0; - const auto n = ::sendfile(out.fd, in.fd, &offset, from_st->st_size); - if (n < 0 && (errno == ENOSYS || errno == EINVAL)) + ssize_t n = ::sendfile(out.fd, in.fd, &offset, count); + if (n < 0 && errno != ENOSYS && errno != EINVAL) { -#endif - __gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in); - __gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out); - if (sbin.is_open()) - in.fd = -1; - if (sbout.is_open()) - out.fd = -1; - if (from_st->st_size && !(std::ostream(&sbout) << &sbin)) - { - ec = std::make_error_code(std::errc::io_error); - return false; - } - if (!sbout.close() || !sbin.close()) + ec.assign(errno, std::generic_category()); + return false; + } + if ((size_t)n == count) + { + if (!out.close() || !in.close()) { ec.assign(errno, std::generic_category()); return false; } - ec.clear(); return true; + } + else if (n > 0) + count -= n; +#endif // _GLIBCXX_USE_SENDFILE + + using std::ios; + __gnu_cxx::stdio_filebuf<char> sbin(in.fd, ios::in|ios::binary); + __gnu_cxx::stdio_filebuf<char> sbout(out.fd, ios::out|ios::binary); + + if (sbin.is_open()) + in.fd = -1; + if (sbout.is_open()) + out.fd = -1; #ifdef _GLIBCXX_USE_SENDFILE + if (n != 0) + { + if (n < 0) + n = 0; + + const auto p1 = sbin.pubseekoff(n, ios::beg, ios::in); + const auto p2 = sbout.pubseekoff(n, ios::beg, ios::out); + + const std::streampos errpos(std::streamoff(-1)); + if (p1 == errpos || p2 == errpos) + { + ec = std::make_error_code(std::errc::io_error); + return false; + } } - if (n != from_st->st_size) +#endif + + if (count && !(std::ostream(&sbout) << &sbin)) { - ec.assign(errno, std::generic_category()); + ec = std::make_error_code(std::errc::io_error); return false; } - if (!out.close() || !in.close()) + if (!sbout.close() || !sbin.close()) { ec.assign(errno, std::generic_category()); return false; } - ec.clear(); return true; -#endif } } #endif @@ -1199,26 +1219,45 @@ fs::read_symlink(const path& p) fs::path fs::read_symlink(const path& p, error_code& ec) { + path result; #ifdef _GLIBCXX_HAVE_SYS_STAT_H stat_type st; if (::lstat(p.c_str(), &st)) { ec.assign(errno, std::generic_category()); - return {}; + return result; } - std::string buf(st.st_size, '\0'); - ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size()); - if (len == -1) + std::string buf(st.st_size ? st.st_size + 1 : 128, '\0'); + do { - ec.assign(errno, std::generic_category()); - return {}; + ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size()); + if (len == -1) + { + ec.assign(errno, std::generic_category()); + return result; + } + else if (len == (ssize_t)buf.size()) + { + if (buf.size() > 4096) + { + ec.assign(ENAMETOOLONG, std::generic_category()); + return result; + } + buf.resize(buf.size() * 2); + } + else + { + buf.resize(len); + result.assign(buf); + ec.clear(); + break; + } } - ec.clear(); - return path{buf.data(), buf.data()+len}; + while (true); #else ec = std::make_error_code(std::errc::not_supported); - return {}; #endif + return result; } @@ -1235,16 +1274,15 @@ fs::remove(const path& p) bool fs::remove(const path& p, error_code& ec) noexcept { - if (exists(symlink_status(p, ec))) + if (::remove(p.c_str()) == 0) { - if (::remove(p.c_str()) == 0) - { - ec.clear(); - return true; - } - else - ec.assign(errno, std::generic_category()); + ec.clear(); + return true; } + else if (errno == ENOENT) + ec.clear(); + else + ec.assign(errno, std::generic_category()); return false; } @@ -1253,7 +1291,7 @@ std::uintmax_t fs::remove_all(const path& p) { error_code ec; - bool result = remove_all(p, ec); + const auto result = remove_all(p, ec); if (ec.value()) _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec)); return result; @@ -1262,14 +1300,28 @@ fs::remove_all(const path& p) std::uintmax_t fs::remove_all(const path& p, error_code& ec) noexcept { - auto fs = symlink_status(p, ec); - uintmax_t count = 0; - if (ec.value() == 0 && fs.type() == file_type::directory) - for (directory_iterator d(p, ec), end; ec.value() == 0 && d != end; ++d) - count += fs::remove_all(d->path(), ec); - if (ec.value()) + const auto s = symlink_status(p, ec); + if (!status_known(s)) return -1; - return fs::remove(p, ec) ? ++count : -1; // fs:remove() calls ec.clear() + + ec.clear(); + if (s.type() == file_type::not_found) + return 0; + + uintmax_t count = 0; + if (s.type() == file_type::directory) + { + for (directory_iterator d(p, ec), end; !ec && d != end; d.increment(ec)) + count += fs::remove_all(d->path(), ec); + if (ec.value() == ENOENT) + ec.clear(); + else if (ec) + return -1; + } + + if (fs::remove(p, ec)) + ++count; + return ec ? -1 : count; } void diff --git a/libstdc++-v3/testsuite/22_locale/conversions/buffer/3.cc b/libstdc++-v3/testsuite/22_locale/conversions/buffer/3.cc new file mode 100644 index 00000000000..99a679dc124 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/conversions/buffer/3.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2017 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 +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } + +#include <locale> +#include <streambuf> +#include <testsuite_hooks.h> + +struct streambuf : std::streambuf +{ + int_type underflow() override + { + if (c != '\0') + { + this->setg(&c, &c, &c + 1); + return *this->gptr(); + } + c = '\0'; + return traits_type::eof(); + } + +private: + char c = 'a'; +}; + +struct codecvt : std::codecvt<wchar_t, char, std::mbstate_t> { }; + +void +test01() +{ + // https://gcc.gnu.org/ml/libstdc++/2017-11/msg00022.html + streambuf sb; + std::wbuffer_convert<codecvt> conv(&sb); + VERIFY( sb.in_avail() == 0 ); + wchar_t c = conv.sgetc(); + VERIFY( c == L'a' ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc b/libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc new file mode 100644 index 00000000000..e292e13311a --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/inserters_extractors/char/59568.cc @@ -0,0 +1,191 @@ +// Copyright (C) 2017 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 +// <http://www.gnu.org/licenses/>. + +#include <complex> +#include <sstream> +#include <testsuite_hooks.h> + +void +test01() +{ + std::istringstream in(" 1 (2) ( 2.0 , 0.5 ) "); + std::complex<double> c1, c2, c3; + in >> c1 >> c2 >> c3; + VERIFY( in.good() ); + VERIFY( c1.real() == 1 && c1.imag() == 0 ); + VERIFY( c2.real() == 2 && c2.imag() == 0 ); + VERIFY( c3.real() == 2 && c3.imag() == 0.5 ); +} + +void +test02() +{ + std::istringstream in; + std::complex<double> c(-1, -1); + const std::complex<double> c0 = c; + + in.str("a"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == 'a' ); + VERIFY( c == c0 ); + + in.str(" ( ) "); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == ')' ); + VERIFY( c == c0 ); + + in.str("(,"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == ',' ); + VERIFY( c == c0 ); + + in.str("(b)"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == 'b' ); + VERIFY( c == c0 ); + + in.str("( c)"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == 'c' ); + VERIFY( c == c0 ); + + in.str("(99d"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + // VERIFY( in.get() == 'd' ); + VERIFY( c == c0 ); + + in.str("(99 e"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + // VERIFY( in.get() == 'e' ); + VERIFY( c == c0 ); + + in.str("(99, f"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == 'f' ); + VERIFY( c == c0 ); + + in.str("(99, 88g"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + // VERIFY( in.get() == 'g' ); + VERIFY( c == c0 ); + + in.str("(99, 88 h"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + // VERIFY( in.get() == 'h' ); + VERIFY( c == c0 ); + + in.str("(99, )"); + in >> c; + VERIFY( in.fail() ); + in.clear(); + VERIFY( in.get() == ')' ); + VERIFY( c == c0 ); +} + +void +test03() +{ + // PR libstdc++/59568 + std::istringstream in; + std::complex<double> c; + + in.str(""); + in >> c; + VERIFY( in.fail() ); + VERIFY( in.eof() ); + in.clear(); + + in.str(" "); + in >> c; + VERIFY( in.fail() ); + VERIFY( in.eof() ); + in.clear(); + + in.str("(99"); + in >> c; + VERIFY( in.fail() ); + VERIFY( in.eof() ); + in.clear(); + + in.str("(99,"); + in >> c; + VERIFY( in.fail() ); + VERIFY( in.eof() ); + in.clear(); + + in.str("(99,99"); + in >> c; + VERIFY( in.fail() ); + VERIFY( in.eof() ); + in.clear(); +} + +void +test04() +{ + // Test noskipws handling + std::istringstream in; + const char* bad_inputs[] = { + " 1", " (2)", "( 2)", "(2 )", "(2 ,3)", "(2,3 )", 0 + }; + const std::complex<double> c0(-1, -1); + std::complex<double> c; + for (int i = 0; bad_inputs[i]; ++i) + { + c = c0; + in.clear(); + in.str(bad_inputs[i]); + in >> std::noskipws >> c; + VERIFY( in.fail() ); + VERIFY( c == c0 ); + + in.clear(); + in.str(bad_inputs[i]); + in >> std::skipws >> c; + VERIFY( !in.fail() ); + VERIFY( c != c0 ); + } +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); +} diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/83598.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/83598.cc new file mode 100644 index 00000000000..b958dfbe42f --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/83598.cc @@ -0,0 +1,37 @@ +// Copyright (C) 2017 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 +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } + +#include <regex> +#include <testsuite_hooks.h> + +void +test01() +{ + // PR libstdc++83598 + std::regex r1(".", std::regex_constants::syntax_option_type{}); + VERIFY(r1.flags() == std::regex_constants::syntax_option_type{}); + std::regex r2(".", std::regex_constants::icase); + VERIFY(r2.flags() == std::regex_constants::icase); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/28_regex/match_results/ctors/char/default.cc b/libstdc++-v3/testsuite/28_regex/match_results/ctors/char/default.cc index 80b8bf767e5..82ae40dc219 100644 --- a/libstdc++-v3/testsuite/28_regex/match_results/ctors/char/default.cc +++ b/libstdc++-v3/testsuite/28_regex/match_results/ctors/char/default.cc @@ -32,6 +32,8 @@ void test01() std::cmatch cm; VERIFY( cm.size() == 0 ); VERIFY( !cm.ready() ); + VERIFY( cm.empty() ); + VERIFY( cm.begin() == cm.end() ); // PR libstdc++/83600 } void test02() @@ -41,6 +43,8 @@ void test02() std::smatch sm; VERIFY( sm.size() == 0 ); VERIFY( !sm.ready() ); + VERIFY( sm.empty() ); + VERIFY( sm.begin() == sm.end() ); // PR libstdc++/83600 } int diff --git a/libstdc++-v3/testsuite/28_regex/match_results/ctors/wchar_t/default.cc b/libstdc++-v3/testsuite/28_regex/match_results/ctors/wchar_t/default.cc index a4f68c1fc0d..88fe6a4f54c 100644 --- a/libstdc++-v3/testsuite/28_regex/match_results/ctors/wchar_t/default.cc +++ b/libstdc++-v3/testsuite/28_regex/match_results/ctors/wchar_t/default.cc @@ -32,6 +32,8 @@ void test01() std::wcmatch cm; VERIFY( cm.size() == 0 ); VERIFY( !cm.ready() ); + VERIFY( cm.empty() ); + VERIFY( cm.begin() == cm.end() ); // PR libstdc++/83600 } void test02() @@ -41,6 +43,8 @@ void test02() std::wsmatch sm; VERIFY( sm.size() == 0 ); VERIFY( !sm.ready() ); + VERIFY( sm.empty() ); + VERIFY( sm.begin() == sm.end() ); // PR libstdc++/83600 } int 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 9e94c4799be..dec59697163 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc @@ -28,6 +28,7 @@ void test01() { bool test __attribute__((unused)) = false; + const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); std::error_code ec; // Test non-existent path. @@ -37,15 +38,19 @@ test01() VERIFY( iter == end(iter) ); // Test empty directory. + ec = bad_ec; create_directory(p, fs::current_path(), ec); VERIFY( !ec ); + ec = bad_ec; iter = fs::recursive_directory_iterator(p, ec); VERIFY( !ec ); VERIFY( iter == end(iter) ); // Test non-empty directory. - create_directories(p / "d1/d2"); + ec = bad_ec; + create_directories(p / "d1/d2", ec); VERIFY( !ec ); + ec = bad_ec; iter = fs::recursive_directory_iterator(p, ec); VERIFY( !ec ); VERIFY( iter != end(iter) ); @@ -56,6 +61,7 @@ test01() VERIFY( iter == end(iter) ); // Test inaccessible directory. + ec = bad_ec; permissions(p, fs::perms::none, ec); VERIFY( !ec ); iter = fs::recursive_directory_iterator(p, ec); @@ -64,15 +70,19 @@ test01() // Test inaccessible directory, skipping permission denied. const auto opts = fs::directory_options::skip_permission_denied; + ec = bad_ec; iter = fs::recursive_directory_iterator(p, opts, ec); VERIFY( !ec ); VERIFY( iter == end(iter) ); // Test inaccessible sub-directory. + ec = bad_ec; permissions(p, fs::perms::owner_all, ec); VERIFY( !ec ); + ec = bad_ec; permissions(p/"d1/d2", fs::perms::none, ec); VERIFY( !ec ); + ec = bad_ec; iter = fs::recursive_directory_iterator(p, ec); VERIFY( !ec ); VERIFY( iter != end(iter) ); @@ -84,12 +94,14 @@ test01() VERIFY( iter == end(iter) ); // Test inaccessible sub-directory, skipping permission denied. + ec = bad_ec; iter = fs::recursive_directory_iterator(p, opts, ec); VERIFY( !ec ); VERIFY( iter != end(iter) ); VERIFY( iter->path() == p/"d1" ); ++iter; // should recurse into d1 VERIFY( iter->path() == p/"d1/d2" ); + ec = bad_ec; iter.increment(ec); // should fail to recurse into p/d1/d2, so skip it VERIFY( !ec ); VERIFY( iter == end(iter) ); @@ -103,12 +115,15 @@ test02() { bool test __attribute__((unused)) = false; + const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); std::error_code ec; const auto p = __gnu_test::nonexistent_path(); + ec = bad_ec; create_directories(p / "d1/d2", ec); VERIFY( !ec ); // Test post-increment (libstdc++/71005) + ec = bad_ec; auto iter = fs::recursive_directory_iterator(p, ec); VERIFY( !ec ); VERIFY( iter != end(iter) ); @@ -130,7 +145,7 @@ test03() { bool test __attribute__((unused)) = false; - std::error_code ec; + std::error_code ec = make_error_code(std::errc::invalid_argument); const auto p = __gnu_test::nonexistent_path(); create_directories(p / "longer_than_small_string_buffer", ec); VERIFY( !ec ); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc index 66c2b3fb796..eae60a05bd4 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directory.cc @@ -50,7 +50,6 @@ test01() VERIFY( !ec ); VERIFY( !b ); b = create_directory(p); - VERIFY( !ec ); VERIFY( !b ); remove_all(p, ec); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/remove.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/remove.cc new file mode 100644 index 00000000000..7c098b4864b --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/remove.cc @@ -0,0 +1,100 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +// { dg-options "-lstdc++fs" } +// { dg-do run { target c++11 } } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + std::error_code ec; + const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); + bool n; + + n = fs::remove("", ec); + VERIFY( !ec ); // This seems odd, but is what the standard requires. + VERIFY( !n ); + + auto p = __gnu_test::nonexistent_path(); + ec = bad_ec; + n = remove(p, ec); + VERIFY( !ec ); + VERIFY( !n ); + + auto link = __gnu_test::nonexistent_path(); + create_symlink(p, link); // dangling symlink + ec = bad_ec; + n = remove(link, ec); + VERIFY( !ec ); + VERIFY( n ); + VERIFY( !exists(symlink_status(link)) ); + + __gnu_test::scoped_file f(p); + create_symlink(p, link); + ec = bad_ec; + n = remove(link, ec); + VERIFY( !ec ); + VERIFY( n ); + VERIFY( !exists(symlink_status(link)) ); // The symlink is removed, but + VERIFY( exists(p) ); // its target is not. + + ec = bad_ec; + n = remove(p, ec); + VERIFY( !ec ); + VERIFY( n ); + VERIFY( !exists(symlink_status(p)) ); + + const auto dir = __gnu_test::nonexistent_path(); + create_directories(dir/"a/b"); + ec.clear(); + n = remove(dir/"a", ec); + VERIFY( ec ); + VERIFY( !n ); + VERIFY( exists(dir/"a/b") ); + + permissions(dir, fs::perms::none, ec); + if (!ec) + { + ec.clear(); + n = remove(dir/"a/b", ec); + VERIFY( ec ); + VERIFY( !n ); + permissions(dir, fs::perms::owner_all, ec); + } + + ec = bad_ec; + n = remove(dir/"a/b", ec); + VERIFY( !ec ); + VERIFY( n ); + VERIFY( !exists(dir/"a/b") ); + + remove(dir/"a", ec); + remove(dir, ec); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/remove_all.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/remove_all.cc index 57d15af9c5c..67f6e989d27 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/remove_all.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/remove_all.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Free Software Foundation, Inc. +// Copyright (C) 2016-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 @@ -29,19 +29,19 @@ void test01() { std::error_code ec; + const std::error_code bad_ec = make_error_code(std::errc::invalid_argument); std::uintmax_t n; n = fs::remove_all("", ec); - VERIFY( ec ); - VERIFY( n == std::uintmax_t(-1) ); + VERIFY( !ec ); // This seems odd, but is what the TS requires. + VERIFY( n == 0 ); auto p = __gnu_test::nonexistent_path(); - ec.clear(); + ec = bad_ec; n = remove_all(p, ec); - VERIFY( ec ); - VERIFY( n == std::uintmax_t(-1) ); + VERIFY( !ec ); + VERIFY( n == 0 ); - const auto bad_ec = ec; auto link = __gnu_test::nonexistent_path(); create_symlink(p, link); // dangling symlink ec = bad_ec; @@ -59,7 +59,7 @@ test01() VERIFY( !exists(symlink_status(link)) ); // The symlink is removed, but VERIFY( exists(p) ); // its target is not. - auto dir = __gnu_test::nonexistent_path(); + const auto dir = __gnu_test::nonexistent_path(); create_directories(dir/"a/b/c"); ec = bad_ec; n = remove_all(dir/"a", ec); @@ -85,8 +85,28 @@ test01() b2.path.clear(); } +void +test02() +{ + const auto dir = __gnu_test::nonexistent_path(); + create_directories(dir/"a/b/c"); + std::uintmax_t n = remove_all(dir/"a"); + VERIFY( n == 3 ); + VERIFY( exists(dir) ); + VERIFY( !exists(dir/"a") ); + + n = remove_all(dir/"a"); + VERIFY( n == 0 ); + VERIFY( exists(dir) ); + + n = remove_all(dir); + VERIFY( n == 1 ); + VERIFY( !exists(dir) ); +} + int main() { test01(); + test02(); } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc index 23d4b9c4ab3..06c48cb2020 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc @@ -44,7 +44,7 @@ test01() if (!fs::exists("/tmp")) return; // just give up - std::error_code ec; + std::error_code ec = make_error_code(std::errc::invalid_argument); fs::path p1 = fs::temp_directory_path(ec); VERIFY( !ec ); VERIFY( exists(p1) ); |