HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Assert.h
Go to the documentation of this file.
1 // UT_Assert.h
2 //
3 // Custom portable UT_ASSERT macro
4 //
5 
6 #ifndef UT_ASSERT_H_INCLUDED
7 #define UT_ASSERT_H_INCLUDED
8 
9 #include "UT_API.h"
10 
11 #define UT_ASSERT_LEVEL_NONE 0
12 #define UT_ASSERT_LEVEL_NORMAL 1
13 #define UT_ASSERT_LEVEL_PARANOID 2
14 #define UT_ASSERT_LEVEL_SLOW 3
15 
16 #ifndef UT_ASSERT_LEVEL
17  #define UT_ASSERT_LEVEL UT_ASSERT_LEVEL_NONE
18 #endif
19 
20 // Generates an assertion. Returns TRUE if we should ignore further asserts.
21 UT_API void UT_Assert( const char *file, int linenum, const char *function,
22  const char *condition, const char *reason, int &ignoreflag);
23 
24 // Similar to UT_Assert() but using a variadic format string for the reason.
25 UT_API void UT_AssertFormat( const char *file, int linenum,
26  const char *function, const char *condition, int &ignoreflag,
27  const char *reason_fmt...);
28 
29 // Return true if the assert dialog is open and we are waiting for the
30 // user to choose a response in the dialog.
32 
33 // Methods to temporarily disable interactive asserts in specific dangerous
34 // situations.
37 
38 using UT_TraceCallback = void (*)();
39 
40 /// Set additional tracing callback when an assertion fails and a stack trace
41 /// is requested. The previous callback is returned.
44 
45 /// Assertions triggered within the lifetime of UT_AssertExceptionScope
46 /// variables will cause UT_AssertException to be thrown instead of the usual
47 /// handling. By default, this is only done when interactive asserts are
48 /// disabled. This class is intended for testing purposes only.
50 {
51 public:
52  UT_AssertExceptionScope(bool when_interactive = true);
54 
57 private:
58  bool myEnabled;
59 };
60 
61 // Exception class thrown when assertions are triggered within an
62 // UT_AssertExceptionScope
64 {
65 public:
66  UT_AssertException(const char *what);
68 
71 
72  const char *what() const noexcept { return myWhat; }
73 
74 private:
75  char *myWhat; // using C string to avoid pulling in UT_String*.h
76 };
77 
78 
79 #if defined(__GNUC__)
80 # define UT_ASSERT_FUNC __PRETTY_FUNCTION__
81 #elif defined(_MSC_VER)
82 # define UT_ASSERT_FUNC __FUNCSIG__
83 #elif defined(__FUNCTION__)
84 # define UT_ASSERT_FUNC __FUNCTION__ "()"
85 #else
86 # define UT_ASSERT_FUNC ((char *)0)
87 #endif
88 
89 #if (UT_ASSERT_LEVEL > UT_ASSERT_LEVEL_NONE)
90  #ifdef UT_INTERNAL_ASSERT
91  #error UT_INTERNAL_UT_ASSERT is already defined!
92  #endif
93  #define UT_INTERNAL_ASSERT(ZZ, ...) \
94  ((ZZ) ? void(0) : \
95  [&]() { \
96  static int ignore = 0; \
97  if( !ignore ) \
98  UT_AssertFormat( __FILE__, __LINE__, UT_ASSERT_FUNC, \
99  #ZZ, ignore, __VA_ARGS__); \
100  }())
101  #define UT_INTERNAL_VERIFY(ZZ, ...) \
102  do { \
103  static int ignore = 0; \
104  /* always run ZZ */ \
105  if( !(ZZ) && !ignore ) \
106  UT_AssertFormat( __FILE__, __LINE__, UT_ASSERT_FUNC, \
107  #ZZ, ignore, __VA_ARGS__); \
108  } while (false)
109 
110  #define UT_INTERNAL_VERIFY_RETURN(ZZ, RV, ...) \
111  if (!(ZZ)) \
112  { \
113  static int ignore = 0; \
114  if (!ignore) \
115  UT_AssertFormat( __FILE__, __LINE__, UT_ASSERT_FUNC, \
116  #ZZ, ignore, __VA_ARGS__); \
117  return RV; \
118  }
119 #endif
120 
121 #ifdef UT_ASSERT_SLOW
122  #error UT_ASSERT_SLOW is already defined!
123 #endif
124 #ifdef UT_ASSERT_P
125  #error UT_ASSERT_P is already defined!
126 #endif
127 #ifdef UT_ASSERT
128  #error UT_ASSERT is already defined!
129 #endif
130 #ifdef UT_ASSERT_MSG_SLOW
131  #error UT_ASSERT_MSG_SLOW is already defined!
132 #endif
133 #ifdef UT_ASSERT_MSG_P
134  #error UT_ASSERT_MSG_P is already defined!
135 #endif
136 #ifdef UT_ASSERT_MSG
137  #error UT_ASSERT_MSG is already defined!
138 #endif
139 
140 // do these in descending order:
141 #if (UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_SLOW)
142  #define UT_ASSERT_SLOW(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
143  #define UT_ASSERT_P(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
144  #define UT_ASSERT(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
145  #define UT_ASSERT_MSG_SLOW(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
146  #define UT_ASSERT_MSG_P(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
147  #define UT_ASSERT_MSG(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
148 #elif (UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_PARANOID)
149  #define UT_ASSERT_SLOW(ZZ) ((void)0)
150  #define UT_ASSERT_P(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
151  #define UT_ASSERT(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
152  #define UT_ASSERT_MSG_SLOW(ZZ, ...) ((void)0)
153  #define UT_ASSERT_MSG_P(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
154  #define UT_ASSERT_MSG(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
155 #elif (UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_NORMAL)
156  #define UT_ASSERT_SLOW(ZZ) ((void)0)
157  #define UT_ASSERT_P(ZZ) ((void)0)
158  #define UT_ASSERT(ZZ) UT_INTERNAL_ASSERT(ZZ, 0)
159  #define UT_ASSERT_MSG_SLOW(ZZ, ...) ((void)0)
160  #define UT_ASSERT_MSG_P(ZZ, ...) ((void)0)
161  #define UT_ASSERT_MSG(ZZ, ...) UT_INTERNAL_ASSERT(ZZ, __VA_ARGS__)
162 #else // if (UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_NONE)
163  #define UT_ASSERT_SLOW(ZZ) ((void)0)
164  #define UT_ASSERT_P(ZZ) ((void)0)
165  #define UT_ASSERT(ZZ) ((void)0)
166  #define UT_ASSERT_MSG_SLOW(ZZ, ...) ((void)0)
167  #define UT_ASSERT_MSG_P(ZZ, ...) ((void)0)
168  #define UT_ASSERT_MSG(ZZ, ...) ((void)0)
169 #endif
170 
171 #include <SYS/SYS_StaticAssert.h>
172 #define UT_ASSERT_COMPILETIME(expr) SYS_STATIC_ASSERT(expr)
173 
174 // This macro allows you to enable a block of code only
175 // when UT_ASSERT is enabled. This will help clean up
176 // "unreferenced variables" in the case where you have variables that
177 // are only referenced in asserts.
178 
179 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_NORMAL
180 #define UT_IF_ASSERT(ZZ) ZZ
181 #define UT_IFNOT_ASSERT(ZZ)
182 #else
183 #define UT_IF_ASSERT(ZZ)
184 #define UT_IFNOT_ASSERT(ZZ) ZZ
185 #endif
186 
187 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_PARANOID
188 #define UT_IF_ASSERT_P(ZZ) ZZ
189 #define UT_IFNOT_ASSERT_P(ZZ)
190 #else
191 #define UT_IF_ASSERT_P(ZZ)
192 #define UT_IFNOT_ASSERT_P(ZZ) ZZ
193 #endif
194 
195 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_SLOW
196 #define UT_IF_ASSERT_SLOW(ZZ) ZZ
197 #define UT_IFNOT_ASSERT_SLOW(ZZ)
198 #else
199 #define UT_IF_ASSERT_SLOW(ZZ)
200 #define UT_IFNOT_ASSERT_SLOW(ZZ) ZZ
201 #endif
202 
203 // When asserts are enabled, UT_VERIFY() will trigger an assert if the expr
204 // is false. When asserts are disabled, the expr is still evaluated.
205 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_NORMAL
206  #define UT_VERIFY(expr) UT_INTERNAL_VERIFY(expr, 0)
207  #define UT_VERIFY_MSG(expr, ...) UT_INTERNAL_VERIFY(expr, __VA_ARGS__)
208  #define UT_VERIFY_RETURN(ZZ, RV) UT_INTERNAL_VERIFY_RETURN(ZZ, RV, 0)
209  #define UT_VERIFY_RETURN_VOID(ZZ) UT_INTERNAL_VERIFY_RETURN(ZZ, , 0)
210  #define UT_VERIFY_RETURN_MSG(ZZ, RV, ...) UT_INTERNAL_VERIFY_RETURN(ZZ, RV, __VA_ARGS__)
211  #define UT_VERIFY_RETURN_VOID_MSG(ZZ, ...) UT_INTERNAL_VERIFY_RETURN(ZZ, ,__VA_ARGS__)
212 #else
213  #define UT_VERIFY(expr) ((void)(expr))
214  #define UT_VERIFY_MSG(expr, ...) ((void)(expr))
215  #define UT_VERIFY_RETURN(ZZ, RV) if (!(ZZ)) { return RV; }
216  #define UT_VERIFY_RETURN_VOID(ZZ) if (!(ZZ)) { return; }
217  #define UT_VERIFY_RETURN_MSG(ZZ, RV, ...) if (!(ZZ)) { return RV; }
218  #define UT_VERIFY_RETURN_VOID_MSG(ZZ, ...) if (!(ZZ)) { return; }
219 #endif
220 #if UT_ASSERT_LEVEL >= UT_ASSERT_LEVEL_PARANOID
221  #define UT_VERIFY_P(expr) UT_INTERNAL_VERIFY(expr, 0)
222 #else
223  #define UT_VERIFY_P(expr) ((void)(expr))
224 #endif
225 
227 {
233 };
234 
235 /// UTverify_cast performs a static_cast, but when paranoid assertions are
236 /// enabled it will also perform a dynamic cast to verify the cast is valid.
237 /// UT_ASSERT_P() is used instead of UT_ASSERT() to avoid overhead in normal
238 /// development builds.
239 #include <SYS/SYS_Inline.h>
240 template <typename TO_T, typename FROM_T>
241 SYS_FORCE_INLINE TO_T
242 UTverify_cast(FROM_T from)
243 {
244  UT_ASSERT_P(dynamic_cast<TO_T>(from) == from && "Invalid static cast");
245  return static_cast<TO_T>(from);
246 }
247 
248 /// UTsubclassResponsibility raises an assertion indicating that a subclass has
249 /// not implemented an inherited method. This should only be called from a
250 /// base class method that is not expected to run.
251 UT_API void UTsubclassResponsibility(const char *classname, const char *member);
252 
253 #endif // UT_ASSERT_H_INCLUDED
void
Definition: png.h:1083
UT_AssertResponse
Definition: UT_Assert.h:226
#define UT_API
Definition: UT_API.h:14
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:242
UT_API void UTsubclassResponsibility(const char *classname, const char *member)
UT_API UT_TraceCallback UTassertSetExtraTraceCallback(UT_TraceCallback callback)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:164
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
UT_API void UTdisableInteractiveAssertsOff()
const char * what() const noexcept
Definition: UT_Assert.h:72
void(*)( UT_TraceCallback)
Definition: UT_Assert.h:38
UT_API bool UTisWaitingForAssertResponse()
LeafData & operator=(const LeafData &)=delete
UT_API void UT_Assert(const char *file, int linenum, const char *function, const char *condition, const char *reason, int &ignoreflag)
UT_API void UT_AssertFormat(const char *file, int linenum, const char *function, const char *condition, int &ignoreflag, const char *reason_fmt...)
UT_API void UTdisableInteractiveAssertsOn()