Project

General

Profile

Actions

Bug #14431

open

Compilation (still) fails with C++17 filesystem and Clang in C++20 mode (or higher)

Added by Erik Solem 7 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
03/25/2026
Due date:
% Done:

0%

Estimated time:

Description

First reported as #14352, but the chosen solution does not actually solve the problem, only a rounding issue mentioned as part of the report.

I suggested a reduction of lines 71–83 in src/web/FileUtils.C to:

#ifdef WT_FILESYSTEM_IMPL_STD
      auto ftime = Wt::cpp17::filesystem::last_write_time(file);
      auto systime = decltype(ftime)::clock::to_sys(ftime);
      return std::chrono::time_point_cast<std::chrono::system_clock::duration>(systime);
#else // !WT_FILESYSTEM_IMPL_STD
      return std::chrono::system_clock::from_time_t(Wt::cpp17::filesystem::last_write_time(file));
#endif // WT_FILESYSTEM_IMPL_STD

In my suggestion I pointed out that time_point_cast is a C++11 feature, but I missed that file_clock::to_sys is a C++20 feature, so I acknowledge the need for the WT_FILESYSTEM_IMPL_STD_CLOCK_17 macro to stay.

The relevant block of code is now lines 71–81 and looks like this:

#ifdef WT_FILESYSTEM_IMPL_STD
  #ifndef WT_FILESYSTEM_IMPL_STD_CLOCK_17
      return std::chrono::clock_cast<std::chrono::system_clock>(Wt::cpp17::filesystem::last_write_time(file));
  #else // WT_FILESYSTEM_IMPL_STD_CLOCK_17
      LOG_DEBUG("When using cpp17 or lower with std::filesystem, the result of this function is an approximation. Use boost::filesystem, instead of std::filesystem (see WT_CPP17_FILESYSTEM_IMPLEMENTATION) if this is a problem for your application.");
      auto ftime = Wt::cpp17::filesystem::last_write_time(file);
      return std::chrono::time_point_cast<std::chrono::system_clock::duration>(ftime - Wt::cpp17::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
  #endif //WT_FILESYSTEM_IMPL_STD_CLOCK_17
#else // !WT_FILESYSTEM_IMPL_STD
      return std::chrono::system_clock::from_time_t(Wt::cpp17::filesystem::last_write_time(file));
#endif // WT_FILESYSTEM_IMPL_STD

The problem is that Clang/libc++ lacks clock_cast (even in the recently released LLVM/Clang 22). I think that clock_cast represents an improvement per se, but since it does not work with Clang, the problem is not at all gone. Therefore I would like to suggest a slightly different solution this time:

#ifdef WT_FILESYSTEM_IMPL_STD
  #ifndef WT_FILESYSTEM_IMPL_STD_CLOCK_17
    #if __cpp_lib_chrono >= 201803L
        return std::chrono::clock_cast<std::chrono::system_clock>(Wt::cpp17::filesystem::last_write_time(file));
    #else
        auto ftime = Wt::cpp17::filesystem::last_write_time(file);
        auto systime = decltype(ftime)::clock::to_sys(ftime);
        return std::chrono::time_point_cast<std::chrono::system_clock::duration>(systime);
    #endif
  #else // WT_FILESYSTEM_IMPL_STD_CLOCK_17
      LOG_DEBUG("When using cpp17 or lower with std::filesystem, the result of this function is an approximation. Use boost::filesystem, instead of std::filesystem (see WT_CPP17_FILESYSTEM_IMPLEMENTATION) if this is a problem for your application.");
      auto ftime = Wt::cpp17::filesystem::last_write_time(file);
      return std::chrono::time_point_cast<std::chrono::system_clock::duration>(ftime - Wt::cpp17::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
  #endif //WT_FILESYSTEM_IMPL_STD_CLOCK_17
#else // !WT_FILESYSTEM_IMPL_STD
      return std::chrono::system_clock::from_time_t(Wt::cpp17::filesystem::last_write_time(file));
#endif // WT_FILESYSTEM_IMPL_STD

That is, inside the #ifndef WT_FILESYSTEM_IMPL_STD_CLOCK_17 block, use clock_cast if it is available (using the feature test macro __cpp_lib_chrono) and fall back on time_point_cast with the code modification I suggested if it is not.

The __cpp_lib_chrono macro will have the value 201803L or higher if and only if the standard library implements P0355R7 (that is where clock_cast came in) in full. As mentioned, libc++ does not do that, and thus we can see in libcxx/include/version (line 60) of libc++ on the main branch of the llvm-project repo that __cpp_lib_chrono is defined to 201611L.

No data to display

Actions

Also available in: Atom PDF