Update clang to r339409b.
Change-Id: Ied8a188bb072c40035320acedc86164b66d920af
diff --git a/linux-x64/clang/include/llvm/Support/FileSystem.h b/linux-x64/clang/include/llvm/Support/FileSystem.h
index 02db459..a76eab6 100644
--- a/linux-x64/clang/include/llvm/Support/FileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/FileSystem.h
@@ -666,7 +666,15 @@
/// @returns errc::success if the file times were successfully set, otherwise a
/// platform-specific error_code or errc::function_not_supported on
/// platforms where the functionality isn't available.
-std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time);
+std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
+ TimePoint<> ModificationTime);
+
+/// Simpler version that sets both file modification and access time to the same
+/// time.
+inline std::error_code setLastAccessAndModificationTime(int FD,
+ TimePoint<> Time) {
+ return setLastAccessAndModificationTime(FD, Time, Time);
+}
/// Is status available?
///
@@ -693,7 +701,7 @@
/// * If it does not already exist, create a new file.
CD_CreateNew = 1,
- /// CD_OpenAlways - When opening a file:
+ /// CD_OpenExisting - When opening a file:
/// * If it already exists, open the file with the offset set to 0.
/// * If it does not already exist, fail.
CD_OpenExisting = 2,
@@ -1092,38 +1100,51 @@
/// @name Iterators
/// @{
-/// directory_entry - A single entry in a directory. Caches the status either
-/// from the result of the iteration syscall, or the first time status is
-/// called.
+/// directory_entry - A single entry in a directory.
class directory_entry {
+ // FIXME: different platforms make different information available "for free"
+ // when traversing a directory. The design of this class wraps most of the
+ // information in basic_file_status, so on platforms where we can't populate
+ // that whole structure, callers end up paying for a stat().
+ // std::filesystem::directory_entry may be a better model.
std::string Path;
- bool FollowSymlinks;
- basic_file_status Status;
+ file_type Type; // Most platforms can provide this.
+ bool FollowSymlinks; // Affects the behavior of status().
+ basic_file_status Status; // If available.
public:
- explicit directory_entry(const Twine &path, bool follow_symlinks = true,
- basic_file_status st = basic_file_status())
- : Path(path.str()), FollowSymlinks(follow_symlinks), Status(st) {}
+ explicit directory_entry(const Twine &Path, bool FollowSymlinks = true,
+ file_type Type = file_type::type_unknown,
+ basic_file_status Status = basic_file_status())
+ : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks),
+ Status(Status) {}
directory_entry() = default;
- void assign(const Twine &path, basic_file_status st = basic_file_status()) {
- Path = path.str();
- Status = st;
- }
-
- void replace_filename(const Twine &filename,
- basic_file_status st = basic_file_status());
+ void replace_filename(const Twine &Filename, file_type Type,
+ basic_file_status Status = basic_file_status());
const std::string &path() const { return Path; }
+ // Get basic information about entry file (a subset of fs::status()).
+ // On most platforms this is a stat() call.
+ // On windows the information was already retrieved from the directory.
ErrorOr<basic_file_status> status() const;
+ // Get the type of this file.
+ // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved.
+ // On some platforms (e.g. Solaris) this is a stat() call.
+ file_type type() const {
+ if (Type != file_type::type_unknown)
+ return Type;
+ auto S = status();
+ return S ? S->type() : file_type::type_unknown;
+ }
- bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
- bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
- bool operator< (const directory_entry& rhs) const;
- bool operator<=(const directory_entry& rhs) const;
- bool operator> (const directory_entry& rhs) const;
- bool operator>=(const directory_entry& rhs) const;
+ bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; }
+ bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); }
+ bool operator< (const directory_entry& RHS) const;
+ bool operator<=(const directory_entry& RHS) const;
+ bool operator> (const directory_entry& RHS) const;
+ bool operator>=(const directory_entry& RHS) const;
};
namespace detail {
@@ -1161,7 +1182,6 @@
SmallString<128> path_storage;
ec = detail::directory_iterator_construct(
*State, path.toStringRef(path_storage), FollowSymlinks);
- update_error_code_for_current_entry(ec);
}
explicit directory_iterator(const directory_entry &de, std::error_code &ec,
@@ -1170,7 +1190,6 @@
State = std::make_shared<detail::DirIterState>();
ec = detail::directory_iterator_construct(
*State, de.path(), FollowSymlinks);
- update_error_code_for_current_entry(ec);
}
/// Construct end iterator.
@@ -1179,7 +1198,6 @@
// No operator++ because we need error_code.
directory_iterator &increment(std::error_code &ec) {
ec = directory_iterator_increment(*State);
- update_error_code_for_current_entry(ec);
return *this;
}
@@ -1199,26 +1217,6 @@
bool operator!=(const directory_iterator &RHS) const {
return !(*this == RHS);
}
- // Other members as required by
- // C++ Std, 24.1.1 Input iterators [input.iterators]
-
-private:
- // Checks if current entry is valid and populates error code. For example,
- // current entry may not exist due to broken symbol links.
- void update_error_code_for_current_entry(std::error_code &ec) {
- // Bail out if error has already occured earlier to avoid overwriting it.
- if (ec)
- return;
-
- // Empty directory entry is used to mark the end of an interation, it's not
- // an error.
- if (State->CurrentEntry == directory_entry())
- return;
-
- ErrorOr<basic_file_status> status = State->CurrentEntry.status();
- if (!status)
- ec = status.getError();
- }
};
namespace detail {
@@ -1256,8 +1254,15 @@
if (State->HasNoPushRequest)
State->HasNoPushRequest = false;
else {
- ErrorOr<basic_file_status> status = State->Stack.top()->status();
- if (status && is_directory(*status)) {
+ file_type type = State->Stack.top()->type();
+ if (type == file_type::symlink_file && Follow) {
+ // Resolve the symlink: is it a directory to recurse into?
+ ErrorOr<basic_file_status> status = State->Stack.top()->status();
+ if (status)
+ type = status->type();
+ // Otherwise broken symlink, and we'll continue.
+ }
+ if (type == file_type::directory_file) {
State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
if (State->Stack.top() != end_itr) {
++State->Level;
@@ -1321,8 +1326,6 @@
bool operator!=(const recursive_directory_iterator &RHS) const {
return !(*this == RHS);
}
- // Other members as required by
- // C++ Std, 24.1.1 Input iterators [input.iterators]
};
/// @}