]> git.proxmox.com Git - mirror_frr.git/blob - lib/assert/assert.h
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / lib / assert / assert.h
1 /*
2 * Copyright (c) 2021 David Lamparter, for NetDEF, Inc.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /* WARNING: this file is "special" in that it overrides the system-provided
18 * assert.h by being on the include path before it. That means it should
19 * provide the functional equivalent.
20 *
21 * This is intentional because FRR extends assert() to write to the log and
22 * add backtraces. Overriding the entire file is the simplest and most
23 * reliable way to get this to work; there were problems previously with the
24 * system assert.h getting included afterwards and redefining assert() back to
25 * the system variant.
26 */
27
28 #ifndef _FRR_ASSERT_H
29 #define _FRR_ASSERT_H
30
31 #include "xref.h"
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 #ifndef __cplusplus
38 /* C++ has this built-in, but C provides it in assert.h for >=C11. Since we
39 * replace assert.h entirely, we need to provide it here too.
40 */
41 #define static_assert _Static_assert
42 #endif
43
44 struct xref_assert {
45 struct xref xref;
46
47 const char *expr;
48 const char *extra, *args;
49 };
50
51 extern void _zlog_assert_failed(const struct xref_assert *xref,
52 const char *extra, ...) PRINTFRR(2, 3)
53 __attribute__((noreturn));
54
55 /* the "do { } while (expr_)" is there to get a warning for assignments inside
56 * the assert expression aka "assert(x = 1)". The (necessary) braces around
57 * expr_ in the if () statement would suppress these warnings. Since
58 * _zlog_assert_failed() is noreturn, the while condition will never be
59 * checked.
60 */
61 #define assert(expr_) \
62 ({ \
63 static const struct xref_assert _xref __attribute__( \
64 (used)) = { \
65 .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
66 .expr = #expr_, \
67 }; \
68 XREF_LINK(_xref.xref); \
69 if (__builtin_expect((expr_) ? 0 : 1, 0)) \
70 do { \
71 _zlog_assert_failed(&_xref, NULL); \
72 } while (expr_); \
73 })
74
75 #define assertf(expr_, extra_, ...) \
76 ({ \
77 static const struct xref_assert _xref __attribute__( \
78 (used)) = { \
79 .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
80 .expr = #expr_, \
81 .extra = extra_, \
82 .args = #__VA_ARGS__, \
83 }; \
84 XREF_LINK(_xref.xref); \
85 if (__builtin_expect((expr_) ? 0 : 1, 0)) \
86 do { \
87 _zlog_assert_failed(&_xref, extra_, \
88 ##__VA_ARGS__); \
89 } while (expr_); \
90 })
91
92 #define zassert assert
93
94 #ifdef __cplusplus
95 }
96 #endif
97
98 #endif /* _FRR_ASSERT_H */