source: tags/ms_r18q1/CORE/arb_assert.h

Last change on this file was 16936, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
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)
96inline 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#define ARB_SIGSEGV(backtrace) do {                             \
157        if (backtrace) GBK_dump_backtrace(NULp, "ARB_SIGSEGV"); \
158        GBK_install_SIGSEGV_handler(false);                     \
159        provoke_core_dump();                                    \
160    } while (0)
161
162#define ARB_STOP(backtrace)                                     \
163    do {                                                        \
164        if (backtrace) GBK_dump_backtrace(NULp, "ARB_STOP");    \
165        stop_in_debugger();                                     \
166    } while(0)
167
168# define arb_assert_crash(cond)         \
169    do {                                \
170        if (!(cond)) ARB_SIGSEGV(0);    \
171    } while (0)
172
173# define arb_assert_stop(cond)          \
174    do {                                \
175        if (!(cond)) ARB_STOP(0);       \
176    } while (0)
177
178# define arb_assert_backtrace_and_crash(cond)                           \
179    do {                                                                \
180        if (!(cond)) {                                                  \
181            fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr);   \
182            fflush(stderr);                                             \
183            ARB_SIGSEGV(1);                                             \
184        }                                                               \
185    } while (0)
186
187# define arb_assert_backtrace_and_stop(cond)                            \
188    do {                                                                \
189        if (!(cond)) {                                                  \
190            fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr);   \
191            fflush(stderr);                                             \
192            ARB_STOP(1);                                                \
193        }                                                               \
194    } while (0)
195
196#ifdef ASSERT_CRASH
197# define arb_assert(cond) arb_assert_crash(cond)
198#endif
199#ifdef ASSERT_STOP
200# define arb_assert(cond) arb_assert_stop(cond)
201#endif
202#ifdef ASSERT_BACKTRACE_AND_CRASH
203# define arb_assert(cond) arb_assert_backtrace_and_crash(cond)
204#endif
205#ifdef ASSERT_BACKTRACE_AND_STOP
206# define arb_assert(cond) arb_assert_backtrace_and_stop(cond)
207#endif
208#ifdef ASSERT_ERROR
209# define arb_assert(cond) assert_or_exit(cond)
210#endif
211
212#ifdef ASSERT_PRINT
213# define arb_assert(cond)                                               \
214    do {                                                                \
215        fprintf(stderr, "at %s #%i\n", __FILE__, __LINE__);             \
216        if (!(cond)) fprintf(stderr, "assertion '%s' failed!\n", #cond); \
217        fflush(stderr);                                                 \
218    } while (0)
219#endif
220
221#endif // SIMPLE_ARB_ASSERT
222
223// ------------------------------------------------------------
224
225#ifdef ASSERT_NONE
226# define arb_assert(cond)
227#else
228# define ASSERTION_USED
229#endif
230
231#undef ASSERT_CRASH
232#undef ASSERT_BACKTRACE_AND_CRASH
233#undef ASSERT_STOP
234#undef ASSERT_BACKTRACE_AND_STOP
235#undef ASSERT_ERROR
236#undef ASSERT_PRINT
237#undef ASSERT_NONE
238
239#ifndef arb_assert
240# error arb_assert has not been defined -- check ASSERT_xxx definitions
241#endif
242
243#if !defined(SIMPLE_ARB_ASSERT)
244#define assert_or_exit(cond)                                            \
245    do {                                                                \
246        if (!(cond)) {                                                  \
247            GBK_terminate(GBK_assert_msg(#cond, __FILE__, __LINE__));   \
248        }                                                               \
249    } while (0)
250#endif // SIMPLE_ARB_ASSERT
251
252// ------------------------------------------------------------
253
254#ifdef UNIT_TESTS // UT_DIFF
255#ifndef TEST_GLOBAL_H
256#include <test_global.h> // overrides arb_assert()!
257#endif
258#else
259#define RUNNING_TEST() false
260#endif
261
262#ifndef CXXFORWARD_H
263#include <cxxforward.h>
264#endif
265
266// ------------------------------------------------------------
267// logical operators (mostly used for assertions)
268
269// Note: 'conclusion' is not evaluated if 'hypothesis' is wrong!
270#define implicated(hypothesis,conclusion) (!(hypothesis) || !!(conclusion))
271
272#ifdef __cplusplus
273CONSTEXPR_INLINE bool correlated(bool hypo1, bool hypo2) { return implicated(hypo1, hypo2) == implicated(hypo2, hypo1); } // equivalence!
274CONSTEXPR_INLINE bool contradicted(bool hypo1, bool hypo2) { return !correlated(hypo1, hypo2); } // non-equivalence!
275#endif
276
277// ------------------------------------------------------------
278// use the following macros for parameters etc. only appearing in one version
279
280#ifdef DEBUG
281# define IF_DEBUG(x) x
282# define IF_NDEBUG(x)
283#else
284# define IF_DEBUG(x)
285# define IF_NDEBUG(x) x
286#endif
287
288#ifdef ASSERTION_USED
289# define IF_ASSERTION_USED(x) x
290#else
291# define IF_ASSERTION_USED(x)
292#endif
293
294// ------------------------------------------------------------
295// assertion tolerant constexpr modifiers
296
297#if defined(ASSERTION_USED)
298# define ASSERTING_CONSTEXPR_INLINE       inline
299# define ASSERTING_CONSTEXPR_INLINE_Cxx14 inline
300#else // !ASSERTION_USED
301# define ASSERTING_CONSTEXPR_INLINE       CONSTEXPR_INLINE
302# define ASSERTING_CONSTEXPR_INLINE_Cxx14 CONSTEXPR_INLINE_Cxx14
303#endif
304
305// ------------------------------------------------------------
306// Assert specific result in DEBUG and silence __ATTR__USERESULT warnings in NDEBUG.
307//
308// The value 'Expected' (or 'Limit') should be side-effect-free (it is only executed in DEBUG mode).
309// The given 'Expr' is evaluated under all conditions!
310//
311// Important note:
312//      When you swap 'Expected' and 'Expr' by mistake,
313//      code working in DEBUG, may suddenly stop working in NDEBUG!
314
315#ifdef ASSERTION_USED
316
317# define ASSERT_RESULT(Type, Expected, Expr) do {       \
318        Type value = (Expr);                            \
319        arb_assert(value == (Expected));                \
320    } while (0)
321
322# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
323        arb_assert(Pred(Expr));                         \
324    } while (0)
325
326#else
327
328template <typename T> inline void dont_warn_unused_result(T) {}
329
330# define ASSERT_RESULT(Type, Expected, Expr) do {       \
331        dont_warn_unused_result<Type>(Expr);            \
332    } while(0)
333
334# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
335        (void)Expr;                                     \
336    } while(0)
337
338#endif
339
340#define ASSERT_NULL_RESULT(ptrExpr) ASSERT_RESULT(const void*, NULp, ptrExpr)
341#define ASSERT_NO_ERROR(errorExpr)  ASSERT_RESULT(GB_ERROR, NULp, errorExpr)
342
343#define ASSERT_TRUE(boolExpr)  ASSERT_RESULT(bool, true, boolExpr)
344#define ASSERT_FALSE(boolExpr) ASSERT_RESULT(bool, false, boolExpr)
345
346// ------------------------------------------------------------
347
348#if defined(ASSERTION_USED)
349inline bool knownNonNull(const void *nonnull) { // use to suppress -Wnonnull-compare (only allowed in assertions)
350    return nonnull;
351}
352#endif
353
354// ------------------------------------------------------------
355// UNCOVERED is used to
356// - check for existing and
357// - document missing test coverage.
358// See ../INCLUDE/test_global.h@UNCOVERED
359
360#ifndef UNCOVERED
361#define UNCOVERED()
362#endif
363
364// ------------------------------------------------------------
365
366#ifdef DEVEL_RELEASE
367# ifdef ASSERTION_USED
368#  error Assertions enabled in release
369# endif
370#endif
371
372// ------------------------------------------------------------
373
374#if !defined(SIMPLE_ARB_ASSERT)
375#ifndef ARB_CORE_H
376#include <arb_core.h>
377#endif
378#endif // SIMPLE_ARB_ASSERT
379
380#else
381#error arb_assert.h included twice
382#endif // ARB_ASSERT_H
383
Note: See TracBrowser for help on using the repository browser.