Commit | Line | Data |
---|---|---|
2bdc32f7 PP |
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 | ||
1778c2a4 PP |
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 | BT_HIDDEN | |
81 | __attribute__((noreturn)) | |
82 | void bt_lib_assert_cond_failed(const char *cond_type, const char *func, | |
83 | const char *id_suffix, const char *fmt, ...); | |
84 | ||
2bdc32f7 PP |
85 | /* |
86 | * Internal to this file: asserts that the library condition `_cond` of | |
1778c2a4 PP |
87 | * type `_cond_type` (`pre` or `post`), related to function `_func`, |
88 | * and having the ID suffix `_id_suffix` is satisfied. | |
2bdc32f7 | 89 | * |
1778c2a4 PP |
90 | * If `_cond` is false, then this macro calls |
91 | * bt_lib_assert_cond_failed(). | |
2bdc32f7 | 92 | * |
1778c2a4 | 93 | * To assert that an _internal_ precondition or postcondition is |
2bdc32f7 PP |
94 | * satisfied, use BT_ASSERT() or BT_ASSERT_DBG(). |
95 | */ | |
1778c2a4 | 96 | #define _BT_ASSERT_COND(_cond_type, _func, _id_suffix, _cond, _fmt, ...) \ |
2bdc32f7 PP |
97 | do { \ |
98 | if (!(_cond)) { \ | |
1778c2a4 PP |
99 | bt_lib_assert_cond_failed(_cond_type, _func, \ |
100 | _id_suffix, _fmt, ##__VA_ARGS__); \ | |
2bdc32f7 PP |
101 | } \ |
102 | } while (0) | |
103 | ||
104 | /* | |
105 | * Asserts that the library precondition `_cond` is satisfied. | |
106 | * | |
1778c2a4 PP |
107 | * See _BT_ASSERT_COND() for details about the `_func` and `_id_suffix` |
108 | * parameters. | |
2bdc32f7 | 109 | */ |
1778c2a4 PP |
110 | #define BT_ASSERT_PRE_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \ |
111 | _BT_ASSERT_COND("pre", _func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__) | |
112 | ||
113 | /* | |
114 | * Like BT_ASSERT_PRE_FROM_FUNC(), but uses `__func__` (current function | |
115 | * name) as the `_func` parameter. | |
116 | */ | |
117 | #define BT_ASSERT_PRE(_id_suffix, _cond, _fmt, ...) \ | |
118 | BT_ASSERT_PRE_FROM_FUNC(__func__, _id_suffix, (_cond), _fmt, ##__VA_ARGS__) | |
2bdc32f7 PP |
119 | |
120 | /* | |
121 | * Asserts that the library postcondition `_cond` is satisfied. | |
122 | * | |
1778c2a4 PP |
123 | * See _BT_ASSERT_COND() for details about the `_func` and `_id_suffix` |
124 | * parameters. | |
2bdc32f7 | 125 | */ |
1778c2a4 PP |
126 | #define BT_ASSERT_POST(_func, _id_suffix, _cond, _fmt, ...) \ |
127 | _BT_ASSERT_COND("post", _func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__); | |
2bdc32f7 PP |
128 | |
129 | #ifdef BT_DEV_MODE | |
1778c2a4 PP |
130 | /* Developer mode version of BT_ASSERT_PRE_FROM_FUNC(). */ |
131 | # define BT_ASSERT_PRE_DEV_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \ | |
132 | BT_ASSERT_PRE_FROM_FUNC(_func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__) | |
133 | ||
2bdc32f7 | 134 | /* Developer mode version of BT_ASSERT_PRE(). */ |
1778c2a4 PP |
135 | # define BT_ASSERT_PRE_DEV(_id_suffix, _cond, _fmt, ...) \ |
136 | BT_ASSERT_PRE(_id_suffix, (_cond), _fmt, ##__VA_ARGS__) | |
2bdc32f7 PP |
137 | |
138 | /* Developer mode version of BT_ASSERT_POST(). */ | |
1778c2a4 PP |
139 | # define BT_ASSERT_POST_DEV(_func, _id_suffix, _cond, _fmt, ...) \ |
140 | BT_ASSERT_POST(_func, _id_suffix, (_cond), _fmt, ##__VA_ARGS__) | |
2bdc32f7 PP |
141 | |
142 | /* Developer mode version of BT_ASSERT_COND_MSG(). */ | |
143 | # define BT_ASSERT_COND_DEV_MSG(_fmt, ...) \ | |
144 | BT_ASSERT_COND_MSG(_fmt, ##__VA_ARGS__) | |
145 | ||
146 | /* | |
147 | * Marks a function as being only used within a BT_ASSERT_PRE_DEV() or | |
148 | * BT_ASSERT_POST_DEV() context. | |
149 | */ | |
150 | # define BT_ASSERT_COND_DEV_FUNC | |
151 | #else | |
152 | # define BT_ASSERT_COND_DEV_MSG(_fmt, ...) | |
153 | ||
1778c2a4 PP |
154 | # define BT_ASSERT_PRE_DEV_FROM_FUNC(_func, _id_suffix, _cond, _fmt, ...) \ |
155 | BT_USE_EXPR4(_func, _id_suffix, _cond, _fmt) | |
156 | ||
157 | # define BT_ASSERT_PRE_DEV(_id_suffix, _cond, _fmt, ...) \ | |
158 | BT_USE_EXPR3(_id_suffix, _cond, _fmt) | |
2bdc32f7 | 159 | |
1778c2a4 PP |
160 | # define BT_ASSERT_POST_DEV(_func, _id_suffix, _cond, _fmt, ...) \ |
161 | BT_USE_EXPR4(_func, _id_suffix, _cond, _fmt) | |
2bdc32f7 PP |
162 | |
163 | # define BT_ASSERT_COND_DEV_FUNC __attribute__((unused)) | |
164 | #endif /* BT_DEV_MODE */ | |
165 | ||
166 | /* | |
167 | * Mark anything that includes this file as supporting precondition and | |
168 | * postcondition assertion macros. | |
169 | */ | |
170 | #define BT_ASSERT_COND_SUPPORTED | |
171 | ||
172 | #endif /* BABELTRACE_ASSERT_COND_BASE_INTERNAL_H */ |