dexonsmith created this revision.
dexonsmith added reviewers: arphaman, Bigcheese, jansvoboda11.
Herald added subscribers: ributzka, JDevlieghere.
Herald added a project: clang.
dexonsmith requested review of this revision.

This reverts commit b34632201987eed369bb7ef4646f341b901c95b8 
<https://reviews.llvm.org/rGb34632201987eed369bb7ef4646f341b901c95b8>,
reapplying 3b18a594c7717a328c33b9c1eba675e9f4bd367c 
<https://reviews.llvm.org/rG3b18a594c7717a328c33b9c1eba675e9f4bd367c> with an 
additional
change to SourceManager.

SourceManager checks if the file entry's size matches the eventually
loaded buffer. This doesn't make sense for named pipes so I've disabled
that check. Since we can't trust `ContentsEntry->getSize()`, we also need
shift the check for files that are too large until after the buffer is
loaded... and load the buffer immediately in `createFileID` so that no
client gets a bad value from `ContentCache::getSize`.

My main goal with this commit is to remove a use of
`SourceManager::overrideFileContents`, whose existance blocks sinking
the content cache down to `FileManager`.

The original commit message follows:

Frontend: Sink named pipe logic from CompilerInstance down to FileManager

Remove compilicated logic from CompilerInstance::InitializeSourceManager
to deal with named pipes, updating FileManager::getBufferForFile to
handle it in a more straightforward way. The existing test at
clang/test/Misc/dev-fd-fs.c covers the new behaviour (just like it did
the old behaviour).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D92531

Files:
  clang/lib/Basic/FileManager.cpp
  clang/lib/Basic/SourceManager.cpp
  clang/lib/Frontend/CompilerInstance.cpp

Index: clang/lib/Frontend/CompilerInstance.cpp
===================================================================
--- clang/lib/Frontend/CompilerInstance.cpp
+++ clang/lib/Frontend/CompilerInstance.cpp
@@ -858,30 +858,8 @@
     }
     FileEntryRef File = *FileOrErr;
 
-    // The natural SourceManager infrastructure can't currently handle named
-    // pipes, but we would at least like to accept them for the main
-    // file. Detect them here, read them with the volatile flag so FileMgr will
-    // pick up the correct size, and simply override their contents as we do for
-    // STDIN.
-    if (File.getFileEntry().isNamedPipe()) {
-      auto MB =
-          FileMgr.getBufferForFile(&File.getFileEntry(), /*isVolatile=*/true);
-      if (MB) {
-        // Create a new virtual file that will have the correct size.
-        const FileEntry *FE =
-            FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0);
-        SourceMgr.overrideFileContents(FE, std::move(*MB));
-        SourceMgr.setMainFileID(
-            SourceMgr.createFileID(FE, SourceLocation(), Kind));
-      } else {
-        Diags.Report(diag::err_cannot_open_file) << InputFile
-                                                 << MB.getError().message();
-        return false;
-      }
-    } else {
-      SourceMgr.setMainFileID(
-          SourceMgr.createFileID(File, SourceLocation(), Kind));
-    }
+    SourceMgr.setMainFileID(
+        SourceMgr.createFileID(File, SourceLocation(), Kind));
   } else {
     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> SBOrErr =
         llvm::MemoryBuffer::getSTDIN();
Index: clang/lib/Basic/SourceManager.cpp
===================================================================
--- clang/lib/Basic/SourceManager.cpp
+++ clang/lib/Basic/SourceManager.cpp
@@ -120,8 +120,10 @@
   // Clang (including elsewhere in this file!) use 'unsigned' to represent file
   // offsets, line numbers, string literal lengths, and so on, and fail
   // miserably on large source files.
-  if ((uint64_t)ContentsEntry->getSize() >=
-      std::numeric_limits<unsigned>::max()) {
+  auto diagnoseFileTooLarge = [&](uint64_t Size) {
+    if (Size < std::numeric_limits<unsigned>::max())
+      return false;
+
     if (Diag.isDiagnosticInFlight())
       Diag.SetDelayedDiagnostic(diag::err_file_too_large,
                                 ContentsEntry->getName());
@@ -129,8 +131,14 @@
       Diag.Report(Loc, diag::err_file_too_large)
         << ContentsEntry->getName();
 
+    return true;
+  };
+
+  // Check ContentsEntry's size, unless it's a named pipe (in which case we
+  // need to load the buffer first).
+  if (!ContentsEntry->isNamedPipe() &&
+      diagnoseFileTooLarge(ContentsEntry->getSize()))
     return None;
-  }
 
   auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile);
 
@@ -153,9 +161,14 @@
 
   Buffer = std::move(*BufferOrError);
 
-  // Check that the file's size is the same as in the file entry (which may
-  // have come from a stat cache).
-  if (Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) {
+  // If this is a named pipe, check the buffer to see if it's too big.
+  // Otherwise, check that the file's size is the same as in the file entry
+  // (which may have come from a stat cache).
+  if (ContentsEntry->isNamedPipe()) {
+    // Check the buffer size directly if this is a named pipe.
+    if (diagnoseFileTooLarge(Buffer->getBufferSize()))
+      return None;
+  } else if (Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) {
     if (Diag.isDiagnosticInFlight())
       Diag.SetDelayedDiagnostic(diag::err_file_modified,
                                 ContentsEntry->getName());
@@ -531,6 +544,12 @@
   assert(SourceFile && "Null source file!");
   SrcMgr::ContentCache &IR =
       getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
+
+  // If this is a named pipe, immediately load the buffer to ensure subsequent
+  // calls to ContentCache::getSize are accurate.
+  if (IR.ContentsEntry->isNamedPipe())
+    (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
+
   return createFileIDImpl(IR, SourceFile->getName(), IncludePos, FileCharacter,
                           LoadedID, LoadedOffset);
 }
@@ -541,6 +560,12 @@
                                    int LoadedID, unsigned LoadedOffset) {
   SrcMgr::ContentCache &IR = getOrCreateContentCache(&SourceFile.getFileEntry(),
                                                      isSystem(FileCharacter));
+
+  // If this is a named pipe, immediately load the buffer to ensure subsequent
+  // calls to ContentCache::getSize are accurate.
+  if (IR.ContentsEntry->isNamedPipe())
+    (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
+
   return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
                           LoadedID, LoadedOffset);
 }
Index: clang/lib/Basic/FileManager.cpp
===================================================================
--- clang/lib/Basic/FileManager.cpp
+++ clang/lib/Basic/FileManager.cpp
@@ -489,7 +489,7 @@
   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();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D92531: Re... Duncan P. N. Exon Smith via Phabricator via cfe-commits

Reply via email to