llvm-6502/lib/Support/ErrorHandling.cpp
Alp Toker 650e286dcf Roll back the ConstStringRef change for now
There are a couple of interesting things here that we want to check over
(particularly the expecting asserts in StringRef) and get right for general use
in ADT so hold back on this one. For clang we have a workable templated
solution to use in the meanwhile.

This reverts commit r200187.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200194 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-27 05:24:39 +00:00

122 lines
4.0 KiB
C++

//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an API used to indicate fatal error conditions. Non-fatal
// errors (most of them) should be handled through LLVMContext.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/ErrorHandling.h"
#include "llvm-c/Core.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdlib>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined(_MSC_VER)
# include <io.h>
# include <fcntl.h>
#endif
using namespace llvm;
static fatal_error_handler_t ErrorHandler = 0;
static void *ErrorHandlerUserData = 0;
void llvm::install_fatal_error_handler(fatal_error_handler_t handler,
void *user_data) {
assert(!llvm_is_multithreaded() &&
"Cannot register error handlers after starting multithreaded mode!\n");
assert(!ErrorHandler && "Error handler already registered!\n");
ErrorHandler = handler;
ErrorHandlerUserData = user_data;
}
void llvm::remove_fatal_error_handler() {
ErrorHandler = 0;
}
void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) {
report_fatal_error(Twine(Reason), GenCrashDiag);
}
void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) {
report_fatal_error(Twine(Reason), GenCrashDiag);
}
void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
report_fatal_error(Twine(Reason), GenCrashDiag);
}
void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
if (ErrorHandler) {
ErrorHandler(ErrorHandlerUserData, Reason.str(), GenCrashDiag);
} else {
// Blast the result out to stderr. We don't try hard to make sure this
// succeeds (e.g. handling EINTR) and we can't use errs() here because
// raw ostreams can call report_fatal_error.
SmallVector<char, 64> Buffer;
raw_svector_ostream OS(Buffer);
OS << "LLVM ERROR: " << Reason << "\n";
StringRef MessageStr = OS.str();
ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
(void)written; // If something went wrong, we deliberately just give up.
}
// If we reached here, we are failing ungracefully. Run the interrupt handlers
// to make sure any special cleanups get done, in particular that we remove
// files registered with RemoveFileOnSignal.
sys::RunInterruptHandlers();
exit(1);
}
void llvm::llvm_unreachable_internal(const char *msg, const char *file,
unsigned line) {
// This code intentionally doesn't call the ErrorHandler callback, because
// llvm_unreachable is intended to be used to indicate "impossible"
// situations, and not legitimate runtime errors.
if (msg)
dbgs() << msg << "\n";
dbgs() << "UNREACHABLE executed";
if (file)
dbgs() << " at " << file << ":" << line;
dbgs() << "!\n";
abort();
#ifdef LLVM_BUILTIN_UNREACHABLE
// Windows systems and possibly others don't declare abort() to be noreturn,
// so use the unreachable builtin to avoid a Clang self-host warning.
LLVM_BUILTIN_UNREACHABLE;
#endif
}
static void bindingsErrorHandler(void *user_data, const std::string& reason,
bool gen_crash_diag) {
LLVMFatalErrorHandler handler =
LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
handler(reason.c_str());
}
void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) {
install_fatal_error_handler(bindingsErrorHandler,
LLVM_EXTENSION reinterpret_cast<void *>(Handler));
}
void LLVMResetFatalErrorHandler() {
remove_fatal_error_handler();
}