Implement LWG 3013 - some filesystem members should not be noexcept.

LWG 3013 points out that the constructors and increment members
of the directory iterators need to allocate, and therefore cannot
be marked noexcept.

It also points out that `is_empty` and `copy` likely need to allocate
as well, and as such can also not be noexcept.

This patch speculatively implements the resolution removing noexcept,
because libc++ does indeed have the possibility of throwing on allocation
failure.

llvm-svn: 316941
This commit is contained in:
Eric Fiselier 2017-10-30 18:59:59 +00:00
parent b81fbf44c7
commit ddfdb32b30
7 changed files with 43 additions and 32 deletions

View File

@ -81,10 +81,10 @@
path canonical(const path& p, const path& base, error_code& ec); path canonical(const path& p, const path& base, error_code& ec);
void copy(const path& from, const path& to); void copy(const path& from, const path& to);
void copy(const path& from, const path& to, error_code& ec) _NOEXCEPT; void copy(const path& from, const path& to, error_code& ec);
void copy(const path& from, const path& to, copy_options options); void copy(const path& from, const path& to, copy_options options);
void copy(const path& from, const path& to, copy_options options, void copy(const path& from, const path& to, copy_options options,
error_code& ec) _NOEXCEPT; error_code& ec);
bool copy_file(const path& from, const path& to); bool copy_file(const path& from, const path& to);
bool copy_file(const path& from, const path& to, error_code& ec) _NOEXCEPT; bool copy_file(const path& from, const path& to, error_code& ec) _NOEXCEPT;
@ -1351,7 +1351,7 @@ void copy(const path& __from, const path& __to) {
} }
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
void copy(const path& __from, const path& __to, error_code& __ec) _NOEXCEPT { void copy(const path& __from, const path& __to, error_code& __ec) {
__copy(__from, __to, copy_options::none, &__ec); __copy(__from, __to, copy_options::none, &__ec);
} }
@ -1362,7 +1362,7 @@ void copy(const path& __from, const path& __to, copy_options __opt) {
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
void copy(const path& __from, const path& __to, void copy(const path& __from, const path& __to,
copy_options __opt, error_code& __ec) _NOEXCEPT { copy_options __opt, error_code& __ec) {
__copy(__from, __to, __opt, &__ec); __copy(__from, __to, __opt, &__ec);
} }
@ -1561,7 +1561,7 @@ bool is_empty(const path& __p) {
} }
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
bool is_empty(const path& __p, error_code& __ec) _NOEXCEPT { bool is_empty(const path& __p, error_code& __ec) {
return __fs_is_empty(__p, &__ec); return __fs_is_empty(__p, &__ec);
} }
@ -1903,12 +1903,12 @@ public:
: directory_iterator(__p, nullptr, __opts) : directory_iterator(__p, nullptr, __opts)
{ } { }
directory_iterator(const path& __p, error_code& __ec) _NOEXCEPT directory_iterator(const path& __p, error_code& __ec)
: directory_iterator(__p, &__ec) : directory_iterator(__p, &__ec)
{ } { }
directory_iterator(const path& __p, directory_options __opts, directory_iterator(const path& __p, directory_options __opts,
error_code& __ec) _NOEXCEPT error_code& __ec)
: directory_iterator(__p, &__ec, __opts) : directory_iterator(__p, &__ec, __opts)
{ } { }
@ -1943,7 +1943,7 @@ public:
return __p; return __p;
} }
directory_iterator& increment(error_code& __ec) _NOEXCEPT directory_iterator& increment(error_code& __ec)
{ return __increment(&__ec); } { return __increment(&__ec); }
private: private:
@ -2013,12 +2013,12 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
recursive_directory_iterator(const path& __p, recursive_directory_iterator(const path& __p,
directory_options __xoptions, error_code& __ec) _NOEXCEPT directory_options __xoptions, error_code& __ec)
: recursive_directory_iterator(__p, __xoptions, &__ec) : recursive_directory_iterator(__p, __xoptions, &__ec)
{ } { }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
recursive_directory_iterator(const path& __p, error_code& __ec) _NOEXCEPT recursive_directory_iterator(const path& __p, error_code& __ec)
: recursive_directory_iterator(__p, directory_options::none, &__ec) : recursive_directory_iterator(__p, directory_options::none, &__ec)
{ } { }
@ -2060,7 +2060,7 @@ public:
} }
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
recursive_directory_iterator& increment(error_code& __ec) _NOEXCEPT recursive_directory_iterator& increment(error_code& __ec)
{ return __increment(&__ec); } { return __increment(&__ec); }
_LIBCPP_FUNC_VIS directory_options options() const; _LIBCPP_FUNC_VIS directory_options options() const;

View File

@ -15,8 +15,8 @@
// explicit directory_iterator(const path& p); // explicit directory_iterator(const path& p);
// directory_iterator(const path& p, directory_options options); // directory_iterator(const path& p, directory_options options);
// directory_iterator(const path& p, error_code& ec) noexcept; // directory_iterator(const path& p, error_code& ec);
// directory_iterator(const path& p, directory_options options, error_code& ec) noexcept; // directory_iterator(const path& p, directory_options options, error_code& ec);
#include <experimental/filesystem> #include <experimental/filesystem>
#include <type_traits> #include <type_traits>
@ -40,15 +40,22 @@ TEST_CASE(test_constructor_signatures)
static_assert(std::is_constructible<D, path>::value, ""); static_assert(std::is_constructible<D, path>::value, "");
static_assert(!std::is_nothrow_constructible<D, path>::value, ""); static_assert(!std::is_nothrow_constructible<D, path>::value, "");
// directory_iterator(path const&, error_code&) noexcept // directory_iterator(path const&, error_code&)
static_assert(std::is_nothrow_constructible<D, path, std::error_code&>::value, ""); static_assert(std::is_constructible<D, path,
std::error_code&>::value, "");
static_assert(!std::is_nothrow_constructible<D, path,
std::error_code&>::value, "");
// directory_iterator(path const&, directory_options); // directory_iterator(path const&, directory_options);
static_assert(std::is_constructible<D, path, directory_options>::value, ""); static_assert(std::is_constructible<D, path, directory_options>::value, "");
static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, ""); static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
// directory_iterator(path const&, directory_options, error_code&) noexcept // directory_iterator(path const&, directory_options, error_code&)
static_assert(std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, ""); static_assert(std::is_constructible<D, path, directory_options,
std::error_code&>::value, "");
static_assert(!std::is_nothrow_constructible<D, path, directory_options,
std::error_code&>::value, "");
} }
TEST_CASE(test_construction_from_bad_path) TEST_CASE(test_construction_from_bad_path)

View File

@ -14,7 +14,7 @@
// class directory_iterator // class directory_iterator
// directory_iterator& operator++(); // directory_iterator& operator++();
// directory_iterator& increment(error_code& ec) noexcept; // directory_iterator& increment(error_code& ec);
#include <experimental/filesystem> #include <experimental/filesystem>
#include <type_traits> #include <type_traits>
@ -40,7 +40,7 @@ TEST_CASE(test_increment_signatures)
ASSERT_NOT_NOEXCEPT(++d); ASSERT_NOT_NOEXCEPT(++d);
ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&); ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&);
ASSERT_NOEXCEPT(d.increment(ec)); ASSERT_NOT_NOEXCEPT(d.increment(ec));
} }
TEST_CASE(test_prefix_increment) TEST_CASE(test_prefix_increment)

View File

@ -16,8 +16,8 @@
// //
// explicit recursive_directory_iterator(const path& p); // explicit recursive_directory_iterator(const path& p);
// recursive_directory_iterator(const path& p, directory_options options); // recursive_directory_iterator(const path& p, directory_options options);
// recursive_directory_iterator(const path& p, error_code& ec) noexcept; // recursive_directory_iterator(const path& p, error_code& ec);
// recursive_directory_iterator(const path& p, directory_options options, error_code& ec) noexcept; // recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
#include <experimental/filesystem> #include <experimental/filesystem>
@ -44,15 +44,19 @@ TEST_CASE(test_constructor_signatures)
static_assert(std::is_constructible<D, path>::value, ""); static_assert(std::is_constructible<D, path>::value, "");
static_assert(!std::is_nothrow_constructible<D, path>::value, ""); static_assert(!std::is_nothrow_constructible<D, path>::value, "");
// directory_iterator(path const&, error_code&) noexcept // directory_iterator(path const&, error_code&)
static_assert(std::is_nothrow_constructible<D, path, std::error_code&>::value, ""); static_assert(std::is_constructible<D, path,
std::error_code&>::value, "");
static_assert(!std::is_nothrow_constructible<D, path,
std::error_code&>::value, "");
// directory_iterator(path const&, directory_options); // directory_iterator(path const&, directory_options);
static_assert(std::is_constructible<D, path, directory_options>::value, ""); static_assert(std::is_constructible<D, path, directory_options>::value, "");
static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, ""); static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
// directory_iterator(path const&, directory_options, error_code&) noexcept // directory_iterator(path const&, directory_options, error_code&)
static_assert(std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, ""); static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, "");
static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, "");
} }
TEST_CASE(test_construction_from_bad_path) TEST_CASE(test_construction_from_bad_path)

View File

@ -40,7 +40,7 @@ TEST_CASE(test_increment_signatures)
ASSERT_NOT_NOEXCEPT(++d); ASSERT_NOT_NOEXCEPT(++d);
ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&); ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
ASSERT_NOEXCEPT(d.increment(ec)); ASSERT_NOT_NOEXCEPT(d.increment(ec));
} }
TEST_CASE(test_prefix_increment) TEST_CASE(test_prefix_increment)

View File

@ -12,10 +12,10 @@
// <experimental/filesystem> // <experimental/filesystem>
// void copy(const path& from, const path& to); // void copy(const path& from, const path& to);
// void copy(const path& from, const path& to, error_code& ec) noexcept; // void copy(const path& from, const path& to, error_code& ec);
// void copy(const path& from, const path& to, copy_options options); // void copy(const path& from, const path& to, copy_options options);
// void copy(const path& from, const path& to, copy_options options, // void copy(const path& from, const path& to, copy_options options,
// error_code& ec) noexcept; // error_code& ec);
#include <experimental/filesystem> #include <experimental/filesystem>
#include <type_traits> #include <type_traits>
@ -39,9 +39,9 @@ TEST_CASE(signature_test)
std::error_code ec; ((void)ec); std::error_code ec; ((void)ec);
const copy_options opts{}; ((void)opts); const copy_options opts{}; ((void)opts);
ASSERT_NOT_NOEXCEPT(fs::copy(p, p)); ASSERT_NOT_NOEXCEPT(fs::copy(p, p));
ASSERT_NOEXCEPT(fs::copy(p, p, ec)); ASSERT_NOT_NOEXCEPT(fs::copy(p, p, ec));
ASSERT_NOT_NOEXCEPT(copy(p, p, opts)); ASSERT_NOT_NOEXCEPT(copy(p, p, opts));
ASSERT_NOEXCEPT(copy(p, p, opts, ec)); ASSERT_NOT_NOEXCEPT(copy(p, p, opts, ec));
} }
// There are 4 cases is the proposal for absolute path. // There are 4 cases is the proposal for absolute path.

View File

@ -12,7 +12,7 @@
// <experimental/filesystem> // <experimental/filesystem>
// bool is_empty(path const& p); // bool is_empty(path const& p);
// bool is_empty(path const& p, std::error_code& ec) noexcept; // bool is_empty(path const& p, std::error_code& ec);
#include <experimental/filesystem> #include <experimental/filesystem>
#include <type_traits> #include <type_traits>
@ -30,7 +30,7 @@ TEST_CASE(signature_test)
{ {
const path p; ((void)p); const path p; ((void)p);
std::error_code ec; ((void)ec); std::error_code ec; ((void)ec);
ASSERT_NOEXCEPT(is_empty(p, ec)); ASSERT_NOT_NOEXCEPT(is_empty(p, ec));
ASSERT_NOT_NOEXCEPT(is_empty(p)); ASSERT_NOT_NOEXCEPT(is_empty(p));
} }