|
17 | 17 | #ifndef SWIFT_BASIC_ASSERTIONS_H |
18 | 18 | #define SWIFT_BASIC_ASSERTIONS_H |
19 | 19 |
|
| 20 | +#include "swift/Basic/LLVM.h" |
| 21 | + |
20 | 22 | // Only for use in this header |
21 | 23 | #if __has_builtin(__builtin_expect) |
22 | 24 | #define ASSERT_UNLIKELY(expression) (__builtin_expect(!!(expression), 0)) |
23 | 25 | #else |
24 | 26 | #define ASSERT_UNLIKELY(expression) ((expression)) |
25 | 27 | #endif |
26 | 28 |
|
| 29 | +// Visual Studio doesn't have __FILE_NAME__ |
| 30 | +#ifdef __FILE_NAME__ |
| 31 | +#define _FILENAME_FOR_ASSERT __FILE_NAME__ |
| 32 | +#else |
| 33 | +#define _FILENAME_FOR_ASSERT __FILE__ |
| 34 | +#endif |
| 35 | + |
27 | 36 | // ================================ Mandatory Asserts ================================ |
28 | 37 |
|
29 | 38 | // `ASSERT(expr)`: |
|
41 | 50 | // that are more expensive than you think. You can switch those to |
42 | 51 | // `CONDITIONAL_ASSERT` or `DEBUG_ASSERT` as needed. |
43 | 52 |
|
44 | | -// Visual Studio doesn't have __FILE_NAME__ |
45 | | -#ifdef __FILE_NAME__ |
46 | | - |
47 | | -#define ASSERT(expr) \ |
48 | | - do { \ |
49 | | - if (ASSERT_UNLIKELY(!(expr))) { \ |
50 | | - ASSERT_failure(#expr, __FILE_NAME__, __LINE__, __func__); \ |
51 | | - } \ |
| 53 | +#define ASSERT(expr) \ |
| 54 | + do { \ |
| 55 | + if (ASSERT_UNLIKELY(!(expr))) { \ |
| 56 | + ASSERT_failure(#expr, _FILENAME_FOR_ASSERT, __LINE__, __func__); \ |
| 57 | + } \ |
52 | 58 | } while (0) |
53 | 59 |
|
54 | | -#else |
55 | | - |
56 | | -#define ASSERT(expr) \ |
57 | | - do { \ |
58 | | - if (ASSERT_UNLIKELY(!(expr))) { \ |
59 | | - ASSERT_failure(#expr, __FILE__, __LINE__, __func__); \ |
60 | | - } \ |
61 | | - } while (0) |
62 | | - |
63 | | -#endif |
64 | | - |
65 | 60 | // Function that reports the actual failure when it occurs. |
66 | 61 | void ASSERT_failure(const char *expr, const char *file, int line, const char *func); |
67 | 62 |
|
@@ -190,11 +185,33 @@ extern int CONDITIONAL_ASSERT_Global_enable_flag; |
190 | 185 | #define SWIFT_ASSERT_ONLY_DECL DEBUG_ASSERT_DECL |
191 | 186 | #define SWIFT_ASSERT_ONLY DEBUG_ASSERT_EXPR |
192 | 187 |
|
193 | | -// ================================ Utility and Helper Functions ================================ |
| 188 | +// ================================ Abort ====================================== |
194 | 189 |
|
195 | | -// Utility function to print out help information for |
196 | | -// various command-line options that affect the assertion |
197 | | -// behavior. |
198 | | -void ASSERT_help(); |
| 190 | +/// Implementation for \c ABORT, not to be used directly. |
| 191 | +[[noreturn]] |
| 192 | +void _ABORT(const char *file, int line, const char *func, |
| 193 | + llvm::function_ref<void(llvm::raw_ostream &)> message); |
| 194 | + |
| 195 | +/// Implementation for \c ABORT, not to be used directly. |
| 196 | +[[noreturn]] |
| 197 | +void _ABORT(const char *file, int line, const char *func, |
| 198 | + llvm::StringRef message); |
| 199 | + |
| 200 | +// Aborts the program, printing a given message to a PrettyStackTrace frame |
| 201 | +// before exiting. This should be preferred over manually logging to stderr and |
| 202 | +// `abort()`'ing since that won't be picked up by the crash reporter. |
| 203 | +// |
| 204 | +// There are two different forms of ABORT: |
| 205 | +// |
| 206 | +// ``` |
| 207 | +// ABORT("abort with string"); |
| 208 | +// |
| 209 | +// ABORT([&](auto &out) { |
| 210 | +// out << "abort with arbitrary stream"; |
| 211 | +// node.dump(out); |
| 212 | +// }); |
| 213 | +// ``` |
| 214 | +// |
| 215 | +#define ABORT(arg) _ABORT(_FILENAME_FOR_ASSERT, __LINE__, __func__, (arg)) |
199 | 216 |
|
200 | 217 | #endif // SWIFT_BASIC_ASSERTIONS_H |
0 commit comments