From e1b7f22b3482be5a0cc4b1ed2d73202ef904f25b Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Fri, 30 Aug 2019 22:59:25 +0000 Subject: ASTReader: Bypass overridden files when reading PCHs If contents of a file that is part of a PCM are overridden when reading it, but weren't overridden when the PCM was being built, the ASTReader will emit an error. Now it creates a separate FileEntry for recovery, bypassing the overridden content instead of discarding it. The pre-existing testcase clang/test/PCH/remap-file-from-pch.cpp confirms that the new recovery method works correctly. This resolves a long-standing FIXME to avoid hypothetically invalidating another precompiled module that's already using the overridden contents. This also removes ContentCache-related API that would be unsafe to use across `CompilerInstance`s in an implicit modules build. This helps to unblock us sinking it from SourceManager into FileManager in the future, which would allow us to delete `InMemoryModuleCache`. https://reviews.llvm.org/D66710 llvm-svn: 370546 --- clang/lib/Basic/FileManager.cpp | 25 +++++++++++++++++++------ clang/lib/Basic/SourceManager.cpp | 22 ++++++++++++---------- 2 files changed, 31 insertions(+), 16 deletions(-) (limited to 'clang/lib/Basic') diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index 4330c7ac61c..cc6c2613fb3 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -390,6 +390,25 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, return UFE; } +llvm::Optional FileManager::getBypassFile(FileEntryRef VF) { + // Stat of the file and return nullptr if it doesn't exist. + llvm::vfs::Status Status; + if (getStatValue(VF.getName(), Status, /*isFile=*/true, /*F=*/nullptr)) + return None; + + // Fill it in from the stat. + BypassFileEntries.push_back(std::make_unique()); + const FileEntry &VFE = VF.getFileEntry(); + FileEntry &BFE = *BypassFileEntries.back(); + BFE.Name = VFE.getName(); + 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); +} + bool FileManager::FixupRelativePath(SmallVectorImpl &path) const { StringRef pathRef(path.data(), path.size()); @@ -515,12 +534,6 @@ void FileManager::GetUniqueIDMapping( UIDToFiles[VFE->getUID()] = VFE.get(); } -void FileManager::modifyFileEntry(FileEntry *File, - off_t Size, time_t ModificationTime) { - File->Size = Size; - File->ModTime = ModificationTime; -} - StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) { // FIXME: use llvm::sys::fs::canonical() when it gets implemented llvm::DenseMap::iterator Known diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index d49d594e290..58b95289eaf 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -669,17 +669,19 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; } -void SourceManager::disableFileContentsOverride(const FileEntry *File) { - if (!isFileOverridden(File)) - return; - - const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); - const_cast(IR)->replaceBuffer(nullptr); - const_cast(IR)->ContentsEntry = IR->OrigEntry; +const FileEntry * +SourceManager::bypassFileContentsOverride(const FileEntry &File) { + assert(isFileOverridden(&File)); + llvm::Optional BypassFile = + FileMgr.getBypassFile(FileEntryRef(File.getName(), File)); + + // If the file can't be found in the FS, give up. + if (!BypassFile) + return nullptr; - assert(OverriddenFilesInfo); - OverriddenFilesInfo->OverriddenFiles.erase(File); - OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File); + const FileEntry *FE = &BypassFile->getFileEntry(); + (void)getOrCreateContentCache(FE); + return FE; } void SourceManager::setFileIsTransient(const FileEntry *File) { -- cgit v1.2.3