xref: /freebsd/sys/contrib/openzfs/lib/libspl/include/assert.h (revision 071ab5a1f3cbfd29c8fbec27f7e619418adaf074)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License, Version 1.0 only
7  * (the "License").  You may not use this file except in compliance
8  * with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or https://opensource.org/licenses/CDDL-1.0.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 /*
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include_next <assert.h>
29 
30 #ifndef _LIBSPL_ASSERT_H
31 #define	_LIBSPL_ASSERT_H
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <sys/types.h>
37 
38 /* Workaround for non-Clang compilers */
39 #ifndef __has_feature
40 #define	__has_feature(x) 0
41 #endif
42 
43 /* We need to workaround libspl_set_assert_ok() that we have for zdb */
44 #if __has_feature(attribute_analyzer_noreturn) || defined(__COVERITY__)
45 #define	NORETURN	__attribute__((__noreturn__))
46 #else
47 #define	NORETURN
48 #endif
49 
50 /* Set to non-zero to avoid abort()ing on an assertion failure */
51 extern void libspl_set_assert_ok(boolean_t val);
52 
53 /* printf version of libspl_assert */
54 extern void libspl_assertf(const char *file, const char *func, int line,
55     const char *format, ...) NORETURN __attribute__((format(printf, 4, 5)));
56 
57 static inline int
libspl_assert(const char * buf,const char * file,const char * func,int line)58 libspl_assert(const char *buf, const char *file, const char *func, int line)
59 {
60 	libspl_assertf(file, func, line, "%s", buf);
61 	return (0);
62 }
63 
64 #ifdef verify
65 #undef verify
66 #endif
67 
68 #define	PANIC(fmt, a...)						\
69 	libspl_assertf(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
70 
71 #define	VERIFY(cond)							\
72 	(void) ((!(cond)) &&						\
73 	    libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
74 
75 #define	VERIFYF(cond, STR, ...)						\
76 do {									\
77 	if (!(cond))							\
78 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
79 		    "%s " STR, #cond,					\
80 		    __VA_ARGS__);					\
81 } while (0)
82 
83 #define	verify(cond)							\
84 	(void) ((!(cond)) &&						\
85 	    libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
86 
87 #define	VERIFY3B(LEFT, OP, RIGHT)					\
88 do {									\
89 	const boolean_t __left = (boolean_t)!!(LEFT);			\
90 	const boolean_t __right = (boolean_t)!!(RIGHT);			\
91 	if (!(__left OP __right))					\
92 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
93 		    "VERIFY3B(%s, %s, %s) failed "			\
94 		    "(%d %s %d)", #LEFT, #OP, #RIGHT,			\
95 		    __left, #OP, __right);				\
96 } while (0)
97 
98 #define	VERIFY3S(LEFT, OP, RIGHT)					\
99 do {									\
100 	const int64_t __left = (int64_t)(LEFT);				\
101 	const int64_t __right = (int64_t)(RIGHT);			\
102 	if (!(__left OP __right))					\
103 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
104 		    "VERIFY3S(%s, %s, %s) failed "			\
105 		    "(%lld %s 0x%lld)", #LEFT, #OP, #RIGHT,		\
106 		    (longlong_t)__left, #OP, (longlong_t)__right);	\
107 } while (0)
108 
109 #define	VERIFY3U(LEFT, OP, RIGHT)					\
110 do {									\
111 	const uint64_t __left = (uint64_t)(LEFT);			\
112 	const uint64_t __right = (uint64_t)(RIGHT);			\
113 	if (!(__left OP __right))					\
114 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
115 		    "VERIFY3U(%s, %s, %s) failed "			\
116 		    "(%llu %s %llu)", #LEFT, #OP, #RIGHT,		\
117 		    (u_longlong_t)__left, #OP, (u_longlong_t)__right);	\
118 } while (0)
119 
120 #define	VERIFY3P(LEFT, OP, RIGHT)					\
121 do {									\
122 	const uintptr_t __left = (uintptr_t)(LEFT);			\
123 	const uintptr_t __right = (uintptr_t)(RIGHT);			\
124 	if (!(__left OP __right))					\
125 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
126 		    "VERIFY3P(%s, %s, %s) failed "			\
127 		    "(%p %s %p)", #LEFT, #OP, #RIGHT,			\
128 		    (void *)__left, #OP, (void *)__right);		\
129 } while (0)
130 
131 #define	VERIFY0(LEFT)							\
132 do {									\
133 	const uint64_t __left = (uint64_t)(LEFT);			\
134 	if (!(__left == 0))						\
135 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
136 		    "VERIFY0(%s) failed (%lld)", #LEFT,			\
137 		    (u_longlong_t)__left);				\
138 } while (0)
139 
140 #define	VERIFY0P(LEFT)							\
141 do {									\
142 	const uintptr_t __left = (uintptr_t)(LEFT);			\
143 	if (!(__left == 0))						\
144 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
145 		    "VERIFY0P(%s) failed (%p)", #LEFT,			\
146 		    (void *)__left);					\
147 } while (0)
148 
149 /*
150  * This is just here because cstyle gets upset about #LEFT
151  * on a newline.
152  */
153 
154 /* BEGIN CSTYLED */
155 #define	VERIFY3BF(LEFT, OP, RIGHT, STR, ...)				\
156 do {									\
157 	const boolean_t __left = (boolean_t)!!(LEFT);			\
158 	const boolean_t __right = (boolean_t)!!(RIGHT);			\
159 	if (!(__left OP __right))					\
160 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
161 		    "VERIFY3B(%s, %s, %s) failed "			\
162 		    "(%d %s %d) " STR, #LEFT, #OP, #RIGHT,		\
163 		    __left, #OP, __right,				\
164 		    __VA_ARGS__);					\
165 } while (0)
166 
167 #define	VERIFY3SF(LEFT, OP, RIGHT, STR, ...)				\
168 do {									\
169 	const int64_t __left = (int64_t)(LEFT);				\
170 	const int64_t __right = (int64_t)(RIGHT);			\
171 	if (!(__left OP __right))					\
172 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
173 		    "VERIFY3S(%s, %s, %s) failed "			\
174 		    "(%lld %s %lld) " STR, #LEFT, #OP, #RIGHT,		\
175 		    (longlong_t)__left, #OP, (longlong_t)__right,	\
176 		    __VA_ARGS__);					\
177 } while (0)
178 
179 #define	VERIFY3UF(LEFT, OP, RIGHT, STR, ...)				\
180 do {									\
181 	const uint64_t __left = (uint64_t)(LEFT);			\
182 	const uint64_t __right = (uint64_t)(RIGHT);			\
183 	if (!(__left OP __right))					\
184 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
185 		    "VERIFY3U(%s, %s, %s) failed "			\
186 		    "(%llu %s %llu) " STR, #LEFT, #OP, #RIGHT,		\
187 		    (u_longlong_t)__left, #OP, (u_longlong_t)__right,	\
188 		    __VA_ARGS__);					\
189 } while (0)
190 
191 #define	VERIFY3PF(LEFT, OP, RIGHT, STR, ...)				\
192 do {									\
193 	const uintptr_t __left = (uintptr_t)(LEFT);			\
194 	const uintptr_t __right = (uintptr_t)(RIGHT);			\
195 	if (!(__left OP __right))					\
196 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
197 		    "VERIFY3P(%s, %s, %s) failed "			\
198 		    "(%p %s %p) " STR, #LEFT, #OP, #RIGHT,		\
199 		    (void *)__left, #OP, (void *)__right,		\
200 		    __VA_ARGS__);					\
201 } while (0)
202 /* END CSTYLED */
203 
204 #define	VERIFY0F(LEFT, STR, ...)					\
205 do {									\
206 	const int64_t __left = (int64_t)(LEFT);				\
207 	if (!(__left == 0))						\
208 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
209 		    "VERIFY0(%s) failed (%lld) " STR, #LEFT,		\
210 		    (longlong_t)__left, __VA_ARGS__);			\
211 } while (0)
212 
213 #define	VERIFY0PF(LEFT, STR, ...)					\
214 do {									\
215 	const uintptr_t __left = (uintptr_t)(LEFT);			\
216 	if (!(__left == 0))						\
217 		libspl_assertf(__FILE__, __FUNCTION__, __LINE__,	\
218 		    "VERIFY0P(%s) failed (%p) " STR, #LEFT,		\
219 		    (void *)__left, __VA_ARGS__);			\
220 } while (0)
221 
222 #ifdef assert
223 #undef assert
224 #endif
225 
226 #ifdef NDEBUG
227 #define	ASSERT3B(x, y, z)						\
228 	((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
229 #define	ASSERT3S(x, y, z)						\
230 	((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
231 #define	ASSERT3U(x, y, z)						\
232 	((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
233 #define	ASSERT3P(x, y, z)						\
234 	((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
235 #define	ASSERT0(x)		((void) sizeof ((uintptr_t)(x)))
236 #define	ASSERT0P(x)		((void) sizeof ((uintptr_t)(x)))
237 #define	ASSERT3BF(x, y, z, str, ...)	ASSERT3B(x, y, z)
238 #define	ASSERT3SF(x, y, z, str, ...)	ASSERT3S(x, y, z)
239 #define	ASSERT3UF(x, y, z, str, ...)	ASSERT3U(x, y, z)
240 #define	ASSERT3PF(x, y, z, str, ...)	ASSERT3P(x, y, z)
241 #define	ASSERT0P(x)		((void) sizeof ((uintptr_t)(x)))
242 #define	ASSERT0PF(x, str, ...)		ASSERT0P(x)
243 #define	ASSERT0F(x, str, ...)		ASSERT0(x)
244 #define	ASSERT(x)		((void) sizeof ((uintptr_t)(x)))
245 #define	ASSERTF(x, str, ...)	ASSERT(x)
246 #define	assert(x)		((void) sizeof ((uintptr_t)(x)))
247 #define	IMPLY(A, B)							\
248 	((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
249 #define	EQUIV(A, B)							\
250 	((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
251 #else
252 #define	ASSERT3B	VERIFY3B
253 #define	ASSERT3S	VERIFY3S
254 #define	ASSERT3U	VERIFY3U
255 #define	ASSERT3P	VERIFY3P
256 #define	ASSERT0		VERIFY0
257 #define	ASSERT0P	VERIFY0P
258 #define	ASSERT3BF	VERIFY3BF
259 #define	ASSERT3SF	VERIFY3SF
260 #define	ASSERT3UF	VERIFY3UF
261 #define	ASSERT3PF	VERIFY3PF
262 #define	ASSERT0PF	VERIFY0PF
263 #define	ASSERT0F	VERIFY0F
264 #define	ASSERT		VERIFY
265 #define	ASSERTF		VERIFYF
266 #define	assert		VERIFY
267 #define	IMPLY(A, B) \
268 	((void)(((!(A)) || (B)) || \
269 	    libspl_assert("(" #A ") implies (" #B ")", \
270 	    __FILE__, __FUNCTION__, __LINE__)))
271 #define	EQUIV(A, B)	VERIFY3B(A, ==, B)
272 
273 #endif  /* NDEBUG */
274 
275 #endif  /* _LIBSPL_ASSERT_H */
276