Index: cfe/trunk/include/clang-c/FatalErrorHandler.h =================================================================== --- cfe/trunk/include/clang-c/FatalErrorHandler.h +++ cfe/trunk/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 Index: cfe/trunk/tools/libclang/CIndex.cpp =================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/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 @@ // 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(); } }; } Index: cfe/trunk/tools/libclang/CMakeLists.txt =================================================================== --- cfe/trunk/tools/libclang/CMakeLists.txt +++ cfe/trunk/tools/libclang/CMakeLists.txt @@ -19,6 +19,7 @@ CXString.cpp CXType.cpp Indexing.cpp + FatalErrorHandler.cpp ADDITIONAL_HEADERS CIndexDiagnostic.h @@ -43,6 +44,7 @@ clangSema clangSerialization clangTooling + LLVMSupport ) if (CLANG_ENABLE_ARCMT) Index: cfe/trunk/tools/libclang/FatalErrorHandler.cpp =================================================================== --- cfe/trunk/tools/libclang/FatalErrorHandler.cpp +++ cfe/trunk/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(); +} Index: cfe/trunk/tools/libclang/libclang.exports =================================================================== --- cfe/trunk/tools/libclang/libclang.exports +++ cfe/trunk/tools/libclang/libclang.exports @@ -379,3 +379,5 @@ clang_PrintingPolicy_getProperty clang_PrintingPolicy_setProperty clang_PrintingPolicy_dispose +clang_install_aborting_llvm_fatal_error_handler +clang_uninstall_llvm_fatal_error_handler Index: cfe/trunk/unittests/libclang/CMakeLists.txt =================================================================== --- cfe/trunk/unittests/libclang/CMakeLists.txt +++ cfe/trunk/unittests/libclang/CMakeLists.txt @@ -6,3 +6,5 @@ PRIVATE libclang ) + +add_subdirectory(CrashTests) Index: cfe/trunk/unittests/libclang/CrashTests/CMakeLists.txt =================================================================== --- cfe/trunk/unittests/libclang/CrashTests/CMakeLists.txt +++ cfe/trunk/unittests/libclang/CrashTests/CMakeLists.txt @@ -0,0 +1,8 @@ +add_clang_unittest(libclangCrashTests + LibclangCrashTest.cpp + ) + +target_link_libraries(libclangCrashTests + PRIVATE + libclang + ) Index: cfe/trunk/unittests/libclang/CrashTests/LibclangCrashTest.cpp =================================================================== --- cfe/trunk/unittests/libclang/CrashTests/LibclangCrashTest.cpp +++ cfe/trunk/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 + +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)); +}