Visibility hidden by default
[babeltrace.git] / src / lib / assert-cond-base.h
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright (c) 2018 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2018-2020 Philippe Proulx <pproulx@efficios.com>
6 */
7
8 #ifndef BABELTRACE_ASSERT_COND_BASE_INTERNAL_H
9 #define BABELTRACE_ASSERT_COND_BASE_INTERNAL_H
10
11 /*
12 * The macros in this header use macros defined in "lib/logging.h". We
13 * don't want this header to automatically include "lib/logging.h"
14 * because you need to manually define BT_LOG_TAG before including
15 * "lib/logging.h" and it is unexpected that you also need to define it
16 * before including this header.
17 *
18 * This is a reminder that in order to use "lib/assert-cond.h", you also
19 * need to use logging explicitly.
20 */
21
22 #ifndef BT_LIB_LOG_SUPPORTED
23 # error Include "lib/logging.h" before this header.
24 #endif
25
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <inttypes.h>
29 #include "common/common.h"
30 #include "common/macros.h"
31
32 /*
33 * Prints the details of an unsatisfied precondition or postcondition
34 * without immediately aborting. You should use this within a function
35 * which checks preconditions or postconditions, but which is called
36 * from a BT_ASSERT_PRE() or BT_ASSERT_POST() context, so that the
37 * function can still return its result for
38 * BT_ASSERT_PRE()/BT_ASSERT_POST() to evaluate it.
39 *
40 * Example:
41 *
42 * static inline bool check_complex_precond(...)
43 * {
44 * ...
45 *
46 * if (...) {
47 * BT_ASSERT_COND_MSG("Invalid object: ...", ...);
48 * return false;
49 * }
50 *
51 * ...
52 * }
53 *
54 * ...
55 *
56 * BT_ASSERT_PRE(check_complex_precond(...),
57 * "Precondition is not satisfied: ...", ...);
58 */
59 #define BT_ASSERT_COND_MSG(_fmt, ...) \
60 do { \
61 bt_lib_log(_BT_LOG_SRCLOC_FUNCTION, __FILE__, \
62 __LINE__, BT_LOG_FATAL, BT_LOG_TAG, \
63 (_fmt), ##__VA_ARGS__); \
64 } while (0)
65
66 /*
67 * This function:
68 *
69 * 1. Generates a condition ID based on `cond_type`, `func`, and
70 * `id_suffix`.
71 *
72 * 2. Logs (FATAL level) the generated condition ID and function name
73 * (`func`).
74 *
75 * 3. Logs (FATAL level) a message using `fmt` and the optional
76 * arguments (same usage as BT_LIB_LOGF()).
77 *
78 * 4. Aborts.
79 */
80 __attribute__((noreturn))
81 void bt_lib_assert_cond_failed(const char *cond_type, const char *func,
82 const char *id_suffix, const char *fmt, ...);
83
84 /*
85 * Internal to this file: asserts that the library condition `_cond` of
86 * type `_cond_type` (`pre` or `post`), related to function `_func`,
87 * and having the ID suffix `_id_suffix` is satisfied.
88 *
89 * If `_cond` is false, then this macro calls
90 * bt_lib_assert_cond_failed().
91 *
92 * To assert that an _internal_ precondition or postcondition is
93 * satisfied, use BT_ASSERT() or BT_ASSERT_DBG().
94 */
95 #define _BT_ASSERT_COND(_cond_type, _func, _id_suffix, _cond, _fmt, ...) \
96 do { \
97 if (!(_cond)) { \
98 bt_lib_assert_cond_failed(_cond_type, _func, \
99 _id_suffix, _fmt, ##__VA_ARGS__); \
100 } \
101 } while (0)
102
103 /*
104 * Asserts that the library precondition `_cond` is satisfied.
105 *
106 * See _BT_ASSERT_COND() for details about the `_func` and `_id_suffix`
107 * parameters.
108 */
109 #define BT_ASSERT_PRE_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \
110 _BT_ASSERT_COND("pre", _func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__)
111
112 /*
113 * Like BT_ASSERT_PRE_FROM_FUNC(), but uses `__func__` (current function
114 * name) as the `_func` parameter.
115 */
116 #define BT_ASSERT_PRE(_id_suffix, _cond, _fmt, ...) \
117 BT_ASSERT_PRE_FROM_FUNC(__func__, _id_suffix, (_cond), _fmt, ##__VA_ARGS__)
118
119 /*
120 * Asserts that the library postcondition `_cond` is satisfied.
121 *
122 * See _BT_ASSERT_COND() for details about the `_func` and `_id_suffix`
123 * parameters.
124 */
125 #define BT_ASSERT_POST(_func, _id_suffix, _cond, _fmt, ...) \
126 _BT_ASSERT_COND("post", _func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__);
127
128 #ifdef BT_DEV_MODE
129 /* Developer mode version of BT_ASSERT_PRE_FROM_FUNC(). */
130 # define BT_ASSERT_PRE_DEV_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \
131 BT_ASSERT_PRE_FROM_FUNC(_func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__)
132
133 /* Developer mode version of BT_ASSERT_PRE(). */
134 # define BT_ASSERT_PRE_DEV(_id_suffix, _cond, _fmt, ...) \
135 BT_ASSERT_PRE(_id_suffix, (_cond), _fmt, ##__VA_ARGS__)
136
137 /* Developer mode version of BT_ASSERT_POST(). */
138 # define BT_ASSERT_POST_DEV(_func, _id_suffix, _cond, _fmt, ...) \
139 BT_ASSERT_POST(_func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__)
140
141 /* Developer mode version of BT_ASSERT_COND_MSG(). */
142 # define BT_ASSERT_COND_DEV_MSG(_fmt, ...) \
143 BT_ASSERT_COND_MSG(_fmt, ##__VA_ARGS__)
144
145 /*
146 * Marks a function as being only used within a BT_ASSERT_PRE_DEV() or
147 * BT_ASSERT_POST_DEV() context.
148 */
149 # define BT_ASSERT_COND_DEV_FUNC
150 #else
151 # define BT_ASSERT_COND_DEV_MSG(_fmt, ...)
152
153 # define BT_ASSERT_PRE_DEV_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \
154 BT_USE_EXPR4(_func, _id_suffix, _cond, _fmt)
155
156 # define BT_ASSERT_PRE_DEV(_id_suffix, _cond, _fmt, ...) \
157 BT_USE_EXPR3(_id_suffix, _cond, _fmt)
158
159 # define BT_ASSERT_POST_DEV(_func, _id_suffix, _cond, _fmt, ...) \
160 BT_USE_EXPR4(_func, _id_suffix, _cond, _fmt)
161
162 # define BT_ASSERT_COND_DEV_FUNC __attribute__((unused))
163 #endif /* BT_DEV_MODE */
164
165 /*
166 * Mark anything that includes this file as supporting precondition and
167 * postcondition assertion macros.
168 */
169 #define BT_ASSERT_COND_SUPPORTED
170
171 #endif /* BABELTRACE_ASSERT_COND_BASE_INTERNAL_H */
This page took 0.035868 seconds and 4 git commands to generate.