From 9e4eb59e9ce57775cf083608bf00db6ebde6eb67 Mon Sep 17 00:00:00 2001 From: Steffen Schuemann Date: Sat, 3 Nov 2018 11:15:18 +0100 Subject: [PATCH] Some cleanup, and warning fixes and test code issues on clang 7. --- README.md | 4 ++++ examples/CMakeLists.txt | 4 ++++ examples/dir.cpp | 3 ++- filesystem.h | 24 ++++++++++++++++++------ test/CMakeLists.txt | 6 ++++-- test/filesystem_test.cpp | 23 ++++++++++++++++++++++- 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 16c5d65..0c1f8e0 100644 --- a/README.md +++ b/README.md @@ -360,6 +360,10 @@ to the expected behavior. * Starting with this version, only even patch level versions will be tagged and odd patch levels mark in-between non-stable wip states. * Tests can now also be run against MS version of std::filesystem for comparison. +* Added missing `fstream` include. +* Removed non-conforming C99 `timespec`/`timeval` usage. +* Fixed some integer type mismatches that could lead to warnings. +* Fixed `chrono` conversion issues in test and example on clang 7.0.0. ### [v1.0.1](https://github.com/gulrak/filesystem/tree/v1.0.1) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 66a95b1..cc0eeeb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,6 +5,10 @@ if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)) + if(APPLE) + include_directories(/usr/local/opt/llvm/include) + link_directories(/usr/local/opt/llvm/lib) + endif() add_executable(std_fs_dir dir.cpp) set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17) target_link_libraries(std_fs_dir -lc++fs) diff --git a/examples/dir.cpp b/examples/dir.cpp index 380f75c..a03790c 100644 --- a/examples/dir.cpp +++ b/examples/dir.cpp @@ -14,7 +14,8 @@ template std::time_t to_time_t(TP tp) { // Based on trick from: Nico Josuttis, C++17 - The Complete Guide - return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + (tp - TP::clock::now())); + std::chrono::system_clock::duration dt = std::chrono::duration_cast(tp - TP::clock::now()); + return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + dt); } static std::string perm_to_str(fs::perms prms) diff --git a/filesystem.h b/filesystem.h index 47ecf9e..250ad0f 100644 --- a/filesystem.h +++ b/filesystem.h @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -1094,7 +1095,7 @@ static inline unsigned consumeUtf8Fragment(const unsigned state, const uint8_t f { uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf; codepoint = (state ? (codepoint << 6) | (fragment & 0x3f) : (0xff >> category) & fragment); - return state == S_RJCT ? S_RJCT : (utf8_state_info[category + 16] >> (state << 2)) & 0xf; + return state == S_RJCT ? static_cast(S_RJCT) : static_cast((utf8_state_info[category + 16] >> (state << 2)) & 0xf); } template @@ -1463,7 +1464,7 @@ inline path resolveSymlink(const path& p, std::error_code& ec) ec = std::error_code(errno, std::system_category()); return path(); } - else if (rc < bufferSize) { + else if (rc < static_cast(bufferSize)) { return path(std::string(buffer.data(), rc)); } bufferSize *= 2; @@ -3481,8 +3482,11 @@ inline void last_write_time(const path& p, file_time_type new_time, std::error_c #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300 struct ::stat fs; if (::stat(p.c_str(), &fs) == 0) { - struct ::timeval tv[2] = {{.tv_sec = fs.st_atimespec.tv_sec, .tv_usec = static_cast(fs.st_atimespec.tv_nsec / 1000)}, - {.tv_sec = std::chrono::duration_cast(d).count(), .tv_usec = static_cast(std::chrono::duration_cast(d).count() % 1000000)}}; + struct ::timeval tv[2]; + tv[0].tv_sec = fs.st_atimespec.tv_sec; + tv[0].tv_usec = static_cast(fs.st_atimespec.tv_nsec / 1000); + tv[1].tv_sec = std::chrono::duration_cast(d).count(); + tv[1].tv_usec = static_cast(std::chrono::duration_cast(d).count() % 1000000); if (::utimes(p.c_str(), tv) == 0) { return; } @@ -3490,7 +3494,11 @@ inline void last_write_time(const path& p, file_time_type new_time, std::error_c ec = std::error_code(errno, std::system_category()); return; #else - struct ::timespec times[2] = {{.tv_nsec = UTIME_OMIT}, {.tv_sec = std::chrono::duration_cast(d).count(), .tv_nsec = std::chrono::duration_cast(d).count() % 1000000000}}; + struct ::timespec times[2]; + times[0].tv_sec = 0; + times[0].tv_nsec = UTIME_OMIT; + times[1].tv_sec = std::chrono::duration_cast(d).count(); + times[1].tv_nsec = std::chrono::duration_cast(d).count() % 1000000000; if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { ec = std::error_code(errno, std::system_category()); } @@ -3498,7 +3506,11 @@ inline void last_write_time(const path& p, file_time_type new_time, std::error_c #endif #endif #else - struct ::timespec times[2] = {{.tv_sec = 0, .tv_nsec = UTIME_OMIT}, {.tv_sec = std::chrono::duration_cast(d).count(), .tv_nsec = std::chrono::duration_cast(d).count() % 1000000000}}; + struct ::timespec times[2]; + times[0].tv_sec = 0; + times[0].tv_nsec = UTIME_OMIT; + times[1].tv_sec = std::chrono::duration_cast(d).count(); + times[1].tv_nsec = std::chrono::duration_cast(d).count() % 1000000000; if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { ec = std::error_code(errno, std::system_category()); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ae1b4a0..77b8aa4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,8 +7,10 @@ if(CMAKE_GENERATOR STREQUAL Xcode) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)) - include_directories(/usr/local/opt/llvm/include) - link_directories(/usr/local/opt/llvm/lib) + if(APPLE) + include_directories(/usr/local/opt/llvm/include) + link_directories(/usr/local/opt/llvm/lib) + endif() add_executable(std_filesystem_test filesystem_test.cpp ../filesystem.h catch.hpp) set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17) target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS) diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index a4fcd2b..58b222c 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -77,6 +77,14 @@ using fstream = ghc::filesystem::fstream; //#define TEST_LWG_2935_BEHAVIOUR #define TEST_LWG_2937_BEHAVIOUR +template +std::time_t to_time_t(TP tp) +{ + // Based on trick from: Nico Josuttis, C++17 - The Complete Guide + std::chrono::system_clock::duration dt = std::chrono::duration_cast(tp - TP::clock::now()); + return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + dt); +} + namespace Catch { template <> struct StringMaker @@ -89,6 +97,18 @@ struct StringMaker { static std::string convert(fs::perms const& value) { return std::to_string(static_cast(value)); } }; + +template <> +struct StringMaker +{ + static std::string convert(fs::file_time_type const& value) { + std::time_t t = to_time_t(value); + std::tm ttm = *std::localtime(&t); + std::ostringstream os; + os << std::put_time(&ttm, "%Y-%m-%d %H:%M:%S"); + return os.str(); + } +}; } // namespace Catch enum class TempOpt { none, change_path }; @@ -1858,7 +1878,8 @@ TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_wr CHECK(std::abs(std::chrono::duration_cast(fs::last_write_time("foo") - now).count()) < 3); CHECK_THROWS_AS(fs::last_write_time("bar"), fs::filesystem_error); CHECK_NOTHROW(ft = fs::last_write_time("bar", ec)); - CHECK(ft == fs::file_time_type::min()); + bool equal = (ft == fs::file_time_type::min()); + CHECK(equal); // Workaround a problem in catch with clang 7 and time_points. CHECK(ec); ec.clear(); if (is_symlink_creation_supported()) {