[llvm-branch-commits] [clang] 3ee43ad - Basic: Add native support for stdin to SourceManager and FileManager

Duncan P. N. Exon Smith via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Dec 23 15:37:53 PST 2020


Author: Duncan P. N. Exon Smith
Date: 2020-12-23T15:18:50-08:00
New Revision: 3ee43adfb20d5dc56b7043b314bd22f457c55483

URL: https://github.com/llvm/llvm-project/commit/3ee43adfb20d5dc56b7043b314bd22f457c55483
DIFF: https://github.com/llvm/llvm-project/commit/3ee43adfb20d5dc56b7043b314bd22f457c55483.diff

LOG: 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 `<stdin>` 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

Added: 
    

Modified: 
    clang/include/clang/Basic/FileEntry.h
    clang/include/clang/Basic/FileManager.h
    clang/lib/Basic/FileEntry.cpp
    clang/lib/Basic/FileManager.cpp
    clang/lib/Basic/SourceManager.cpp
    clang/lib/Frontend/CompilerInstance.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h
index aa7bedec44ac..6e91b42e18b7 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 @@ class FileEntryRef {
   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<llvm::vfs::File> File;
 
+  /// The file content, if it is owned by the \p FileEntry.
+  std::unique_ptr<llvm::MemoryBuffer> 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 449aec2b3541..974771a8f8f3 100644
--- a/clang/include/clang/Basic/FileManager.h
+++ b/clang/include/clang/Basic/FileManager.h
@@ -99,6 +99,9 @@ class FileManager : public RefCountedBase<FileManager> {
   std::unique_ptr<llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>
       SeenBypassFileEntries;
 
+  /// The file entry for stdin, if it has been accessed through the FileManager.
+  Optional<FileEntryRef> STDIN;
+
   /// The canonical names of files and directories .
   llvm::DenseMap<const void *, llvm::StringRef> CanonicalNames;
 
@@ -217,6 +220,14 @@ class FileManager : public RefCountedBase<FileManager> {
                                           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<FileEntryRef> getSTDIN();
+
   /// Get a FileEntryRef if it exists, without doing anything on error.
   llvm::Optional<FileEntryRef> getOptionalFileRef(StringRef Filename,
                                                   bool OpenFile = false,

diff  --git a/clang/lib/Basic/FileEntry.cpp b/clang/lib/Basic/FileEntry.cpp
index 2efdcbbd46aa..5ee9bef9523e 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 f3afe6dd5f48..6e9d5d7fb422 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<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();
@@ -486,6 +505,10 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
 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.

diff  --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index d2c0de5006c4..56b233b517aa 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 d96afae44296..5c413ec4dfa9 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<std::unique_ptr<llvm::MemoryBuffer>> 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<llvm::MemoryBuffer> 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;


        


More information about the llvm-branch-commits mailing list