diff options
-rw-r--r-- | lib/Basic/SourceManager.cpp | 20 | ||||
-rw-r--r-- | test/PCH/inconsistent-pch.c | 15 |
2 files changed, 33 insertions, 2 deletions
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index a3e72e8b40..354bf7befb 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -56,9 +56,25 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) { const llvm::MemoryBuffer *ContentCache::getBuffer(std::string *ErrorStr) const { // Lazily create the Buffer for ContentCaches that wrap files. if (!Buffer && Entry) { - // FIXME: Should we support a way to not have to do this check over - // and over if we cannot open the file? Buffer = MemoryBuffer::getFile(Entry->getName(), ErrorStr,Entry->getSize()); + + // If we were unable to open the file, then we are in an inconsistent + // situation where the content cache referenced a file which no longer + // exists. Most likely, we were using a stat cache with an invalid entry but + // the file could also have been removed during processing. Since we can't + // really deal with this situation, just create an empty buffer. + // + // FIXME: This is definitely not ideal, but our immediate clients can't + // currently handle returning a null entry here. Ideally we should detect + // that we are in an inconsistent situation and error out as quickly as + // possible. + if (!Buffer) { + const llvm::StringRef FillStr("<<<MISSING SOURCE FILE>>>\n"); + Buffer = MemoryBuffer::getNewMemBuffer(Entry->getSize(), "<invalid>"); + char *Ptr = const_cast<char*>(Buffer->getBufferStart()); + for (unsigned i = 0, e = Entry->getSize(); i != e; ++i) + Ptr[i] = FillStr[i % FillStr.size()]; + } } return Buffer; } diff --git a/test/PCH/inconsistent-pch.c b/test/PCH/inconsistent-pch.c new file mode 100644 index 0000000000..9573118c53 --- /dev/null +++ b/test/PCH/inconsistent-pch.c @@ -0,0 +1,15 @@ +// Check that we don't crash in an inconsistent situation created by the stat +// cache. + +// RUN: echo 'void f0(float *a0);' > %t.h +// RUN: clang-cc -emit-pch -o %t.h.pch %t.h +// RUN: rm %t.h +// RUN: not clang-cc -include-pch %t.h.pch %s 2> %t.err +// RUN: FileCheck %s < %t.err + +// CHECK: inconsistent-pch.c:{{.*}}:{{.*}}: error: conflicting types for 'f0' +// CHECK: void f0(int *a0); +// CHECK: inconsistent-pch.c.tmp.h:{{.*}}:{{.*}}: note: previous declaration is here +// CHECK: 2 diagnostics generated. + +void f0(int *a0); |