aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic')
-rw-r--r--clang/lib/Basic/FileManager.cpp2
-rw-r--r--clang/lib/Basic/SourceManager.cpp49
2 files changed, 31 insertions, 20 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);
}