aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic/FileManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic/FileManager.cpp')
-rw-r--r--clang/lib/Basic/FileManager.cpp61
1 files changed, 46 insertions, 15 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index 2666868..3af2756 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -184,13 +184,30 @@ FileManager::getDirectory(StringRef DirName, bool CacheFailure) {
llvm::ErrorOr<const FileEntry *>
FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
+ auto Result = getFileRef(Filename, openFile, CacheFailure);
+ if (Result)
+ return &Result->getFileEntry();
+ return Result.getError();
+}
+
+llvm::ErrorOr<FileEntryRef>
+FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
++NumFileLookups;
// See if there is already an entry in the map.
auto SeenFileInsertResult =
SeenFileEntries.insert({Filename, std::errc::no_such_file_or_directory});
- if (!SeenFileInsertResult.second)
- return promoteInnerReference(SeenFileInsertResult.first->second);
+ if (!SeenFileInsertResult.second) {
+ if (!SeenFileInsertResult.first->second)
+ return 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);
+ }
// We've not seen this before. Fill it in.
++NumFileCacheMisses;
@@ -241,16 +258,20 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Status.getUniqueID()];
- NamedFileEnt.second = UFE;
+ NamedFileEnt.second = &UFE;
// If the name returned by getStatValue is different than Filename, re-intern
// the name.
if (Status.getName() != Filename) {
auto &NamedFileEnt =
- *SeenFileEntries.insert({Status.getName(), UFE}).first;
- assert(&*NamedFileEnt.second == &UFE &&
+ *SeenFileEntries.insert({Status.getName(), &UFE}).first;
+ assert((*NamedFileEnt.second).get<FileEntry *>() == &UFE &&
"filename from getStatValue() refers to wrong file");
InterndFileName = NamedFileEnt.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);
+ SeenFileInsertResult.first->second = Redirect;
}
if (UFE.isValid()) { // Already have an entry with this inode, return it.
@@ -269,9 +290,11 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
// 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;
- return &UFE;
+ return FileEntryRef(InterndFileName, UFE);
}
// Otherwise, we don't have this file yet, add it.
@@ -292,7 +315,7 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
// We should still fill the path even if we aren't opening the file.
fillRealPathName(&UFE, InterndFileName);
}
- return &UFE;
+ return FileEntryRef(InterndFileName, UFE);
}
const FileEntry *
@@ -303,8 +326,14 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
// 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)
- return &*NamedFileEnt.second;
+ 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);
+ }
// We've not seen this before, or the file is cached as non-existent.
++NumFileCacheMisses;
@@ -329,7 +358,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
Status.getUser(), Status.getGroup(), Size,
Status.getType(), Status.getPermissions());
- NamedFileEnt.second = *UFE;
+ NamedFileEnt.second = 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
@@ -347,7 +376,7 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
} else {
VirtualFileEntries.push_back(std::make_unique<FileEntry>());
UFE = VirtualFileEntries.back().get();
- NamedFileEnt.second = *UFE;
+ NamedFileEnt.second = UFE;
}
UFE->Name = InterndFileName;
@@ -493,12 +522,14 @@ void FileManager::GetUniqueIDMapping(
UIDToFiles.resize(NextFileUID);
// Map file entries
- for (llvm::StringMap<llvm::ErrorOr<FileEntry &>,
+ for (llvm::StringMap<llvm::ErrorOr<SeenFileEntryOrRedirect>,
llvm::BumpPtrAllocator>::const_iterator
- FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
+ FE = SeenFileEntries.begin(),
+ FEEnd = SeenFileEntries.end();
FE != FEEnd; ++FE)
- if (auto Entry = FE->getValue()) {
- UIDToFiles[Entry->getUID()] = &*Entry;
+ if (llvm::ErrorOr<SeenFileEntryOrRedirect> Entry = FE->getValue()) {
+ if (const auto *FE = (*Entry).dyn_cast<FileEntry *>())
+ UIDToFiles[FE->getUID()] = FE;
}
// Map virtual file entries