[cfe-commits] r90699 - in /cfe/trunk: lib/Basic/SourceManager.cpp test/PCH/inconsistent-pch.c

Daniel Dunbar daniel at zuster.org
Sat Dec 5 21:43:36 PST 2009


Author: ddunbar
Date: Sat Dec  5 23:43:36 2009
New Revision: 90699

URL: http://llvm.org/viewvc/llvm-project?rev=90699&view=rev
Log:
Add a pretty horrible hack to prevent clang from crashing with inconsistent PCH
files.
 - The issue is that PCH uses a stat cache, which may reference files which have
   been deleted or moved. In such cases ContentCache::getBuffer was returning 0
   but most clients are incapable of dealing with this (i.e., they don't).

   For the time being, resolve this issue by just making up some invalid file
   contents and. Eventually we should detect that we are in an inconsistent
   situation and error out with a nice message that the PCH is out of date.

Added:
    cfe/trunk/test/PCH/inconsistent-pch.c
Modified:
    cfe/trunk/lib/Basic/SourceManager.cpp

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=90699&r1=90698&r2=90699&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Sat Dec  5 23:43:36 2009
@@ -56,9 +56,25 @@
 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;
 }

Added: cfe/trunk/test/PCH/inconsistent-pch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/inconsistent-pch.c?rev=90699&view=auto

==============================================================================
--- cfe/trunk/test/PCH/inconsistent-pch.c (added)
+++ cfe/trunk/test/PCH/inconsistent-pch.c Sat Dec  5 23:43:36 2009
@@ -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);





More information about the cfe-commits mailing list