LCOV - code coverage report
Current view: top level - include/llvm/Support - FileSystem.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 90 96 93.8 %
Date: 2018-05-20 00:06:23 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file declares the llvm::sys::fs namespace. It is designed after
      11             : // TR2/boost filesystem (v3), but modified to remove exception handling and the
      12             : // path class.
      13             : //
      14             : // All functions return an error_code and their actual work via the last out
      15             : // argument. The out argument is defined if and only if errc::success is
      16             : // returned. A function may return any error code in the generic or system
      17             : // category. However, they shall be equivalent to any error conditions listed
      18             : // in each functions respective documentation if the condition applies. [ note:
      19             : // this does not guarantee that error_code will be in the set of explicitly
      20             : // listed codes, but it does guarantee that if any of the explicitly listed
      21             : // errors occur, the correct error_code will be used ]. All functions may
      22             : // return errc::not_enough_memory if there is not enough memory to complete the
      23             : // operation.
      24             : //
      25             : //===----------------------------------------------------------------------===//
      26             : 
      27             : #ifndef LLVM_SUPPORT_FILESYSTEM_H
      28             : #define LLVM_SUPPORT_FILESYSTEM_H
      29             : 
      30             : #include "llvm/ADT/SmallString.h"
      31             : #include "llvm/ADT/StringRef.h"
      32             : #include "llvm/ADT/Twine.h"
      33             : #include "llvm/Config/llvm-config.h"
      34             : #include "llvm/Support/Chrono.h"
      35             : #include "llvm/Support/Error.h"
      36             : #include "llvm/Support/ErrorHandling.h"
      37             : #include "llvm/Support/ErrorOr.h"
      38             : #include "llvm/Support/MD5.h"
      39             : #include <cassert>
      40             : #include <cstdint>
      41             : #include <ctime>
      42             : #include <memory>
      43             : #include <stack>
      44             : #include <string>
      45             : #include <system_error>
      46             : #include <tuple>
      47             : #include <vector>
      48             : 
      49             : #ifdef HAVE_SYS_STAT_H
      50             : #include <sys/stat.h>
      51             : #endif
      52             : 
      53             : namespace llvm {
      54             : namespace sys {
      55             : namespace fs {
      56             : 
      57             : /// An enumeration for the file system's view of the type.
      58             : enum class file_type {
      59             :   status_error,
      60             :   file_not_found,
      61             :   regular_file,
      62             :   directory_file,
      63             :   symlink_file,
      64             :   block_file,
      65             :   character_file,
      66             :   fifo_file,
      67             :   socket_file,
      68             :   type_unknown
      69             : };
      70             : 
      71             : /// space_info - Self explanatory.
      72             : struct space_info {
      73             :   uint64_t capacity;
      74             :   uint64_t free;
      75             :   uint64_t available;
      76             : };
      77             : 
      78             : enum perms {
      79             :   no_perms = 0,
      80             :   owner_read = 0400,
      81             :   owner_write = 0200,
      82             :   owner_exe = 0100,
      83             :   owner_all = owner_read | owner_write | owner_exe,
      84             :   group_read = 040,
      85             :   group_write = 020,
      86             :   group_exe = 010,
      87             :   group_all = group_read | group_write | group_exe,
      88             :   others_read = 04,
      89             :   others_write = 02,
      90             :   others_exe = 01,
      91             :   others_all = others_read | others_write | others_exe,
      92             :   all_read = owner_read | group_read | others_read,
      93             :   all_write = owner_write | group_write | others_write,
      94             :   all_exe = owner_exe | group_exe | others_exe,
      95             :   all_all = owner_all | group_all | others_all,
      96             :   set_uid_on_exe = 04000,
      97             :   set_gid_on_exe = 02000,
      98             :   sticky_bit = 01000,
      99             :   all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
     100             :   perms_not_known = 0xFFFF
     101             : };
     102             : 
     103             : // Helper functions so that you can use & and | to manipulate perms bits:
     104             : inline perms operator|(perms l, perms r) {
     105       60240 :   return static_cast<perms>(static_cast<unsigned short>(l) |
     106       60240 :                             static_cast<unsigned short>(r));
     107             : }
     108             : inline perms operator&(perms l, perms r) {
     109     1898497 :   return static_cast<perms>(static_cast<unsigned short>(l) &
     110     1898343 :                             static_cast<unsigned short>(r));
     111             : }
     112             : inline perms &operator|=(perms &l, perms r) {
     113             :   l = l | r;
     114             :   return l;
     115             : }
     116             : inline perms &operator&=(perms &l, perms r) {
     117             :   l = l & r;
     118             :   return l;
     119             : }
     120             : inline perms operator~(perms x) {
     121             :   // Avoid UB by explicitly truncating the (unsigned) ~ result.
     122             :   return static_cast<perms>(
     123             :       static_cast<unsigned short>(~static_cast<unsigned short>(x)));
     124             : }
     125             : 
     126             : class UniqueID {
     127             :   uint64_t Device;
     128             :   uint64_t File;
     129             : 
     130             : public:
     131             :   UniqueID() = default;
     132      463116 :   UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
     133             : 
     134             :   bool operator==(const UniqueID &Other) const {
     135       36993 :     return Device == Other.Device && File == Other.File;
     136             :   }
     137             :   bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
     138             :   bool operator<(const UniqueID &Other) const {
     139             :     return std::tie(Device, File) < std::tie(Other.Device, Other.File);
     140             :   }
     141             : 
     142             :   uint64_t getDevice() const { return Device; }
     143             :   uint64_t getFile() const { return File; }
     144             : };
     145             : 
     146             : /// Represents the result of a call to directory_iterator::status(). This is a
     147             : /// subset of the information returned by a regular sys::fs::status() call, and
     148             : /// represents the information provided by Windows FileFirstFile/FindNextFile.
     149             : class basic_file_status {
     150             : protected:
     151             :   #if defined(LLVM_ON_UNIX)
     152             :   time_t fs_st_atime = 0;
     153             :   time_t fs_st_mtime = 0;
     154             :   uid_t fs_st_uid = 0;
     155             :   gid_t fs_st_gid = 0;
     156             :   off_t fs_st_size = 0;
     157             :   #elif defined (_WIN32)
     158             :   uint32_t LastAccessedTimeHigh = 0;
     159             :   uint32_t LastAccessedTimeLow = 0;
     160             :   uint32_t LastWriteTimeHigh = 0;
     161             :   uint32_t LastWriteTimeLow = 0;
     162             :   uint32_t FileSizeHigh = 0;
     163             :   uint32_t FileSizeLow = 0;
     164             :   #endif
     165             :   file_type Type = file_type::status_error;
     166             :   perms Perms = perms_not_known;
     167             : 
     168             : public:
     169     9282716 :   basic_file_status() = default;
     170             : 
     171             :   explicit basic_file_status(file_type Type) : Type(Type) {}
     172             : 
     173             :   #if defined(LLVM_ON_UNIX)
     174             :   basic_file_status(file_type Type, perms Perms, time_t ATime, time_t MTime,
     175             :                     uid_t UID, gid_t GID, off_t Size)
     176             :       : fs_st_atime(ATime), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID),
     177             :         fs_st_size(Size), Type(Type), Perms(Perms) {}
     178             : #elif defined(_WIN32)
     179             :   basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,
     180             :                     uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
     181             :                     uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
     182             :                     uint32_t FileSizeLow)
     183             :       : LastAccessedTimeHigh(LastAccessTimeHigh),
     184             :         LastAccessedTimeLow(LastAccessTimeLow),
     185             :         LastWriteTimeHigh(LastWriteTimeHigh),
     186             :         LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh),
     187             :         FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {}
     188             :   #endif
     189             : 
     190             :   // getters
     191             :   file_type type() const { return Type; }
     192             :   perms permissions() const { return Perms; }
     193             :   TimePoint<> getLastAccessedTime() const;
     194             :   TimePoint<> getLastModificationTime() const;
     195             : 
     196             :   #if defined(LLVM_ON_UNIX)
     197             :   uint32_t getUser() const { return fs_st_uid; }
     198             :   uint32_t getGroup() const { return fs_st_gid; }
     199     1471426 :   uint64_t getSize() const { return fs_st_size; }
     200             :   #elif defined (_WIN32)
     201             :   uint32_t getUser() const {
     202             :     return 9999; // Not applicable to Windows, so...
     203             :   }
     204             : 
     205             :   uint32_t getGroup() const {
     206             :     return 9999; // Not applicable to Windows, so...
     207             :   }
     208             : 
     209             :   uint64_t getSize() const {
     210             :     return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
     211             :   }
     212             :   #endif
     213             : 
     214             :   // setters
     215             :   void type(file_type v) { Type = v; }
     216             :   void permissions(perms p) { Perms = p; }
     217             : };
     218             : 
     219             : /// Represents the result of a call to sys::fs::status().
     220             : class file_status : public basic_file_status {
     221             :   friend bool equivalent(file_status A, file_status B);
     222             : 
     223             :   #if defined(LLVM_ON_UNIX)
     224             :   dev_t fs_st_dev = 0;
     225             :   nlink_t fs_st_nlinks = 0;
     226             :   ino_t fs_st_ino = 0;
     227             :   #elif defined (_WIN32)
     228             :   uint32_t NumLinks = 0;
     229             :   uint32_t VolumeSerialNumber = 0;
     230             :   uint32_t FileIndexHigh = 0;
     231             :   uint32_t FileIndexLow = 0;
     232             :   #endif
     233             : 
     234             : public:
     235             :   file_status() = default;
     236             : 
     237             :   explicit file_status(file_type Type) : basic_file_status(Type) {}
     238             : 
     239             :   #if defined(LLVM_ON_UNIX)
     240             :   file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
     241             :               time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size)
     242             :       : basic_file_status(Type, Perms, ATime, MTime, UID, GID, Size),
     243             :         fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
     244             :   #elif defined(_WIN32)
     245             :   file_status(file_type Type, perms Perms, uint32_t LinkCount,
     246             :               uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
     247             :               uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
     248             :               uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
     249             :               uint32_t FileSizeLow, uint32_t FileIndexHigh,
     250             :               uint32_t FileIndexLow)
     251             :       : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow,
     252             :                           LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh,
     253             :                           FileSizeLow),
     254             :         NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber),
     255             :         FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {}
     256             :   #endif
     257             : 
     258             :   UniqueID getUniqueID() const;
     259             :   uint32_t getLinkCount() const;
     260             : };
     261             : 
     262             : /// @}
     263             : /// @name Physical Operators
     264             : /// @{
     265             : 
     266             : /// Make \a path an absolute path.
     267             : ///
     268             : /// Makes \a path absolute using the \a current_directory if it is not already.
     269             : /// An empty \a path will result in the \a current_directory.
     270             : ///
     271             : /// /absolute/path   => /absolute/path
     272             : /// relative/../path => <current-directory>/relative/../path
     273             : ///
     274             : /// @param path A path that is modified to be an absolute path.
     275             : /// @returns errc::success if \a path has been made absolute, otherwise a
     276             : ///          platform-specific error_code.
     277             : std::error_code make_absolute(const Twine &current_directory,
     278             :                               SmallVectorImpl<char> &path);
     279             : 
     280             : /// Make \a path an absolute path.
     281             : ///
     282             : /// Makes \a path absolute using the current directory if it is not already. An
     283             : /// empty \a path will result in the current directory.
     284             : ///
     285             : /// /absolute/path   => /absolute/path
     286             : /// relative/../path => <current-directory>/relative/../path
     287             : ///
     288             : /// @param path A path that is modified to be an absolute path.
     289             : /// @returns errc::success if \a path has been made absolute, otherwise a
     290             : ///          platform-specific error_code.
     291             : std::error_code make_absolute(SmallVectorImpl<char> &path);
     292             : 
     293             : /// Create all the non-existent directories in path.
     294             : ///
     295             : /// @param path Directories to create.
     296             : /// @returns errc::success if is_directory(path), otherwise a platform
     297             : ///          specific error_code. If IgnoreExisting is false, also returns
     298             : ///          error if the directory already existed.
     299             : std::error_code create_directories(const Twine &path,
     300             :                                    bool IgnoreExisting = true,
     301             :                                    perms Perms = owner_all | group_all);
     302             : 
     303             : /// Create the directory in path.
     304             : ///
     305             : /// @param path Directory to create.
     306             : /// @returns errc::success if is_directory(path), otherwise a platform
     307             : ///          specific error_code. If IgnoreExisting is false, also returns
     308             : ///          error if the directory already existed.
     309             : std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
     310             :                                  perms Perms = owner_all | group_all);
     311             : 
     312             : /// Create a link from \a from to \a to.
     313             : ///
     314             : /// The link may be a soft or a hard link, depending on the platform. The caller
     315             : /// may not assume which one. Currently on windows it creates a hard link since
     316             : /// soft links require extra privileges. On unix, it creates a soft link since
     317             : /// hard links don't work on SMB file systems.
     318             : ///
     319             : /// @param to The path to hard link to.
     320             : /// @param from The path to hard link from. This is created.
     321             : /// @returns errc::success if the link was created, otherwise a platform
     322             : /// specific error_code.
     323             : std::error_code create_link(const Twine &to, const Twine &from);
     324             : 
     325             : /// Create a hard link from \a from to \a to, or return an error.
     326             : ///
     327             : /// @param to The path to hard link to.
     328             : /// @param from The path to hard link from. This is created.
     329             : /// @returns errc::success if the link was created, otherwise a platform
     330             : /// specific error_code.
     331             : std::error_code create_hard_link(const Twine &to, const Twine &from);
     332             : 
     333             : /// Collapse all . and .. patterns, resolve all symlinks, and optionally
     334             : ///        expand ~ expressions to the user's home directory.
     335             : ///
     336             : /// @param path The path to resolve.
     337             : /// @param output The location to store the resolved path.
     338             : /// @param expand_tilde If true, resolves ~ expressions to the user's home
     339             : ///                     directory.
     340             : std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
     341             :                           bool expand_tilde = false);
     342             : 
     343             : /// Get the current path.
     344             : ///
     345             : /// @param result Holds the current path on return.
     346             : /// @returns errc::success if the current path has been stored in result,
     347             : ///          otherwise a platform-specific error_code.
     348             : std::error_code current_path(SmallVectorImpl<char> &result);
     349             : 
     350             : /// Set the current path.
     351             : ///
     352             : /// @param path The path to set.
     353             : /// @returns errc::success if the current path was successfully set,
     354             : ///          otherwise a platform-specific error_code.
     355             : std::error_code set_current_path(const Twine &path);
     356             : 
     357             : /// Remove path. Equivalent to POSIX remove().
     358             : ///
     359             : /// @param path Input path.
     360             : /// @returns errc::success if path has been removed or didn't exist, otherwise a
     361             : ///          platform-specific error code. If IgnoreNonExisting is false, also
     362             : ///          returns error if the file didn't exist.
     363             : std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
     364             : 
     365             : /// Recursively delete a directory.
     366             : ///
     367             : /// @param path Input path.
     368             : /// @returns errc::success if path has been removed or didn't exist, otherwise a
     369             : ///          platform-specific error code.
     370             : std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
     371             : 
     372             : /// Rename \a from to \a to.
     373             : ///
     374             : /// Files are renamed as if by POSIX rename(), except that on Windows there may
     375             : /// be a short interval of time during which the destination file does not
     376             : /// exist.
     377             : ///
     378             : /// @param from The path to rename from.
     379             : /// @param to The path to rename to. This is created.
     380             : std::error_code rename(const Twine &from, const Twine &to);
     381             : 
     382             : /// Copy the contents of \a From to \a To.
     383             : ///
     384             : /// @param From The path to copy from.
     385             : /// @param To The path to copy to. This is created.
     386             : std::error_code copy_file(const Twine &From, const Twine &To);
     387             : 
     388             : /// Resize path to size. File is resized as if by POSIX truncate().
     389             : ///
     390             : /// @param FD Input file descriptor.
     391             : /// @param Size Size to resize to.
     392             : /// @returns errc::success if \a path has been resized to \a size, otherwise a
     393             : ///          platform-specific error_code.
     394             : std::error_code resize_file(int FD, uint64_t Size);
     395             : 
     396             : /// Compute an MD5 hash of a file's contents.
     397             : ///
     398             : /// @param FD Input file descriptor.
     399             : /// @returns An MD5Result with the hash computed, if successful, otherwise a
     400             : ///          std::error_code.
     401             : ErrorOr<MD5::MD5Result> md5_contents(int FD);
     402             : 
     403             : /// Version of compute_md5 that doesn't require an open file descriptor.
     404             : ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
     405             : 
     406             : /// @}
     407             : /// @name Physical Observers
     408             : /// @{
     409             : 
     410             : /// Does file exist?
     411             : ///
     412             : /// @param status A basic_file_status previously returned from stat.
     413             : /// @returns True if the file represented by status exists, false if it does
     414             : ///          not.
     415             : bool exists(const basic_file_status &status);
     416             : 
     417             : enum class AccessMode { Exist, Write, Execute };
     418             : 
     419             : /// Can the file be accessed?
     420             : ///
     421             : /// @param Path Input path.
     422             : /// @returns errc::success if the path can be accessed, otherwise a
     423             : ///          platform-specific error_code.
     424             : std::error_code access(const Twine &Path, AccessMode Mode);
     425             : 
     426             : /// Does file exist?
     427             : ///
     428             : /// @param Path Input path.
     429             : /// @returns True if it exists, false otherwise.
     430             : inline bool exists(const Twine &Path) {
     431      243509 :   return !access(Path, AccessMode::Exist);
     432             : }
     433             : 
     434             : /// Can we execute this file?
     435             : ///
     436             : /// @param Path Input path.
     437             : /// @returns True if we can execute it, false otherwise.
     438             : bool can_execute(const Twine &Path);
     439             : 
     440             : /// Can we write this file?
     441             : ///
     442             : /// @param Path Input path.
     443             : /// @returns True if we can write to it, false otherwise.
     444             : inline bool can_write(const Twine &Path) {
     445        2280 :   return !access(Path, AccessMode::Write);
     446             : }
     447             : 
     448             : /// Do file_status's represent the same thing?
     449             : ///
     450             : /// @param A Input file_status.
     451             : /// @param B Input file_status.
     452             : ///
     453             : /// assert(status_known(A) || status_known(B));
     454             : ///
     455             : /// @returns True if A and B both represent the same file system entity, false
     456             : ///          otherwise.
     457             : bool equivalent(file_status A, file_status B);
     458             : 
     459             : /// Do paths represent the same thing?
     460             : ///
     461             : /// assert(status_known(A) || status_known(B));
     462             : ///
     463             : /// @param A Input path A.
     464             : /// @param B Input path B.
     465             : /// @param result Set to true if stat(A) and stat(B) have the same device and
     466             : ///               inode (or equivalent).
     467             : /// @returns errc::success if result has been successfully set, otherwise a
     468             : ///          platform-specific error_code.
     469             : std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
     470             : 
     471             : /// Simpler version of equivalent for clients that don't need to
     472             : ///        differentiate between an error and false.
     473             : inline bool equivalent(const Twine &A, const Twine &B) {
     474             :   bool result;
     475        3869 :   return !equivalent(A, B, result) && result;
     476             : }
     477             : 
     478             : /// Is the file mounted on a local filesystem?
     479             : ///
     480             : /// @param path Input path.
     481             : /// @param result Set to true if \a path is on fixed media such as a hard disk,
     482             : ///               false if it is not.
     483             : /// @returns errc::success if result has been successfully set, otherwise a
     484             : ///          platform specific error_code.
     485             : std::error_code is_local(const Twine &path, bool &result);
     486             : 
     487             : /// Version of is_local accepting an open file descriptor.
     488             : std::error_code is_local(int FD, bool &result);
     489             : 
     490             : /// Simpler version of is_local for clients that don't need to
     491             : ///        differentiate between an error and false.
     492             : inline bool is_local(const Twine &Path) {
     493             :   bool Result;
     494       24984 :   return !is_local(Path, Result) && Result;
     495             : }
     496             : 
     497             : /// Simpler version of is_local accepting an open file descriptor for
     498             : ///        clients that don't need to differentiate between an error and false.
     499             : inline bool is_local(int FD) {
     500             :   bool Result;
     501             :   return !is_local(FD, Result) && Result;
     502             : }
     503             : 
     504             : /// Does status represent a directory?
     505             : ///
     506             : /// @param Path The path to get the type of.
     507             : /// @param Follow For symbolic links, indicates whether to return the file type
     508             : ///               of the link itself, or of the target.
     509             : /// @returns A value from the file_type enumeration indicating the type of file.
     510             : file_type get_file_type(const Twine &Path, bool Follow = true);
     511             : 
     512             : /// Does status represent a directory?
     513             : ///
     514             : /// @param status A basic_file_status previously returned from status.
     515             : /// @returns status.type() == file_type::directory_file.
     516             : bool is_directory(const basic_file_status &status);
     517             : 
     518             : /// Is path a directory?
     519             : ///
     520             : /// @param path Input path.
     521             : /// @param result Set to true if \a path is a directory (after following
     522             : ///               symlinks, false if it is not. Undefined otherwise.
     523             : /// @returns errc::success if result has been successfully set, otherwise a
     524             : ///          platform-specific error_code.
     525             : std::error_code is_directory(const Twine &path, bool &result);
     526             : 
     527             : /// Simpler version of is_directory for clients that don't need to
     528             : ///        differentiate between an error and false.
     529             : inline bool is_directory(const Twine &Path) {
     530             :   bool Result;
     531        7693 :   return !is_directory(Path, Result) && Result;
     532             : }
     533             : 
     534             : /// Does status represent a regular file?
     535             : ///
     536             : /// @param status A basic_file_status previously returned from status.
     537             : /// @returns status_known(status) && status.type() == file_type::regular_file.
     538             : bool is_regular_file(const basic_file_status &status);
     539             : 
     540             : /// Is path a regular file?
     541             : ///
     542             : /// @param path Input path.
     543             : /// @param result Set to true if \a path is a regular file (after following
     544             : ///               symlinks), false if it is not. Undefined otherwise.
     545             : /// @returns errc::success if result has been successfully set, otherwise a
     546             : ///          platform-specific error_code.
     547             : std::error_code is_regular_file(const Twine &path, bool &result);
     548             : 
     549             : /// Simpler version of is_regular_file for clients that don't need to
     550             : ///        differentiate between an error and false.
     551             : inline bool is_regular_file(const Twine &Path) {
     552             :   bool Result;
     553         664 :   if (is_regular_file(Path, Result))
     554             :     return false;
     555         616 :   return Result;
     556             : }
     557             : 
     558             : /// Does status represent a symlink file?
     559             : ///
     560             : /// @param status A basic_file_status previously returned from status.
     561             : /// @returns status_known(status) && status.type() == file_type::symlink_file.
     562             : bool is_symlink_file(const basic_file_status &status);
     563             : 
     564             : /// Is path a symlink file?
     565             : ///
     566             : /// @param path Input path.
     567             : /// @param result Set to true if \a path is a symlink file, false if it is not.
     568             : ///               Undefined otherwise.
     569             : /// @returns errc::success if result has been successfully set, otherwise a
     570             : ///          platform-specific error_code.
     571             : std::error_code is_symlink_file(const Twine &path, bool &result);
     572             : 
     573             : /// Simpler version of is_symlink_file for clients that don't need to
     574             : ///        differentiate between an error and false.
     575             : inline bool is_symlink_file(const Twine &Path) {
     576             :   bool Result;
     577           0 :   if (is_symlink_file(Path, Result))
     578             :     return false;
     579           0 :   return Result;
     580             : }
     581             : 
     582             : /// Does this status represent something that exists but is not a
     583             : ///        directory or regular file?
     584             : ///
     585             : /// @param status A basic_file_status previously returned from status.
     586             : /// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
     587             : bool is_other(const basic_file_status &status);
     588             : 
     589             : /// Is path something that exists but is not a directory,
     590             : ///        regular file, or symlink?
     591             : ///
     592             : /// @param path Input path.
     593             : /// @param result Set to true if \a path exists, but is not a directory, regular
     594             : ///               file, or a symlink, false if it does not. Undefined otherwise.
     595             : /// @returns errc::success if result has been successfully set, otherwise a
     596             : ///          platform-specific error_code.
     597             : std::error_code is_other(const Twine &path, bool &result);
     598             : 
     599             : /// Get file status as if by POSIX stat().
     600             : ///
     601             : /// @param path Input path.
     602             : /// @param result Set to the file status.
     603             : /// @param follow When true, follows symlinks.  Otherwise, the symlink itself is
     604             : ///               statted.
     605             : /// @returns errc::success if result has been successfully set, otherwise a
     606             : ///          platform-specific error_code.
     607             : std::error_code status(const Twine &path, file_status &result,
     608             :                        bool follow = true);
     609             : 
     610             : /// A version for when a file descriptor is already available.
     611             : std::error_code status(int FD, file_status &Result);
     612             : 
     613             : /// Set file permissions.
     614             : ///
     615             : /// @param Path File to set permissions on.
     616             : /// @param Permissions New file permissions.
     617             : /// @returns errc::success if the permissions were successfully set, otherwise
     618             : ///          a platform-specific error_code.
     619             : /// @note On Windows, all permissions except *_write are ignored. Using any of
     620             : ///       owner_write, group_write, or all_write will make the file writable.
     621             : ///       Otherwise, the file will be marked as read-only.
     622             : std::error_code setPermissions(const Twine &Path, perms Permissions);
     623             : 
     624             : /// Get file permissions.
     625             : ///
     626             : /// @param Path File to get permissions from.
     627             : /// @returns the permissions if they were successfully retrieved, otherwise a
     628             : ///          platform-specific error_code.
     629             : /// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY
     630             : ///       attribute, all_all will be returned. Otherwise, all_read | all_exe
     631             : ///       will be returned.
     632             : ErrorOr<perms> getPermissions(const Twine &Path);
     633             : 
     634             : /// Get file size.
     635             : ///
     636             : /// @param Path Input path.
     637             : /// @param Result Set to the size of the file in \a Path.
     638             : /// @returns errc::success if result has been successfully set, otherwise a
     639             : ///          platform-specific error_code.
     640       28260 : inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
     641       28260 :   file_status Status;
     642       28260 :   std::error_code EC = status(Path, Status);
     643       28260 :   if (EC)
     644       12951 :     return EC;
     645       30618 :   Result = Status.getSize();
     646       15309 :   return std::error_code();
     647             : }
     648             : 
     649             : /// Set the file modification and access time.
     650             : ///
     651             : /// @returns errc::success if the file times were successfully set, otherwise a
     652             : ///          platform-specific error_code or errc::function_not_supported on
     653             : ///          platforms where the functionality isn't available.
     654             : std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time);
     655             : 
     656             : /// Is status available?
     657             : ///
     658             : /// @param s Input file status.
     659             : /// @returns True if status() != status_error.
     660             : bool status_known(const basic_file_status &s);
     661             : 
     662             : /// Is status available?
     663             : ///
     664             : /// @param path Input path.
     665             : /// @param result Set to true if status() != status_error.
     666             : /// @returns errc::success if result has been successfully set, otherwise a
     667             : ///          platform-specific error_code.
     668             : std::error_code status_known(const Twine &path, bool &result);
     669             : 
     670             : enum OpenFlags : unsigned {
     671             :   F_None = 0,
     672             : 
     673             :   /// F_Excl - When opening a file, this flag makes raw_fd_ostream
     674             :   /// report an error if the file already exists.
     675             :   F_Excl = 1,
     676             : 
     677             :   /// F_Append - When opening a file, if it already exists append to the
     678             :   /// existing file instead of returning an error.  This may not be specified
     679             :   /// with F_Excl.
     680             :   F_Append = 2,
     681             : 
     682             :   /// F_NoTrunc - When opening a file, if it already exists don't truncate
     683             :   /// the file contents.  F_Append implies F_NoTrunc, but F_Append seeks to
     684             :   /// the end of the file, which F_NoTrunc doesn't.
     685             :   F_NoTrunc = 4,
     686             : 
     687             :   /// The file should be opened in text mode on platforms that make this
     688             :   /// distinction.
     689             :   F_Text = 8,
     690             : 
     691             :   /// Open the file for read and write.
     692             :   F_RW = 16,
     693             : 
     694             :   /// Delete the file on close. Only makes a difference on windows.
     695             :   F_Delete = 32
     696             : };
     697             : 
     698             : /// Create a uniquely named file.
     699             : ///
     700             : /// Generates a unique path suitable for a temporary file and then opens it as a
     701             : /// file. The name is based on \a model with '%' replaced by a random char in
     702             : /// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
     703             : /// created in the current directory.
     704             : ///
     705             : /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
     706             : ///
     707             : /// This is an atomic operation. Either the file is created and opened, or the
     708             : /// file system is left untouched.
     709             : ///
     710             : /// The intended use is for files that are to be kept, possibly after
     711             : /// renaming them. For example, when running 'clang -c foo.o', the file can
     712             : /// be first created as foo-abc123.o and then renamed.
     713             : ///
     714             : /// @param Model Name to base unique path off of.
     715             : /// @param ResultFD Set to the opened file's file descriptor.
     716             : /// @param ResultPath Set to the opened file's absolute path.
     717             : /// @returns errc::success if Result{FD,Path} have been successfully set,
     718             : ///          otherwise a platform-specific error_code.
     719             : std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
     720             :                                  SmallVectorImpl<char> &ResultPath,
     721             :                                  unsigned Mode = all_read | all_write,
     722             :                                  sys::fs::OpenFlags Flags = sys::fs::F_RW);
     723             : 
     724             : /// Simpler version for clients that don't want an open file. An empty
     725             : /// file will still be created.
     726             : std::error_code createUniqueFile(const Twine &Model,
     727             :                                  SmallVectorImpl<char> &ResultPath,
     728             :                                  unsigned Mode = all_read | all_write);
     729             : 
     730             : /// Represents a temporary file.
     731             : ///
     732             : /// The temporary file must be eventually discarded or given a final name and
     733             : /// kept.
     734             : ///
     735             : /// The destructor doesn't implicitly discard because there is no way to
     736             : /// properly handle errors in a destructor.
     737             : class TempFile {
     738             :   bool Done = false;
     739             :   TempFile(StringRef Name, int FD);
     740             : 
     741             : public:
     742             :   /// This creates a temporary file with createUniqueFile and schedules it for
     743             :   /// deletion with sys::RemoveFileOnSignal.
     744             :   static Expected<TempFile> create(const Twine &Model,
     745             :                                    unsigned Mode = all_read | all_write);
     746             :   TempFile(TempFile &&Other);
     747             :   TempFile &operator=(TempFile &&Other);
     748             : 
     749             :   // Name of the temporary file.
     750             :   std::string TmpName;
     751             : 
     752             :   // The open file descriptor.
     753             :   int FD = -1;
     754             : 
     755             :   // Keep this with the given name.
     756             :   Error keep(const Twine &Name);
     757             : 
     758             :   // Keep this with the temporary name.
     759             :   Error keep();
     760             : 
     761             :   // Delete the file.
     762             :   Error discard();
     763             : 
     764             :   // This checks that keep or delete was called.
     765             :   ~TempFile();
     766             : };
     767             : 
     768             : /// Create a file in the system temporary directory.
     769             : ///
     770             : /// The filename is of the form prefix-random_chars.suffix. Since the directory
     771             : /// is not know to the caller, Prefix and Suffix cannot have path separators.
     772             : /// The files are created with mode 0600.
     773             : ///
     774             : /// This should be used for things like a temporary .s that is removed after
     775             : /// running the assembler.
     776             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     777             :                                     int &ResultFD,
     778             :                                     SmallVectorImpl<char> &ResultPath,
     779             :                                     sys::fs::OpenFlags Flags = sys::fs::F_RW);
     780             : 
     781             : /// Simpler version for clients that don't want an open file. An empty
     782             : /// file will still be created.
     783             : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     784             :                                     SmallVectorImpl<char> &ResultPath);
     785             : 
     786             : std::error_code createUniqueDirectory(const Twine &Prefix,
     787             :                                       SmallVectorImpl<char> &ResultPath);
     788             : 
     789             : /// Get a unique name, not currently exisiting in the filesystem. Subject
     790             : /// to race conditions, prefer to use createUniqueFile instead.
     791             : ///
     792             : /// Similar to createUniqueFile, but instead of creating a file only
     793             : /// checks if it exists. This function is subject to race conditions, if you
     794             : /// want to use the returned name to actually create a file, use
     795             : /// createUniqueFile instead.
     796             : std::error_code getPotentiallyUniqueFileName(const Twine &Model,
     797             :                                              SmallVectorImpl<char> &ResultPath);
     798             : 
     799             : /// Get a unique temporary file name, not currently exisiting in the
     800             : /// filesystem. Subject to race conditions, prefer to use createTemporaryFile
     801             : /// instead.
     802             : ///
     803             : /// Similar to createTemporaryFile, but instead of creating a file only
     804             : /// checks if it exists. This function is subject to race conditions, if you
     805             : /// want to use the returned name to actually create a file, use
     806             : /// createTemporaryFile instead.
     807             : std::error_code
     808             : getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
     809             :                                  SmallVectorImpl<char> &ResultPath);
     810             : 
     811             : inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
     812       20759 :   return OpenFlags(unsigned(A) | unsigned(B));
     813             : }
     814             : 
     815             : inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
     816             :   A = A | B;
     817             :   return A;
     818             : }
     819             : 
     820             : /// @brief Opens the file with the given name in a write-only or read-write
     821             : /// mode, returning its open file descriptor. If the file does not exist, it
     822             : /// is created.
     823             : ///
     824             : /// The caller is responsible for closing the file descriptor once they are
     825             : /// finished with it.
     826             : ///
     827             : /// @param Name The path of the file to open, relative or absolute.
     828             : /// @param ResultFD If the file could be opened successfully, its descriptor
     829             : ///                 is stored in this location. Otherwise, this is set to -1.
     830             : /// @param Flags Additional flags used to determine whether the file should be
     831             : ///              opened in, for example, read-write or in write-only mode.
     832             : /// @param Mode The access permissions of the file, represented in octal.
     833             : /// @returns errc::success if \a Name has been opened, otherwise a
     834             : ///          platform-specific error_code.
     835             : std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
     836             :                                  OpenFlags Flags, unsigned Mode = 0666);
     837             : 
     838             : /// @brief Opens the file with the given name in a read-only mode, returning
     839             : /// its open file descriptor.
     840             : ///
     841             : /// The caller is responsible for closing the file descriptor once they are
     842             : /// finished with it.
     843             : ///
     844             : /// @param Name The path of the file to open, relative or absolute.
     845             : /// @param ResultFD If the file could be opened successfully, its descriptor
     846             : ///                 is stored in this location. Otherwise, this is set to -1.
     847             : /// @param RealPath If nonnull, extra work is done to determine the real path
     848             : ///                 of the opened file, and that path is stored in this
     849             : ///                 location.
     850             : /// @returns errc::success if \a Name has been opened, otherwise a
     851             : ///          platform-specific error_code.
     852             : std::error_code openFileForRead(const Twine &Name, int &ResultFD,
     853             :                                 SmallVectorImpl<char> *RealPath = nullptr);
     854             : 
     855             : std::error_code getUniqueID(const Twine Path, UniqueID &Result);
     856             : 
     857             : /// Get disk space usage information.
     858             : ///
     859             : /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
     860             : /// Note: Windows reports results according to the quota allocated to the user.
     861             : ///
     862             : /// @param Path Input path.
     863             : /// @returns a space_info structure filled with the capacity, free, and
     864             : /// available space on the device \a Path is on. A platform specific error_code
     865             : /// is returned on error.
     866             : ErrorOr<space_info> disk_space(const Twine &Path);
     867             : 
     868             : /// This class represents a memory mapped file. It is based on
     869             : /// boost::iostreams::mapped_file.
     870             : class mapped_file_region {
     871             : public:
     872             :   enum mapmode {
     873             :     readonly, ///< May only access map via const_data as read only.
     874             :     readwrite, ///< May access map via data and modify it. Written to path.
     875             :     priv ///< May modify via data, but changes are lost on destruction.
     876             :   };
     877             : 
     878             : private:
     879             :   /// Platform-specific mapping state.
     880             :   size_t Size;
     881             :   void *Mapping;
     882             :   int FD;
     883             :   mapmode Mode;
     884             : 
     885             :   std::error_code init(int FD, uint64_t Offset, mapmode Mode);
     886             : 
     887             : public:
     888             :   mapped_file_region() = delete;
     889             :   mapped_file_region(mapped_file_region&) = delete;
     890             :   mapped_file_region &operator =(mapped_file_region&) = delete;
     891             : 
     892             :   /// \param fd An open file descriptor to map. mapped_file_region takes
     893             :   ///   ownership if closefd is true. It must have been opended in the correct
     894             :   ///   mode.
     895             :   mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset,
     896             :                      std::error_code &ec);
     897             : 
     898             :   ~mapped_file_region();
     899             : 
     900             :   size_t size() const;
     901             :   char *data() const;
     902             : 
     903             :   /// Get a const view of the data. Modifying this memory has undefined
     904             :   /// behavior.
     905             :   const char *const_data() const;
     906             : 
     907             :   /// \returns The minimum alignment offset must be.
     908             :   static int alignment();
     909             : };
     910             : 
     911             : /// Return the path to the main executable, given the value of argv[0] from
     912             : /// program startup and the address of main itself. In extremis, this function
     913             : /// may fail and return an empty path.
     914             : std::string getMainExecutable(const char *argv0, void *MainExecAddr);
     915             : 
     916             : /// @}
     917             : /// @name Iterators
     918             : /// @{
     919             : 
     920             : /// directory_entry - A single entry in a directory. Caches the status either
     921             : /// from the result of the iteration syscall, or the first time status is
     922             : /// called.
     923     2799410 : class directory_entry {
     924             :   std::string Path;
     925             :   bool FollowSymlinks;
     926             :   basic_file_status Status;
     927             : 
     928             : public:
     929             :   explicit directory_entry(const Twine &path, bool follow_symlinks = true,
     930             :                            basic_file_status st = basic_file_status())
     931       27243 :       : Path(path.str()), FollowSymlinks(follow_symlinks), Status(st) {}
     932             : 
     933             :   directory_entry() = default;
     934             : 
     935             :   void assign(const Twine &path, basic_file_status st = basic_file_status()) {
     936             :     Path = path.str();
     937             :     Status = st;
     938             :   }
     939             : 
     940             :   void replace_filename(const Twine &filename,
     941             :                         basic_file_status st = basic_file_status());
     942             : 
     943      327992 :   const std::string &path() const { return Path; }
     944             :   ErrorOr<basic_file_status> status() const;
     945             : 
     946     3434269 :   bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
     947             :   bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
     948             :   bool operator< (const directory_entry& rhs) const;
     949             :   bool operator<=(const directory_entry& rhs) const;
     950             :   bool operator> (const directory_entry& rhs) const;
     951             :   bool operator>=(const directory_entry& rhs) const;
     952             : };
     953             : 
     954             : namespace detail {
     955             : 
     956             :   struct DirIterState;
     957             : 
     958             :   std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
     959             :   std::error_code directory_iterator_increment(DirIterState &);
     960             :   std::error_code directory_iterator_destruct(DirIterState &);
     961             : 
     962             :   /// Keeps state for the directory_iterator.
     963             :   struct DirIterState {
     964     5489943 :     ~DirIterState() {
     965     2744946 :       directory_iterator_destruct(*this);
     966     2744997 :     }
     967             : 
     968             :     intptr_t IterationHandle = 0;
     969             :     directory_entry CurrentEntry;
     970             :   };
     971             : 
     972             : } // end namespace detail
     973             : 
     974             : /// directory_iterator - Iterates through the entries in path. There is no
     975             : /// operator++ because we need an error_code. If it's really needed we can make
     976             : /// it call report_fatal_error on error.
     977     2745278 : class directory_iterator {
     978             :   std::shared_ptr<detail::DirIterState> State;
     979             :   bool FollowSymlinks = true;
     980             : 
     981             : public:
     982     2744864 :   explicit directory_iterator(const Twine &path, std::error_code &ec,
     983             :                               bool follow_symlinks = true)
     984     5489728 :       : FollowSymlinks(follow_symlinks) {
     985     2744832 :     State = std::make_shared<detail::DirIterState>();
     986             :     SmallString<128> path_storage;
     987     2744838 :     ec = detail::directory_iterator_construct(
     988     2744832 :         *State, path.toStringRef(path_storage), FollowSymlinks);
     989     2744882 :     update_error_code_for_current_entry(ec);
     990     2744875 :   }
     991             : 
     992          94 :   explicit directory_iterator(const directory_entry &de, std::error_code &ec,
     993             :                               bool follow_symlinks = true)
     994         188 :       : FollowSymlinks(follow_symlinks) {
     995          94 :     State = std::make_shared<detail::DirIterState>();
     996          94 :     ec = detail::directory_iterator_construct(
     997         188 :         *State, de.path(), FollowSymlinks);
     998          94 :     update_error_code_for_current_entry(ec);
     999          94 :   }
    1000             : 
    1001             :   /// Construct end iterator.
    1002     3071766 :   directory_iterator() = default;
    1003             : 
    1004             :   // No operator++ because we need error_code.
    1005             :   directory_iterator &increment(std::error_code &ec) {
    1006      331241 :     ec = directory_iterator_increment(*State);
    1007      331241 :     update_error_code_for_current_entry(ec);
    1008             :     return *this;
    1009             :   }
    1010             : 
    1011         364 :   const directory_entry &operator*() const { return State->CurrentEntry; }
    1012         271 :   const directory_entry *operator->() const { return &State->CurrentEntry; }
    1013             : 
    1014     3075967 :   bool operator==(const directory_iterator &RHS) const {
    1015     3075967 :     if (State == RHS.State)
    1016             :       return true;
    1017     3075785 :     if (!RHS.State)
    1018     6151570 :       return State->CurrentEntry == directory_entry();
    1019           0 :     if (!State)
    1020           0 :       return RHS.State->CurrentEntry == directory_entry();
    1021           0 :     return State->CurrentEntry == RHS.State->CurrentEntry;
    1022             :   }
    1023             : 
    1024             :   bool operator!=(const directory_iterator &RHS) const {
    1025     2747982 :     return !(*this == RHS);
    1026             :   }
    1027             :   // Other members as required by
    1028             :   // C++ Std, 24.1.1 Input iterators [input.iterators]
    1029             : 
    1030             : private:
    1031             :   // Checks if current entry is valid and populates error code. For example,
    1032             :   // current entry may not exist due to broken symbol links.
    1033     3076213 :   void update_error_code_for_current_entry(std::error_code &ec) {
    1034             :     // Bail out if error has already occured earlier to avoid overwriting it.
    1035     3076213 :     if (ec)
    1036     2744956 :       return;
    1037             : 
    1038             :     // Empty directory entry is used to mark the end of an interation, it's not
    1039             :     // an error.
    1040      716968 :     if (State->CurrentEntry == directory_entry())
    1041             :       return;
    1042             : 
    1043      331257 :     ErrorOr<basic_file_status> status = State->CurrentEntry.status();
    1044      331257 :     if (!status)
    1045          15 :       ec = status.getError();
    1046             :   }
    1047             : };
    1048             : 
    1049             : namespace detail {
    1050             : 
    1051             :   /// Keeps state for the recursive_directory_iterator.
    1052          41 :   struct RecDirIterState {
    1053             :     std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
    1054             :     uint16_t Level = 0;
    1055             :     bool HasNoPushRequest = false;
    1056             :   };
    1057             : 
    1058             : } // end namespace detail
    1059             : 
    1060             : /// recursive_directory_iterator - Same as directory_iterator except for it
    1061             : /// recurses down into child directories.
    1062           2 : class recursive_directory_iterator {
    1063             :   std::shared_ptr<detail::RecDirIterState> State;
    1064             :   bool Follow;
    1065             : 
    1066             : public:
    1067             :   recursive_directory_iterator() = default;
    1068          41 :   explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
    1069             :                                         bool follow_symlinks = true)
    1070          41 :       : State(std::make_shared<detail::RecDirIterState>()),
    1071          41 :         Follow(follow_symlinks) {
    1072          82 :     State->Stack.push(directory_iterator(path, ec, Follow));
    1073          82 :     if (State->Stack.top() == directory_iterator())
    1074             :       State.reset();
    1075          41 :   }
    1076             : 
    1077             :   // No operator++ because we need error_code.
    1078         214 :   recursive_directory_iterator &increment(std::error_code &ec) {
    1079             :     const directory_iterator end_itr = {};
    1080             : 
    1081         214 :     if (State->HasNoPushRequest)
    1082           1 :       State->HasNoPushRequest = false;
    1083             :     else {
    1084         213 :       ErrorOr<basic_file_status> status = State->Stack.top()->status();
    1085         213 :       if (status && is_directory(*status)) {
    1086         132 :         State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
    1087          44 :         if (State->Stack.top() != end_itr) {
    1088          35 :           ++State->Level;
    1089             :           return *this;
    1090             :         }
    1091             :         State->Stack.pop();
    1092             :       }
    1093             :     }
    1094             : 
    1095          75 :     while (!State->Stack.empty()
    1096         467 :            && State->Stack.top().increment(ec) == end_itr) {
    1097             :       State->Stack.pop();
    1098          75 :       --State->Level;
    1099             :     }
    1100             : 
    1101             :     // Check if we are done. If so, create an end iterator.
    1102         179 :     if (State->Stack.empty())
    1103             :       State.reset();
    1104             : 
    1105             :     return *this;
    1106             :   }
    1107             : 
    1108             :   const directory_entry &operator*() const { return *State->Stack.top(); }
    1109             :   const directory_entry *operator->() const { return &*State->Stack.top(); }
    1110             : 
    1111             :   // observers
    1112             :   /// Gets the current level. Starting path is at level 0.
    1113           3 :   int level() const { return State->Level; }
    1114             : 
    1115             :   /// Returns true if no_push has been called for this directory_entry.
    1116             :   bool no_push_request() const { return State->HasNoPushRequest; }
    1117             : 
    1118             :   // modifiers
    1119             :   /// Goes up one level if Level > 0.
    1120           1 :   void pop() {
    1121             :     assert(State && "Cannot pop an end iterator!");
    1122             :     assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
    1123             : 
    1124             :     const directory_iterator end_itr = {};
    1125             :     std::error_code ec;
    1126             :     do {
    1127           1 :       if (ec)
    1128           0 :         report_fatal_error("Error incrementing directory iterator.");
    1129             :       State->Stack.pop();
    1130           1 :       --State->Level;
    1131             :     } while (!State->Stack.empty()
    1132           2 :              && State->Stack.top().increment(ec) == end_itr);
    1133             : 
    1134             :     // Check if we are done. If so, create an end iterator.
    1135           1 :     if (State->Stack.empty())
    1136             :       State.reset();
    1137           1 :   }
    1138             : 
    1139             :   /// Does not go down into the current directory_entry.
    1140           1 :   void no_push() { State->HasNoPushRequest = true; }
    1141             : 
    1142             :   bool operator==(const recursive_directory_iterator &RHS) const {
    1143             :     return State == RHS.State;
    1144             :   }
    1145             : 
    1146             :   bool operator!=(const recursive_directory_iterator &RHS) const {
    1147             :     return !(*this == RHS);
    1148             :   }
    1149             :   // Other members as required by
    1150             :   // C++ Std, 24.1.1 Input iterators [input.iterators]
    1151             : };
    1152             : 
    1153             : /// @}
    1154             : 
    1155             : } // end namespace fs
    1156             : } // end namespace sys
    1157             : } // end namespace llvm
    1158             : 
    1159             : #endif // LLVM_SUPPORT_FILESYSTEM_H

Generated by: LCOV version 1.13