Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/error/error_macros.h
20791 views
1
/**************************************************************************/
2
/* error_macros.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/typedefs.h"
34
35
#ifdef _MSC_VER
36
#include <intrin.h> // `__fastfail()`.
37
#endif
38
39
class String;
40
class ObjectID;
41
42
enum ErrorHandlerType {
43
ERR_HANDLER_ERROR,
44
ERR_HANDLER_WARNING,
45
ERR_HANDLER_SCRIPT,
46
ERR_HANDLER_SHADER,
47
};
48
49
constexpr const char *_error_handler_type_string(ErrorHandlerType p_type) {
50
switch (p_type) {
51
case ERR_HANDLER_ERROR:
52
return "ERROR";
53
case ERR_HANDLER_WARNING:
54
return "WARNING";
55
case ERR_HANDLER_SCRIPT:
56
return "SCRIPT ERROR";
57
case ERR_HANDLER_SHADER:
58
return "SHADER ERROR";
59
}
60
return "UNKNOWN ERROR";
61
}
62
63
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
64
// Parameters: userdata, function, file, line, error, explanation, type.
65
typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type);
66
67
struct ErrorHandlerList {
68
ErrorHandlerFunc errfunc = nullptr;
69
void *userdata = nullptr;
70
71
ErrorHandlerList *next = nullptr;
72
};
73
74
void add_error_handler(ErrorHandlerList *p_handler);
75
void remove_error_handler(const ErrorHandlerList *p_handler);
76
77
// Functions used by the error macros.
78
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
79
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
80
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
81
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
82
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
83
_NO_INLINE_ void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
84
void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
85
_NO_INLINE_ void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false);
86
_NO_INLINE_ void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
87
_NO_INLINE_ void _err_flush_stdout();
88
89
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string);
90
91
#ifdef __GNUC__
92
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
93
#define FUNCTION_STR __FUNCTION__
94
#else
95
#define FUNCTION_STR __FUNCTION__
96
#endif
97
98
#ifdef _MSC_VER
99
/**
100
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
101
*/
102
#define GENERATE_TRAP() __fastfail(7 /* FAST_FAIL_FATAL_APP_EXIT */)
103
#else
104
/**
105
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
106
*/
107
#define GENERATE_TRAP() __builtin_trap()
108
#endif
109
110
/**
111
* Error macros.
112
* WARNING: These macros work in the opposite way to assert().
113
*
114
* Unlike exceptions and asserts, these macros try to maintain consistency and stability.
115
* In most cases, bugs and/or invalid data are not fatal. They should never allow a perfectly
116
* running application to fail or crash.
117
* Always try to return processable data, so the engine can keep running well.
118
* Use the _MSG versions to print a meaningful message to help with debugging.
119
*
120
* The `((void)0)` no-op statement is used as a trick to force us to put a semicolon after
121
* those macros, making them look like proper statements.
122
* The if wrappers are used to ensure that the macro replacement does not trigger unexpected
123
* issues when expanded e.g. after an `if (cond) ERR_FAIL();` without braces.
124
*/
125
126
// Index out of bounds error macros.
127
// These macros should be used instead of `ERR_FAIL_COND` for bounds checking.
128
129
// Integer index out of bounds error macros.
130
131
/**
132
* Try using `ERR_FAIL_INDEX_MSG`.
133
* Only use this macro if there is no sensible error message.
134
*
135
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
136
* If not, the current function returns.
137
*/
138
#define ERR_FAIL_INDEX(m_index, m_size) \
139
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
140
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
141
return; \
142
} else \
143
((void)0)
144
145
/**
146
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
147
* If not, prints `m_msg` and the current function returns.
148
*/
149
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
150
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
151
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
152
return; \
153
} else \
154
((void)0)
155
156
/**
157
* Same as `ERR_FAIL_INDEX_MSG` but also notifies the editor.
158
*/
159
#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
160
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
161
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
162
return; \
163
} else \
164
((void)0)
165
166
/**
167
* Try using `ERR_FAIL_INDEX_V_MSG`.
168
* Only use this macro if there is no sensible error message.
169
*
170
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
171
* If not, the current function returns `m_retval`.
172
*/
173
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
174
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
175
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
176
return m_retval; \
177
} else \
178
((void)0)
179
180
/**
181
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
182
* If not, prints `m_msg` and the current function returns `m_retval`.
183
*/
184
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
185
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
186
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
187
return m_retval; \
188
} else \
189
((void)0)
190
191
/**
192
* Same as `ERR_FAIL_INDEX_V_MSG` but also notifies the editor.
193
*/
194
#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
195
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
196
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
197
return m_retval; \
198
} else \
199
((void)0)
200
201
/**
202
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
203
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
204
* there is no sensible error message.
205
*
206
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
207
* If not, the application crashes.
208
*/
209
#define CRASH_BAD_INDEX(m_index, m_size) \
210
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
211
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
212
_err_flush_stdout(); \
213
GENERATE_TRAP(); \
214
} else \
215
((void)0)
216
217
/**
218
* Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
219
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
220
*
221
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
222
* If not, prints `m_msg` and the application crashes.
223
*/
224
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
225
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
226
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
227
_err_flush_stdout(); \
228
GENERATE_TRAP(); \
229
} else \
230
((void)0)
231
232
// Unsigned integer index out of bounds error macros.
233
234
/**
235
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG`.
236
* Only use this macro if there is no sensible error message.
237
*
238
* Ensures an unsigned integer index `m_index` is less than `m_size`.
239
* If not, the current function returns.
240
*/
241
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
242
if (unlikely((m_index) >= (m_size))) { \
243
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
244
return; \
245
} else \
246
((void)0)
247
248
/**
249
* Ensures an unsigned integer index `m_index` is less than `m_size`.
250
* If not, prints `m_msg` and the current function returns.
251
*/
252
#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
253
if (unlikely((m_index) >= (m_size))) { \
254
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
255
return; \
256
} else \
257
((void)0)
258
259
/**
260
* Same as `ERR_FAIL_UNSIGNED_INDEX_MSG` but also notifies the editor.
261
*/
262
#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
263
if (unlikely((m_index) >= (m_size))) { \
264
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
265
return; \
266
} else \
267
((void)0)
268
269
/**
270
* Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
271
* Only use this macro if there is no sensible error message.
272
*
273
* Ensures an unsigned integer index `m_index` is less than `m_size`.
274
* If not, the current function returns `m_retval`.
275
*/
276
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
277
if (unlikely((m_index) >= (m_size))) { \
278
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
279
return m_retval; \
280
} else \
281
((void)0)
282
283
/**
284
* Ensures an unsigned integer index `m_index` is less than `m_size`.
285
* If not, prints `m_msg` and the current function returns `m_retval`.
286
*/
287
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
288
if (unlikely((m_index) >= (m_size))) { \
289
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
290
return m_retval; \
291
} else \
292
((void)0)
293
294
/**
295
* Same as `ERR_FAIL_UNSIGNED_INDEX_V_MSG` but also notifies the editor.
296
*/
297
#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
298
if (unlikely((m_index) >= (m_size))) { \
299
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
300
return m_retval; \
301
} else \
302
((void)0)
303
304
/**
305
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
306
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
307
* there is no sensible error message.
308
*
309
* Ensures an unsigned integer index `m_index` is less than `m_size`.
310
* If not, the application crashes.
311
*/
312
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
313
if (unlikely((m_index) >= (m_size))) { \
314
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
315
_err_flush_stdout(); \
316
GENERATE_TRAP(); \
317
} else \
318
((void)0)
319
320
/**
321
* Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
322
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
323
*
324
* Ensures an unsigned integer index `m_index` is less than `m_size`.
325
* If not, prints `m_msg` and the application crashes.
326
*/
327
#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
328
if (unlikely((m_index) >= (m_size))) { \
329
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
330
_err_flush_stdout(); \
331
GENERATE_TRAP(); \
332
} else \
333
((void)0)
334
335
// Null reference error macros.
336
337
/**
338
* Try using `ERR_FAIL_NULL_MSG`.
339
* Only use this macro if there is no sensible error message.
340
*
341
* Ensures a pointer `m_param` is not null.
342
* If it is null, the current function returns.
343
*/
344
#define ERR_FAIL_NULL(m_param) \
345
if (unlikely(m_param == nullptr)) { \
346
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
347
return; \
348
} else \
349
((void)0)
350
351
/**
352
* Ensures a pointer `m_param` is not null.
353
* If it is null, prints `m_msg` and the current function returns.
354
*/
355
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
356
if (unlikely(m_param == nullptr)) { \
357
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
358
return; \
359
} else \
360
((void)0)
361
362
/**
363
* Same as `ERR_FAIL_NULL_MSG` but also notifies the editor.
364
*/
365
#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
366
if (unlikely(m_param == nullptr)) { \
367
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
368
return; \
369
} else \
370
((void)0)
371
372
/**
373
* Try using `ERR_FAIL_NULL_V_MSG`.
374
* Only use this macro if there is no sensible error message.
375
*
376
* Ensures a pointer `m_param` is not null.
377
* If it is null, the current function returns `m_retval`.
378
*/
379
#define ERR_FAIL_NULL_V(m_param, m_retval) \
380
if (unlikely(m_param == nullptr)) { \
381
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
382
return m_retval; \
383
} else \
384
((void)0)
385
386
/**
387
* Ensures a pointer `m_param` is not null.
388
* If it is null, prints `m_msg` and the current function returns `m_retval`.
389
*/
390
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
391
if (unlikely(m_param == nullptr)) { \
392
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
393
return m_retval; \
394
} else \
395
((void)0)
396
397
/**
398
* Same as `ERR_FAIL_NULL_V_MSG` but also notifies the editor.
399
*/
400
#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
401
if (unlikely(m_param == nullptr)) { \
402
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
403
return m_retval; \
404
} else \
405
((void)0)
406
407
/**
408
* Try using `ERR_FAIL_COND_MSG`.
409
* Only use this macro if there is no sensible error message.
410
* If checking for null use ERR_FAIL_NULL_MSG instead.
411
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
412
*
413
* Ensures `m_cond` is false.
414
* If `m_cond` is true, the current function returns.
415
*/
416
#define ERR_FAIL_COND(m_cond) \
417
if (unlikely(m_cond)) { \
418
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
419
return; \
420
} else \
421
((void)0)
422
423
/**
424
* Ensures `m_cond` is false.
425
* If `m_cond` is true, prints `m_msg` and the current function returns.
426
*
427
* If checking for null use ERR_FAIL_NULL_MSG instead.
428
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
429
*/
430
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
431
if (unlikely(m_cond)) { \
432
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
433
return; \
434
} else \
435
((void)0)
436
437
/**
438
* Same as `ERR_FAIL_COND_MSG` but also notifies the editor.
439
*/
440
#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
441
if (unlikely(m_cond)) { \
442
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
443
return; \
444
} else \
445
((void)0)
446
447
/**
448
* Try using `ERR_FAIL_COND_V_MSG`.
449
* Only use this macro if there is no sensible error message.
450
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
451
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
452
*
453
* Ensures `m_cond` is false.
454
* If `m_cond` is true, the current function returns `m_retval`.
455
*/
456
#define ERR_FAIL_COND_V(m_cond, m_retval) \
457
if (unlikely(m_cond)) { \
458
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
459
return m_retval; \
460
} else \
461
((void)0)
462
463
/**
464
* Ensures `m_cond` is false.
465
* If `m_cond` is true, prints `m_msg` and the current function returns `m_retval`.
466
*
467
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
468
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
469
*/
470
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
471
if (unlikely(m_cond)) { \
472
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg); \
473
return m_retval; \
474
} else \
475
((void)0)
476
477
/**
478
* Same as `ERR_FAIL_COND_V_MSG` but also notifies the editor.
479
*/
480
#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
481
if (unlikely(m_cond)) { \
482
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
483
return m_retval; \
484
} else \
485
((void)0)
486
487
/**
488
* Try using `ERR_CONTINUE_MSG`.
489
* Only use this macro if there is no sensible error message.
490
*
491
* Ensures `m_cond` is false.
492
* If `m_cond` is true, the current loop continues.
493
*/
494
#define ERR_CONTINUE(m_cond) \
495
if (unlikely(m_cond)) { \
496
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
497
continue; \
498
} else \
499
((void)0)
500
501
/**
502
* Ensures `m_cond` is false.
503
* If `m_cond` is true, prints `m_msg` and the current loop continues.
504
*/
505
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
506
if (unlikely(m_cond)) { \
507
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
508
continue; \
509
} else \
510
((void)0)
511
512
/**
513
* Same as `ERR_CONTINUE_MSG` but also notifies the editor.
514
*/
515
#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
516
if (unlikely(m_cond)) { \
517
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
518
continue; \
519
} else \
520
((void)0)
521
522
/**
523
* Try using `ERR_BREAK_MSG`.
524
* Only use this macro if there is no sensible error message.
525
*
526
* Ensures `m_cond` is false.
527
* If `m_cond` is true, the current loop breaks.
528
*/
529
#define ERR_BREAK(m_cond) \
530
if (unlikely(m_cond)) { \
531
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
532
break; \
533
} else \
534
((void)0)
535
536
/**
537
* Ensures `m_cond` is false.
538
* If `m_cond` is true, prints `m_msg` and the current loop breaks.
539
*/
540
#define ERR_BREAK_MSG(m_cond, m_msg) \
541
if (unlikely(m_cond)) { \
542
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
543
break; \
544
} else \
545
((void)0)
546
547
/**
548
* Same as `ERR_BREAK_MSG` but also notifies the editor.
549
*/
550
#define ERR_BREAK_EDMSG(m_cond, m_msg) \
551
if (unlikely(m_cond)) { \
552
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
553
break; \
554
} else \
555
((void)0)
556
557
/**
558
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
559
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
560
* there is no sensible error message.
561
*
562
* Ensures `m_cond` is false.
563
* If `m_cond` is true, the application crashes.
564
*/
565
#define CRASH_COND(m_cond) \
566
if (unlikely(m_cond)) { \
567
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
568
_err_flush_stdout(); \
569
GENERATE_TRAP(); \
570
} else \
571
((void)0)
572
573
/**
574
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
575
* Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
576
*
577
* Ensures `m_cond` is false.
578
* If `m_cond` is true, prints `m_msg` and the application crashes.
579
*/
580
#define CRASH_COND_MSG(m_cond, m_msg) \
581
if (unlikely(m_cond)) { \
582
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
583
_err_flush_stdout(); \
584
GENERATE_TRAP(); \
585
} else \
586
((void)0)
587
588
// Generic error macros.
589
590
/**
591
* Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_MSG`.
592
* Only use this macro if more complex error detection or recovery is required, and
593
* there is no sensible error message.
594
*
595
* The current function returns.
596
*/
597
#define ERR_FAIL() \
598
if (true) { \
599
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
600
return; \
601
} else \
602
((void)0)
603
604
/**
605
* Try using `ERR_FAIL_COND_MSG`.
606
* Only use this macro if more complex error detection or recovery is required.
607
*
608
* Prints `m_msg`, and the current function returns.
609
*/
610
#define ERR_FAIL_MSG(m_msg) \
611
if (true) { \
612
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg); \
613
return; \
614
} else \
615
((void)0)
616
617
/**
618
* Same as `ERR_FAIL_MSG` but also notifies the editor.
619
*/
620
#define ERR_FAIL_EDMSG(m_msg) \
621
if (true) { \
622
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
623
return; \
624
} else \
625
((void)0)
626
627
/**
628
* Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`.
629
* Only use this macro if more complex error detection or recovery is required, and
630
* there is no sensible error message.
631
*
632
* The current function returns `m_retval`.
633
*/
634
#define ERR_FAIL_V(m_retval) \
635
if (true) { \
636
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
637
return m_retval; \
638
} else \
639
((void)0)
640
641
/**
642
* Try using `ERR_FAIL_COND_V_MSG`.
643
* Only use this macro if more complex error detection or recovery is required.
644
*
645
* Prints `m_msg`, and the current function returns `m_retval`.
646
*/
647
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
648
if (true) { \
649
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg); \
650
return m_retval; \
651
} else \
652
((void)0)
653
654
/**
655
* Same as `ERR_FAIL_V_MSG` but also notifies the editor.
656
*/
657
#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
658
if (true) { \
659
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
660
return m_retval; \
661
} else \
662
((void)0)
663
664
/**
665
* Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or `ERR_BREAK_MSG`.
666
* Only use this macro at the start of a function that has not been implemented yet, or
667
* if more complex error detection or recovery is required.
668
*
669
* Prints `m_msg`.
670
*/
671
#define ERR_PRINT(m_msg) \
672
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
673
674
/**
675
* Same as `ERR_PRINT` but also notifies the editor.
676
*/
677
#define ERR_PRINT_ED(m_msg) \
678
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
679
680
/**
681
* Prints `m_msg` once during the application lifetime.
682
*/
683
#define ERR_PRINT_ONCE(m_msg) \
684
if (true) { \
685
static bool warning_shown = false; \
686
if (unlikely(!warning_shown)) { \
687
warning_shown = true; \
688
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
689
} \
690
} else \
691
((void)0)
692
693
/**
694
* Same as `ERR_PRINT_ONCE` but also notifies the editor.
695
*/
696
#define ERR_PRINT_ONCE_ED(m_msg) \
697
if (true) { \
698
static bool warning_shown = false; \
699
if (unlikely(!warning_shown)) { \
700
warning_shown = true; \
701
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
702
} \
703
} else \
704
((void)0)
705
706
// Print warning message macros.
707
708
/**
709
* Prints `m_msg`.
710
*
711
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
712
*/
713
#define WARN_PRINT(m_msg) \
714
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING)
715
716
/**
717
* Same as `WARN_PRINT` but also notifies the editor.
718
*/
719
#define WARN_PRINT_ED(m_msg) \
720
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING)
721
722
/**
723
* Prints `m_msg` once during the application lifetime.
724
*
725
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
726
*/
727
#define WARN_PRINT_ONCE(m_msg) \
728
if (true) { \
729
static bool warning_shown = false; \
730
if (unlikely(!warning_shown)) { \
731
warning_shown = true; \
732
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
733
} \
734
} else \
735
((void)0)
736
737
/**
738
* Same as `WARN_PRINT_ONCE` but also notifies the editor.
739
*/
740
#define WARN_PRINT_ONCE_ED(m_msg) \
741
if (true) { \
742
static bool warning_shown = false; \
743
if (unlikely(!warning_shown)) { \
744
warning_shown = true; \
745
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
746
} \
747
} else \
748
((void)0)
749
750
/**
751
* Warns about `m_msg` only when verbose mode is enabled.
752
*/
753
#define WARN_VERBOSE(m_msg) \
754
{ \
755
if (is_print_verbose_enabled()) { \
756
WARN_PRINT(m_msg); \
757
} \
758
}
759
760
// Print deprecated warning message macros.
761
762
/**
763
* Warns that the current function is deprecated.
764
*/
765
#define WARN_DEPRECATED \
766
if (true) { \
767
static bool warning_shown = false; \
768
if (unlikely(!warning_shown)) { \
769
warning_shown = true; \
770
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
771
} \
772
} else \
773
((void)0)
774
775
/**
776
* Warns that the current function is deprecated and prints `m_msg`.
777
*/
778
#define WARN_DEPRECATED_MSG(m_msg) \
779
if (true) { \
780
static bool warning_shown = false; \
781
if (unlikely(!warning_shown)) { \
782
warning_shown = true; \
783
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
784
} \
785
} else \
786
((void)0)
787
788
/**
789
* Do not use.
790
* If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why.
791
*
792
* The application crashes.
793
*/
794
#define CRASH_NOW() \
795
if (true) { \
796
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
797
_err_flush_stdout(); \
798
GENERATE_TRAP(); \
799
} else \
800
((void)0)
801
802
/**
803
* Only use if the application should never reach this point.
804
*
805
* Prints `m_msg`, and then the application crashes.
806
*/
807
#define CRASH_NOW_MSG(m_msg) \
808
if (true) { \
809
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
810
_err_flush_stdout(); \
811
GENERATE_TRAP(); \
812
} else \
813
((void)0)
814
815
/**
816
* Note: IN MOST CASES YOU SHOULD NOT USE THIS MACRO.
817
* Do not use unless you understand the trade-offs.
818
*
819
* DEV macros will be compiled out in releases, they are wrapped in DEV_ENABLED.
820
*
821
* Prefer WARNINGS / ERR_FAIL macros (which fail without crashing) - ERR_FAIL should be used in most cases.
822
* Then CRASH_NOW_MSG macros (on rare occasions where error cannot be recovered).
823
*
824
* DEV_ASSERT should generally only be used when both of the following conditions are met:
825
* 1) Bottleneck code where a check in release would be too expensive.
826
* 2) Situations where the check would fail obviously and straight away during the maintenance of the code
827
* (i.e. strict conditions that should be true no matter what)
828
* and that can't fail for other contributors once the code is finished and merged.
829
*/
830
#ifdef DEV_ENABLED
831
#define DEV_ASSERT(m_cond) \
832
if (unlikely(!(m_cond))) { \
833
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed \"" _STR(m_cond) "\" is false."); \
834
_err_flush_stdout(); \
835
GENERATE_TRAP(); \
836
} else \
837
((void)0)
838
#else
839
#define DEV_ASSERT(m_cond)
840
#endif
841
842
#ifdef DEV_ENABLED
843
#define DEV_CHECK_ONCE(m_cond) \
844
if (true) { \
845
static bool first_print = true; \
846
if (first_print && unlikely(!(m_cond))) { \
847
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
848
first_print = false; \
849
} \
850
} else \
851
((void)0)
852
#else
853
#define DEV_CHECK_ONCE(m_cond)
854
#endif
855
856
/**
857
* Physics Interpolation warnings.
858
* These are spam protection warnings.
859
*/
860
#define PHYSICS_INTERPOLATION_NODE_WARNING(m_object_id, m_string) \
861
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, m_object_id, m_string)
862
863
#define PHYSICS_INTERPOLATION_WARNING(m_string) \
864
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, ObjectID(UINT64_MAX), m_string)
865
866