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