From 874111587212182c588aafd083505af417165a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Schu=CC=88mann?= Date: Fri, 10 Jul 2026 17:01:36 +0200 Subject: [PATCH] Allow iteration while exceptions are disabled and reactivate `proximate(...)` for that case --- CMakeLists.txt | 5 +-- include/ghc/filesystem.hpp | 23 +++++-------- test/CMakeLists.txt | 6 +++- test/exception.cpp | 67 +++++++++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de97dd9..937b634 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.7.2) -project( - ghcfilesystem, - VERSION 1.5.15 -) +project(ghcfilesystem VERSION 1.5.15) if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index 1b292c2..985472b 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -181,6 +181,7 @@ #include #include #include +#include #include #include #include @@ -932,20 +933,16 @@ public: directory_iterator& operator=(directory_iterator&& rhs) noexcept; const directory_entry& operator*() const; const directory_entry* operator->() const; -#ifdef GHC_WITH_EXCEPTIONS directory_iterator& operator++(); -#endif directory_iterator& increment(std::error_code& ec) noexcept; // other members as required by [input.iterators] -#ifdef GHC_WITH_EXCEPTIONS proxy operator++(int) { proxy p{**this}; ++*this; return p; } -#endif bool operator==(const directory_iterator& rhs) const; bool operator!=(const directory_iterator& rhs) const; @@ -992,9 +989,7 @@ public: // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator& recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs); recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept; -#ifdef GHC_WITH_EXCEPTIONS recursive_directory_iterator& operator++(); -#endif recursive_directory_iterator& increment(std::error_code& ec) noexcept; #ifdef GHC_WITH_EXCEPTIONS @@ -1004,14 +999,12 @@ public: void disable_recursion_pending(); // other members as required by [input.iterators] -#ifdef GHC_WITH_EXCEPTIONS directory_iterator::proxy operator++(int) { directory_iterator::proxy proxy{**this}; ++*this; return proxy; } -#endif bool operator==(const recursive_directory_iterator& rhs) const; bool operator!=(const recursive_directory_iterator& rhs) const; @@ -4751,7 +4744,6 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e #endif } -#ifdef GHC_WITH_EXCEPTIONS GHC_INLINE path proximate(const path& p, std::error_code& ec) { auto cp = current_path(ec); @@ -4760,7 +4752,6 @@ GHC_INLINE path proximate(const path& p, std::error_code& ec) } return path(); } -#endif #ifdef GHC_WITH_EXCEPTIONS GHC_INLINE path proximate(const path& p, const path& base) @@ -5860,17 +5851,19 @@ GHC_INLINE const directory_entry* directory_iterator::operator->() const return &_impl->_dir_entry; } -#ifdef GHC_WITH_EXCEPTIONS GHC_INLINE directory_iterator& directory_iterator::operator++() { std::error_code ec; _impl->increment(ec); if (ec) { +#ifdef GHC_WITH_EXCEPTIONS throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_entry._path, ec); +#else + std::terminate(); +#endif } return *this; } -#endif GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec) noexcept { @@ -5986,17 +5979,19 @@ GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator= return *this; } -#ifdef GHC_WITH_EXCEPTIONS GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator++() { std::error_code ec; increment(ec); if (ec) { +#ifdef GHC_WITH_EXCEPTIONS throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec); +#else + std::terminate(); +#endif } return *this; } -#endif GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1401ef0..48bd2d2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -98,8 +98,12 @@ endif() add_test(fwd_impl_test fwd_impl_test) add_executable(exception exception.cpp) -if(NOT MSVC) +if(MSVC) + target_compile_options(exception PRIVATE /EHs-c-) + target_compile_definitions(exception PRIVATE _HAS_EXCEPTIONS=0) +else() target_compile_options(exception PRIVATE -fno-exceptions) endif() target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) SetTestCompileOptions(exception) +add_test(NAME no_exception_test COMMAND exception "${CMAKE_CURRENT_SOURCE_DIR}/exception.cpp") diff --git a/test/exception.cpp b/test/exception.cpp index 8d8b745..de13bc2 100644 --- a/test/exception.cpp +++ b/test/exception.cpp @@ -1,5 +1,70 @@ #include -int main() { +#ifdef GHC_WITH_EXCEPTIONS +#error "This test must be compiled without exception support" +#endif + +int main(int argc, char** argv) +{ + namespace fs = ghc::filesystem; + + if (argc != 2) { + return 1; + } + + const fs::path regular_file(argv[1]); + const fs::path test_directory = regular_file.parent_path(); + std::error_code ec; + const fs::path proximate = fs::proximate(test_directory, ec); + if (ec || proximate.empty()) { + return 2; + } + + fs::directory_iterator invalid_iter(regular_file, ec); + if (!ec || invalid_iter != fs::directory_iterator()) { + return 3; + } + + ec.clear(); + fs::recursive_directory_iterator invalid_recursive_iter(regular_file, ec); + if (!ec || invalid_recursive_iter != fs::recursive_directory_iterator()) { + return 4; + } + + ec.clear(); + fs::directory_iterator iter(test_directory, ec); + if (ec) { + return 5; + } + if (iter != fs::directory_iterator()) { + iter++; + } + for (; iter != fs::directory_iterator(); ++iter) { + } + + for (const auto& entry : fs::directory_iterator(test_directory, ec)) { + (void)entry; + } + if (ec) { + return 6; + } + + fs::recursive_directory_iterator recursive_iter(test_directory, ec); + if (ec) { + return 7; + } + if (recursive_iter != fs::recursive_directory_iterator()) { + recursive_iter++; + } + for (; recursive_iter != fs::recursive_directory_iterator(); ++recursive_iter) { + } + + for (const auto& entry : fs::recursive_directory_iterator(test_directory, ec)) { + (void)entry; + } + if (ec) { + return 8; + } + return 0; }