|
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