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