|
@@ -5,6 +5,8 @@
|
|
|
#ifndef COMMON_CHECK_INTERNAL_H_
|
|
#ifndef COMMON_CHECK_INTERNAL_H_
|
|
|
#define COMMON_CHECK_INTERNAL_H_
|
|
#define COMMON_CHECK_INTERNAL_H_
|
|
|
|
|
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
#include "llvm/Support/Signals.h"
|
|
#include "llvm/Support/Signals.h"
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
@@ -23,6 +25,12 @@ class ExitingStream {
|
|
|
// Internal type used in macros to dispatch to the `operator|` overload.
|
|
// Internal type used in macros to dispatch to the `operator|` overload.
|
|
|
struct Helper {};
|
|
struct Helper {};
|
|
|
|
|
|
|
|
|
|
+ ExitingStream() {
|
|
|
|
|
+ // Start all messages with a stack trace.
|
|
|
|
|
+ llvm::errs() << "Stack trace:\n";
|
|
|
|
|
+ llvm::sys::PrintStackTrace(llvm::errs());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
[[noreturn]] ~ExitingStream() {
|
|
[[noreturn]] ~ExitingStream() {
|
|
|
llvm_unreachable(
|
|
llvm_unreachable(
|
|
|
"Exiting streams should only be constructed by check.h macros that "
|
|
"Exiting streams should only be constructed by check.h macros that "
|
|
@@ -45,7 +53,7 @@ class ExitingStream {
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- auto operator<<(AddSeparator /*discarded*/) -> ExitingStream& {
|
|
|
|
|
|
|
+ auto operator<<(AddSeparator /*add_separator*/) -> ExitingStream& {
|
|
|
separator_ = true;
|
|
separator_ = true;
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
@@ -53,10 +61,14 @@ class ExitingStream {
|
|
|
// Low-precedence binary operator overload used in check.h macros to flush the
|
|
// Low-precedence binary operator overload used in check.h macros to flush the
|
|
|
// output and exit the program. We do this in a binary operator rather than
|
|
// output and exit the program. We do this in a binary operator rather than
|
|
|
// the destructor to ensure good debug info and backtraces for errors.
|
|
// the destructor to ensure good debug info and backtraces for errors.
|
|
|
- [[noreturn]] friend auto operator|(Helper /*discarded*/, ExitingStream& rhs) {
|
|
|
|
|
|
|
+ [[noreturn]] friend auto operator|(Helper /*helper*/,
|
|
|
|
|
+ ExitingStream& /*rhs*/) {
|
|
|
// Finish with a newline.
|
|
// Finish with a newline.
|
|
|
llvm::errs() << "\n";
|
|
llvm::errs() << "\n";
|
|
|
- std::abort();
|
|
|
|
|
|
|
+ // We assume LLVM's exit handling is installed, which will stack trace on
|
|
|
|
|
+ // std::abort(). We print a stack trace on construction, so this avoids that
|
|
|
|
|
+ // stack trace on exit.
|
|
|
|
|
+ _exit(1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
private:
|