MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
AssertMacros.h
Go to the documentation of this file.
1
/** @noop License Comment
2
* @file
3
* @copyright
4
* This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5
* If a copy of the MPL was not distributed with this file You can obtain one at
6
* https://mozilla.org/MPL/2.0/
7
*
8
* @author David Mórász
9
* @date 2025
10
*/
11
12
#pragma once
13
14
/**
15
* @file
16
* By default `ASSERT_QUIT|CRASH` macros are also active in Shipping builds. This was a personal preference and
17
* that's why you can turn it off if you define `MCRO_ASSERT_IGNORE_SHIPPING`.
18
*
19
* @remarks
20
* Yes I know that "shipping builds must have all debug info and checks removed" but I have yet to see one project in
21
* my career where Shipping builds didn't have weird issues or crashes not present in other debug builds, and debugging
22
* them removed many years from my expected life-span.
23
*/
24
25
#include "CoreMinimal.h"
26
#include "
Mcro/Error.h
"
27
#include "
Mcro/Macros.h
"
28
#include "Logging/LogMacros.h"
29
30
/** Do not use this namespace directly use `ASSERT_QUIT|CRASH` macros instead */
31
namespace
Mcro::AssertMacros
32
{
33
using namespace
Mcro::Error
;
34
35
namespace
Detail
36
{
37
MCRO_API
void
SubmitError
(
38
EErrorSeverity
severity,
39
FString
const
& codeContext,
40
bool
async,
bool
important,
41
TUniqueFunction<
void
(
IErrorRef
const
&)>&& extraSetup
42
);
43
MCRO_API
bool
IsRunningPIE
();
44
MCRO_API
void
StopPie
();
45
}
46
}
47
48
#define MCRO_ASSERT_SUBMIT_ERROR(condition, severity, async, important, ...) \
49
Mcro::AssertMacros::Detail::SubmitError( \
50
Mcro::Error::EErrorSeverity::severity, \
51
PREPROCESSOR_TO_TEXT(condition), \
52
async, important, \
53
[&](Mcro::Error::IErrorRef const& error) { (error __VA_ARGS__); } \
54
);
//
55
56
#define MCRO_ASSERT_CRASH_METHOD \
57
UE_LOG(LogTemp, Fatal, \
58
TEXT("Program cannot continue for the reasons above. (at ") \
59
PREPROCESSOR_TO_TEXT(__FILE__:__LINE__) TEXT(")") \
60
)
//
61
62
#define MCRO_CRASH_BODY(condition, ...) \
63
MCRO_ASSERT_SUBMIT_ERROR( \
64
condition, Crashing, false, false, \
65
__VA_ARGS__ \
66
) \
67
MCRO_ASSERT_CRASH_METHOD;
//
68
69
#define MCRO_QUIT_BODY(condition, returnOnFailure, ...) \
70
MCRO_ASSERT_SUBMIT_ERROR( \
71
condition, Fatal, \
72
Mcro::AssertMacros::Detail::IsRunningPIE(), \
73
Mcro::AssertMacros::Detail::IsRunningPIE(), \
74
__VA_ARGS__ \
75
) \
76
if (Mcro::AssertMacros::Detail::IsRunningPIE()) \
77
{ \
78
Mcro::AssertMacros::Detail::StopPie(); \
79
return returnOnFailure; \
80
} \
81
else { MCRO_ASSERT_CRASH_METHOD }
//
82
83
#define MCRO_ASSERT_CRASH_COMMON(condition, ...) \
84
if (UNLIKELY(!(condition))) \
85
{ \
86
MCRO_CRASH_BODY(condition, __VA_ARGS__) \
87
}
//
88
89
#define MCRO_ASSERT_QUIT_COMMON(condition, returnOnFailure, ...) \
90
if (UNLIKELY(!(condition))) \
91
{ \
92
MCRO_QUIT_BODY(condition, returnOnFailure, __VA_ARGS__) \
93
}
//
94
95
#if WITH_EDITOR
96
97
/**
98
* Use this instead of `check` macro if the checked expression shouldn't be ignored in shipping builds. This version will
99
* also crash the entire editor even during a PIE session. Use this only if there's absolutely no way to recover from
100
* an invalid state, like a situation when early return is not possible / doesn't make sense (e.g.: return a checked
101
* pointer by reference).
102
*
103
* This macro will attempt to display the error before crashing via the IError type. You can also append extra
104
* information to it, or even override preset information like so:
105
*
106
* @code
107
* ASSERT_CRASH(arrayNum > 0,
108
* ->WithDetails(TEXT("Did you forget to specify data?"))
109
* ->WithAppendix(TEXT("Data"), data.ToString())
110
* )
111
* @endcode
112
*/
113
#define ASSERT_CRASH(condition, ...) MCRO_ASSERT_CRASH_COMMON(condition, __VA_ARGS__)
114
115
/** This is equivalent to ASSERT_CRASH but if a code path reaches this macro it will always crash */
116
#define FORCE_CRASH(...) MCRO_CRASH_BODY(Invalid code path, __VA_ARGS__)
117
118
/**
119
* Use this instead of `check` macro if the checked expression shouldn't be ignored in shipping builds. This version will
120
* not crash the editor but will display an error, stops the PIE, and should return the calling function. A return value
121
* should be provided on failure, or leave it empty to return void. so either
122
*
123
* @code
124
* ASSERT_QUIT(SomethingImportantButNullable, ) // important to leave an extra comma for void functions
125
* // or return default
126
* ASSERT_QUIT(SomethingImportantButNullable, {})
127
* // or return whatever
128
* ASSERT_QUIT(SomethingImportantButNullable, myReturnValue)
129
* @endcode
130
*
131
* This is done in the hopes that these checks failing in PIE sessions doesn't crash the entire editor giving the
132
* developer a chance for fixing the error before restarting. However early returns might cause undefined/vaguely-defined
133
* side effects and may lead to uninitialized resources or in worst case scenario may lead to incorrect states in
134
* resource cleanups which then might crash the editor. Always check the validity of your resources in destructors.
135
* Failing this check outside of PIE or in a Standalone session will still crash with a `check` macro.
136
*
137
* This macro will attempt to display the error before quitting via the IError type. You can also append extra
138
* information to it like so, or even override preset information like so:
139
*
140
* @code
141
* ASSERT_QUIT(arrayNum > 0, myReturnValue,
142
* ->WithDetails(TEXT("Did you forget to specify data?"))
143
* ->WithAppendix(TEXT("Data"), data.ToString())
144
* )
145
* @endcode
146
*/
147
#define ASSERT_QUIT(condition, returnOnFailure, ...) MCRO_ASSERT_QUIT_COMMON(condition, returnOnFailure, __VA_ARGS__)
148
149
/** This is equivalent to ASSERT_QUIT but if a code path reaches this macro it will always quit */
150
#define FORCE_QUIT(returnOnFailure, ...) MCRO_QUIT_BODY(Invalid code path, returnOnFailure, __VA_ARGS__)
151
152
#elif UE_BUILD_SHIPPING && defined(MCRO_ASSERT_IGNORE_SHIPPING)
153
154
#define ASSERT_CRASH(condition, ...)
155
#define ASSERT_QUIT(condition, returnOnFailure, ...)
156
157
#else
158
159
#define ASSERT_CRASH(condition, ...) MCRO_ASSERT_CRASH_COMMON(condition, __VA_ARGS__)
160
#define ASSERT_QUIT(condition, returnOnFailure, ...) MCRO_ASSERT_CRASH_COMMON(condition, __VA_ARGS__)
161
162
#endif
Error.h
Macros.h
Mcro::AssertMacros::Detail::StopPie
MCRO_API void StopPie()
Mcro::AssertMacros::Detail::IsRunningPIE
MCRO_API bool IsRunningPIE()
Mcro::AssertMacros::Detail::SubmitError
MCRO_API void SubmitError(EErrorSeverity severity, FString const &codeContext, bool async, bool important, TUniqueFunction< void(IErrorRef const &)> &&extraSetup)
Mcro::AssertMacros
Definition
AssertMacros.h:32
Mcro::Error
Definition
Error.Fwd.h:19
Mcro::Error::IErrorRef
TSharedRef< IError > IErrorRef
Definition
Error.Fwd.h:25
Mcro::Error::EErrorSeverity
EErrorSeverity
Definition
Error.Fwd.h:53
Mcro_Origin
Public
Mcro
AssertMacros.h
Generated by
1.12.0