[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