Ruby: include/ruby/assert.h Source File

Ruby 4.0.6p0 (2026-07-14 revision 03b6d3f8898a28604fe6cb00eae3226b821168f4)

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"
24#include "ruby/internal/attr/cold.h"
25#include "ruby/internal/attr/format.h"
26#include "ruby/internal/attr/noreturn.h"
27#include "ruby/internal/cast.h"
28#include "ruby/internal/dllexport.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
53
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
81
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
132 RBIMPL_SYMBOL_EXPORT_BEGIN()
133 RBIMPL_ATTR_NORETURN()
134 RBIMPL_ATTR_COLD()
135void rb_assert_failure(const char *file, int line, const char *name, const char *expr);
136
137 RBIMPL_ATTR_NORETURN()
138 RBIMPL_ATTR_COLD()
139 RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 5, 6)
140void rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr, const char *fmt, ...);
141 RBIMPL_SYMBOL_EXPORT_END()
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
150
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 */
assume.h
Defines ASSUME / RB_LIKELY / UNREACHABLE.
cold.h
Defines RBIMPL_ATTR_COLD.
RBIMPL_ATTR_COLD
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold)).
Definition cold.h:34
dllexport.h
Tweaking visibility of C variables/functions.
RBIMPL_SYMBOL_EXPORT_END
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition dllexport.h:74
RBIMPL_SYMBOL_EXPORT_BEGIN
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition dllexport.h:65
format.h
Defines RBIMPL_ATTR_FORMAT.
RBIMPL_ATTR_FORMAT
#define RBIMPL_ATTR_FORMAT(x, y, z)
Wraps (or simulates) __attribute__((format)).
Definition format.h:29
assume.h
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
noreturn.h
Defines RBIMPL_ATTR_NORETURN.
RBIMPL_ATTR_NORETURN
#define RBIMPL_ATTR_NORETURN()
Wraps (or simulates) [[noreturn]].
Definition noreturn.h:38
RBIMPL_WARNING_IGNORED
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
Definition warning_push.h:80