Index: clang/include/clang/Basic/FileEntry.h =================================================================== --- /dev/null +++ clang/include/clang/Basic/FileEntry.h @@ -0,0 +1,169 @@ +//===- clang/Basic/FileEntry.h - File references ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines interfaces for clang::FileEntry and clang::FileEntryRef. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_FILEENTRY_H +#define LLVM_CLANG_BASIC_FILEENTRY_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem/UniqueID.h" + +namespace llvm { +namespace vfs { + +class File; + +} // namespace vfs +} // namespace llvm + +namespace clang { + +class DirectoryEntry; +class FileEntry; + +/// A reference to a \c FileEntry that includes the name of the file as it was +/// accessed by the FileManager's client. +class FileEntryRef { +public: + const StringRef getName() const { return Entry->first(); } + const FileEntry &getFileEntry() const { + return *Entry->second->V.get(); + } + + inline bool isValid() const; + inline off_t getSize() const; + inline unsigned getUID() const; + inline const llvm::sys::fs::UniqueID &getUniqueID() const; + inline time_t getModificationTime() const; + + friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) { + return LHS.Entry == RHS.Entry; + } + friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) { + return !(LHS == RHS); + } + + struct MapValue; + + /// Type used in the StringMap. + using MapEntry = llvm::StringMapEntry>; + + /// Type stored in the StringMap. + struct MapValue { + /// The pointer at another MapEntry is used when the FileManager should + /// silently forward from one name to another, which occurs in Redirecting + /// VFSs that use external names. In that case, the \c FileEntryRef + /// returned by the \c FileManager will have the external name, and not the + /// name that was used to lookup the file. + llvm::PointerUnion V; + + MapValue() = delete; + MapValue(FileEntry &FE) : V(&FE) {} + MapValue(MapEntry &ME) : V(&ME) {} + }; + +private: + friend class FileManager; + + FileEntryRef() = delete; + explicit FileEntryRef(const MapEntry &Entry) + : Entry(&Entry) { + assert(Entry.second && "Expected payload"); + assert(Entry.second->V && "Expected non-null"); + assert(Entry.second->V.is() && "Expected FileEntry"); + } + + const MapEntry *Entry; +}; + +/// Cached information about one file (either on disk +/// or in the virtual file system). +/// +/// If the 'File' member is valid, then this FileEntry has an open file +/// descriptor for the file. +class FileEntry { + friend class FileManager; + + std::string RealPathName; // Real path to the file; could be empty. + off_t Size; // File size in bytes. + time_t ModTime; // Modification time of file. + const DirectoryEntry *Dir; // Directory file lives in. + llvm::sys::fs::UniqueID UniqueID; + unsigned UID; // A unique (small) ID for the file. + bool IsNamedPipe; + bool IsValid; // Is this \c FileEntry initialized and valid? + + /// The open file, if it is owned by the \p FileEntry. + mutable std::unique_ptr File; + + // First access name for this FileEntry. + // + // This is Optional only to allow delayed construction (FileEntryRef has no + // default constructor). It should always have a value in practice. + // + // TODO: remote this once everyone that needs a name uses FileEntryRef. + Optional LastRef; + +public: + FileEntry(); + ~FileEntry(); + + FileEntry(const FileEntry &) = delete; + FileEntry &operator=(const FileEntry &) = delete; + + StringRef getName() const { return LastRef->getName(); } + FileEntryRef getLastRef() const { return *LastRef; } + + StringRef tryGetRealPathName() const { return RealPathName; } + bool isValid() const { return IsValid; } + off_t getSize() const { return Size; } + unsigned getUID() const { return UID; } + const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } + time_t getModificationTime() const { return ModTime; } + + /// Return the directory the file lives in. + const DirectoryEntry *getDir() const { return Dir; } + + bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; } + + /// Check whether the file is a named pipe (and thus can't be opened by + /// the native FileManager methods). + bool isNamedPipe() const { return IsNamedPipe; } + + void closeFile() const; + + // Only for use in tests to see if deferred opens are happening, rather than + // relying on RealPathName being empty. + bool isOpenForTests() const { return File != nullptr; } +}; + +bool FileEntryRef::isValid() const { return getFileEntry().isValid(); } + +off_t FileEntryRef::getSize() const { return getFileEntry().getSize(); } + +unsigned FileEntryRef::getUID() const { return getFileEntry().getUID(); } + +const llvm::sys::fs::UniqueID &FileEntryRef::getUniqueID() const { + return getFileEntry().getUniqueID(); +} + +time_t FileEntryRef::getModificationTime() const { + return getFileEntry().getModificationTime(); +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_FILEENTRY_H Index: clang/include/clang/Basic/FileManager.h =================================================================== --- clang/include/clang/Basic/FileManager.h +++ clang/include/clang/Basic/FileManager.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_BASIC_FILEMANAGER_H #define LLVM_CLANG_BASIC_FILEMANAGER_H +#include "clang/Basic/FileEntry.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" @@ -71,141 +72,6 @@ const llvm::StringMapEntry> *Entry; }; -class FileEntry; - -/// A reference to a \c FileEntry that includes the name of the file as it was -/// accessed by the FileManager's client. -class FileEntryRef { -public: - const StringRef getName() const { return Entry->first(); } - const FileEntry &getFileEntry() const { - return *Entry->second->V.get(); - } - - inline bool isValid() const; - inline off_t getSize() const; - inline unsigned getUID() const; - inline const llvm::sys::fs::UniqueID &getUniqueID() const; - inline time_t getModificationTime() const; - - friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) { - return LHS.Entry == RHS.Entry; - } - friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) { - return !(LHS == RHS); - } - - struct MapValue; - - /// Type used in the StringMap. - using MapEntry = llvm::StringMapEntry>; - - /// Type stored in the StringMap. - struct MapValue { - /// The pointer at another MapEntry is used when the FileManager should - /// silently forward from one name to another, which occurs in Redirecting - /// VFSs that use external names. In that case, the \c FileEntryRef - /// returned by the \c FileManager will have the external name, and not the - /// name that was used to lookup the file. - llvm::PointerUnion V; - - MapValue() = delete; - MapValue(FileEntry &FE) : V(&FE) {} - MapValue(MapEntry &ME) : V(&ME) {} - }; - -private: - friend class FileManager; - - FileEntryRef() = delete; - explicit FileEntryRef(const MapEntry &Entry) - : Entry(&Entry) { - assert(Entry.second && "Expected payload"); - assert(Entry.second->V && "Expected non-null"); - assert(Entry.second->V.is() && "Expected FileEntry"); - } - - const MapEntry *Entry; -}; - -/// Cached information about one file (either on disk -/// or in the virtual file system). -/// -/// If the 'File' member is valid, then this FileEntry has an open file -/// descriptor for the file. -class FileEntry { - friend class FileManager; - - std::string RealPathName; // Real path to the file; could be empty. - off_t Size; // File size in bytes. - time_t ModTime; // Modification time of file. - const DirectoryEntry *Dir; // Directory file lives in. - llvm::sys::fs::UniqueID UniqueID; - unsigned UID; // A unique (small) ID for the file. - bool IsNamedPipe; - bool IsValid; // Is this \c FileEntry initialized and valid? - - /// The open file, if it is owned by the \p FileEntry. - mutable std::unique_ptr File; - - // First access name for this FileEntry. - // - // This is Optional only to allow delayed construction (FileEntryRef has no - // default constructor). It should always have a value in practice. - // - // TODO: remote this once everyone that needs a name uses FileEntryRef. - Optional LastRef; - -public: - FileEntry() - : UniqueID(0, 0), IsNamedPipe(false), IsValid(false) - {} - - FileEntry(const FileEntry &) = delete; - FileEntry &operator=(const FileEntry &) = delete; - - StringRef getName() const { return LastRef->getName(); } - FileEntryRef getLastRef() const { return *LastRef; } - - StringRef tryGetRealPathName() const { return RealPathName; } - bool isValid() const { return IsValid; } - off_t getSize() const { return Size; } - unsigned getUID() const { return UID; } - const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } - time_t getModificationTime() const { return ModTime; } - - /// Return the directory the file lives in. - const DirectoryEntry *getDir() const { return Dir; } - - bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; } - - /// Check whether the file is a named pipe (and thus can't be opened by - /// the native FileManager methods). - bool isNamedPipe() const { return IsNamedPipe; } - - void closeFile() const { - File.reset(); // rely on destructor to close File - } - - // Only for use in tests to see if deferred opens are happening, rather than - // relying on RealPathName being empty. - bool isOpenForTests() const { return File != nullptr; } -}; - -bool FileEntryRef::isValid() const { return getFileEntry().isValid(); } - -off_t FileEntryRef::getSize() const { return getFileEntry().getSize(); } - -unsigned FileEntryRef::getUID() const { return getFileEntry().getUID(); } - -const llvm::sys::fs::UniqueID &FileEntryRef::getUniqueID() const { - return getFileEntry().getUniqueID(); -} - -time_t FileEntryRef::getModificationTime() const { - return getFileEntry().getModificationTime(); -} - /// Implements support for file system lookup, file system caching, /// and directory search management. /// Index: clang/lib/Basic/CMakeLists.txt =================================================================== --- clang/lib/Basic/CMakeLists.txt +++ clang/lib/Basic/CMakeLists.txt @@ -46,6 +46,7 @@ DiagnosticIDs.cpp DiagnosticOptions.cpp ExpressionTraits.cpp + FileEntry.cpp FileManager.cpp FileSystemStatCache.cpp IdentifierTable.cpp Index: clang/lib/Basic/FileEntry.cpp =================================================================== --- /dev/null +++ clang/lib/Basic/FileEntry.cpp @@ -0,0 +1,23 @@ +//===- FileEntry.cpp - File references --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines implementation for clang::FileEntry and clang::FileEntryRef. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/FileEntry.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang; + +FileEntry::FileEntry() : UniqueID(0, 0), IsNamedPipe(false), IsValid(false) {} + +FileEntry::~FileEntry() = default; + +void FileEntry::closeFile() const { File.reset(); } Index: llvm/include/llvm/Support/FileSystem.h =================================================================== --- llvm/include/llvm/Support/FileSystem.h +++ llvm/include/llvm/Support/FileSystem.h @@ -34,6 +34,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem/UniqueID.h" #include "llvm/Support/MD5.h" #include #include @@ -131,26 +132,6 @@ static_cast(~static_cast(x))); } -class UniqueID { - uint64_t Device; - uint64_t File; - -public: - UniqueID() = default; - UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} - - bool operator==(const UniqueID &Other) const { - return Device == Other.Device && File == Other.File; - } - bool operator!=(const UniqueID &Other) const { return !(*this == Other); } - bool operator<(const UniqueID &Other) const { - return std::tie(Device, File) < std::tie(Other.Device, Other.File); - } - - uint64_t getDevice() const { return Device; } - uint64_t getFile() const { return File; } -}; - /// Represents the result of a call to directory_iterator::status(). This is a /// subset of the information returned by a regular sys::fs::status() call, and /// represents the information provided by Windows FileFirstFile/FindNextFile. Index: llvm/include/llvm/Support/FileSystem/UniqueID.h =================================================================== --- /dev/null +++ llvm/include/llvm/Support/FileSystem/UniqueID.h @@ -0,0 +1,47 @@ +//===- llvm/Support/FileSystem/UniqueID.h - UniqueID for files --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is cut out of llvm/Support/FileSystem.h to allow UniqueID to be +// reused without bloating the includes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H +#define LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H + +#include + +namespace llvm { +namespace sys { +namespace fs { + +class UniqueID { + uint64_t Device; + uint64_t File; + +public: + UniqueID() = default; + UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} + + bool operator==(const UniqueID &Other) const { + return Device == Other.Device && File == Other.File; + } + bool operator!=(const UniqueID &Other) const { return !(*this == Other); } + bool operator<(const UniqueID &Other) const { + return std::tie(Device, File) < std::tie(Other.Device, Other.File); + } + + uint64_t getDevice() const { return Device; } + uint64_t getFile() const { return File; } +}; + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif // LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H