Importing rustc-1.52.1
Change-Id: I3598a97301b4b2e71385e5a519f6d2ad946548b6
diff --git a/src/llvm-project/clang/lib/Basic/FileManager.cpp b/src/llvm-project/clang/lib/Basic/FileManager.cpp
index e92e9d5..6e9d5d7 100644
--- a/src/llvm-project/clang/lib/Basic/FileManager.cpp
+++ b/src/llvm-project/clang/lib/Basic/FileManager.cpp
@@ -69,21 +69,22 @@
/// Retrieve the directory that the given file name resides in.
/// Filename can point to either a real file or a virtual file.
-static llvm::ErrorOr<const DirectoryEntry *>
+static llvm::Expected<DirectoryEntryRef>
getDirectoryFromFile(FileManager &FileMgr, StringRef Filename,
bool CacheFailure) {
if (Filename.empty())
- return std::errc::no_such_file_or_directory;
+ return llvm::errorCodeToError(
+ make_error_code(std::errc::no_such_file_or_directory));
if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
- return std::errc::is_a_directory;
+ return llvm::errorCodeToError(make_error_code(std::errc::is_a_directory));
StringRef DirName = llvm::sys::path::parent_path(Filename);
// Use the current directory if file has no path component.
if (DirName.empty())
DirName = ".";
- return FileMgr.getDirectory(DirName, CacheFailure);
+ return FileMgr.getDirectoryRef(DirName, CacheFailure);
}
/// Add all ancestors of the given path (pointing to either a file or
@@ -141,7 +142,7 @@
SeenDirEntries.insert({DirName, std::errc::no_such_file_or_directory});
if (!SeenDirInsertResult.second) {
if (SeenDirInsertResult.first->second)
- return DirectoryEntryRef(&*SeenDirInsertResult.first);
+ return DirectoryEntryRef(*SeenDirInsertResult.first);
return llvm::errorCodeToError(SeenDirInsertResult.first->second.getError());
}
@@ -180,7 +181,7 @@
UDE.Name = InterndDirName;
}
- return DirectoryEntryRef(&NamedDirEnt);
+ return DirectoryEntryRef(NamedDirEnt);
}
llvm::ErrorOr<const DirectoryEntry *>
@@ -212,11 +213,11 @@
SeenFileInsertResult.first->second.getError());
// Construct and return and FileEntryRef, unless it's a redirect to another
// filename.
- SeenFileEntryOrRedirect Value = *SeenFileInsertResult.first->second;
- FileEntry *FE;
- if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>()))
- return FileEntryRef(SeenFileInsertResult.first->first(), *FE);
- return getFileRef(*Value.get<const StringRef *>(), openFile, CacheFailure);
+ FileEntryRef::MapValue Value = *SeenFileInsertResult.first->second;
+ if (LLVM_LIKELY(Value.V.is<FileEntry *>()))
+ return FileEntryRef(*SeenFileInsertResult.first);
+ return FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>(
+ Value.V.get<const void *>()));
}
// We've not seen this before. Fill it in.
@@ -235,14 +236,15 @@
// without a 'sys' subdir will get a cached failure result.
auto DirInfoOrErr = getDirectoryFromFile(*this, Filename, CacheFailure);
if (!DirInfoOrErr) { // Directory doesn't exist, file can't exist.
+ std::error_code Err = errorToErrorCode(DirInfoOrErr.takeError());
if (CacheFailure)
- NamedFileEnt->second = DirInfoOrErr.getError();
+ NamedFileEnt->second = Err;
else
SeenFileEntries.erase(Filename);
- return llvm::errorCodeToError(DirInfoOrErr.getError());
+ return llvm::errorCodeToError(Err);
}
- const DirectoryEntry *DirInfo = *DirInfoOrErr;
+ DirectoryEntryRef DirInfo = *DirInfoOrErr;
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
@@ -268,26 +270,30 @@
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()];
- NamedFileEnt->second = &UFE;
-
- // If the name returned by getStatValue is different than Filename, re-intern
- // the name.
- if (Status.getName() != Filename) {
- auto &NewNamedFileEnt =
- *SeenFileEntries.insert({Status.getName(), &UFE}).first;
- assert((*NewNamedFileEnt.second).get<FileEntry *>() == &UFE &&
+ if (Status.getName() == Filename) {
+ // The name matches. Set the FileEntry.
+ NamedFileEnt->second = FileEntryRef::MapValue(UFE, DirInfo);
+ } else {
+ // Name mismatch. We need a redirect. First grab the actual entry we want
+ // to return.
+ auto &Redirection =
+ *SeenFileEntries
+ .insert({Status.getName(), FileEntryRef::MapValue(UFE, DirInfo)})
+ .first;
+ assert(Redirection.second->V.is<FileEntry *>() &&
+ "filename redirected to a non-canonical filename?");
+ assert(Redirection.second->V.get<FileEntry *>() == &UFE &&
"filename from getStatValue() refers to wrong file");
- InterndFileName = NewNamedFileEnt.first().data();
- // In addition to re-interning the name, construct a redirecting seen file
- // entry, that will point to the name the filesystem actually wants to use.
- StringRef *Redirect = new (CanonicalNameStorage) StringRef(InterndFileName);
- auto SeenFileInsertResultIt = SeenFileEntries.find(Filename);
- assert(SeenFileInsertResultIt != SeenFileEntries.end() &&
- "unexpected SeenFileEntries cache miss");
- SeenFileInsertResultIt->second = Redirect;
- NamedFileEnt = &*SeenFileInsertResultIt;
+
+ // Cache the redirection in the previously-inserted entry, still available
+ // in the tentative return value.
+ NamedFileEnt->second = FileEntryRef::MapValue(Redirection);
+
+ // Fix the tentative return value.
+ NamedFileEnt = &Redirection;
}
+ FileEntryRef ReturnedRef(*NamedFileEnt);
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
@@ -296,26 +302,26 @@
// 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 && Status.IsVFSMapped)
- UFE.Dir = DirInfo;
+ if (&DirInfo.getDirEntry() != UFE.Dir && Status.IsVFSMapped)
+ UFE.Dir = &DirInfo.getDirEntry();
- // Always update the name to use the last name by which a file was accessed.
- // FIXME: Neither this nor always using the first name is correct; we want
- // to switch towards a design where we return a FileName object that
+ // Always update LastRef to the last name by which a file was accessed.
+ // FIXME: Neither this nor always using the first reference is correct; we
+ // want to switch towards a design where we return a FileName object that
// encapsulates both the name by which the file was accessed and the
// corresponding FileEntry.
- // FIXME: The Name should be removed from FileEntry once all clients
- // adopt FileEntryRef.
- UFE.Name = InterndFileName;
+ // FIXME: LastRef should be removed from FileEntry once all clients adopt
+ // FileEntryRef.
+ UFE.LastRef = ReturnedRef;
- return FileEntryRef(InterndFileName, UFE);
+ return ReturnedRef;
}
// Otherwise, we don't have this file yet, add it.
- UFE.Name = InterndFileName;
+ UFE.LastRef = ReturnedRef;
UFE.Size = Status.getSize();
UFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
- UFE.Dir = DirInfo;
+ UFE.Dir = &DirInfo.getDirEntry();
UFE.UID = NextFileUID++;
UFE.UniqueID = Status.getUniqueID();
UFE.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
@@ -329,24 +335,46 @@
// We should still fill the path even if we aren't opening the file.
fillRealPathName(&UFE, InterndFileName);
}
- return FileEntryRef(InterndFileName, UFE);
+ return ReturnedRef;
}
-const FileEntry *
-FileManager::getVirtualFile(StringRef Filename, off_t Size,
- time_t ModificationTime) {
+llvm::Expected<FileEntryRef> FileManager::getSTDIN() {
+ // Only read stdin once.
+ if (STDIN)
+ return *STDIN;
+
+ std::unique_ptr<llvm::MemoryBuffer> Content;
+ if (auto ContentOrError = llvm::MemoryBuffer::getSTDIN())
+ Content = std::move(*ContentOrError);
+ else
+ return llvm::errorCodeToError(ContentOrError.getError());
+
+ STDIN = getVirtualFileRef(Content->getBufferIdentifier(),
+ Content->getBufferSize(), 0);
+ FileEntry &FE = const_cast<FileEntry &>(STDIN->getFileEntry());
+ FE.Content = std::move(Content);
+ FE.IsNamedPipe = true;
+ return *STDIN;
+}
+
+const FileEntry *FileManager::getVirtualFile(StringRef Filename, off_t Size,
+ time_t ModificationTime) {
+ return &getVirtualFileRef(Filename, Size, ModificationTime).getFileEntry();
+}
+
+FileEntryRef FileManager::getVirtualFileRef(StringRef Filename, off_t Size,
+ time_t ModificationTime) {
++NumFileLookups;
// See if there is already an entry in the map for an existing file.
auto &NamedFileEnt = *SeenFileEntries.insert(
{Filename, std::errc::no_such_file_or_directory}).first;
if (NamedFileEnt.second) {
- SeenFileEntryOrRedirect Value = *NamedFileEnt.second;
- FileEntry *FE;
- if (LLVM_LIKELY(FE = Value.dyn_cast<FileEntry *>()))
- return FE;
- return getVirtualFile(*Value.get<const StringRef *>(), Size,
- ModificationTime);
+ FileEntryRef::MapValue Value = *NamedFileEnt.second;
+ if (LLVM_LIKELY(Value.V.is<FileEntry *>()))
+ return FileEntryRef(NamedFileEnt);
+ return FileEntryRef(*reinterpret_cast<const FileEntryRef::MapEntry *>(
+ Value.V.get<const void *>()));
}
// We've not seen this before, or the file is cached as non-existent.
@@ -357,7 +385,8 @@
// Now that all ancestors of Filename are in the cache, the
// following call is guaranteed to find the DirectoryEntry from the
// cache.
- auto DirInfo = getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true);
+ auto DirInfo = expectedToOptional(
+ getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true));
assert(DirInfo &&
"The directory of a virtual file should already be in the cache.");
@@ -372,7 +401,7 @@
Status.getUser(), Status.getGroup(), Size,
Status.getType(), Status.getPermissions());
- NamedFileEnt.second = UFE;
+ NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo);
// 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
@@ -381,8 +410,11 @@
UFE->closeFile();
// If we already have an entry with this inode, return it.
+ //
+ // FIXME: Surely this should add a reference by the new name, and return
+ // it instead...
if (UFE->isValid())
- return UFE;
+ return FileEntryRef(NamedFileEnt);
UFE->UniqueID = Status.getUniqueID();
UFE->IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
@@ -390,17 +422,17 @@
} else {
VirtualFileEntries.push_back(std::make_unique<FileEntry>());
UFE = VirtualFileEntries.back().get();
- NamedFileEnt.second = UFE;
+ NamedFileEnt.second = FileEntryRef::MapValue(*UFE, *DirInfo);
}
- UFE->Name = InterndFileName;
+ UFE->LastRef = FileEntryRef(NamedFileEnt);
UFE->Size = Size;
UFE->ModTime = ModificationTime;
- UFE->Dir = *DirInfo;
+ UFE->Dir = &DirInfo->getDirEntry();
UFE->UID = NextFileUID++;
UFE->IsValid = true;
UFE->File.reset();
- return UFE;
+ return FileEntryRef(NamedFileEnt);
}
llvm::Optional<FileEntryRef> FileManager::getBypassFile(FileEntryRef VF) {
@@ -409,17 +441,30 @@
if (getStatValue(VF.getName(), Status, /*isFile=*/true, /*F=*/nullptr))
return None;
- // Fill it in from the stat.
+ if (!SeenBypassFileEntries)
+ SeenBypassFileEntries = std::make_unique<
+ llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>();
+
+ // If we've already bypassed just use the existing one.
+ auto Insertion = SeenBypassFileEntries->insert(
+ {VF.getName(), std::errc::no_such_file_or_directory});
+ if (!Insertion.second)
+ return FileEntryRef(*Insertion.first);
+
+ // Fill in the new entry from the stat.
BypassFileEntries.push_back(std::make_unique<FileEntry>());
const FileEntry &VFE = VF.getFileEntry();
FileEntry &BFE = *BypassFileEntries.back();
- BFE.Name = VFE.getName();
+ Insertion.first->second = FileEntryRef::MapValue(BFE, VF.getDir());
+ BFE.LastRef = FileEntryRef(*Insertion.first);
BFE.Size = Status.getSize();
BFE.Dir = VFE.Dir;
BFE.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
BFE.UID = NextFileUID++;
BFE.IsValid = true;
- return FileEntryRef(VF.getName(), BFE);
+
+ // Save the entry in the bypass table and return.
+ return FileEntryRef(*Insertion.first);
}
bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
@@ -460,10 +505,14 @@
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
bool RequiresNullTerminator) {
+ // If the content is living on the file entry, return a reference to it.
+ if (Entry->Content)
+ return llvm::MemoryBuffer::getMemBuffer(Entry->Content->getMemBufferRef());
+
uint64_t FileSize = Entry->getSize();
// If there's a high enough chance that the file have changed since we
// got its size, force a stat before opening it.
- if (isVolatile)
+ if (isVolatile || Entry->isNamedPipe())
FileSize = -1;
StringRef Filename = Entry->getName();
@@ -534,13 +583,13 @@
UIDToFiles.resize(NextFileUID);
// Map file entries
- for (llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>,
+ for (llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>,
llvm::BumpPtrAllocator>::const_iterator
FE = SeenFileEntries.begin(),
FEEnd = SeenFileEntries.end();
FE != FEEnd; ++FE)
- if (llvm::ErrorOr<SeenFileEntryOrRedirect> Entry = FE->getValue()) {
- if (const auto *FE = (*Entry).dyn_cast<FileEntry *>())
+ if (llvm::ErrorOr<FileEntryRef::MapValue> Entry = FE->getValue()) {
+ if (const auto *FE = Entry->V.dyn_cast<FileEntry *>())
UIDToFiles[FE->getUID()] = FE;
}