aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/FileManager.cpp2
-rw-r--r--clang/lib/Basic/SourceManager.cpp49
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp29
3 files changed, 34 insertions, 46 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index c0d3685..f3afe6d 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -489,7 +489,7 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
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();
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index b71b2be..d2c0de5 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -115,23 +115,6 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
// return paths.
IsBufferInvalid = true;
- // Check that the file's size fits in an 'unsigned' (with room for a
- // past-the-end value). This is deeply regrettable, but various parts of
- // 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()) {
- if (Diag.isDiagnosticInFlight())
- Diag.SetDelayedDiagnostic(diag::err_file_too_large,
- ContentsEntry->getName());
- else
- Diag.Report(Loc, diag::err_file_too_large)
- << ContentsEntry->getName();
-
- return None;
- }
-
auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile);
// If we were unable to open the file, then we are in an inconsistent
@@ -153,9 +136,31 @@ ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
Buffer = std::move(*BufferOrError);
- // Check that the file's size is the same as in the file entry (which may
+ // Check that the file's size fits in an 'unsigned' (with room for a
+ // past-the-end value). This is deeply regrettable, but various parts of
+ // 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.
+ //
+ // Note: ContentsEntry could be a named pipe, in which case
+ // ContentsEntry::getSize() could have the wrong size. Use
+ // MemoryBuffer::getBufferSize() instead.
+ if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_file_too_large,
+ ContentsEntry->getName());
+ else
+ Diag.Report(Loc, diag::err_file_too_large)
+ << ContentsEntry->getName();
+
+ return None;
+ }
+
+ // Unless this is a named pipe (in which case we can handle a mismatch),
+ // 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 (!ContentsEntry->isNamedPipe() &&
+ Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) {
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_file_modified,
ContentsEntry->getName());
@@ -541,6 +546,12 @@ FileID SourceManager::createFileID(FileEntryRef SourceFile,
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);
}
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 69e2e55..d96afae 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -856,32 +856,9 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
Diags.Report(diag::err_fe_error_reading) << InputFile;
return false;
}
- 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.
- FileEntryRef FE =
- FileMgr.getVirtualFileRef(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(*FileOrErr, SourceLocation(), Kind));
} else {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> SBOrErr =
llvm::MemoryBuffer::getSTDIN();