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;
}
--- /dev/null
+// 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);