From: Duncan P. N. Exon Smith Date: Thu, 10 Dec 2020 23:27:51 +0000 (-0800) Subject: Basic: Add native support for stdin to SourceManager and FileManager X-Git-Tag: llvmorg-13-init~2611 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ee43adfb20d5dc56b7043b314bd22f457c55483;p=platform%2Fupstream%2Fllvm.git Basic: Add native support for stdin to SourceManager and FileManager Add support for stdin to SourceManager and FileManager. Adds FileManager::getSTDIN, which adds a FileEntryRef for `` and reads the MemoryBuffer, which is stored as `FileEntry::Content`. Eventually the other buffers in `ContentCache` will sink to here as well -- we probably usually want to load/save a MemoryBuffer eagerly -- but it's happening early for stdin to get rid of CompilerInstance::InitializeSourceManager's final call to `SourceManager::overrideFileContents`. clang/test/CXX/modules-ts/dcl.dcl/dcl.module/dcl.module.export/p1.cpp relies on building a module from stdin; supporting that requires setting ContentCache::BufferOverridden. Differential Revision: https://reviews.llvm.org/D93148 --- diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index aa7bede..6e91b42 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -25,6 +25,9 @@ #include "llvm/Support/FileSystem/UniqueID.h" namespace llvm { + +class MemoryBuffer; + namespace vfs { class File; @@ -67,6 +70,7 @@ public: inline unsigned getUID() const; inline const llvm::sys::fs::UniqueID &getUniqueID() const; inline time_t getModificationTime() const; + inline bool isNamedPipe() const; inline void closeFile() const; /// Check if the underlying FileEntry is the same, intentially ignoring @@ -339,6 +343,9 @@ class FileEntry { /// The open file, if it is owned by the \p FileEntry. mutable std::unique_ptr File; + /// The file content, if it is owned by the \p FileEntry. + std::unique_ptr Content; + // First access name for this FileEntry. // // This is Optional only to allow delayed construction (FileEntryRef has no @@ -390,6 +397,8 @@ time_t FileEntryRef::getModificationTime() const { return getFileEntry().getModificationTime(); } +bool FileEntryRef::isNamedPipe() const { return getFileEntry().isNamedPipe(); } + void FileEntryRef::closeFile() const { getFileEntry().closeFile(); } } // end namespace clang diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index 449aec2..974771a 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -99,6 +99,9 @@ class FileManager : public RefCountedBase { std::unique_ptr>> SeenBypassFileEntries; + /// The file entry for stdin, if it has been accessed through the FileManager. + Optional STDIN; + /// The canonical names of files and directories . llvm::DenseMap CanonicalNames; @@ -217,6 +220,14 @@ public: bool OpenFile = false, bool CacheFailure = true); + /// Get the FileEntryRef for stdin, returning an error if stdin cannot be + /// read. + /// + /// This reads and caches stdin before returning. Subsequent calls return the + /// same file entry, and a reference to the cached input is returned by calls + /// to getBufferForFile. + llvm::Expected getSTDIN(); + /// Get a FileEntryRef if it exists, without doing anything on error. llvm::Optional getOptionalFileRef(StringRef Filename, bool OpenFile = false, diff --git a/clang/lib/Basic/FileEntry.cpp b/clang/lib/Basic/FileEntry.cpp index 2efdcbb..5ee9bef 100644 --- a/clang/lib/Basic/FileEntry.cpp +++ b/clang/lib/Basic/FileEntry.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/FileEntry.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/VirtualFileSystem.h" using namespace clang; diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index f3afe6d..6e9d5d7 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -338,6 +338,25 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { return ReturnedRef; } +llvm::Expected FileManager::getSTDIN() { + // Only read stdin once. + if (STDIN) + return *STDIN; + + std::unique_ptr 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(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(); @@ -486,6 +505,10 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { llvm::ErrorOr> 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. diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index d2c0de5..56b233b 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -414,6 +414,7 @@ ContentCache &SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile; Entry->IsTransient = FilesAreTransient; + Entry->BufferOverridden |= FileEnt->isNamedPipe(); return *Entry; } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index d96afae..5c413ec 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -848,33 +848,22 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, StringRef InputFile = Input.getFile(); // Figure out where to get and map in the main file. - if (InputFile != "-") { - auto FileOrErr = FileMgr.getFileRef(InputFile, /*OpenFile=*/true); - if (!FileOrErr) { - // FIXME: include the error in the diagnostic. - consumeError(FileOrErr.takeError()); + auto FileOrErr = InputFile == "-" + ? FileMgr.getSTDIN() + : FileMgr.getFileRef(InputFile, /*OpenFile=*/true); + if (!FileOrErr) { + // FIXME: include the error in the diagnostic even when it's not stdin. + auto EC = llvm::errorToErrorCode(FileOrErr.takeError()); + if (InputFile != "-") Diags.Report(diag::err_fe_error_reading) << InputFile; - return false; - } - - SourceMgr.setMainFileID( - SourceMgr.createFileID(*FileOrErr, SourceLocation(), Kind)); - } else { - llvm::ErrorOr> SBOrErr = - llvm::MemoryBuffer::getSTDIN(); - if (std::error_code EC = SBOrErr.getError()) { + else Diags.Report(diag::err_fe_error_reading_stdin) << EC.message(); - return false; - } - std::unique_ptr SB = std::move(SBOrErr.get()); - - FileEntryRef File = FileMgr.getVirtualFileRef(SB->getBufferIdentifier(), - SB->getBufferSize(), 0); - SourceMgr.setMainFileID( - SourceMgr.createFileID(File, SourceLocation(), Kind)); - SourceMgr.overrideFileContents(File, std::move(SB)); + return false; } + SourceMgr.setMainFileID( + SourceMgr.createFileID(*FileOrErr, SourceLocation(), Kind)); + assert(SourceMgr.getMainFileID().isValid() && "Couldn't establish MainFileID!"); return true;