Commit Graph

16 Commits

Author SHA1 Message Date
Eric Fiselier
a0866c5fb5 Implement <filesystem>
This patch implements the <filesystem> header and uses that
to provide <experimental/filesystem>.

Unlike other standard headers, the symbols needed for <filesystem>
have not yet been placed in libc++.so. Instead they live in the
new libc++fs.a library. Users of filesystem are required to link this
library. (Also note that libc++experimental no longer contains the
definition of <experimental/filesystem>, which now requires linking libc++fs).

The reason for keeping <filesystem> out of the dylib for now is that
it's still somewhat experimental, and the possibility of requiring an
ABI breaking change is very real. In the future the symbols will likely
be moved into the dylib, or the dylib will be made to link libc++fs automagically).

Note that moving the symbols out of libc++experimental may break user builds
until they update to -lc++fs. This should be OK, because the experimental
library provides no stability guarantees. However, I plan on looking into
ways we can force libc++experimental to automagically link libc++fs.

In order to use a single implementation and set of tests for <filesystem>, it
has been placed in a special `__fs` namespace. This namespace is inline in
C++17 onward, but not before that. As such implementation is available
in C++11 onward, but no filesystem namespace is present "directly", and
as such name conflicts shouldn't occur in C++11 or C++14.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338093 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-27 03:07:09 +00:00
Eric Fiselier
98e53227eb Work around GCC bug in constexpr function
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337976 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-25 22:21:47 +00:00
Eric Fiselier
81872e95bf [libc++] Use __int128_t to represent file_time_type.
Summary:
The ``file_time_type`` time point is used to represent the write times for files.
Its job is to act as part of a C++ wrapper for less ideal system interfaces. The
underlying filesystem uses the ``timespec`` struct for the same purpose.

However, the initial implementation of ``file_time_type`` could not represent
either the range or resolution of ``timespec``, making it unsuitable. Fixing
this requires an implementation which uses more than 64 bits to store the
time point.

I primarily considered two solutions: Using ``__int128_t`` and using a
arithmetic emulation of ``timespec``. Each has its pros and cons, and both
come with more than one complication.

However, after a lot of consideration, I decided on using `__int128_t`. This patch implements that change.

Please see the [FileTimeType Design Document](http://libcxx.llvm.org/docs/DesignDocs/FileTimeType.html) for more information.

Reviewers: mclow.lists, ldionne, joerg, arthur.j.odwyer, EricWF

Reviewed By: EricWF

Subscribers: christof, K-ballo, cfe-commits, BillyONeal

Differential Revision: https://reviews.llvm.org/D49774

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337960 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-25 20:51:49 +00:00
Eric Fiselier
0ddb77a467 Implement filesystem_error::what() and improve reporting.
This patch implements the `what()` for filesystem errors. The message
includes the 'what_arg', any paths that were specified, and the
error code message.

Additionally this patch refactors how errors are created, making it easier
to report them correctly.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337664 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-23 02:00:52 +00:00
Eric Fiselier
77c9cf44e3 Fix two test failures in <experimental/filesystem>
First, <experimental/filesystem> didn't correctly guard
against min/max macros. This adds the proper push/pop macro guards.

Second, an internal time helper had been renamed but the test for
it hadn't been updated. This patch updates those tests.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337520 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-20 01:51:48 +00:00
Eric Fiselier
e274f439c6 [libc++] Implement Directory Entry Caching -- Sort of.
Summary:
This patch implements directory_entry caching *almost* as specified in P0317r1. However, I explicitly chose to deviate from the standard as I'll explain below.

The approach I decided to take is a fully caching one. When `refresh()` is called, the cache is populated by calls to `stat` and `lstat` as needed.
During directory iteration the cache is only populated with the `file_type` as reported by `readdir`.
The cache can be in the following states:

* `_Empty`: There is nothing in the cache (likely due to an error)
* `_IterSymlink`: Created by directory iteration when we walk onto a symlink only the symlink file type is known.
* `_IterNonSymlink`: Created by directory iteration when we walk onto a non-symlink. Both the regular file type and symlink file type are known.
* `_RefreshSymlink` and `_RefreshNonSymlink`: A full cache created by `refresh()`.  This case includes dead symlinks.
* `_RefreshSymlinkUnresolved`: A partial cache created by refresh when we fail to resolve the file pointed to by a symlink (likely due to permissions). Symlink attributes are cached, but attributes about the linked entity are not.

As mentioned, this implementation purposefully deviates from the standard. According to some readings of the specification, and the Windows filesystem implementation, the constructors and modifiers which don't pass an `error_code` must throw when the `directory_entry` points to a entity which doesn't exist. or when attribute resolution fails for another reason. 

@BillyONeal  has proposed a more reasonable set of requirements, where modifiers other than refresh ignore errors. This is the behavior libc++ currently implements, with the expectation some form of the new language will be accepted into the standard.

Some additional semantics which differ from the Windows implementation:

1. `refresh` will not throw when the entry doesn't exist. In this case we can still meet the functions specification, so we don't treat it as an error.
2. We don't clear the path name when a constructor fails via refresh (this will hopefully be changed in the standard as well).

It should be noted that libstdc++'s current implementation has the same behavior as libc++, except for point (2).

If the changes to the specification don't get accepted, we'll be able to make the changes later.

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0317r1.html

Reviewers: mclow.lists, gromer, ldionne, aaron.ballman

Subscribers: BillyONeal, christof, cfe-commits

Differential Revision: https://reviews.llvm.org/D49530

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337516 91177308-0d34-0410-b5e6-96231b3b80d8
2018-07-20 01:22:32 +00:00
Eric Fiselier
1e34c76d33 Implement filesystem NB comments, relative paths, and related issues.
This is a fairly large patch that implements all of the filesystem NB comments
and the relative paths changes (ex. adding weakly_canonical). These issues
and papers are all interrelated so their implementation couldn't be split up
nicely.

This patch upgrades <experimental/filesystem> to match the C++17 spec and not
the published experimental TS spec. Some of the changes in this patch are both
API and ABI breaking, however libc++ makes no guarantee about stability for
experimental implementations.

The major changes in this patch are:

* Implement NB comments for filesystem (P0492R2), including:
  * Implement `perm_options` enum as part of NB comments, and update the
    `permissions` function to match.
  * Implement changes to `remove_filename` and `replace_filename`
  * Implement changes to `path::stem()` and `path::extension()` which support
    splitting examples like `.profile`.
  * Change path iteration to return an empty path instead of '.' for trailing
    separators.
  * Change `operator/=` to handle absolute paths on the RHS.
  * Change `absolute` to no longer accept a current path argument.

* Implement relative paths according to NB comments (P0219r1)

* Combine `path.cpp` and `operations.cpp` since some path functions require
  access to the operations internals, and some fs operations require access
  to the path parser.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@329028 91177308-0d34-0410-b5e6-96231b3b80d8
2018-04-02 23:03:41 +00:00
Eric Fiselier
73e00f8321 Avoid Clang error about throwing _LIBCPP_ASSERT in noexcept function.
This fixes a couple of tests which produced a warning that a 'throw'
occurred in a noexcept function (by way of _LIBCPP_ASSERT). It does
so by hiding the 'throw' across an opaque function boundary.

This fix isn't ideal, since we still have _LIBCPP_ASSERT's in functions
marked noexcept -- and this problem should be addressed in the future.
However, throwing _LIBCPP_ASSERT is really only meant to allow testing
of the assertions, and is not yet ready for general use.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@328265 91177308-0d34-0410-b5e6-96231b3b80d8
2018-03-22 23:01:08 +00:00
Eric Fiselier
dfcb00a2c5 Fix failing -verify tests due to change in Clangs static_assert message.
Clang recently changed the way it outputs static assert diagnostics.
This patch fixes libc++'s -verify tests so they tolerate both the old
and new message format.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@313499 91177308-0d34-0410-b5e6-96231b3b80d8
2017-09-17 20:57:05 +00:00
Stephan T. Lavavej
25072f0004 [libcxx] [test] Make files consistently end with newlines, NFC.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@309465 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-29 00:55:22 +00:00
Eric Fiselier
b2e9337b06 Fix filesystem build on platforms with weird time_t types.
32-bit powerpc provides a 64 bit time_t type and older ppc64 systems
provide time_t as a floating point type. This caused problems when building
operations.cpp since operations.cpp contained compile time tests for conversions
between time_t and filesystem time type.

When these tests failed they caused the libc++ build to fail as well. This is unfortunate.

This patch moves the tests out of the source file and into the test suite. It also
expands the tests to allow testing of the weird time_t configurations on all platforms.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@307461 91177308-0d34-0410-b5e6-96231b3b80d8
2017-07-08 04:18:41 +00:00
Eric Fiselier
706e2c7374 Diagnose when reverse_iterator is used on path::iterator.
path::iterator isn't a strictly conforming iterator. Specifically
it stashes the current element inside the iterator. This leads to
UB when used with reverse_iterator since it requires the element
to outlive the lifetime of the iterator.

This patch adds a static_assert inside reverse_iterator to disallow
"stashing iterator types", and it tags path::iterator as such a type.

Additionally this patch removes all uses of reverse_iterator<path::iterator>
within the tests.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@300164 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-13 02:54:13 +00:00
Eric Fiselier
271a19ec19 Rewrite std::filesystem::path iterators and parser
This patch entirely rewrites the parsing logic for paths. Unlike the previous
implementation this one stores information about the current state; For example
if we are in a trailing separator or a root separator. This avoids the need for
extra lookahead (and extra work) when incrementing or decrementing an iterator.
Roughly this gives us a 15% speedup over the previous implementation.

Unfortunately this implementation is still a lot slower than libstdc++'s.
Because libstdc++ pre-parses and splits the path upon construction their
iterators are trivial to increment/decrement. This makes libc++ lazy parsing
100x slower than libstdc++. However the pre-parsing libstdc++ causes a ton
of extra and unneeded allocations when constructing the string. For example
`path("/foo/bar/")` would require at least 5 allocations with libstdc++
whereas libc++ uses only one. The non-allocating behavior is much preferable
when you consider filesystem usages like 'exists("/foo/bar/")'.

Even then libc++'s path seems to be twice as slow to simply construct compared
to libstdc++. More investigation is needed about this.


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@285526 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-30 23:30:38 +00:00
Eric Fiselier
4ca4e5038b Implement LWG2664 and update its status
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@284310 91177308-0d34-0410-b5e6-96231b3b80d8
2016-10-15 21:29:44 +00:00
Eric Fiselier
2645dbe87f Implement P0392r0. Integrate filesystem::path and string_view.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@276511 91177308-0d34-0410-b5e6-96231b3b80d8
2016-07-23 03:10:56 +00:00
Eric Fiselier
6e9a694dce Add Filesystem TS -- Complete
Add the completed std::experimental::filesystem implementation and tests.
The implementation supports C++11 or newer.

The TS is built as part of 'libc++experimental.a'. Users of the TS need to
manually link this library. Building and testing the TS can be disabled using
the CMake option '-DLIBCXX_ENABLE_FILESYSTEM=OFF'.

Currently 'libc++experimental.a' is not installed by default. To turn on the
installation of the library use '-DLIBCXX_INSTALL_EXPERIMENTAL_LIBRARY=ON'.


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@273034 91177308-0d34-0410-b5e6-96231b3b80d8
2016-06-17 19:46:40 +00:00