Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2026 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : /**
19 : * @file
20 : * Define and implement basic support for handling assertions and aborting code execution.
21 : * Macros and functions in this file do not perform any logging therefore can be used in
22 : * contexts where I/O or memory allocation are not allowed.
23 : *
24 : * The abort function is customizable by defining `CHIP_CONFIG_ABORT`.
25 : */
26 :
27 : #pragma once
28 :
29 : #include <cstdlib>
30 : #include <lib/core/CHIPConfig.h>
31 :
32 : /**
33 : * @brief
34 : * Base-level abnormal termination.
35 : *
36 : * Terminate the program immediately, without invoking destructors, atexit callbacks, etc.
37 : * Used to implement the default `chipAbort()` function.
38 : *
39 : * @note
40 : * This should never be invoked directly by code outside this file.
41 : */
42 : #if !defined(CHIP_CONFIG_ABORT)
43 : #define CHIP_CONFIG_ABORT() abort()
44 : #endif
45 :
46 : /**
47 : * @brief
48 : * This is invoked when an assertion expression evaluates to false.
49 : *
50 : * Developers may override and customize this by defining #chipAbort
51 : * before this file is included by the preprocessor.
52 : */
53 : #ifndef chipAbort
54 : extern "C" void chipAbort(void) __attribute((noreturn));
55 :
56 0 : inline void chipAbort(void)
57 : {
58 : while (true)
59 : {
60 0 : CHIP_CONFIG_ABORT();
61 : }
62 : }
63 : #endif // chipAbort
64 :
65 : /**
66 : * @def VerifyOrDieWithoutLogging(expr)
67 : *
68 : * @brief
69 : * This checks for the specified @a cond, which is expected to
70 : * commonly be true. Aborts if the condition is false. This macro
71 : * does not log.
72 : *
73 : * @param[in] cond A Boolean expression to be evaluated.
74 : */
75 : #define VerifyOrDieWithoutLogging(cond) \
76 : do \
77 : { \
78 : if (!(cond)) \
79 : { \
80 : chipAbort(); \
81 : } \
82 : } while (false)
83 :
84 : /**
85 : * @def AbortWithAction(anAction...)
86 : *
87 : * @brief
88 : * Do something and abort code execution by calling chipAbort()
89 : *
90 : * @param[in] ... Statements to execute.
91 : */
92 : #define AbortWithAction(...) \
93 : do \
94 : { \
95 : __VA_ARGS__; \
96 : chipAbort(); \
97 : } while (false)
98 :
99 : /**
100 : * @def VerifyOrExit(aCondition, anAction)
101 : *
102 : * @brief
103 : * This checks for the specified condition, which is expected to
104 : * commonly be true, and both executes @a anAction and branches to
105 : * the local label 'exit' if the condition is false.
106 : *
107 : * Example Usage:
108 : *
109 : * @code
110 : * CHIP_ERROR MakeBuffer(const uint8_t *& buf)
111 : * {
112 : * CHIP_ERROR err = CHIP_NO_ERROR;
113 : *
114 : * buf = (uint8_t *)malloc(1024);
115 : * VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
116 : *
117 : * memset(buf, 0, 1024);
118 : *
119 : * exit:
120 : * return err;
121 : * }
122 : * @endcode
123 : *
124 : * @param[in] aCondition A Boolean expression to be evaluated.
125 : * @param[in] anAction An expression or block to execute when the
126 : * assertion fails.
127 : *
128 : */
129 : #define VerifyOrExit(aCondition, anAction) VerifyOrDo(aCondition, anAction; goto exit)
130 :
131 : /**
132 : * @def VerifyOrReturnError(expr, code, ...)
133 : *
134 : * @brief
135 : * Returns a specified error code if expression evaluates to false
136 : *
137 : * Example usage:
138 : *
139 : * @code
140 : * VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
141 : * @endcode
142 : *
143 : * @param[in] expr A Boolean expression to be evaluated.
144 : * @param[in] code A value to return if @a expr is false.
145 : * @param[in] ... Statements to execute before returning. Optional.
146 : */
147 : #define VerifyOrReturnError(expr, code, ...) VerifyOrReturnValue(expr, code, ##__VA_ARGS__)
148 :
149 : /**
150 : * @def VerifyOrReturnValue(expr, value, ...)
151 : *
152 : * @brief
153 : * Returns a specified value if expression evaluates to false
154 : *
155 : * Example usage:
156 : *
157 : * @code
158 : * VerifyOrReturnError(param != nullptr, Foo());
159 : * @endcode
160 : *
161 : * @param[in] expr A Boolean expression to be evaluated.
162 : * @param[in] value A value to return if @a expr is false.
163 : * @param[in] ... Statements to execute before returning. Optional.
164 : */
165 : #define VerifyOrReturnValue(expr, value, ...) \
166 : do \
167 : { \
168 : if (!(expr)) \
169 : { \
170 : __VA_ARGS__; \
171 : return (value); \
172 : } \
173 : } while (false)
174 :
175 : /**
176 : * @def VerifyOrReturn(expr, ...)
177 : *
178 : * @brief
179 : * Returns from the void function if expression evaluates to false
180 : *
181 : * Example usage:
182 : *
183 : * @code
184 : * VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
185 : * @endcode
186 : *
187 : * @param[in] expr A Boolean expression to be evaluated.
188 : * @param[in] ... Statements to execute before returning. Optional.
189 : */
190 : #define VerifyOrReturn(expr, ...) \
191 : do \
192 : { \
193 : if (!(expr)) \
194 : { \
195 : __VA_ARGS__; \
196 : return; \
197 : } \
198 : } while (false)
199 :
200 : /**
201 : * @def VerifyOrDo(expr, ...)
202 : *
203 : * @brief
204 : * do something if expression evaluates to false
205 : *
206 : * Example usage:
207 : *
208 : * @code
209 : * VerifyOrDo(param != nullptr, LogError("param is nullptr"));
210 : * @endcode
211 : *
212 : * @param[in] expr A Boolean expression to be evaluated.
213 : * @param[in] ... Statements to execute.
214 : */
215 : #define VerifyOrDo(expr, ...) \
216 : do \
217 : { \
218 : if (!(expr)) \
219 : { \
220 : __VA_ARGS__; \
221 : } \
222 : } while (false)
223 :
224 : /**
225 : * @def ExitNow(...)
226 : *
227 : * @brief
228 : * This unconditionally executes @a ... and branches to the local
229 : * label 'exit'.
230 : *
231 : * @note The use of this interface implies neither success nor
232 : * failure for the overall exit status of the enclosing function
233 : * body.
234 : *
235 : * Example Usage:
236 : *
237 : * @code
238 : * CHIP_ERROR ReadAll(Reader& reader)
239 : * {
240 : * CHIP_ERROR err;
241 : *
242 : * while (true)
243 : * {
244 : * err = reader.ReadNext();
245 : * if (err == CHIP_ERROR_AT_END)
246 : * ExitNow(err = CHIP_NO_ERROR);
247 : * SuccessOrExit(err);
248 : * DoSomething();
249 : * }
250 : *
251 : * exit:
252 : * return err;
253 : * }
254 : * @endcode
255 : *
256 : * @param[in] ... Statements to execute. Optional.
257 : */
258 : #define ExitNow(...) \
259 : do \
260 : { \
261 : __VA_ARGS__; \
262 : goto exit; \
263 : } while (0)
264 :
265 : /**
266 : * @def IgnoreUnusedVariable(aVariable)
267 : *
268 : * @brief
269 : * This casts the specified @a aVariable to void to quell any
270 : * compiler-issued unused variable warnings or errors.
271 : *
272 : * @code
273 : * void foo (int err)
274 : * {
275 : * IgnoreUnusedVariable(err)
276 : * }
277 : * @endcode
278 : *
279 : */
280 : #define IgnoreUnusedVariable(aVariable) ((void) (aVariable))
|