root/trunk/ARBDB/arb_assert.h

Revision 8659, 9.3 KB (checked in by westram, 4 weeks ago)
  • provoke_core_dump via volatile pointer (otherwise clang will skip the code which is crashing on purpose)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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
39/* ------------------------------------------------------------
40 * Define SIMPLE_ARB_ASSERT before including this header
41 * to avoid ARBDB dependency!
42 *
43 * ASSERT_CRASH                 if assert fails debugger stops at assert macro
44 * ASSERT_BACKTRACE_AND_CRASH   like ASSERT_CRASH - with backtrace
45 * ASSERT_ERROR                 assert prints an error and ARB exits
46 * ASSERT_PRINT                 assert prints a message (anyway) and ARB continues
47 * ASSERT_NONE                  assertions inactive
48 *
49 * ------------------------------------------------------------ */
50
51// check correct definition of DEBUG/NDEBUG
52#ifndef NDEBUG
53# ifndef DEBUG
54#  error Neither DEBUG nor NDEBUG is defined!
55# endif
56#else
57# ifdef DEBUG
58#  error Both DEBUG and NDEBUG are defined - only one should be!
59# endif
60#endif
61
62#ifdef arb_assert
63#error arb_assert already defined
64#endif
65
66// only use ONE of the following ASSERT_xxx defines :
67
68#if defined(DEBUG) && !defined(DEVEL_RELEASE)
69
70// assert that raises SIGSEGV (recommended for DEBUG version!)
71// # define ASSERT_CRASH
72# define ASSERT_BACKTRACE_AND_CRASH
73// test if a bug has to do with assertion code
74// # define ASSERT_NONE
75
76#else
77
78// no assert (recommended for final version!)
79# define ASSERT_NONE
80// assert as error in final version (allows basic debugging of NDEBUG version)
81// # define ASSERT_ERROR
82// assert as print in final version (allows basic debugging of NDEBUG version)
83// # define ASSERT_PRINT
84
85#endif
86
87// ------------------------------------------------------------
88
89#if defined(__cplusplus)
90inline void provoke_core_dump() {
91    volatile int *np = 0; // if not volatile, the clang compiler will skip the crashing code
92    // cppcheck-suppress nullPointer
93    *(int*)np = 666;
94}
95#else // !defined(__cplusplus)
96#define provoke_core_dump() do { *(int*)0 = 0; } while(0)
97#endif
98
99// ------------------------------------------------------------
100
101#if defined(SIMPLE_ARB_ASSERT)
102
103// code here is independent from ARBDB!
104
105#define ARB_SIGSEGV(backtrace) do {                             \
106        provoke_core_dump();                                    \
107    } while (0)
108
109#ifndef ASSERT_NONE
110# define arb_assert(cond)                                               \
111    do {                                                                \
112        if (!(cond)) {                                                  \
113            fprintf(stderr, "Assertion '%s' failed in '%s' #%i\n",      \
114                    #cond, __FILE__, __LINE__);                         \
115            provoke_core_dump();                                        \
116        }                                                               \
117    } while (0)
118#endif
119
120
121// ------------------------------------------------------------
122
123#else
124
125/* Provoke a SIGSEGV (which will stop the debugger or terminated the application)
126 * Do backtrace manually here and uninstall SIGSEGV-handler
127 * (done because automatic backtrace on SIGSEGV lacks name of current function)
128 */
129
130#ifndef ARB_CORE_H
131#include <arb_core.h>
132#endif
133
134#define ARB_SIGSEGV(backtrace) do {                             \
135        if (backtrace) GBK_dump_backtrace(NULL, "ARB_SIGSEGV"); \
136        GBK_install_SIGSEGV_handler(false);                     \
137        provoke_core_dump();                                    \
138    } while (0)
139
140
141# define arb_assert_crash(cond)                 \
142    do {                                        \
143        if (!(cond)) ARB_SIGSEGV(0);            \
144    } while (0)
145
146# define arb_assert_backtrace_and_crash(cond)                           \
147    do {                                                                \
148        if (!(cond)) {                                                  \
149            fputs(GBK_assert_msg(#cond, __FILE__, __LINE__), stderr);   \
150            fflush(stderr);                                             \
151            ARB_SIGSEGV(1);                                             \
152        }                                                               \
153    } while (0)
154
155#ifdef ASSERT_CRASH
156# define arb_assert(cond) arb_assert_crash(cond)
157#endif
158
159#ifdef ASSERT_BACKTRACE_AND_CRASH
160# define arb_assert(cond) arb_assert_backtrace_and_crash(cond)
161#endif
162
163#ifdef ASSERT_ERROR
164# define arb_assert(cond) assert_or_exit(cond)
165#endif
166
167#ifdef ASSERT_PRINT
168# define arb_assert(cond)                                               \
169    do {                                                                \
170        fprintf(stderr, "at %s #%i\n", __FILE__, __LINE__);             \
171        if (!(cond)) fprintf(stderr, "assertion '%s' failed!\n", #cond); \
172        fflush(stderr);                                                 \
173    } while (0)
174#endif
175
176#endif // SIMPLE_ARB_ASSERT
177
178// ------------------------------------------------------------
179
180#ifdef ASSERT_NONE
181# define arb_assert(cond)
182#else
183# define ASSERTION_USED
184#endif
185
186#undef ASSERT_CRASH
187#undef ASSERT_BACKTRACE_AND_CRASH
188#undef ASSERT_ERROR
189#undef ASSERT_PRINT
190#undef ASSERT_NONE
191
192#ifndef arb_assert
193# error arb_assert has not been defined -- check ASSERT_xxx definitions
194#endif
195
196#if !defined(SIMPLE_ARB_ASSERT)
197#define assert_or_exit(cond)                                            \
198    do {                                                                \
199        if (!(cond)) {                                                  \
200            GBK_terminate(GBK_assert_msg(#cond, __FILE__, __LINE__));   \
201        }                                                               \
202    } while (0)
203#endif // SIMPLE_ARB_ASSERT
204
205// ------------------------------------------------------------
206
207#ifdef UNIT_TESTS
208#ifndef TEST_GLOBAL_H
209#include <test_global.h> // overrides arb_assert()!
210#endif
211#else
212#define RUNNING_TEST() false
213#endif
214
215// ------------------------------------------------------------
216// logical operators (mostly used for assertions)
217
218// Note: 'conclusion' is not evaluated if 'hypothesis' is wrong!
219#define implicated(hypothesis,conclusion) (!(hypothesis) || !!(conclusion))
220
221#ifdef __cplusplus
222inline bool correlated(bool hypo1, bool hypo2) { return implicated(hypo1, hypo2) == implicated(hypo2, hypo1); } // equivalence!
223inline bool contradicted(bool hypo1, bool hypo2) { return !correlated(hypo1, hypo2); } // non-equivalence!
224#endif
225
226// ------------------------------------------------------------
227// use the following macros for parameters etc. only appearing in one version
228
229#ifdef DEBUG
230# define IF_DEBUG(x) x
231# define IF_NDEBUG(x)
232#else
233# define IF_DEBUG(x)
234# define IF_NDEBUG(x) x
235#endif
236
237#ifdef ASSERTION_USED
238# define IF_ASSERTION_USED(x) x
239#else
240# define IF_ASSERTION_USED(x)
241#endif
242
243// ------------------------------------------------------------
244// Assert specific result in DEBUG and silence __ATTR__USERESULT warnings in NDEBUG.
245//
246// The value 'Expected' (or 'Limit') should be side-effect-free (it is only executed in DEBUG mode).
247// The given 'Expr' is evaluated under all conditions!
248//
249// Important note:
250//      When you swap 'Expected' and 'Expr' by mistake,
251//      code working in DEBUG, may suddenly stop working in NDEBUG!
252
253#ifdef ASSERTION_USED
254
255# define ASSERT_RESULT(Type, Expected, Expr) do {       \
256        Type value = (Expr);                            \
257        arb_assert(value == (Expected));                \
258    } while (0)
259
260# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
261        arb_assert(Pred(Expr));                         \
262    } while (0)
263
264#else
265
266template <typename T> inline void dont_warn_unused_result(T) {}
267
268# define ASSERT_RESULT(Type, Expected, Expr) do {       \
269        dont_warn_unused_result<Type>(Expr);            \
270    } while(0)
271
272# define ASSERT_RESULT_PREDICATE(Pred, Expr) do {       \
273        (void)Expr;                                     \
274    } while(0)
275
276#endif
277
278#define ASSERT_NULL_RESULT(ptrExpr) ASSERT_RESULT(const void*, NULL, ptrExpr)
279#define ASSERT_NO_ERROR(errorExpr)  ASSERT_RESULT(GB_ERROR, NULL, errorExpr)
280
281#define ASSERT_TRUE(boolExpr)  ASSERT_RESULT(bool, true, boolExpr)
282#define ASSERT_FALSE(boolExpr) ASSERT_RESULT(bool, false, boolExpr)
283
284// ------------------------------------------------------------
285// UNCOVERED is used to document/test missing test coverage
286// see ../INCLUDE/test_global.h@UNCOVERED
287
288#ifndef UNCOVERED
289#define UNCOVERED()
290#endif
291
292// ------------------------------------------------------------
293
294#ifdef DEVEL_RELEASE
295# ifdef ASSERTION_USED
296#  error Assertions enabled in release
297# endif
298#endif
299
300// ------------------------------------------------------------
301
302#if !defined(SIMPLE_ARB_ASSERT)
303#ifndef ARB_CORE_H
304#include <arb_core.h>
305#endif
306#endif // SIMPLE_ARB_ASSERT
307
308#else
309#error arb_assert.h included twice
310#endif // ARB_ASSERT_H
Note: See TracBrowser for help on using the browser.