Index: cfe/trunk/include/clang/Basic/VirtualFileSystem.h =================================================================== --- cfe/trunk/include/clang/Basic/VirtualFileSystem.h +++ cfe/trunk/include/clang/Basic/VirtualFileSystem.h @@ -45,7 +45,8 @@ namespace clang { namespace vfs { -/// The result of a \p status operation. +/// File information from a \p File::status() operation. +/// This is roughly equivalent to a `struct stat` plus a file path. class Status { std::string Name; llvm::sys::fs::UniqueID UID; @@ -66,13 +67,14 @@ llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms); + Status(const llvm::sys::fs::file_status &FSStatus, StringRef Name); - /// Get a copy of a Status with a different name. - static Status copyWithNewName(const Status &In, StringRef NewName); - static Status copyWithNewName(const llvm::sys::fs::file_status &In, - StringRef NewName); + /// Get a copy of a this Status with a different name. + Status copyWithNewName(StringRef NewName); /// Returns the name that should be used for this file or directory. + /// This is usually the path that the file was opened as, without resolving + /// relative paths or symlinks. StringRef getName() const { return Name; } /// @name Status interface from llvm::sys::fs @@ -107,15 +109,16 @@ virtual ~File(); /// Get the status of the file. + /// This may access the filesystem (e.g. `stat()`), or return a cached value. virtual llvm::ErrorOr status() = 0; - /// Get the name of the file - virtual llvm::ErrorOr getName() { - if (auto Status = status()) - return Status->getName().str(); - else - return Status.getError(); - } + /// Get the "real name" of the file, if available. + /// This should be absolute, and typically has symlinks resolved. + /// + /// Only some VFS implementations provide this, and only sometimes. + /// FIXME: these maybe-available semantics are not very useful. It would be + /// nice if this was more consistent with FileSystem::getRealPath(). + virtual llvm::Optional getRealPath() { return llvm::None; } /// Get the contents of the file as a \p MemoryBuffer. virtual llvm::ErrorOr> Index: cfe/trunk/lib/Basic/FileManager.cpp =================================================================== --- cfe/trunk/lib/Basic/FileManager.cpp +++ cfe/trunk/lib/Basic/FileManager.cpp @@ -316,7 +316,7 @@ UFE.File = std::move(F); UFE.IsValid = true; if (UFE.File) - if (auto RealPathName = UFE.File->getName()) + if (auto RealPathName = UFE.File->getRealPath()) UFE.RealPathName = *RealPathName; return &UFE; } Index: cfe/trunk/lib/Basic/VirtualFileSystem.cpp =================================================================== --- cfe/trunk/lib/Basic/VirtualFileSystem.cpp +++ cfe/trunk/lib/Basic/VirtualFileSystem.cpp @@ -73,16 +73,14 @@ : Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size), Type(Type), Perms(Perms) {} -Status Status::copyWithNewName(const Status &In, StringRef NewName) { - return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), - In.getUser(), In.getGroup(), In.getSize(), In.getType(), - In.getPermissions()); -} - -Status Status::copyWithNewName(const file_status &In, StringRef NewName) { - return Status(NewName, In.getUniqueID(), In.getLastModificationTime(), - In.getUser(), In.getGroup(), In.getSize(), In.type(), - In.permissions()); +Status::Status(const file_status &In, StringRef NewName) + : Status(NewName, In.getUniqueID(), In.getLastModificationTime(), + In.getUser(), In.getGroup(), In.getSize(), In.type(), + In.permissions()) {} + +Status Status::copyWithNewName(StringRef NewName) { + return Status(NewName, getUniqueID(), getLastModificationTime(), getUser(), + getGroup(), getSize(), getType(), getPermissions()); } bool Status::equivalent(const Status &Other) const { @@ -178,6 +176,7 @@ Status S; std::string RealName; + // NewRealPathName is used only if non-empty. RealFile(int FD, StringRef NewName, StringRef NewRealPathName) : FD(FD), S(NewName, {}, {}, {}, {}, {}, llvm::sys::fs::file_type::status_error, {}), @@ -189,7 +188,7 @@ ~RealFile() override; ErrorOr status() override; - ErrorOr getName() override; + Optional getRealPath() override; ErrorOr> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -207,13 +206,15 @@ file_status RealStatus; if (std::error_code EC = sys::fs::status(FD, RealStatus)) return EC; - S = Status::copyWithNewName(RealStatus, S.getName()); + S = Status(RealStatus, S.getName()); } return S; } -ErrorOr RealFile::getName() { - return RealName.empty() ? S.getName().str() : RealName; +Optional RealFile::getRealPath() { + if (RealName.empty()) + return llvm::None; + return RealName; } ErrorOr> @@ -251,7 +252,7 @@ sys::fs::file_status RealStatus; if (std::error_code EC = sys::fs::status(Path, RealStatus)) return EC; - return Status::copyWithNewName(RealStatus, Path.str()); + return Status(RealStatus, Path.str()); } ErrorOr> @@ -303,7 +304,7 @@ if (Iter != llvm::sys::fs::directory_iterator()) { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -317,7 +318,7 @@ } else { llvm::sys::fs::file_status S; std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true); - CurrentEntry = Status::copyWithNewName(S, Iter->path()); + CurrentEntry = Status(S, Iter->path()); if (!EC) EC = ErrorCode; } @@ -1641,7 +1642,7 @@ Status ExternalStatus) { Status S = ExternalStatus; if (!UseExternalNames) - S = Status::copyWithNewName(S, Path.str()); + S = S.copyWithNewName(Path.str()); S.IsVFSMapped = true; return S; } @@ -1657,7 +1658,7 @@ return S; } else { // directory auto *DE = cast(E); - return Status::copyWithNewName(DE->getStatus(), Path.str()); + return DE->getStatus().copyWithNewName(Path.str()); } }