Ruby  3.4.0dev (2024-12-06 revision 892c46283a5ea4179500d951c9d4866c0051f27b)
assert.h
Go to the documentation of this file.
1 #ifndef RUBY_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/
2 #define RUBY_ASSERT_H
23 #include "ruby/internal/assume.h"
27 #include "ruby/internal/cast.h"
29 #include "ruby/backward/2/assume.h"
30 
31 /* RUBY_NDEBUG is very simple: after everything described below are done,
32  * define it with either NDEBUG is undefined (=0) or defined (=1). It is truly
33  * subordinate.
34  *
35  * RUBY_DEBUG versus NDEBUG is complicated. Assertions shall be:
36  *
37  * | -UNDEBUG | -DNDEBUG
38  * ---------------+----------+---------
39  * -URUBY_DEBUG | (*1) | disabled
40  * -DRUBY_DEBUG=0 | disabled | disabled
41  * -DRUBY_DEBUG=1 | enabled | (*2)
42  * -DRUBY_DEBUG | enabled | (*2)
43  *
44  * where:
45  *
46  * - (*1): Assertions shall be silently disabled, no warnings, in favour of
47  * commit 21991e6ca59274e41a472b5256bd3245f6596c90.
48  *
49  * - (*2): Compile-time warnings shall be issued.
50  */
51 
54 /*
55  * Pro tip: `!!RUBY_DEBUG-1` expands to...
56  *
57  * - `!!(-1)` (== `!0` == `1`) when RUBY_DEBUG is defined to be empty,
58  * - `(!!0)-1` (== `0-1` == `-1`) when RUBY_DEBUG is defined as 0, and
59  * - `(!!n)-1` (== `1-1` == `0`) when RUBY_DEBUG is defined as something else.
60  */
61 #if ! defined(RUBY_DEBUG)
62 # define RBIMPL_RUBY_DEBUG 0
63 #elif !!RUBY_DEBUG-1 < 0
64 # define RBIMPL_RUBY_DEBUG 0
65 #else
66 # define RBIMPL_RUBY_DEBUG 1
67 #endif
68 
69 /*
70  * ISO/IEC 9899 (all past versions) says that "If NDEBUG is defined as a macro
71  * name at the point in the source file where <assert.h> is included, ..."
72  * which means we must not take its defined value into account.
73  */
74 #if defined(NDEBUG)
75 # define RBIMPL_NDEBUG 1
76 #else
77 # define RBIMPL_NDEBUG 0
78 #endif
79 
82 /* Here we go... */
83 #undef RUBY_DEBUG
84 #undef RUBY_NDEBUG
85 #undef NDEBUG
86 #if defined(__DOXYGEN__)
87 #
88 # define RUBY_DEBUG 0
89 #
90 # define NDEBUG
91 #
92 # define RUBY_NDEBUG 1
93 
94 #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 0)
95 # /* Assertions disabled as per request, no conflicts. */
96 # define RUBY_DEBUG 0
97 # define RUBY_NDEBUG 1
98 # define NDEBUG
99 
100 #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 1)
101 # /* Assertions enabled as per request, no conflicts. */
102 # define RUBY_DEBUG 1
103 # define RUBY_NDEBUG 0
104 # /* keep NDEBUG undefined */
105 
106 #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0)
107 # /* The (*1) situation in above diagram. */
108 # define RUBY_DEBUG 0
109 # define RUBY_NDEBUG 1
110 # define NDEBUG
111 
112 #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 1)
113 # /* The (*2) situation in above diagram. */
114 # define RUBY_DEBUG 1
115 # define RUBY_NDEBUG 0
116 # /* keep NDEBUG undefined */
117 
118 # if defined(_MSC_VER)
119 # pragma message("NDEBUG is ignored because RUBY_DEBUG>0.")
120 # elif defined(__GNUC__)
121 # pragma GCC warning "NDEBUG is ignored because RUBY_DEBUG>0."
122 # else
123 # error NDEBUG is ignored because RUBY_DEBUG>0.
124 # endif
125 #endif
126 #undef RBIMPL_NDEBUG
127 #undef RBIMPL_RUBY_DEBUG
128 
130 #define RBIMPL_ASSERT_NOTHING RBIMPL_CAST((void)0)
131 
135 void rb_assert_failure(const char *file, int line, const char *name, const char *expr);
136 
139 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 6)
140 void rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr, const char *fmt, ...);
142 
143 #ifdef RUBY_FUNCTION_NAME_STRING
144 # define RBIMPL_ASSERT_FUNC RUBY_FUNCTION_NAME_STRING
145 #else
146 # define RBIMPL_ASSERT_FUNC RBIMPL_CAST((const char *)0)
147 #endif
148 
156 #if defined(HAVE___VA_OPT__)
157 # if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
158 /* __VA_OPT__ is to be used for the zero variadic macro arguments
159  * cases. */
160 RBIMPL_WARNING_IGNORED(-Wgnu-zero-variadic-macro-arguments)
161 # endif
162 # define RBIMPL_VA_OPT_ARGS(...) __VA_OPT__(,) __VA_ARGS__
163 
164 # define RUBY_ASSERT_FAIL(mesg, ...) \
165  rb_assert_failure##__VA_OPT__(_detail)( \
166  __FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
167 #elif !defined(__cplusplus)
168 # define RBIMPL_VA_OPT_ARGS(...)
169 
170 # define RUBY_ASSERT_FAIL(mesg, ...) \
171  rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg)
172 #else
173 # undef RBIMPL_VA_OPT_ARGS
174 
175 # define RUBY_ASSERT_FAIL(mesg) \
176  rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg)
177 #endif
178 
185 #if defined(RBIMPL_VA_OPT_ARGS)
186 # define RUBY_ASSERT_MESG(expr, ...) \
187  (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(__VA_ARGS__))
188 #else
189 # define RUBY_ASSERT_MESG(expr, mesg) \
190  (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg))
191 #endif
192 
198 #if defined(RBIMPL_VA_OPT_ARGS)
199 # define RUBY_ASSERT_ALWAYS(expr, ...) \
200  RUBY_ASSERT_MESG(expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
201 #else
202 # define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr)
203 #endif
204 
210 #if RUBY_DEBUG
211 # if defined(RBIMPL_VA_OPT_ARGS)
212 # define RUBY_ASSERT(expr, ...) \
213  RUBY_ASSERT_MESG((expr), #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
214 # else
215 # define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr)
216 # endif
217 #else
218 # if defined(RBIMPL_VA_OPT_ARGS)
219 # define RUBY_ASSERT(/* expr, */...) RBIMPL_ASSERT_NOTHING
220 # else
221 # define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING
222 # endif
223 #endif
224 
232 /* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no
233  * difference any longer between this one and `RUBY_ASSERT`. */
234 #if defined(NDEBUG)
235 # if defined(RBIMPL_VA_OPT_ARGS)
236 # define RUBY_ASSERT_NDEBUG(/* expr, */...) RBIMPL_ASSERT_NOTHING
237 # else
238 # define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING
239 # endif
240 #else
241 # if defined(RBIMPL_VA_OPT_ARGS)
242 # define RUBY_ASSERT_NDEBUG(expr, ...) \
243  RUBY_ASSERT_MESG((expr), #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
244 # else
245 # define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr)
246 # endif
247 #endif
248 
253 #if RUBY_DEBUG
254 # if defined(RBIMPL_VA_OPT_ARGS)
255 # define RUBY_ASSERT_MESG_WHEN(cond, /* expr, */...) \
256  RUBY_ASSERT_MESG(__VA_ARGS__)
257 # else
258 # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg))
259 # endif
260 #else
261 # if defined(RBIMPL_VA_OPT_ARGS)
262 # define RUBY_ASSERT_MESG_WHEN(cond, expr, ...) \
263  ((cond) ? RUBY_ASSERT_MESG((expr), __VA_ARGS__) : RBIMPL_ASSERT_NOTHING)
264 # else
265 # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
266  ((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING)
267 # endif
268 #endif
269 
277 #if defined(RBIMPL_VA_OPT_ARGS)
278 # define RUBY_ASSERT_WHEN(cond, expr, ...) \
279  RUBY_ASSERT_MESG_WHEN(cond, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
280 #else
281 # define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr)
282 #endif
283 
291 #define RUBY_ASSERT_BUILTIN_TYPE(obj, type) \
292  RUBY_ASSERT(RB_TYPE_P(obj, type), \
293  "Actual type is %s", rb_builtin_type_name(BUILTIN_TYPE(obj)))
294 
300 #if RUBY_DEBUG
301 # define RBIMPL_ASSERT_OR_ASSUME RUBY_ASSERT_ALWAYS
302 #elif ! defined(RBIMPL_VA_OPT_ARGS)
303 # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr)
304 #elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0)
305 # /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */
306 # define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
307 #elif defined(RUBY_ASSERT_NOASSUME)
308 # /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */
309 # define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
310 #elif ! defined(RBIMPL_HAVE___ASSUME)
311 # define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
312 #else
313 # define RBIMPL_ASSERT_OR_ASSUME(expr, ...) RBIMPL_ASSUME(expr)
314 #endif
315 
316 #endif /* RUBY_ASSERT_H */
Defines ASSUME / RB_LIKELY / UNREACHABLE.
Defines RBIMPL_ATTR_COLD.
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition: cold.h:32
Tweaking visibility of C variables/functions.
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition: dllexport.h:74
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition: dllexport.h:65
Defines RBIMPL_ATTR_FORMAT.
#define RBIMPL_ATTR_FORMAT(x, y, z)
Wraps (or simulates) __attribute__((format))
Definition: format.h:27
RBIMPL_ATTR_NORETURN() void rb_eof_error(void)
Utility function to raise rb_eEOFError.
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
Defines RBIMPL_ATTR_NORETURN.
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
Definition: warning_push.h:80