r319702 - [libclang] Record parsing invocation to a temporary file when requested
Alex Lorenz via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 4 13:56:36 PST 2017
Author: arphaman
Date: Mon Dec 4 13:56:36 2017
New Revision: 319702
URL: http://llvm.org/viewvc/llvm-project?rev=319702&view=rev
Log:
[libclang] Record parsing invocation to a temporary file when requested
by client
This patch extends libclang by allowing it to record parsing operations to a
temporary JSON file. The file is deleted after parsing succeeds. When a crash
happens during parsing, the file is preserved and the client will be able to use
it to generate a reproducer for the crash.
These files are not emitted by default, and the client has to specify the
invocation emission path first.
rdar://35322543
Differential Revision: https://reviews.llvm.org/D40527
Added:
cfe/trunk/test/Index/record-parsing-invocation.c
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CIndexer.cpp
cfe/trunk/tools/libclang/CIndexer.h
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Mon Dec 4 13:56:36 2017
@@ -334,6 +334,16 @@ CINDEX_LINKAGE void clang_CXIndex_setGlo
CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
/**
+ * \brief Sets the invocation emission path option in a CXIndex.
+ *
+ * The invocation emission path specifies a path which will contain log
+ * files for certain libclang invocations. A null value (default) implies that
+ * libclang invocations are not logged..
+ */
+CINDEX_LINKAGE void
+clang_CXIndex_setInvocationEmissionPathOption(CXIndex, const char *Path);
+
+/**
* \defgroup CINDEX_FILES File manipulation routines
*
* @{
Added: cfe/trunk/test/Index/record-parsing-invocation.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/record-parsing-invocation.c?rev=319702&view=auto
==============================================================================
--- cfe/trunk/test/Index/record-parsing-invocation.c (added)
+++ cfe/trunk/test/Index/record-parsing-invocation.c Mon Dec 4 13:56:36 2017
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: not env CINDEXTEST_INVOCATION_EMISSION_PATH=%t c-index-test -test-load-source all %s
+// RUN: cat %t/libclang-* | FileCheck %s
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 CINDEXTEST_INVOCATION_EMISSION_PATH=%t not --crash c-index-test -test-load-source all %s
+// RUN: cat %t/libclang-* | FileCheck %s
+
+// Verify that the file is removed for successful operation:
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: env CINDEXTEST_INVOCATION_EMISSION_PATH=%t c-index-test -test-load-source all %s -DAVOID_CRASH
+// RUN: ls %t | count 0
+
+#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"]}
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Mon Dec 4 13:56:36 2017
@@ -1747,11 +1747,15 @@ int perform_test_load_source(int argc, c
int result;
unsigned Repeats = 0;
unsigned I;
+ const char *InvocationPath;
Idx = clang_createIndex(/* excludeDeclsFromPCH */
(!strcmp(filter, "local") ||
!strcmp(filter, "local-display"))? 1 : 0,
/* displayDiagnostics=*/1);
+ InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
+ if (InvocationPath)
+ clang_CXIndex_setInvocationEmissionPathOption(Idx, InvocationPath);
if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
argc--;
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Dec 4 13:56:36 2017
@@ -3255,6 +3255,12 @@ unsigned clang_CXIndex_getGlobalOptions(
return 0;
}
+void clang_CXIndex_setInvocationEmissionPathOption(CXIndex CIdx,
+ const char *Path) {
+ if (CIdx)
+ static_cast<CIndexer *>(CIdx)->setInvocationEmissionPath(Path ? Path : "");
+}
+
void clang_toggleCrashRecovery(unsigned isEnabled) {
if (isEnabled)
llvm::CrashRecoveryContext::Enable();
@@ -3431,6 +3437,11 @@ clang_parseTranslationUnit_Impl(CXIndex
// faster, trading for a slower (first) reparse.
unsigned PrecompilePreambleAfterNParses =
!PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse;
+
+ // FIXME: Record the hash of the unsaved files.
+ LibclangInvocationReporter InvocationReporter(
+ *CXXIdx, LibclangInvocationReporter::OperationKind::ParseOperation,
+ options, llvm::makeArrayRef(*Args));
std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCommandLine(
Args->data(), Args->data() + Args->size(),
CXXIdx->getPCHContainerOperations(), Diags,
Modified: cfe/trunk/tools/libclang/CIndexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexer.cpp?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexer.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexer.cpp Mon Dec 4 13:56:36 2017
@@ -14,8 +14,10 @@
#include "CIndexer.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/MutexGuard.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include <cstdio>
@@ -76,3 +78,56 @@ const std::string &CIndexer::getClangRes
ResourcesPath = LibClangPath.str();
return ResourcesPath;
}
+
+StringRef CIndexer::getClangToolchainPath() {
+ if (!ToolchainPath.empty())
+ return ToolchainPath;
+ StringRef ResourcePath = getClangResourcesPath();
+ ToolchainPath = llvm::sys::path::parent_path(
+ llvm::sys::path::parent_path(llvm::sys::path::parent_path(ResourcePath)));
+ return ToolchainPath;
+}
+
+LibclangInvocationReporter::LibclangInvocationReporter(
+ CIndexer &Idx, OperationKind Op, unsigned ParseOptions,
+ llvm::ArrayRef<const char *> Args) {
+ StringRef Path = Idx.getInvocationEmissionPath();
+ if (Path.empty())
+ return;
+
+ // Create a temporary file for the invocation log.
+ SmallString<256> TempPath;
+ TempPath = Path;
+ llvm::sys::path::append(TempPath, "libclang-%%%%%%%%%%%%");
+ int FD;
+ if (llvm::sys::fs::createUniqueFile(TempPath, FD, TempPath))
+ return;
+ File = std::string(TempPath.begin(), TempPath.end());
+ llvm::raw_fd_ostream OS(FD, /*ShouldClose=*/true);
+
+ // Write out the information about the invocation to it.
+ auto WriteStringKey = [&OS](StringRef Key, StringRef Value) {
+ OS << R"(")" << Key << R"(":")";
+ OS << Value << '"';
+ };
+ OS << '{';
+ WriteStringKey("toolchain", Idx.getClangToolchainPath());
+ OS << ',';
+ WriteStringKey("libclang.operation",
+ Op == OperationKind::ParseOperation ? "parse" : "complete");
+ OS << ',';
+ OS << R"("libclang.opts":)" << ParseOptions;
+ OS << ',';
+ OS << R"("args":[)";
+ for (const auto &I : llvm::enumerate(Args)) {
+ if (I.index())
+ OS << ',';
+ OS << '"' << I.value() << '"';
+ }
+ OS << "]}";
+}
+
+LibclangInvocationReporter::~LibclangInvocationReporter() {
+ if (!File.empty())
+ llvm::sys::fs::remove(File);
+}
Modified: cfe/trunk/tools/libclang/CIndexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexer.h?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexer.h (original)
+++ cfe/trunk/tools/libclang/CIndexer.h Mon Dec 4 13:56:36 2017
@@ -18,6 +18,7 @@
#include "clang-c/Index.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Mutex.h"
#include <utility>
namespace llvm {
@@ -40,6 +41,10 @@ class CIndexer {
std::string ResourcesPath;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+ std::string ToolchainPath;
+
+ std::string InvocationEmissionPath;
+
public:
CIndexer(std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>())
@@ -71,6 +76,29 @@ public:
/// \brief Get the path of the clang resource files.
const std::string &getClangResourcesPath();
+
+ StringRef getClangToolchainPath();
+
+ void setInvocationEmissionPath(StringRef Str) {
+ InvocationEmissionPath = Str;
+ }
+
+ StringRef getInvocationEmissionPath() const { return InvocationEmissionPath; }
+};
+
+/// Logs information about a particular libclang operation like parsing to
+/// a new file in the invocation emission path.
+class LibclangInvocationReporter {
+public:
+ enum class OperationKind { ParseOperation, CompletionOperation };
+
+ LibclangInvocationReporter(CIndexer &Idx, OperationKind Op,
+ unsigned ParseOptions,
+ llvm::ArrayRef<const char *> Args);
+ ~LibclangInvocationReporter();
+
+private:
+ std::string File;
};
/// \brief Return the current size to request for "safety".
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=319702&r1=319701&r2=319702&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Mon Dec 4 13:56:36 2017
@@ -2,6 +2,7 @@ clang_CXCursorSet_contains
clang_CXCursorSet_insert
clang_CXIndex_getGlobalOptions
clang_CXIndex_setGlobalOptions
+clang_CXIndex_setInvocationEmissionPathOption
clang_CXXConstructor_isConvertingConstructor
clang_CXXConstructor_isCopyConstructor
clang_CXXConstructor_isDefaultConstructor
More information about the cfe-commits
mailing list