Line data Source code
1 : //===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file defines an API used to indicate fatal error conditions. Non-fatal
11 : // errors (most of them) should be handled through LLVMContext.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #ifndef LLVM_SUPPORT_ERRORHANDLING_H
16 : #define LLVM_SUPPORT_ERRORHANDLING_H
17 :
18 : #include "llvm/Support/Compiler.h"
19 : #include <string>
20 :
21 : namespace llvm {
22 : class StringRef;
23 : class Twine;
24 :
25 : /// An error handler callback.
26 : typedef void (*fatal_error_handler_t)(void *user_data,
27 : const std::string& reason,
28 : bool gen_crash_diag);
29 :
30 : /// install_fatal_error_handler - Installs a new error handler to be used
31 : /// whenever a serious (non-recoverable) error is encountered by LLVM.
32 : ///
33 : /// If no error handler is installed the default is to print the error message
34 : /// to stderr, and call exit(1). If an error handler is installed then it is
35 : /// the handler's responsibility to log the message, it will no longer be
36 : /// printed to stderr. If the error handler returns, then exit(1) will be
37 : /// called.
38 : ///
39 : /// It is dangerous to naively use an error handler which throws an exception.
40 : /// Even though some applications desire to gracefully recover from arbitrary
41 : /// faults, blindly throwing exceptions through unfamiliar code isn't a way to
42 : /// achieve this.
43 : ///
44 : /// \param user_data - An argument which will be passed to the install error
45 : /// handler.
46 : void install_fatal_error_handler(fatal_error_handler_t handler,
47 : void *user_data = nullptr);
48 :
49 : /// Restores default error handling behaviour.
50 : void remove_fatal_error_handler();
51 :
52 : /// ScopedFatalErrorHandler - This is a simple helper class which just
53 : /// calls install_fatal_error_handler in its constructor and
54 : /// remove_fatal_error_handler in its destructor.
55 : struct ScopedFatalErrorHandler {
56 : explicit ScopedFatalErrorHandler(fatal_error_handler_t handler,
57 : void *user_data = nullptr) {
58 15 : install_fatal_error_handler(handler, user_data);
59 : }
60 :
61 15 : ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); }
62 : };
63 :
64 : /// Reports a serious error, calling any installed error handler. These
65 : /// functions are intended to be used for error conditions which are outside
66 : /// the control of the compiler (I/O errors, invalid user input, etc.)
67 : ///
68 : /// If no error handler is installed the default is to print the message to
69 : /// standard error, followed by a newline.
70 : /// After the error handler is called this function will call exit(1), it
71 : /// does not return.
72 : LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
73 : bool gen_crash_diag = true);
74 : LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
75 : bool gen_crash_diag = true);
76 : LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason,
77 : bool gen_crash_diag = true);
78 : LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason,
79 : bool gen_crash_diag = true);
80 :
81 : /// Installs a new bad alloc error handler that should be used whenever a
82 : /// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
83 : ///
84 : /// The user can install a bad alloc handler, in order to define the behavior
85 : /// in case of failing allocations, e.g. throwing an exception. Note that this
86 : /// handler must not trigger any additional allocations itself.
87 : ///
88 : /// If no error handler is installed the default is to print the error message
89 : /// to stderr, and call exit(1). If an error handler is installed then it is
90 : /// the handler's responsibility to log the message, it will no longer be
91 : /// printed to stderr. If the error handler returns, then exit(1) will be
92 : /// called.
93 : ///
94 : ///
95 : /// \param user_data - An argument which will be passed to the installed error
96 : /// handler.
97 : void install_bad_alloc_error_handler(fatal_error_handler_t handler,
98 : void *user_data = nullptr);
99 :
100 : /// Restores default bad alloc error handling behavior.
101 : void remove_bad_alloc_error_handler();
102 :
103 : void install_out_of_memory_new_handler();
104 :
105 : /// Reports a bad alloc error, calling any user defined bad alloc
106 : /// error handler. In contrast to the generic 'report_fatal_error'
107 : /// functions, this function is expected to return, e.g. the user
108 : /// defined error handler throws an exception.
109 : ///
110 : /// Note: When throwing an exception in the bad alloc handler, make sure that
111 : /// the following unwind succeeds, e.g. do not trigger additional allocations
112 : /// in the unwind chain.
113 : ///
114 : /// If no error handler is installed (default), then a bad_alloc exception
115 : /// is thrown, if LLVM is compiled with exception support, otherwise an assertion
116 : /// is called.
117 : void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true);
118 :
119 : /// This function calls abort(), and prints the optional message to stderr.
120 : /// Use the llvm_unreachable macro (that adds location info), instead of
121 : /// calling this function directly.
122 : LLVM_ATTRIBUTE_NORETURN void
123 : llvm_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
124 : unsigned line = 0);
125 : }
126 :
127 : /// Marks that the current location is not supposed to be reachable.
128 : /// In !NDEBUG builds, prints the message and location info to stderr.
129 : /// In NDEBUG builds, becomes an optimizer hint that the current location
130 : /// is not supposed to be reachable. On compilers that don't support
131 : /// such hints, prints a reduced message instead.
132 : ///
133 : /// Use this instead of assert(0). It conveys intent more clearly and
134 : /// allows compilers to omit some unnecessary code.
135 : #ifndef NDEBUG
136 : #define llvm_unreachable(msg) \
137 : ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
138 : #elif defined(LLVM_BUILTIN_UNREACHABLE)
139 : #define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
140 : #else
141 : #define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
142 : #endif
143 :
144 : #endif
|