]> git.proxmox.com Git - mirror_frr.git/blob - lib/assert/assert.h
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / assert / assert.h
1 // SPDX-License-Identifier: ISC
2 /*
3 * Copyright (c) 2021 David Lamparter, for NetDEF, Inc.
4 */
5
6 /* WARNING: this file is "special" in that it overrides the system-provided
7 * assert.h by being on the include path before it. That means it should
8 * provide the functional equivalent.
9 *
10 * This is intentional because FRR extends assert() to write to the log and
11 * add backtraces. Overriding the entire file is the simplest and most
12 * reliable way to get this to work; there were problems previously with the
13 * system assert.h getting included afterwards and redefining assert() back to
14 * the system variant.
15 */
16
17 #ifndef _FRR_ASSERT_H
18 #define _FRR_ASSERT_H
19
20 #include "xref.h"
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 #ifndef __cplusplus
27 /* C++ has this built-in, but C provides it in assert.h for >=C11. Since we
28 * replace assert.h entirely, we need to provide it here too.
29 */
30 #define static_assert _Static_assert
31 #endif
32
33 struct xref_assert {
34 struct xref xref;
35
36 const char *expr;
37 const char *extra, *args;
38 };
39
40 extern void _zlog_assert_failed(const struct xref_assert *xref,
41 const char *extra, ...) PRINTFRR(2, 3)
42 __attribute__((noreturn));
43
44 /* the "do { } while (expr_)" is there to get a warning for assignments inside
45 * the assert expression aka "assert(x = 1)". The (necessary) braces around
46 * expr_ in the if () statement would suppress these warnings. Since
47 * _zlog_assert_failed() is noreturn, the while condition will never be
48 * checked.
49 */
50 #define assert(expr_) \
51 ({ \
52 static const struct xref_assert _xref __attribute__( \
53 (used)) = { \
54 .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
55 .expr = #expr_, \
56 }; \
57 XREF_LINK(_xref.xref); \
58 if (__builtin_expect((expr_) ? 0 : 1, 0)) \
59 do { \
60 _zlog_assert_failed(&_xref, NULL); \
61 } while (expr_); \
62 })
63
64 #define assertf(expr_, extra_, ...) \
65 ({ \
66 static const struct xref_assert _xref __attribute__( \
67 (used)) = { \
68 .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
69 .expr = #expr_, \
70 .extra = extra_, \
71 .args = #__VA_ARGS__, \
72 }; \
73 XREF_LINK(_xref.xref); \
74 if (__builtin_expect((expr_) ? 0 : 1, 0)) \
75 do { \
76 _zlog_assert_failed(&_xref, extra_, \
77 ##__VA_ARGS__); \
78 } while (expr_); \
79 })
80
81 #define zassert assert
82
83 #ifdef __cplusplus
84 }
85 #endif
86
87 #endif /* _FRR_ASSERT_H */