summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang-c/FatalErrorHandler.h33
-rw-r--r--clang/tools/libclang/CIndex.cpp11
-rw-r--r--clang/tools/libclang/CMakeLists.txt2
-rw-r--r--clang/tools/libclang/FatalErrorHandler.cpp28
-rw-r--r--clang/tools/libclang/libclang.exports2
-rw-r--r--clang/unittests/libclang/CMakeLists.txt2
-rw-r--r--clang/unittests/libclang/CrashTests/CMakeLists.txt8
-rw-r--r--clang/unittests/libclang/CrashTests/LibclangCrashTest.cpp36
8 files changed, 113 insertions, 9 deletions
diff --git a/clang/include/clang-c/FatalErrorHandler.h b/clang/include/clang-c/FatalErrorHandler.h
new file mode 100644
index 00000000000..74c9a8fe98b
--- /dev/null
+++ b/clang/include/clang-c/FatalErrorHandler.h
@@ -0,0 +1,33 @@
+/*===-- clang-c/FatalErrorHandler.h - Fatal Error Handling --------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
+#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Installs error handler that prints error message to stderr and calls abort().
+ * Replaces currently installed error handler (if any).
+ */
+void clang_install_aborting_llvm_fatal_error_handler();
+
+/**
+ * Removes currently installed error handler (if any).
+ * If no error handler is intalled, the default strategy is to print error
+ * message to stderr and call exit(1).
+ */
+void clang_uninstall_llvm_fatal_error_handler();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 5ea2d5e4a8c..5e77808a749 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -20,6 +20,7 @@
#include "CXTranslationUnit.h"
#include "CXType.h"
#include "CursorVisitor.h"
+#include "clang-c/FatalErrorHandler.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtVisitor.h"
@@ -3243,18 +3244,10 @@ RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
// Misc. API hooks.
//===----------------------------------------------------------------------===//
-static void fatal_error_handler(void *user_data, const std::string& reason,
- bool gen_crash_diag) {
- // Write the result out to stderr avoiding errs() because raw_ostreams can
- // call report_fatal_error.
- fprintf(stderr, "LIBCLANG FATAL ERROR: %s\n", reason.c_str());
- ::abort();
-}
-
namespace {
struct RegisterFatalErrorHandler {
RegisterFatalErrorHandler() {
- llvm::install_fatal_error_handler(fatal_error_handler, nullptr);
+ clang_install_aborting_llvm_fatal_error_handler();
}
};
}
diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt
index 9fd24ff463a..bd0c945a5e1 100644
--- a/clang/tools/libclang/CMakeLists.txt
+++ b/clang/tools/libclang/CMakeLists.txt
@@ -19,6 +19,7 @@ set(SOURCES
CXString.cpp
CXType.cpp
Indexing.cpp
+ FatalErrorHandler.cpp
ADDITIONAL_HEADERS
CIndexDiagnostic.h
@@ -43,6 +44,7 @@ set(LIBS
clangSema
clangSerialization
clangTooling
+ LLVMSupport
)
if (CLANG_ENABLE_ARCMT)
diff --git a/clang/tools/libclang/FatalErrorHandler.cpp b/clang/tools/libclang/FatalErrorHandler.cpp
new file mode 100644
index 00000000000..e9a0d41bab3
--- /dev/null
+++ b/clang/tools/libclang/FatalErrorHandler.cpp
@@ -0,0 +1,28 @@
+/*===-- clang-c/FatalErrorHandler.cpp - Fatal Error Handling ------*- C -*-===*\
+|* *|
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
+|* Exceptions. *|
+|* See https://llvm.org/LICENSE.txt for license information. *|
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#include "clang-c/FatalErrorHandler.h"
+#include "llvm/Support/ErrorHandling.h"
+
+static void aborting_fatal_error_handler(void *, const std::string &reason,
+ bool) {
+ // Write the result out to stderr avoiding errs() because raw_ostreams can
+ // call report_fatal_error.
+ fprintf(stderr, "LIBCLANG FATAL ERROR: %s\n", reason.c_str());
+ ::abort();
+}
+
+void clang_install_aborting_llvm_fatal_error_handler() {
+ llvm::remove_fatal_error_handler();
+ llvm::install_fatal_error_handler(aborting_fatal_error_handler, nullptr);
+}
+
+void clang_uninstall_llvm_fatal_error_handler() {
+ llvm::remove_fatal_error_handler();
+}
diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index 3c76090d64f..9408c02083f 100644
--- a/clang/tools/libclang/libclang.exports
+++ b/clang/tools/libclang/libclang.exports
@@ -379,3 +379,5 @@ clang_EvalResult_dispose
clang_PrintingPolicy_getProperty
clang_PrintingPolicy_setProperty
clang_PrintingPolicy_dispose
+clang_install_aborting_llvm_fatal_error_handler
+clang_uninstall_llvm_fatal_error_handler
diff --git a/clang/unittests/libclang/CMakeLists.txt b/clang/unittests/libclang/CMakeLists.txt
index 36f6089787d..b3644a0e710 100644
--- a/clang/unittests/libclang/CMakeLists.txt
+++ b/clang/unittests/libclang/CMakeLists.txt
@@ -6,3 +6,5 @@ target_link_libraries(libclangTests
PRIVATE
libclang
)
+
+add_subdirectory(CrashTests)
diff --git a/clang/unittests/libclang/CrashTests/CMakeLists.txt b/clang/unittests/libclang/CrashTests/CMakeLists.txt
new file mode 100644
index 00000000000..82f0e4c16e9
--- /dev/null
+++ b/clang/unittests/libclang/CrashTests/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_clang_unittest(libclangCrashTests
+ LibclangCrashTest.cpp
+ )
+
+target_link_libraries(libclangCrashTests
+ PRIVATE
+ libclang
+ )
diff --git a/clang/unittests/libclang/CrashTests/LibclangCrashTest.cpp b/clang/unittests/libclang/CrashTests/LibclangCrashTest.cpp
new file mode 100644
index 00000000000..821ef849ae3
--- /dev/null
+++ b/clang/unittests/libclang/CrashTests/LibclangCrashTest.cpp
@@ -0,0 +1,36 @@
+//===- unittests/libclang/LibclangCrashTest.cpp --- libclang tests --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../TestUtils.h"
+#include "clang-c/FatalErrorHandler.h"
+#include "gtest/gtest.h"
+#include <string>
+
+TEST_F(LibclangParseTest, InstallAbortingLLVMFatalErrorHandler) {
+ clang_toggleCrashRecovery(0);
+ clang_install_aborting_llvm_fatal_error_handler();
+
+ std::string Main = "main.h";
+ WriteFile(Main, "#pragma clang __debug llvm_fatal_error");
+
+ EXPECT_DEATH(clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags),
+ "");
+}
+
+TEST_F(LibclangParseTest, UninstallAbortingLLVMFatalErrorHandler) {
+ clang_toggleCrashRecovery(0);
+ clang_install_aborting_llvm_fatal_error_handler();
+ clang_uninstall_llvm_fatal_error_handler();
+
+ std::string Main = "main.h";
+ WriteFile(Main, "#pragma clang __debug llvm_fatal_error");
+
+ EXPECT_NO_FATAL_FAILURE(clang_parseTranslationUnit(
+ Index, Main.c_str(), nullptr, 0, nullptr, 0, TUFlags));
+}
OpenPOWER on IntegriCloud