Ruby  3.1.4p223 (2023-03-30 revision HEAD)
value_type.h
Go to the documentation of this file.
1 #ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
2 #define RBIMPL_VALUE_TYPE_H
23 #include "ruby/internal/assume.h"
29 #include "ruby/internal/cast.h"
33 #include "ruby/internal/error.h"
36 #include "ruby/internal/stdbool.h"
37 #include "ruby/internal/value.h"
38 #include "ruby/assert.h"
39 
40 #if defined(T_DATA)
41 /*
42  * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of
43  * T_DATA. Let us stop here. Please have a workaround like this:
44  *
45  * ```C
46  * #include <ruby/ruby.h> // <- Include this one first.
47  * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever.
48  * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced.
49  * ```
50  *
51  * See also [ruby-core:4261]
52  */
53 # error Bail out due to conflicting definition of T_DATA.
54 #endif
55 
56 #define T_ARRAY RUBY_T_ARRAY
57 #define T_BIGNUM RUBY_T_BIGNUM
58 #define T_CLASS RUBY_T_CLASS
59 #define T_COMPLEX RUBY_T_COMPLEX
60 #define T_DATA RUBY_T_DATA
61 #define T_FALSE RUBY_T_FALSE
62 #define T_FILE RUBY_T_FILE
63 #define T_FIXNUM RUBY_T_FIXNUM
64 #define T_FLOAT RUBY_T_FLOAT
65 #define T_HASH RUBY_T_HASH
66 #define T_ICLASS RUBY_T_ICLASS
67 #define T_IMEMO RUBY_T_IMEMO
68 #define T_MASK RUBY_T_MASK
69 #define T_MATCH RUBY_T_MATCH
70 #define T_MODULE RUBY_T_MODULE
71 #define T_MOVED RUBY_T_MOVED
72 #define T_NIL RUBY_T_NIL
73 #define T_NODE RUBY_T_NODE
74 #define T_NONE RUBY_T_NONE
75 #define T_OBJECT RUBY_T_OBJECT
76 #define T_RATIONAL RUBY_T_RATIONAL
77 #define T_REGEXP RUBY_T_REGEXP
78 #define T_STRING RUBY_T_STRING
79 #define T_STRUCT RUBY_T_STRUCT
80 #define T_SYMBOL RUBY_T_SYMBOL
81 #define T_TRUE RUBY_T_TRUE
82 #define T_UNDEF RUBY_T_UNDEF
83 #define T_ZOMBIE RUBY_T_ZOMBIE
85 #define BUILTIN_TYPE RB_BUILTIN_TYPE
86 #define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
87 #define RB_INTEGER_TYPE_P rb_integer_type_p
88 #define SYMBOL_P RB_SYMBOL_P
89 #define rb_type_p RB_TYPE_P
92 #define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
93 #define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
94 #define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P
95 #define RB_SYMBOL_P RB_SYMBOL_P
96 #define RB_TYPE_P RB_TYPE_P
97 #define Check_Type Check_Type
98 
99 #if !RUBY_DEBUG
100 # define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t)))
101 #else
102 # define RBIMPL_ASSERT_TYPE Check_Type
103 #endif
107 #define TYPE(_) RBIMPL_CAST((int)rb_type(_))
108 
110 enum
113  RUBY_T_NONE = 0x00,
115  RUBY_T_OBJECT = 0x01,
116  RUBY_T_CLASS = 0x02,
117  RUBY_T_MODULE = 0x03,
118  RUBY_T_FLOAT = 0x04,
119  RUBY_T_STRING = 0x05,
120  RUBY_T_REGEXP = 0x06,
121  RUBY_T_ARRAY = 0x07,
122  RUBY_T_HASH = 0x08,
123  RUBY_T_STRUCT = 0x09,
124  RUBY_T_BIGNUM = 0x0a,
125  RUBY_T_FILE = 0x0b,
126  RUBY_T_DATA = 0x0c,
127  RUBY_T_MATCH = 0x0d,
128  RUBY_T_COMPLEX = 0x0e,
131  RUBY_T_NIL = 0x11,
132  RUBY_T_TRUE = 0x12,
133  RUBY_T_FALSE = 0x13,
134  RUBY_T_SYMBOL = 0x14,
135  RUBY_T_FIXNUM = 0x15,
136  RUBY_T_UNDEF = 0x16,
138  RUBY_T_IMEMO = 0x1a,
139  RUBY_T_NODE = 0x1b,
140  RUBY_T_ICLASS = 0x1c,
141  RUBY_T_ZOMBIE = 0x1d,
142  RUBY_T_MOVED = 0x1e,
144  RUBY_T_MASK = 0x1f
145 };
146 
168 void rb_check_type(VALUE obj, int t);
170 
180 static inline enum ruby_value_type
182 {
184 
185 #if 0 && defined __GNUC__ && !defined __clang__
186  /* Don't move the access to `flags` before the preceding
187  * RB_SPECIAL_CONST_P check. */
188  __asm volatile("": : :"memory");
189 #endif
190  VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK;
191  return RBIMPL_CAST((enum ruby_value_type)ret);
192 }
193 
202 static inline bool
204 {
205  if (RB_FIXNUM_P(obj)) {
206  return true;
207  }
208  else if (RB_SPECIAL_CONST_P(obj)) {
209  return false;
210  }
211  else {
212  return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM;
213  }
214 }
215 
223 static inline enum ruby_value_type
224 rb_type(VALUE obj)
225 {
226  if (! RB_SPECIAL_CONST_P(obj)) {
227  return RB_BUILTIN_TYPE(obj);
228  }
229  else if (obj == RUBY_Qfalse) {
230  return RUBY_T_FALSE;
231  }
232  else if (obj == RUBY_Qnil) {
233  return RUBY_T_NIL;
234  }
235  else if (obj == RUBY_Qtrue) {
236  return RUBY_T_TRUE;
237  }
238  else if (obj == RUBY_Qundef) {
239  return RUBY_T_UNDEF;
240  }
241  else if (RB_FIXNUM_P(obj)) {
242  return RUBY_T_FIXNUM;
243  }
244  else if (RB_STATIC_SYM_P(obj)) {
245  return RUBY_T_SYMBOL;
246  }
247  else {
249  return RUBY_T_FLOAT;
250  }
251 }
252 
262 static inline bool
264 {
265  if (RB_FLONUM_P(obj)) {
266  return true;
267  }
268  else if (RB_SPECIAL_CONST_P(obj)) {
269  return false;
270  }
271  else {
272  return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT;
273  }
274 }
275 
285 static inline bool
287 {
288  if (RB_SPECIAL_CONST_P(obj)) {
289  return false;
290  }
291  else {
292  return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL;
293  }
294 }
295 
305 static inline bool
307 {
308  return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj);
309 }
310 
324 static bool
325 rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
326 {
327  if (t == RUBY_T_TRUE) {
328  return obj == RUBY_Qtrue;
329  }
330  else if (t == RUBY_T_FALSE) {
331  return obj == RUBY_Qfalse;
332  }
333  else if (t == RUBY_T_NIL) {
334  return obj == RUBY_Qnil;
335  }
336  else if (t == RUBY_T_UNDEF) {
337  return obj == RUBY_Qundef;
338  }
339  else if (t == RUBY_T_FIXNUM) {
340  return RB_FIXNUM_P(obj);
341  }
342  else if (t == RUBY_T_SYMBOL) {
343  return RB_SYMBOL_P(obj);
344  }
345  else if (t == RUBY_T_FLOAT) {
346  return RB_FLOAT_TYPE_P(obj);
347  }
348  else if (RB_SPECIAL_CONST_P(obj)) {
349  return false;
350  }
351  else if (t == RB_BUILTIN_TYPE(obj)) {
352  return true;
353  }
354  else {
355  return false;
356  }
357 }
358 
374 static inline bool
376 {
377  if (RBIMPL_CONSTANT_P(t)) {
378  return rbimpl_RB_TYPE_P_fastpath(obj, t);
379  }
380  else {
381  return t == rb_type(obj);
382  }
383 }
384 
386 /* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function
387  * boundary. */
388 #if defined(__clang__)
389 # undef RB_TYPE_P
390 # define RB_TYPE_P(obj, t) \
391  (RBIMPL_CONSTANT_P(t) ? \
392  rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \
393  (RB_TYPE_P)((obj), (t)))
394 #endif
395 
396 /* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
397  * in inline function and caller function
398  * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba
399  */
400 #if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0)
401 # undef rb_integer_type_p
402 # define rb_integer_type_p(obj) \
403  __extension__ ({ \
404  const VALUE integer_type_obj = (obj); \
405  (RB_FIXNUM_P(integer_type_obj) || \
406  (!RB_SPECIAL_CONST_P(integer_type_obj) && \
407  RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
408  })
409 #endif
418 static inline bool rbimpl_rtypeddata_p(VALUE obj);
419 
431 static inline void
433 {
434  if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
435  goto unexpected_type;
436  }
437  else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) {
438  /* Typed data is not simple `T_DATA`, see `rb_check_type` */
439  goto unexpected_type;
440  }
441  else {
442  return;
443  }
444 
445  unexpected_type:
446  rb_unexpected_type(v, t);
447 }
448 
449 #endif /* RBIMPL_VALUE_TYPE_H */
Defines RBIMPL_ATTR_ARTIFICIAL.
#define RBIMPL_ATTR_ARTIFICIAL()
Wraps (or simulates) __attribute__((artificial))
Definition: artificial.h:41
#define RBIMPL_ASSERT_OR_ASSUME(expr)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition: assert.h:229
#define RB_UNLIKELY(x)
Asserts that the given Boolean expression likely doesn't hold.
Definition: assume.h:52
Defines RBIMPL_ATTR_COLD.
#define RBIMPL_ATTR_COLD()
Wraps (or simulates) __attribute__((cold))
Definition: cold.h:32
Defines RBIMPL_CONSTANT_P.
#define RBIMPL_CONSTANT_P(expr)
Wraps (or simulates) __builtin_constant_p
Definition: constant_p.h:33
Tweaking visibility of C variables/functions.
#define RBIMPL_SYMBOL_EXPORT_END()
Counterpart of RBIMPL_SYMBOL_EXPORT_BEGIN.
Definition: dllexport.h:106
#define RBIMPL_SYMBOL_EXPORT_BEGIN()
Shortcut macro equivalent to RUBY_SYMBOL_EXPORT_BEGIN extern "C" {.
Definition: dllexport.h:97
RBIMPL_ATTR_ENUM_EXTENSIBILITY.
#define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_)
Wraps (or simulates) __attribute__((enum_extensibility))
Defines RBIMPL_ATTR_FORCEINLINE.
#define RBIMPL_ATTR_FORCEINLINE()
Wraps (or simulates) __forceinline.
Definition: forceinline.h:35
void rb_unexpected_type(VALUE x, int t)
Fails with the given object's type incompatibility to the type.
Definition: error.c:1029
void rb_check_type(VALUE x, int t)
This was the old implementation of Check_Type(), but they diverged.
Definition: error.c:1006
Declares rb_raise().
Defines RBIMPL_HAS_BUILTIN.
RBIMPL_ATTR_PURE() int rb_io_read_pending(rb_io_t *fptr)
Queries if the passed IO has any pending reads.
Defines RBIMPL_ASSUME / RBIMPL_UNREACHABLE.
#define RBIMPL_ASSUME
Wraps (or simulates) __assume.
Definition: assume.h:76
Defines RBIMPL_ATTR_PURE.
#define RBIMPL_ATTR_PURE_UNLESS_DEBUG()
Enables RBIMPL_ATTR_PURE if and only if.
Definition: pure.h:38
Defines struct RBasic.
#define RBASIC(obj)
Convenient casting macro.
Definition: rbasic.h:40
Defines enum ruby_special_consts.
static bool RB_STATIC_SYM_P(VALUE obj)
Checks if the given object is a static symbol.
static bool RB_FIXNUM_P(VALUE obj)
Checks if the given object is a so-called Fixnum.
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
@ RUBY_Qtrue
@ RUBY_Qnil
@ RUBY_Qundef
Represents so-called undef.
@ RUBY_Qfalse
static bool RB_FLONUM_P(VALUE obj)
Checks if the given object is a so-called Flonum.
C99 shim for <stdbool.h>
Defines VALUE and ID.
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
Definition: value_type.h:224
static enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj)
Queries the type of the object.
Definition: value_type.h:181
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition: value_type.h:263
static bool RB_SYMBOL_P(VALUE obj)
Queries if the object is an instance of rb_cSymbol.
Definition: value_type.h:306
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:432
static bool rb_integer_type_p(VALUE obj)
Queries if the object is an instance of rb_cInteger.
Definition: value_type.h:203
static bool RB_DYNAMIC_SYM_P(VALUE obj)
Queries if the object is a dynamic symbol.
Definition: value_type.h:286
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:375
ruby_value_type
C-level type of an object.
Definition: value_type.h:112
@ RUBY_T_SYMBOL
Definition: value_type.h:134
@ RUBY_T_MATCH
Definition: value_type.h:127
@ RUBY_T_MODULE
Definition: value_type.h:117
@ RUBY_T_ICLASS
Hidden classes known as IClasses.
Definition: value_type.h:140
@ RUBY_T_MOVED
Definition: value_type.h:142
@ RUBY_T_FIXNUM
Integers formerly known as Fixnums.
Definition: value_type.h:135
@ RUBY_T_IMEMO
Definition: value_type.h:138
@ RUBY_T_NODE
Definition: value_type.h:139
@ RUBY_T_OBJECT
Definition: value_type.h:115
@ RUBY_T_DATA
Definition: value_type.h:126
@ RUBY_T_FALSE
Definition: value_type.h:133
@ RUBY_T_UNDEF
Definition: value_type.h:136
@ RUBY_T_COMPLEX
Definition: value_type.h:128
@ RUBY_T_STRING
Definition: value_type.h:119
@ RUBY_T_HASH
Definition: value_type.h:122
@ RUBY_T_NIL
Definition: value_type.h:131
@ RUBY_T_CLASS
Definition: value_type.h:116
@ RUBY_T_ARRAY
Definition: value_type.h:121
@ RUBY_T_MASK
Bitmask of ruby_value_type.
Definition: value_type.h:144
@ RUBY_T_RATIONAL
Definition: value_type.h:129
@ RUBY_T_ZOMBIE
Definition: value_type.h:141
@ RUBY_T_BIGNUM
Definition: value_type.h:124
@ RUBY_T_TRUE
Definition: value_type.h:132
@ RUBY_T_FLOAT
Definition: value_type.h:118
@ RUBY_T_STRUCT
Definition: value_type.h:123
@ RUBY_T_NONE
Non-object (swept etc.)
Definition: value_type.h:113
@ RUBY_T_REGEXP
Definition: value_type.h:120
@ RUBY_T_FILE
Definition: value_type.h:125