From: Chris Lattner Date: Tue, 23 Nov 2010 20:50:22 +0000 (+0000) Subject: pull "is directory" handling into FileManager::getStatValue X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9f7766846a205bc900b578f944567e679b221aa;p=clang pull "is directory" handling into FileManager::getStatValue which simplifies clients and is important for future directions. Add a FD member to FileEntry which isn't used but will be shortly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120056 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 3367cddc03..8e97062b44 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -45,7 +45,9 @@ public: const char *getName() const { return Name; } }; -/// FileEntry - Cached information about one file on the disk. +/// FileEntry - Cached information about one file on the disk. If the 'FD' +/// member is valid, then this FileEntry has an open file descriptor for the +/// file. /// class FileEntry { const char *Name; // Name of the file. @@ -56,12 +58,25 @@ class FileEntry { dev_t Device; // ID for the device containing the file. ino_t Inode; // Inode number for the file. mode_t FileMode; // The file mode as returned by 'stat'. + + /// FD - The file descriptor for the file entry if it is opened and owned + /// by the FileEntry. If not, this is set to -1. + int FD; friend class FileManager; + + void operator=(const FileEntry&); // DO NOT IMPLEMENT. public: FileEntry(dev_t device, ino_t inode, mode_t m) - : Name(0), Device(device), Inode(inode), FileMode(m) {} + : Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {} // Add a default constructor for use with llvm::StringMap - FileEntry() : Name(0), Device(0), Inode(0), FileMode(0) {} + FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {} + + FileEntry(const FileEntry &FE) { + memcpy(this, &FE, sizeof(FE)); + assert(FD == -1 && "Cannot copy an file-owning FileEntry"); + } + + ~FileEntry(); const char *getName() const { return Name; } off_t getSize() const { return Size; } @@ -75,7 +90,7 @@ public: /// const DirectoryEntry *getDir() const { return Dir; } - bool operator<(const FileEntry& RHS) const { + bool operator<(const FileEntry &RHS) const { return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode); } }; @@ -116,7 +131,7 @@ class FileManager { // Caching. llvm::OwningPtr StatCache; - bool getStatValue(const char *Path, struct stat &StatBuf); + bool getStatValue(const char *Path, struct stat &StatBuf, bool isForDir); public: FileManager(const FileSystemOptions &FileSystemOpts); ~FileManager(); diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index 2465cac56e..b56d96f21f 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -41,6 +41,17 @@ using namespace clang; /// represent a dir name that doesn't exist on the disk. #define NON_EXISTENT_DIR reinterpret_cast((intptr_t)-1) +/// NON_EXISTENT_FILE - A special value distinct from null that is used to +/// represent a filename that doesn't exist on the disk. +#define NON_EXISTENT_FILE reinterpret_cast((intptr_t)-1) + + +FileEntry::~FileEntry() { + // If this FileEntry owns an open file descriptor that never got used, close + // it. + if (FD != -1) ::close(FD); +} + //===----------------------------------------------------------------------===// // Windows. //===----------------------------------------------------------------------===// @@ -102,7 +113,6 @@ public: class FileManager::UniqueDirContainer { /// UniqueDirs - Cache from ID's to existing directories/files. - /// std::map, DirectoryEntry> UniqueDirs; public: @@ -115,7 +125,6 @@ public: class FileManager::UniqueFileContainer { /// UniqueFiles - Cache from ID's to existing directories/files. - /// std::set UniqueFiles; public: @@ -182,10 +191,9 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) { FileSystemStatCache *PrevCache = StatCache.get(); while (PrevCache && PrevCache->getNextStatCache() != statCache) PrevCache = PrevCache->getNextStatCache(); - if (PrevCache) - PrevCache->setNextStatCache(statCache->getNextStatCache()); - else - assert(false && "Stat cache not found for removal"); + + assert(PrevCache && "Stat cache not found for removal"); + PrevCache->setNextStatCache(statCache->getNextStatCache()); } /// \brief Retrieve the directory that the given file name resides in. @@ -240,8 +248,7 @@ const DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename) { // Check to see if the directory exists. struct stat StatBuf; - if (getStatValue(InterndDirName, StatBuf) || // Error stat'ing. - !S_ISDIR(StatBuf.st_mode)) // Not a directory? + if (getStatValue(InterndDirName, StatBuf, true)) return 0; // It exists. See if we have already opened a directory with the same inode. @@ -258,10 +265,6 @@ const DirectoryEntry *FileManager::getDirectory(llvm::StringRef Filename) { return &UDE; } -/// NON_EXISTENT_FILE - A special value distinct from null that is used to -/// represent a filename that doesn't exist on the disk. -#define NON_EXISTENT_FILE reinterpret_cast((intptr_t)-1) - /// getFile - Lookup, cache, and verify the specified file. This returns null /// if the file doesn't exist. /// @@ -302,12 +305,8 @@ const FileEntry *FileManager::getFile(llvm::StringRef Filename) { // Nope, there isn't. Check to see if the file exists. struct stat StatBuf; - if (getStatValue(InterndFileName, StatBuf) || // Error stat'ing. - S_ISDIR(StatBuf.st_mode)) { // A directory? - // If this file doesn't exist, we leave NON_EXISTENT_FILE in FileEntries for - // this path so subsequent queries get the negative result. + if (getStatValue(InterndFileName, StatBuf, false)) return 0; - } // It exists. See if we have already opened a file with the same inode. // This occurs when one dir is symlinked to another, for example. @@ -355,7 +354,11 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, VirtualFileEntries.push_back(UFE); NamedFileEnt.setValue(UFE); - UFE->Name = NamedFileEnt.getKeyData(); + // Get the null-terminated file name as stored as the key of the + // FileEntries map. + const char *InterndFileName = NamedFileEnt.getKeyData(); + + UFE->Name = InterndFileName; UFE->Size = Size; UFE->ModTime = ModificationTime; UFE->Dir = DirInfo; @@ -363,15 +366,13 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, // If this virtual file resolves to a file, also map that file to the // newly-created file entry. - const char *InterndFileName = NamedFileEnt.getKeyData(); struct stat StatBuf; - if (!getStatValue(InterndFileName, StatBuf) && - !S_ISDIR(StatBuf.st_mode)) { - llvm::sys::Path FilePath(InterndFileName); - FilePath.makeAbsolute(); - FileEntries[FilePath.str()] = UFE; - } - + if (getStatValue(InterndFileName, StatBuf, false)) + return UFE; + + llvm::sys::Path FilePath(UFE->Name); + FilePath.makeAbsolute(); + FileEntries[FilePath.str()] = UFE; return UFE; } @@ -409,16 +410,22 @@ getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr) { /// getStatValue - Get the 'stat' information for the specified path, using the /// cache to accellerate it if possible. This returns true if the path does not /// exist or false if it exists. -bool FileManager::getStatValue(const char *Path, struct stat &StatBuf) { +/// +/// The isForDir member indicates whether this is a directory lookup or not. +/// This will return failure if the lookup isn't the expected kind. +bool FileManager::getStatValue(const char *Path, struct stat &StatBuf, + bool isForDir) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) - return FileSystemStatCache::get(Path, StatBuf, StatCache.get()); + return FileSystemStatCache::get(Path, StatBuf, StatCache.get()) || + S_ISDIR(StatBuf.st_mode) != isForDir; llvm::sys::Path FilePath(Path); FixupRelativePath(FilePath, FileSystemOpts); - return FileSystemStatCache::get(FilePath.c_str(), StatBuf, StatCache.get()); + return FileSystemStatCache::get(FilePath.c_str(), StatBuf, StatCache.get()) || + S_ISDIR(StatBuf.st_mode) != isForDir; }