]> granicus.if.org Git - clang/commitdiff
[libclang] Store unsaved file hashes when recording parsing invocations
authorAlex Lorenz <arphaman@gmail.com>
Tue, 5 Dec 2017 02:30:43 +0000 (02:30 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 5 Dec 2017 02:30:43 +0000 (02:30 +0000)
Storing the contents of unsaved files is too expensive.
Instead a hash is stored with a record invocation. When a reproducer is
generated, Clang will compare the stored hashes to the new hashes to determine
if the contents of a file has changed. This way we'll know when a reproducer was
generated for a different source to the one that triggered the original crash.

rdar://35322543

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319729 91177308-0d34-0410-b5e6-96231b3b80d8

test/Index/Inputs/record-parsing-invocation-remap.c [new file with mode: 0644]
test/Index/record-parsing-invocation.c
tools/libclang/CIndex.cpp
tools/libclang/CIndexer.cpp
tools/libclang/CIndexer.h

diff --git a/test/Index/Inputs/record-parsing-invocation-remap.c b/test/Index/Inputs/record-parsing-invocation-remap.c
new file mode 100644 (file)
index 0000000..4a32ca6
--- /dev/null
@@ -0,0 +1,2 @@
+
+#pragma clang __debug parser_crash
index 3daa71c028076c4e9ca92aac8a13dc2807d9a0d2..31883a93737e2e2dbacc76cb90de810e295ceb50 100644 (file)
 // RUN: env CINDEXTEST_INVOCATION_EMISSION_PATH=%t c-index-test -test-load-source all %s -DAVOID_CRASH
 // RUN: ls %t | count 0
 
+// Make sure we record the unsaved file hash.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: not env CINDEXTEST_INVOCATION_EMISSION_PATH=%t c-index-test -test-load-source all "-remap-file=%s,%S/Inputs/record-parsing-invocation-remap.c" %s
+// RUN: cat %t/libclang-* | FileCheck --check-prefix=CHECK-UNSAVED %s
+
 #ifndef AVOID_CRASH
 #  pragma clang __debug parser_crash
 #endif
 
 // CHECK: {"toolchain":"{{.*}}","libclang.operation":"parse","libclang.opts":1,"args":["clang","-fno-spell-checking","{{.*}}record-parsing-invocation.c","-Xclang","-detailed-preprocessing-record","-fallow-editor-placeholders"]}
+// CHECK-UNSAVED: {"toolchain":"{{.*}}","libclang.operation":"parse","libclang.opts":1,"args":["clang","-fno-spell-checking","{{.*}}record-parsing-invocation.c","-Xclang","-detailed-preprocessing-record","-fallow-editor-placeholders"],"unsaved_file_hashes":[{"name":"{{.*}}record-parsing-invocation.c","md5":"aee23773de90e665992b48209351d70e"}]}
index b642014c439665a5b9ff25968906d2eac5abef29..b2edd42cb0df7f9917e37eb30ec42fccf51bef32 100644 (file)
@@ -3438,10 +3438,9 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
   unsigned PrecompilePreambleAfterNParses =
       !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
 
-  // FIXME: Record the hash of the unsaved files.
   LibclangInvocationReporter InvocationReporter(
       *CXXIdx, LibclangInvocationReporter::OperationKind::ParseOperation,
-      options, llvm::makeArrayRef(*Args));
+      options, llvm::makeArrayRef(*Args), unsaved_files);
   std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
       Args->data(), Args->data() + Args->size(),
       CXXIdx->getPCHContainerOperations(), Diags,
index 13774bd8b71fe48e5043f421f57bbfa43affc632..b70501625103b4567c8b9b59a9cf862d450cb58c 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "CIndexer.h"
+#include "CXString.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/Version.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Support/MD5.h"
 #include "llvm/Support/MutexGuard.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
@@ -90,7 +92,8 @@ StringRef CIndexer::getClangToolchainPath() {
 
 LibclangInvocationReporter::LibclangInvocationReporter(
     CIndexer &Idx, OperationKind Op, unsigned ParseOptions,
-    llvm::ArrayRef<const char *> Args) {
+    llvm::ArrayRef<const char *> Args,
+    llvm::ArrayRef<CXUnsavedFile> UnsavedFiles) {
   StringRef Path = Idx.getInvocationEmissionPath();
   if (Path.empty())
     return;
@@ -124,6 +127,23 @@ LibclangInvocationReporter::LibclangInvocationReporter(
       OS << ',';
     OS << '"' << I.value() << '"';
   }
+  if (!UnsavedFiles.empty()) {
+    OS << R"(],"unsaved_file_hashes":[)";
+    for (const auto &UF : llvm::enumerate(UnsavedFiles)) {
+      if (UF.index())
+        OS << ',';
+      OS << '{';
+      WriteStringKey("name", UF.value().Filename);
+      OS << ',';
+      llvm::MD5 Hash;
+      Hash.update(getContents(UF.value()));
+      llvm::MD5::MD5Result Result;
+      Hash.final(Result);
+      SmallString<32> Digest = Result.digest();
+      WriteStringKey("md5", Digest);
+      OS << '}';
+    }
+  }
   OS << "]}";
 }
 
index b3346cd955c5e752b3d7f583afef7ababe0469e9..dafbb08cfa76718e177b7658c4d76fd36cdd1392 100644 (file)
@@ -94,7 +94,8 @@ public:
 
   LibclangInvocationReporter(CIndexer &Idx, OperationKind Op,
                              unsigned ParseOptions,
-                             llvm::ArrayRef<const char *> Args);
+                             llvm::ArrayRef<const char *> Args,
+                             llvm::ArrayRef<CXUnsavedFile> UnsavedFiles);
   ~LibclangInvocationReporter();
 
 private: