summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-11-24 18:11:16 +0000
committerdim <dim@FreeBSD.org>2014-11-24 18:11:16 +0000
commit6148c19c738a92f344008aa3f88f4e008bada0ee (patch)
treed4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
parent2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff)
parent173a4f43a911175643bda81ee675e8d9269056ea (diff)
downloadFreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.zip
FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.tar.gz
Merge clang 3.5.0 release from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/FileManager.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp226
1 files changed, 91 insertions, 135 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
index af9b266..9421032 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -25,29 +25,13 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
#include <map>
#include <set>
#include <string>
+#include <system_error>
-// FIXME: This is terrible, we need this for ::close.
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#include <sys/uio.h>
-#else
-#include <io.h>
-#ifndef S_ISFIFO
-#define S_ISFIFO(x) (0)
-#endif
-#endif
-#if defined(LLVM_ON_UNIX)
-#include <limits.h>
-#endif
using namespace clang;
-// FIXME: Enhance libsystem to support inode and other fields.
-#include <sys/stat.h>
-
/// NON_EXISTENT_DIR - A special value distinct from null that is used to
/// represent a dir name that doesn't exist on the disk.
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
@@ -56,63 +40,24 @@ using namespace clang;
/// represent a filename that doesn't exist on the disk.
#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
-
-FileEntry::~FileEntry() {
- // If this FileEntry owns an open file descriptor that never got used, close
- // it.
- if (FD != -1) ::close(FD);
-}
-
-class FileManager::UniqueDirContainer {
- /// UniqueDirs - Cache from ID's to existing directories/files.
- std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueDirs;
-
-public:
- /// getDirectory - Return an existing DirectoryEntry with the given
- /// ID's if there is already one; otherwise create and return a
- /// default-constructed DirectoryEntry.
- DirectoryEntry &getDirectory(const llvm::sys::fs::UniqueID &UniqueID) {
- return UniqueDirs[UniqueID];
- }
-
- size_t size() const { return UniqueDirs.size(); }
-};
-
-class FileManager::UniqueFileContainer {
- /// UniqueFiles - Cache from ID's to existing directories/files.
- std::set<FileEntry> UniqueFiles;
-
-public:
- /// getFile - Return an existing FileEntry with the given ID's if
- /// there is already one; otherwise create and return a
- /// default-constructed FileEntry.
- FileEntry &getFile(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe,
- bool InPCH) {
- return const_cast<FileEntry &>(
- *UniqueFiles.insert(FileEntry(UniqueID, IsNamedPipe, InPCH)).first);
- }
-
- size_t size() const { return UniqueFiles.size(); }
-
- void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); }
-};
-
//===----------------------------------------------------------------------===//
// Common logic.
//===----------------------------------------------------------------------===//
-FileManager::FileManager(const FileSystemOptions &FSO)
- : FileSystemOpts(FSO),
- UniqueRealDirs(*new UniqueDirContainer()),
- UniqueRealFiles(*new UniqueFileContainer()),
+FileManager::FileManager(const FileSystemOptions &FSO,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS)
+ : FS(FS), FileSystemOpts(FSO),
SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) {
NumDirLookups = NumFileLookups = 0;
NumDirCacheMisses = NumFileCacheMisses = 0;
+
+ // If the caller doesn't provide a virtual file system, just grab the real
+ // file system.
+ if (!FS)
+ this->FS = vfs::getRealFileSystem();
}
FileManager::~FileManager() {
- delete &UniqueRealDirs;
- delete &UniqueRealFiles;
for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i)
delete VirtualFileEntries[i];
for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i)
@@ -122,8 +67,8 @@ FileManager::~FileManager() {
void FileManager::addStatCache(FileSystemStatCache *statCache,
bool AtBeginning) {
assert(statCache && "No stat cache provided?");
- if (AtBeginning || StatCache.get() == 0) {
- statCache->setNextStatCache(StatCache.take());
+ if (AtBeginning || !StatCache.get()) {
+ statCache->setNextStatCache(StatCache.release());
StatCache.reset(statCache);
return;
}
@@ -155,7 +100,7 @@ void FileManager::removeStatCache(FileSystemStatCache *statCache) {
}
void FileManager::clearStatCaches() {
- StatCache.reset(0);
+ StatCache.reset();
}
/// \brief Retrieve the directory that the given file name resides in.
@@ -164,10 +109,10 @@ static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
StringRef Filename,
bool CacheFailure) {
if (Filename.empty())
- return NULL;
+ return nullptr;
if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
- return NULL; // If Filename is a directory.
+ return nullptr; // If Filename is a directory.
StringRef DirName = llvm::sys::path::parent_path(Filename);
// Use the current directory if file has no path component.
@@ -231,8 +176,8 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
// See if there was already an entry in the map. Note that the map
// contains both virtual and real directories.
if (NamedDirEnt.getValue())
- return NamedDirEnt.getValue() == NON_EXISTENT_DIR
- ? 0 : NamedDirEnt.getValue();
+ return NamedDirEnt.getValue() == NON_EXISTENT_DIR ? nullptr
+ : NamedDirEnt.getValue();
++NumDirCacheMisses;
@@ -245,19 +190,18 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
// Check to see if the directory exists.
FileData Data;
- if (getStatValue(InterndDirName, Data, false, 0 /*directory lookup*/)) {
+ if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) {
// There's no real directory at the given path.
if (!CacheFailure)
SeenDirEntries.erase(DirName);
- return 0;
+ return nullptr;
}
// It exists. See if we have already opened a directory with the
// same inode (this occurs on Unix-like systems when one dir is
// symlinked to another, for example) or the same path (on
// Windows).
- DirectoryEntry &UDE =
- UniqueRealDirs.getDirectory(Data.UniqueID);
+ DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
NamedDirEnt.setValue(&UDE);
if (!UDE.getName()) {
@@ -280,7 +224,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// See if there is already an entry in the map.
if (NamedFileEnt.getValue())
return NamedFileEnt.getValue() == NON_EXISTENT_FILE
- ? 0 : NamedFileEnt.getValue();
+ ? nullptr : NamedFileEnt.getValue();
++NumFileCacheMisses;
@@ -298,56 +242,59 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// without a 'sys' subdir will get a cached failure result.
const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
CacheFailure);
- if (DirInfo == 0) { // Directory doesn't exist, file can't exist.
+ if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
-
- return 0;
+
+ return nullptr;
}
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
// Nope, there isn't. Check to see if the file exists.
- int FileDescriptor = -1;
+ std::unique_ptr<vfs::File> F;
FileData Data;
- if (getStatValue(InterndFileName, Data, true,
- openFile ? &FileDescriptor : 0)) {
+ if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
// There's no real file at the given path.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
-
- return 0;
- }
- if (FileDescriptor != -1 && !openFile) {
- close(FileDescriptor);
- FileDescriptor = -1;
+ return nullptr;
}
+ assert((openFile || !F) && "undesired open file");
+
// 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.
- FileEntry &UFE =
- UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH);
+ FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
NamedFileEnt.setValue(&UFE);
- if (UFE.getName()) { // Already have an entry with this inode, return it.
- // If the stat process opened the file, close it to avoid a FD leak.
- if (FileDescriptor != -1)
- close(FileDescriptor);
+ if (UFE.isValid()) { // Already have an entry with this inode, return it.
+
+ // FIXME: this hack ensures that if we look up a file by a virtual path in
+ // the VFS that the getDir() will have the virtual path, even if we found
+ // the file by a 'real' path first. This is required in order to find a
+ // module's structure when its headers/module map are mapped in the VFS.
+ // We should remove this as soon as we can properly support a file having
+ // multiple names.
+ if (DirInfo != UFE.Dir && Data.IsVFSMapped)
+ UFE.Dir = DirInfo;
return &UFE;
}
- // Otherwise, we don't have this directory yet, add it.
- // FIXME: Change the name to be a char* that points back to the
- // 'SeenFileEntries' key.
- UFE.Name = InterndFileName;
+ // Otherwise, we don't have this file yet, add it.
+ UFE.Name = Data.Name;
UFE.Size = Data.Size;
UFE.ModTime = Data.ModTime;
UFE.Dir = DirInfo;
UFE.UID = NextFileUID++;
- UFE.FD = FileDescriptor;
+ UFE.UniqueID = Data.UniqueID;
+ UFE.IsNamedPipe = Data.IsNamedPipe;
+ UFE.InPCH = Data.InPCH;
+ UFE.File = std::move(F);
+ UFE.IsValid = true;
return &UFE;
}
@@ -370,7 +317,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
NamedFileEnt.setValue(NON_EXISTENT_FILE);
addAncestorsAsVirtualDirs(Filename);
- FileEntry *UFE = 0;
+ FileEntry *UFE = nullptr;
// Now that all ancestors of Filename are in the cache, the
// following call is guaranteed to find the DirectoryEntry from the
@@ -383,24 +330,26 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
// Check to see if the file exists. If so, drop the virtual file
FileData Data;
const char *InterndFileName = NamedFileEnt.getKeyData();
- if (getStatValue(InterndFileName, Data, true, 0) == 0) {
+ if (getStatValue(InterndFileName, Data, true, nullptr) == 0) {
Data.Size = Size;
Data.ModTime = ModificationTime;
- UFE = &UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH);
+ UFE = &UniqueRealFiles[Data.UniqueID];
NamedFileEnt.setValue(UFE);
// If we had already opened this file, close it now so we don't
// leak the descriptor. We're not going to use the file
// descriptor anyway, since this is a virtual file.
- if (UFE->FD != -1) {
- close(UFE->FD);
- UFE->FD = -1;
- }
+ if (UFE->File)
+ UFE->closeFile();
// If we already have an entry with this inode, return it.
- if (UFE->getName())
+ if (UFE->isValid())
return UFE;
+
+ UFE->UniqueID = Data.UniqueID;
+ UFE->IsNamedPipe = Data.IsNamedPipe;
+ UFE->InPCH = Data.InPCH;
}
if (!UFE) {
@@ -414,7 +363,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
UFE->ModTime = ModificationTime;
UFE->Dir = DirInfo;
UFE->UID = NextFileUID++;
- UFE->FD = -1;
+ UFE->File.reset();
return UFE;
}
@@ -432,9 +381,9 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
llvm::MemoryBuffer *FileManager::
getBufferForFile(const FileEntry *Entry, std::string *ErrorStr,
- bool isVolatile) {
- OwningPtr<llvm::MemoryBuffer> Result;
- llvm::error_code ec;
+ bool isVolatile, bool ShouldCloseOpenFile) {
+ std::unique_ptr<llvm::MemoryBuffer> Result;
+ std::error_code ec;
uint64_t FileSize = Entry->getSize();
// If there's a high enough chance that the file have changed since we
@@ -444,50 +393,54 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr,
const char *Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
- if (Entry->FD != -1) {
- ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize);
+ if (Entry->File) {
+ ec = Entry->File->getBuffer(Filename, Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ErrorStr)
*ErrorStr = ec.message();
-
- close(Entry->FD);
- Entry->FD = -1;
- return Result.take();
+ // FIXME: we need a set of APIs that can make guarantees about whether a
+ // FileEntry is open or not.
+ if (ShouldCloseOpenFile)
+ Entry->closeFile();
+ return Result.release();
}
// Otherwise, open the file.
if (FileSystemOpts.WorkingDir.empty()) {
- ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize);
+ ec = FS->getBufferForFile(Filename, Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ec && ErrorStr)
*ErrorStr = ec.message();
- return Result.take();
+ return Result.release();
}
SmallString<128> FilePath(Entry->getName());
FixupRelativePath(FilePath);
- ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize);
+ ec = FS->getBufferForFile(FilePath.str(), Result, FileSize,
+ /*RequiresNullTerminator=*/true, isVolatile);
if (ec && ErrorStr)
*ErrorStr = ec.message();
- return Result.take();
+ return Result.release();
}
llvm::MemoryBuffer *FileManager::
getBufferForFile(StringRef Filename, std::string *ErrorStr) {
- OwningPtr<llvm::MemoryBuffer> Result;
- llvm::error_code ec;
+ std::unique_ptr<llvm::MemoryBuffer> Result;
+ std::error_code ec;
if (FileSystemOpts.WorkingDir.empty()) {
- ec = llvm::MemoryBuffer::getFile(Filename, Result);
+ ec = FS->getBufferForFile(Filename, Result);
if (ec && ErrorStr)
*ErrorStr = ec.message();
- return Result.take();
+ return Result.release();
}
SmallString<128> FilePath(Filename);
FixupRelativePath(FilePath);
- ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
+ ec = FS->getBufferForFile(FilePath.c_str(), Result);
if (ec && ErrorStr)
*ErrorStr = ec.message();
- return Result.take();
+ return Result.release();
}
/// getStatValue - Get the 'stat' information for the specified path,
@@ -496,26 +449,29 @@ getBufferForFile(StringRef Filename, std::string *ErrorStr) {
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile,
- int *FileDescriptor) {
+ std::unique_ptr<vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
if (FileSystemOpts.WorkingDir.empty())
- return FileSystemStatCache::get(Path, Data, isFile, FileDescriptor,
- StatCache.get());
+ return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS);
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
- return FileSystemStatCache::get(FilePath.c_str(), Data, isFile,
- FileDescriptor, StatCache.get());
+ return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F,
+ StatCache.get(), *FS);
}
bool FileManager::getNoncachedStatValue(StringRef Path,
- llvm::sys::fs::file_status &Result) {
+ vfs::Status &Result) {
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
- return llvm::sys::fs::status(FilePath.c_str(), Result);
+ llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str());
+ if (!S)
+ return true;
+ Result = *S;
+ return false;
}
void FileManager::invalidateCache(const FileEntry *Entry) {
@@ -526,7 +482,7 @@ void FileManager::invalidateCache(const FileEntry *Entry) {
// FileEntry invalidation should not block future optimizations in the file
// caches. Possible alternatives are cache truncation (invalidate last N) or
// invalidation of the whole cache.
- UniqueRealFiles.erase(Entry);
+ UniqueRealFiles.erase(Entry->getUniqueID());
}
OpenPOWER on IntegriCloud