ARB
arb_assert.h
Go to the documentation of this file.
1 /* ====================================================================
2 
3  File : arb_assert.h
4  Purpose : Global assert macro
5 
6 
7  Coded by Ralf Westram (coder@reallysoft.de) in August 2002
8  Copyright Department of Microbiology (Technical University Munich)
9 
10  Visit our web site at: http://www.arb-home.de/
11 
12 
13  ==================================================================== */
14 
15 #ifndef ARB_ASSERT_H
16 #define ARB_ASSERT_H
17 
18 // [WhyIncludeHere]
19 // need to include all headers needed for unit-tests here [sic]
20 // if only included inside test_global.h, developing with active unit-tests
21 // will always break non-unit-test-builds.
22 
23 #ifndef _STDARG_H
24 #include <stdarg.h>
25 #endif
26 #ifndef _STDIO_H
27 #include <stdio.h>
28 #endif
29 #ifndef _STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifndef _ERRNO_H
33 #include <errno.h>
34 #endif
35 #ifndef _STRING_H
36 #include <string.h>
37 #endif
38 #ifndef _SIGNAL_H
39 #include <signal.h>
40 #endif
41 
42 /* ------------------------------------------------------------
43  * Include arb_simple_assert.h to avoid dependency from CORE library!
44  * ------------------------------------------------------------
45  * available assertion flavors:
46  *
47  * ASSERT_CRASH if assert fails debugger stops at assert macro
48  * ASSERT_BACKTRACE_AND_CRASH like ASSERT_CRASH - with backtrace
49  * ASSERT_ERROR assert prints an error and ARB exits
50  * ASSERT_PRINT assert prints a message (anyway) and ARB continues
51  * ASSERT_NONE assertions inactive
52  *
53  * ------------------------------------------------------------ */
54 
55 // check correct definition of DEBUG/NDEBUG
56 #ifndef NDEBUG
57 # ifndef DEBUG
58 # error Neither DEBUG nor NDEBUG is defined!
59 # endif
60 #else
61 # ifdef DEBUG
62 # error Both DEBUG and NDEBUG are defined - only one should be!
63 # endif
64 #endif
65 
66 #ifdef arb_assert
67 #error arb_assert already defined
68 #endif
69 
70 // --------------------------------------------------------------------
71 // use exactly ONE of the following ASSERT_xxx defines in each section:
72 #if defined(DEBUG) && !defined(DEVEL_RELEASE)
73 
74 // assert that raises SIGSEGV (recommended for DEBUG version!)
75 // # define ASSERT_CRASH
76 // # define ASSERT_BACKTRACE_AND_CRASH
77 // # define ASSERT_STOP
78 # define ASSERT_BACKTRACE_AND_STOP
79 // test if a bug has to do with assertion code
80 // # define ASSERT_NONE
81 
82 #else
83 
84 // no assert (recommended for final version!)
85 # define ASSERT_NONE
86 // assert as error in final version (allows basic debugging of NDEBUG version)
87 // # define ASSERT_ERROR
88 // assert as print in final version (allows basic debugging of NDEBUG version)
89 // # define ASSERT_PRINT
90 
91 #endif
92 
93 // ------------------------------------------------------------
94 
95 #if defined(__cplusplus)
96 inline void provoke_core_dump() {
97  raise(SIGSEGV);
98 }
99 #else // !defined(__cplusplus)
100 #define provoke_core_dump() do { *(int*)0 = 0; } while(0)
101 #endif
102 
103 // ------------------------------------------------------------
104 
105 #if defined(SIMPLE_ARB_ASSERT)
106 
107 // code here is independent from CORE library and glib
108 
109 #define ARB_SIGSEGV(backtrace) do { \
110  provoke_core_dump(); \
111  } while (0)
112 
113 #define ARB_STOP(backtrace) ARB_SIGSEGV(backtrace)
114 
115 #ifndef ASSERT_NONE
116 # define arb_assert(cond) \
117  do { \
118  if (!(cond)) { \
119  fprintf(stderr, "Assertion '%s' failed in '%s' #%i\n", \
120  #cond, __FILE__, __LINE__); \
121  provoke_core_dump(); \
122  } \
123  } while (0)
124 #endif
125 
126 
127 // ------------------------------------------------------------
128 
129 #else // !SIMPLE_ARB_ASSERT
130 
131 /* Provoke a SIGSEGV (which will stop the debugger or terminated the application)
132  * Do backtrace manually here and uninstall SIGSEGV-handler
133  * (done because automatic backtrace on SIGSEGV lacks name of current function)
134  */
135 
136 #ifndef ARB_CORE_H
137 #include <arb_core.h>
138 #endif
139 
140 #if (GCC_VERSION_CODE>=407) && (GCC_VERSION_CODE<600)
141 // unfixable warnings in glib headers for gcc 4.7.x .. 5.5.0
142 # pragma GCC diagnostic push
143 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
144 #endif
145 
146 #ifndef __G_LIB_H__
147 #include <glib.h>
148 #endif
149 
150 #if (GCC_VERSION_CODE>=407) && (GCC_VERSION_CODE<600)
151 # pragma GCC diagnostic pop
152 #endif
153 
154 #define stop_in_debugger() G_BREAKPOINT()
155 
156 // the purpose of TRIGGER_SANITIZER is simply to provide a traceback
157 // leading to the location of the assert(or similar) which triggered
158 // this function.
159 //
160 // With older gcc versions provoke_core_dump() itself caused AddressSanitizer
161 // to dump the stack to the compile log (in error-message format).
162 //
163 // Now we need to do something illegal in such a complicated way,
164 // that the compiler is not able to detect that it is illegal.
165 // -> sanitizer will trigger
166 
167 #if defined(LEAKS_SANITIZED)
168 # define TRIGGER_SANITIZER() delete ((char*)GBK_getNonfreeableAddress())
169 #else // !LEAKS_SANITIZED
170 # define TRIGGER_SANITIZER()
171 #endif
172 
173 
174 #define ARB_SIGSEGV(backtrace) do { \
175  if (backtrace) GBK_dump_backtrace(NULp, "ARB_SIGSEGV"); \
176  GBK_install_SIGSEGV_handler(false); \
177  TRIGGER_SANITIZER(); \
178  provoke_core_dump(); \
179  } while (0)
180 
181 #define ARB_STOP(backtrace) \
182  do { \
183  if (backtrace) GBK_dump_backtrace(NULp, "ARB_STOP"); \
184  stop_in_debugger(); \
185  } while(0)
186 
187 # define arb_assert_crash(cond) \
188  do { \
189  if (!(cond)) ARB_SIGSEGV(0); \
190  } while (0)
191 
192 # define arb_assert_stop(cond) \
193  do { \
194  if (!(cond)) ARB_STOP(0); \
195  } while (0)
196 
197 # define arb_assert_backtrace_and_crash(cond) \
198  do { \
199  if (!(cond)) { \
200  fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr); \
201  fflush(stderr); \
202  ARB_SIGSEGV(1); \
203  } \
204  } while (0)
205 
206 # define arb_assert_backtrace_and_stop(cond) \
207  do { \
208  if (!(cond)) { \
209  fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr); \
210  fflush(stderr); \
211  ARB_STOP(1); \
212  } \
213  } while (0)
214 
215 #ifdef ASSERT_CRASH
216 # define arb_assert(cond) arb_assert_crash(cond)
217 #endif
218 #ifdef ASSERT_STOP
219 # define arb_assert(cond) arb_assert_stop(cond)
220 #endif
221 #ifdef ASSERT_BACKTRACE_AND_CRASH
222 # define arb_assert(cond) arb_assert_backtrace_and_crash(cond)
223 #endif
224 #ifdef ASSERT_BACKTRACE_AND_STOP
225 # define arb_assert(cond) arb_assert_backtrace_and_stop(cond)
226 #endif
227 #ifdef ASSERT_ERROR
228 # define arb_assert(cond) assert_or_exit(cond)
229 #endif
230 
231 #ifdef ASSERT_PRINT
232 # define arb_assert(cond) \
233  do { \
234  fprintf(stderr, "at %s #%i\n", __FILE__, __LINE__); \
235  if (!(cond)) fprintf(stderr, "assertion '%s' failed!\n", #cond); \
236  fflush(stderr); \
237  } while (0)
238 #endif
239 
240 #endif // SIMPLE_ARB_ASSERT
241 
242 // ------------------------------------------------------------
243 
244 #ifdef ASSERT_NONE
245 # define arb_assert(cond)
246 #else
247 # define ASSERTION_USED
248 #endif
249 
250 #undef ASSERT_CRASH
251 #undef ASSERT_BACKTRACE_AND_CRASH
252 #undef ASSERT_STOP
253 #undef ASSERT_BACKTRACE_AND_STOP
254 #undef ASSERT_ERROR
255 #undef ASSERT_PRINT
256 #undef ASSERT_NONE
257 
258 #ifndef arb_assert
259 # error arb_assert has not been defined -- check ASSERT_xxx definitions
260 #endif
261 
262 #if !defined(SIMPLE_ARB_ASSERT)
263 #define assert_or_exit(cond) \
264  do { \
265  if (!(cond)) { \
266  GBK_terminate(GBK_assert_msg(#cond, __FILE__, __LINE__)); \
267  } \
268  } while (0)
269 #endif // SIMPLE_ARB_ASSERT
270 
271 // ------------------------------------------------------------
272 
273 #ifdef UNIT_TESTS // UT_DIFF
274 #ifndef TEST_GLOBAL_H
275 #include <test_global.h> // overrides arb_assert()!
276 #endif
277 #else
278 #define RUNNING_TEST() false
279 #endif
280 
281 #ifndef CXXFORWARD_H
282 #include <cxxforward.h>
283 #endif
284 
285 // ------------------------------------------------------------
286 // logical operators (mostly used for assertions)
287 
288 // Note: 'conclusion' is not evaluated if 'hypothesis' is wrong!
289 #define implicated(hypothesis,conclusion) (!(hypothesis) || !!(conclusion))
290 
291 #ifdef __cplusplus
292 CONSTEXPR_INLINE bool correlated(bool hypo1, bool hypo2) { return implicated(hypo1, hypo2) == implicated(hypo2, hypo1); } // equivalence!
293 CONSTEXPR_INLINE bool contradicted(bool hypo1, bool hypo2) { return !correlated(hypo1, hypo2); } // non-equivalence!
294 #endif
295 
296 // ------------------------------------------------------------
297 // use the following macros for parameters etc. only appearing in one version
298 
299 #ifdef DEBUG
300 # define IF_DEBUG(x) x
301 # define IF_NDEBUG(x)
302 #else
303 # define IF_DEBUG(x)
304 # define IF_NDEBUG(x) x
305 #endif
306 
307 #ifdef ASSERTION_USED
308 # define IF_ASSERTION_USED(x) x
309 #else
310 # define IF_ASSERTION_USED(x)
311 #endif
312 
313 // ------------------------------------------------------------
314 // assertion tolerant constexpr modifiers
315 
316 #if defined(ASSERTION_USED)
317 # define ASSERTING_CONSTEXPR_INLINE inline
318 # define ASSERTING_CONSTEXPR_INLINE_Cxx14 inline
319 #else // !ASSERTION_USED
320 # define ASSERTING_CONSTEXPR_INLINE CONSTEXPR_INLINE
321 # define ASSERTING_CONSTEXPR_INLINE_Cxx14 CONSTEXPR_INLINE_Cxx14
322 #endif
323 
324 // ------------------------------------------------------------
325 // Assert specific result in DEBUG and silence __ATTR__USERESULT warnings in NDEBUG.
326 //
327 // The value 'Expected' (or 'Limit') should be side-effect-free (it is only executed in DEBUG mode).
328 // The given 'Expr' is evaluated under all conditions!
329 //
330 // Important note:
331 // When you swap 'Expected' and 'Expr' by mistake,
332 // code working in DEBUG, may suddenly stop working in NDEBUG!
333 
334 #ifdef ASSERTION_USED
335 
336 # define ASSERT_RESULT(Type, Expected, Expr) do { \
337  Type value = (Expr); \
338  arb_assert(value == (Expected)); \
339  } while (0)
340 
341 # define ASSERT_RESULT_PREDICATE(Pred, Expr) do { \
342  arb_assert(Pred(Expr)); \
343  } while (0)
344 
345 #else
346 
347 template <typename T> inline void dont_warn_unused_result(T) {}
348 
349 # define ASSERT_RESULT(Type, Expected, Expr) do { \
350  dont_warn_unused_result<Type>(Expr); \
351  } while(0)
352 
353 # define ASSERT_RESULT_PREDICATE(Pred, Expr) do { \
354  (void)Expr; \
355  } while(0)
356 
357 #endif
358 
359 #define ASSERT_NULL_RESULT(ptrExpr) ASSERT_RESULT(const void*, NULp, ptrExpr)
360 #define ASSERT_NO_ERROR(errorExpr) ASSERT_RESULT(GB_ERROR, NULp, errorExpr)
361 
362 #define ASSERT_TRUE(boolExpr) ASSERT_RESULT(bool, true, boolExpr)
363 #define ASSERT_FALSE(boolExpr) ASSERT_RESULT(bool, false, boolExpr)
364 
365 // ------------------------------------------------------------
366 
367 #if defined(ASSERTION_USED)
368 inline bool knownNonNull(const void *nonnull) { // use to suppress -Wnonnull-compare (only allowed in assertions)
369  return nonnull;
370 }
371 #endif
372 
373 // ------------------------------------------------------------
374 // UNCOVERED is used to
375 // - check for existing and
376 // - document missing test coverage.
377 // See ../INCLUDE/test_global.h@UNCOVERED
378 
379 #ifndef UNCOVERED
380 #define UNCOVERED()
381 #endif
382 
383 // ------------------------------------------------------------
384 
385 #ifdef DEVEL_RELEASE
386 # ifdef ASSERTION_USED
387 # error Assertions enabled in release
388 # endif
389 #endif
390 
391 // ------------------------------------------------------------
392 
393 #if !defined(SIMPLE_ARB_ASSERT)
394 #ifndef ARB_CORE_H
395 #include <arb_core.h>
396 #endif
397 #endif // SIMPLE_ARB_ASSERT
398 
399 #else
400 #error arb_assert.h included twice
401 #endif // ARB_ASSERT_H
402 
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
#define provoke_core_dump()
Definition: arb_assert.h:100
#define CONSTEXPR_INLINE
Definition: cxxforward.h:92
bool knownNonNull(const void *nonnull)
Definition: arb_assert.h:368
Definition: trnsprob.h:20