#include "llvm/Support/FileSystem/UniqueID.h"
namespace llvm {
+
+class MemoryBuffer;
+
namespace vfs {
class File;
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
/// 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
return getFileEntry().getModificationTime();
}
+bool FileEntryRef::isNamedPipe() const { return getFileEntry().isNamedPipe(); }
+
void FileEntryRef::closeFile() const { getFileEntry().closeFile(); }
} // end namespace clang
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;
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,
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileEntry.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
using namespace clang;
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();
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.
Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
Entry->IsTransient = FilesAreTransient;
+ Entry->BufferOverridden |= FileEnt->isNamedPipe();
return *Entry;
}
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;