diff options
Diffstat (limited to 'include/ruby/internal')
69 files changed, 984 insertions, 871 deletions
diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h index 8e1bbf3951..e6d1fa7e8f 100644 --- a/include/ruby/internal/abi.h +++ b/include/ruby/internal/abi.h @@ -24,7 +24,7 @@ * In released versions of Ruby, this number is not defined since teeny * versions of Ruby should guarantee ABI compatibility. */ -#define RUBY_ABI_VERSION 0 +#define RUBY_ABI_VERSION 1 /* Windows does not support weak symbols so ruby_abi_version will not exist * in the shared library. */ @@ -33,7 +33,7 @@ #endif #endif /* RUBY_ABI_VERSION */ -#ifdef RUBY_DLN_CHECK_ABI +#if defined(RUBY_DLN_CHECK_ABI) && !defined(RUBY_EXPORT) # ifdef __cplusplus extern "C" { diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h index e3e1b6166d..e4c6d155cc 100644 --- a/include/ruby/internal/anyargs.h +++ b/include/ruby/internal/anyargs.h @@ -84,12 +84,15 @@ #elif defined(_WIN32) || defined(__CYGWIN__) # /* Skip due to [Bug #16134] */ +# define RBIMPL_CAST_FN_PTR 1 #elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union) # /* :TODO: improve here, please find a way to support. */ +# define RBIMPL_CAST_FN_PTR 1 #elif ! defined(HAVE_VA_ARGS_MACRO) # /* :TODO: improve here, please find a way to support. */ +# define RBIMPL_CAST_FN_PTR 1 #else # /** @cond INTERNAL_MACRO */ @@ -348,6 +351,25 @@ RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) #endif /* __cplusplus */ +#if defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus) +/* In C23, K&R style prototypes are gone and so `void foo(ANYARGS)` became + * equivalent to `void foo(void)` unlike in earlier versions. This is a problem + * for rb_define_* functions since that makes all valid functions one can pass + * trip -Wincompatible-pointer-types, which we treat as errors. This is mostly + * not a problem for the __builtin_choose_expr path, but outside of that we + * need to add a cast for compatibility. + */ +#define rb_define_method(klass, mid, func, arity) rb_define_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_singleton_method(obj, mid, func, arity) rb_define_singleton_method((obj), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_module_function(mod, mid, func, arity) rb_define_module_function((mod), (mid), (VALUE (*)(ANYARGS))(func), (arity)) +#define rb_define_global_function(mid, func, arity) rb_define_global_function((mid), (VALUE (*)(ANYARGS))(func), (arity)) + +#undef RBIMPL_CAST_FN_PTR +#endif /* defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus) */ + /** * This macro is to properly cast a function parameter of *_define_method * family. It has been around since 1.x era so you can maximise backwards diff --git a/include/ruby/internal/arithmetic/int.h b/include/ruby/internal/arithmetic/int.h index 6bd8ec2184..7b24d16887 100644 --- a/include/ruby/internal/arithmetic/int.h +++ b/include/ruby/internal/arithmetic/int.h @@ -254,7 +254,7 @@ static inline VALUE rb_uint2num_inline(unsigned int v) { if (RB_POSFIXABLE(v)) - return RB_LONG2FIX(v); + return RB_LONG2FIX(RBIMPL_CAST((long)v)); else return rb_uint2big(v); } diff --git a/include/ruby/internal/arithmetic/intptr_t.h b/include/ruby/internal/arithmetic/intptr_t.h index a354f4469c..70090f88e6 100644 --- a/include/ruby/internal/arithmetic/intptr_t.h +++ b/include/ruby/internal/arithmetic/intptr_t.h @@ -32,6 +32,18 @@ #define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */ #define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */ +// These definitions are same as fiddle/conversions.h +#if SIZEOF_VOIDP <= SIZEOF_LONG +# define PTR2NUM(x) (LONG2NUM((long)(x))) +# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) +#elif SIZEOF_VOIDP <= SIZEOF_LONG_LONG +# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x))) +# define NUM2PTR(x) ((void*)(NUM2ULL(x))) +#else +// should have been an error in ruby/internal/value.h +# error Need integer for VALUE +#endif + RBIMPL_SYMBOL_EXPORT_BEGIN() /** diff --git a/include/ruby/internal/arithmetic/long.h b/include/ruby/internal/arithmetic/long.h index 6b8fd8ffc3..6c00dbceb7 100644 --- a/include/ruby/internal/arithmetic/long.h +++ b/include/ruby/internal/arithmetic/long.h @@ -114,11 +114,11 @@ RB_INT2FIX(long i) /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully * defined. Also it can be compiled into a single LEA instruction. */ - const unsigned long j = i; + const unsigned long j = RBIMPL_CAST((unsigned long)i); const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG; - const long l = k; + const long l = RBIMPL_CAST((long)k); const SIGNED_VALUE m = l; /* Sign extend */ - const VALUE n = m; + const VALUE n = RBIMPL_CAST((VALUE)m); RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n)); return n; @@ -166,7 +166,7 @@ rbimpl_fix2long_by_idiv(VALUE x) /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1 * below. */ - const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG; + const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)(x - RUBY_FIXNUM_FLAG)); const SIGNED_VALUE z = y / 2; const long w = RBIMPL_CAST((long)z); @@ -193,7 +193,7 @@ rbimpl_fix2long_by_shift(VALUE x) /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this * is noticeably faster than above. */ - const SIGNED_VALUE y = x; + const SIGNED_VALUE y = RBIMPL_CAST((SIGNED_VALUE)x); const SIGNED_VALUE z = y >> 1; const long w = RBIMPL_CAST((long)z); @@ -252,7 +252,7 @@ static inline unsigned long rb_fix2ulong(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); - return rb_fix2long(x); + return RBIMPL_CAST((unsigned long)rb_fix2long(x)); } /** @@ -323,7 +323,7 @@ static inline VALUE rb_ulong2num_inline(unsigned long v) { if (RB_POSFIXABLE(v)) - return RB_LONG2FIX(v); + return RB_LONG2FIX(RBIMPL_CAST((long)v)); else return rb_uint2big(v); } diff --git a/include/ruby/internal/arithmetic/long_long.h b/include/ruby/internal/arithmetic/long_long.h index 65dec8729d..aab455c830 100644 --- a/include/ruby/internal/arithmetic/long_long.h +++ b/include/ruby/internal/arithmetic/long_long.h @@ -127,7 +127,7 @@ static inline unsigned LONG_LONG rb_num2ull_inline(VALUE x) { if (RB_FIXNUM_P(x)) - return RB_FIX2LONG(x); + return RBIMPL_CAST((unsigned LONG_LONG)RB_FIX2LONG(x)); else return rb_num2ull(x); } diff --git a/include/ruby/internal/arithmetic/st_data_t.h b/include/ruby/internal/arithmetic/st_data_t.h index 3bff4ffc0b..91776b3fce 100644 --- a/include/ruby/internal/arithmetic/st_data_t.h +++ b/include/ruby/internal/arithmetic/st_data_t.h @@ -58,7 +58,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline VALUE RB_ST2FIX(st_data_t i) { - SIGNED_VALUE x = i; + SIGNED_VALUE x = RBIMPL_CAST((SIGNED_VALUE)i); if (x >= 0) { x &= RUBY_FIXNUM_MAX; @@ -69,7 +69,7 @@ RB_ST2FIX(st_data_t i) RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x)); unsigned long y = RBIMPL_CAST((unsigned long)x); - return RB_LONG2FIX(y); + return RB_LONG2FIX(RBIMPL_CAST((long)y)); } #endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */ diff --git a/include/ruby/internal/attr/deprecated.h b/include/ruby/internal/attr/deprecated.h index e1bbdbd15a..a374ace868 100644 --- a/include/ruby/internal/attr/deprecated.h +++ b/include/ruby/internal/attr/deprecated.h @@ -48,7 +48,7 @@ #elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */ # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated) @@ -72,4 +72,11 @@ # define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg) #endif +#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) \ + RBIMPL_ATTR_DEPRECATED(("since " #ver)) +#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) \ + RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal")) +#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() \ + RBIMPL_ATTR_DEPRECATED(("only for internal use")) + #endif /* RBIMPL_ATTR_DEPRECATED_H */ diff --git a/include/ruby/internal/attr/forceinline.h b/include/ruby/internal/attr/forceinline.h index b7daafede7..5b9ae794af 100644 --- a/include/ruby/internal/attr/forceinline.h +++ b/include/ruby/internal/attr/forceinline.h @@ -29,7 +29,7 @@ * `__forceinline` are mutually exclusive. We have to mimic that behaviour for * non-MSVC compilers. */ -#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +#if RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_FORCEINLINE() __forceinline #elif RBIMPL_HAS_ATTRIBUTE(always_inline) # define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h index ea3001df2a..dd4c667407 100644 --- a/include/ruby/internal/attr/noexcept.h +++ b/include/ruby/internal/attr/noexcept.h @@ -54,7 +54,7 @@ * get smarter and smarter. Today they can infer if it actually throws * or not without any annotations by humans (correct me if I'm wrong). * - * - When an inline function attributed `noexcepr` actually _does_ throw an + * - When an inline function attributed `noexcept` actually _does_ throw an * exception: they have to call `std::terminate` then (C++ standard * mandates so). This means exception handling routines are actually * enforced, not omitted. This doesn't impact runtime performance (The @@ -78,7 +78,7 @@ #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif __cplusplus >= 201103L diff --git a/include/ruby/internal/attr/nonstring.h b/include/ruby/internal/attr/nonstring.h new file mode 100644 index 0000000000..5ad6ef2a86 --- /dev/null +++ b/include/ruby/internal/attr/nonstring.h @@ -0,0 +1,40 @@ +#ifndef RBIMPL_ATTR_NONSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_ATTR_NONSTRING_H +/** + * @file + * @author Ruby developers <ruby-core@ruby-lang.org> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Defines #RBIMPL_ATTR_NONSTRING. + */ +#include "ruby/internal/has/attribute.h" + +/** Wraps (or simulates) `__attribute__((nonstring))` */ +#if RBIMPL_HAS_ATTRIBUTE(nonstring) +# define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring)) +# if RBIMPL_COMPILER_SINCE(GCC, 15, 0, 0) +# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() +# elif RBIMPL_COMPILER_SINCE(Clang, 21, 0, 0) +# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() +# else +# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ +# endif +#else +# define RBIMPL_ATTR_NONSTRING() /* void */ +# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ +#endif + +#endif /* RBIMPL_ATTR_NONSTRING_H */ diff --git a/include/ruby/internal/attr/restrict.h b/include/ruby/internal/attr/restrict.h index e39104138c..b12fdc9dbc 100644 --- a/include/ruby/internal/attr/restrict.h +++ b/include/ruby/internal/attr/restrict.h @@ -28,7 +28,7 @@ * `__has_declspec_attribute()` which involves macro substitution. */ /** Wraps (or simulates) `__declspec(restrict)` */ -#if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +#if RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_RESTRICT() __declspec(re ## strict) #elif RBIMPL_HAS_ATTRIBUTE(malloc) diff --git a/include/ruby/internal/compiler_is/msvc.h b/include/ruby/internal/compiler_is/msvc.h index 8a864ea558..824f0ecc21 100644 --- a/include/ruby/internal/compiler_is/msvc.h +++ b/include/ruby/internal/compiler_is/msvc.h @@ -38,19 +38,8 @@ # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000) -#elif defined(_MSC_FULL_VER) -# define RBIMPL_COMPILER_IS_MSVC 1 -# /* _MSC_FULL_VER = XXYYZZZZ */ -# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000) -# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000) -# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000) - #else -# define RBIMPL_COMPILER_IS_MSVC 1 -# /* _MSC_VER = XXYY */ -# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100) -# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100) -# define RBIMPL_COMPILER_VERSION_PATCH 0 +# error Unsupported MSVC version #endif #endif /* RBIMPL_COMPILER_IS_MSVC_H */ diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h index da070f0979..34862ded6e 100644 --- a/include/ruby/internal/config.h +++ b/include/ruby/internal/config.h @@ -50,7 +50,7 @@ # define HAVE_VA_ARGS_MACRO # elif defined(__INTEL_CXX11_MODE__) # define HAVE_VA_ARGS_MACRO -# elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +# elif RBIMPL_COMPILER_IS(MSVC) # define HAVE_VA_ARGS_MACRO # else # /* NG, not known. */ diff --git a/include/ruby/internal/core/rarray.h b/include/ruby/internal/core/rarray.h index 90690fe794..73cc0f5dd9 100644 --- a/include/ruby/internal/core/rarray.h +++ b/include/ruby/internal/core/rarray.h @@ -80,6 +80,8 @@ * here is at least incomplete. */ enum ruby_rarray_flags { + /* RUBY_FL_USER0 is for ELTS_SHARED */ + /** * This flag has something to do with memory footprint. If the array is * "small" enough, ruby tries to be creative to abuse padding bits of @@ -99,8 +101,6 @@ enum ruby_rarray_flags { */ RARRAY_EMBED_FLAG = RUBY_FL_USER1, - /* RUBY_FL_USER2 is for ELTS_SHARED */ - /** * When an array employs embedded strategy (see ::RARRAY_EMBED_FLAG), these * bits are used to store the number of elements actually filled into diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h index 4617f743a7..63cdff8e09 100644 --- a/include/ruby/internal/core/rbasic.h +++ b/include/ruby/internal/core/rbasic.h @@ -55,23 +55,27 @@ enum ruby_rvalue_flags { RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX }; +#if (SIZEOF_VALUE < SIZEOF_UINT64_T) +#define RBASIC_SHAPE_ID_FIELD 1 +#else +#define RBASIC_SHAPE_ID_FIELD 0 +#endif + /** - * Ruby's object's, base components. Every single ruby objects have them in - * common. + * Ruby object's base components. All Ruby objects have them in common. */ struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { /** - * Per-object flags. Each ruby objects have their own characteristics - * apart from their classes. For instance whether an object is frozen or - * not is not controlled by its class. This is where such properties are - * stored. + * Per-object flags. Each Ruby object has its own characteristics apart + * from its class. For instance, whether an object is frozen or not is not + * controlled by its class. This is where such properties are stored. * * @see enum ::ruby_fl_type * - * @note This is ::VALUE rather than an enum for alignment purpose. Back + * @note This is ::VALUE rather than an enum for alignment purposes. Back * in the 1990s there were no such thing like `_Alignas` in C. */ VALUE flags; @@ -79,14 +83,18 @@ RBasic { /** * Class of an object. Every object has its class. Also, everything is an * object in Ruby. This means classes are also objects. Classes have - * their own classes, classes of classes have their classes, too ... and - * it recursively continues forever. + * their own classes, classes of classes have their classes too, and it + * recursively continues forever. * - * Also note the `const` qualifier. In ruby an object cannot "change" its + * Also note the `const` qualifier. In Ruby, an object cannot "change" its * class. */ const VALUE klass; +#if RBASIC_SHAPE_ID_FIELD + VALUE shape_id; +#endif + #ifdef __cplusplus public: RBIMPL_ATTR_CONSTEXPR(CXX11) @@ -102,8 +110,14 @@ RBasic { RBasic() : flags(RBIMPL_VALUE_NULL), klass(RBIMPL_VALUE_NULL) +#if RBASIC_SHAPE_ID_FIELD + , shape_id(RBIMPL_VALUE_NULL) +#endif { } +# define RBASIC_INIT RBasic() +#else +# define RBASIC_INIT {RBIMPL_VALUE_NULL} #endif }; diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h index b0b6bfc80c..6f78cc569b 100644 --- a/include/ruby/internal/core/rclass.h +++ b/include/ruby/internal/core/rclass.h @@ -58,7 +58,7 @@ enum ruby_rmodule_flags { * rb_mod_refine() has this flag set. This is the bit which controls * difference between normal inclusion versus refinements. */ - RMODULE_IS_REFINEMENT = RUBY_FL_USER3 + RMODULE_IS_REFINEMENT = RUBY_FL_USER1 }; struct RClass; /* Opaque, declared here for RCLASS() macro. */ diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h index 43ab3c01e7..cee5e7b5ea 100644 --- a/include/ruby/internal/core/rdata.h +++ b/include/ruby/internal/core/rdata.h @@ -37,12 +37,8 @@ #include "ruby/defines.h" /** @cond INTERNAL_MACRO */ -#ifdef RUBY_UNTYPED_DATA_WARNING -# /* Take that. */ -#elif defined(RUBY_EXPORT) -# define RUBY_UNTYPED_DATA_WARNING 1 -#else -# define RUBY_UNTYPED_DATA_WARNING 0 +#ifndef RUBY_UNTYPED_DATA_WARNING +#define RUBY_UNTYPED_DATA_WARNING 1 #endif #define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f)) @@ -146,7 +142,10 @@ struct RData { */ RUBY_DATA_FUNC dfree; - /** Pointer to the actual C level struct that you want to wrap. */ + /** Pointer to the actual C level struct that you want to wrap. + * This is after dmark and dfree to allow DATA_PTR to continue to work for + * both RData and non-embedded RTypedData. + */ void *data; }; @@ -181,11 +180,6 @@ VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_D */ VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); -/** - * @private - * Documented in include/ruby/internal/globals.h - */ -RUBY_EXTERN VALUE rb_cObject; RBIMPL_SYMBOL_EXPORT_END() /** @@ -331,15 +325,6 @@ rb_data_object_get_warning(VALUE obj) return rb_data_object_get(obj); } -#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) -# define rb_data_object_wrap_warning(klass, ptr, mark, free) \ - RB_GNUC_EXTENSION( \ - __builtin_choose_expr( \ - __builtin_constant_p(klass) && !(klass), \ - rb_data_object_wrap(klass, ptr, mark, free), \ - (rb_data_object_wrap_warning)(klass, ptr, mark, free))) -#endif - /** * This is an implementation detail of #Data_Make_Struct. People don't use it * directly. @@ -361,14 +346,6 @@ rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_f return result; } -RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap")) -/** @deprecated This function was renamed to rb_data_object_wrap(). */ -static inline VALUE -rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) -{ - return rb_data_object_wrap(klass, data, dmark, dfree); -} - /** @cond INTERNAL_MACRO */ #define rb_data_object_wrap_0 rb_data_object_wrap #define rb_data_object_wrap_1 rb_data_object_wrap_warning diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h index c2bcae6306..99f6470ac1 100644 --- a/include/ruby/internal/core/robject.h +++ b/include/ruby/internal/core/robject.h @@ -42,10 +42,10 @@ */ #define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj)) /** @cond INTERNAL_MACRO */ -#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX -#define ROBJECT_EMBED ROBJECT_EMBED -#define ROBJECT_IV_CAPACITY ROBJECT_IV_CAPACITY -#define ROBJECT_IVPTR ROBJECT_IVPTR +#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX +#define ROBJECT_HEAP ROBJECT_HEAP +#define ROBJECT_FIELDS_CAPACITY ROBJECT_FIELDS_CAPACITY +#define ROBJECT_FIELDS ROBJECT_FIELDS /** @endcond */ /** @@ -55,10 +55,12 @@ */ enum ruby_robject_flags { /** - * This flag has something to do with memory footprint. If the object is - * "small" enough, ruby tries to be creative to abuse padding bits of - * struct ::RObject for storing instance variables. This flag denotes that - * situation. + * This flag marks that the object's instance variables are stored in an + * external heap buffer. + * Normally, instance variable references are stored inside the object slot, + * but if it overflow, Ruby may have to allocate a separate buffer and spills + * the instance variables there. + * This flag denotes that situation. * * @warning This bit has to be considered read-only. Setting/clearing * this bit without corresponding fix up must cause immediate @@ -71,7 +73,7 @@ enum ruby_robject_flags { * 3rd parties must not be aware that there even is more than one way to * store instance variables. Might better be hidden. */ - ROBJECT_EMBED = RUBY_FL_USER1 + ROBJECT_HEAP = RUBY_FL_USER4 }; struct st_table; @@ -94,17 +96,7 @@ struct RObject { */ struct { /** Pointer to a C array that holds instance variables. */ - VALUE *ivptr; - - /** - * This is a table that holds instance variable name to index - * mapping. Used when accessing instance variables using names. - * - * @internal - * - * This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`. - */ - struct rb_id_table *iv_index_tbl; + VALUE *fields; } heap; /* Embedded instance variables. When an object is small enough, it @@ -133,17 +125,17 @@ RBIMPL_ATTR_ARTIFICIAL() * @shyouhei finds no reason for this to be visible from extension libraries. */ static inline VALUE * -ROBJECT_IVPTR(VALUE obj) +ROBJECT_FIELDS(VALUE obj) { RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); struct RObject *const ptr = ROBJECT(obj); - if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { - return ptr->as.ary; + if (RB_UNLIKELY(RB_FL_ANY_RAW(obj, ROBJECT_HEAP))) { + return ptr->as.heap.fields; } else { - return ptr->as.heap.ivptr; + return ptr->as.ary; } } diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h index 0bca74e688..35175ea94a 100644 --- a/include/ruby/internal/core/rstring.h +++ b/include/ruby/internal/core/rstring.h @@ -369,41 +369,6 @@ RSTRING_LEN(VALUE str) return RSTRING(str)->len; } -RBIMPL_WARNING_PUSH() -#if RBIMPL_COMPILER_IS(Intel) -RBIMPL_WARNING_IGNORED(413) -#endif - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -/** - * @private - * - * "Expands" an embedded string into an ordinal one. This is a function that - * returns aggregated type. The returned struct always has its `as.heap.len` - * an `as.heap.ptr` fields set appropriately. - * - * This is an implementation detail that 3rd parties should never bother. - */ -static inline struct RString -rbimpl_rstring_getmem(VALUE str) -{ - RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); - - if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) { - return *RSTRING(str); - } - else { - /* Expecting compilers to optimize this on-stack struct away. */ - struct RString retval; - retval.len = RSTRING_LEN(str); - retval.as.heap.ptr = RSTRING(str)->as.embed.ary; - return retval; - } -} - -RBIMPL_WARNING_POP() - RBIMPL_ATTR_ARTIFICIAL() /** * Queries the contents pointer of the string. @@ -415,7 +380,9 @@ RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_PTR(VALUE str) { - char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; + char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ? + RSTRING(str)->as.heap.ptr : + RSTRING(str)->as.embed.ary; if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) { /* :BEWARE: @shyouhei thinks that currently, there are rooms for this @@ -441,14 +408,17 @@ RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_END(VALUE str) { - struct RString buf = rbimpl_rstring_getmem(str); + char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ? + RSTRING(str)->as.heap.ptr : + RSTRING(str)->as.embed.ary; + long len = RSTRING_LEN(str); - if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) { + if (RUBY_DEBUG && RB_UNLIKELY(!ptr)) { /* Ditto. */ rb_debug_rstring_null_ptr("RSTRING_END"); } - return &buf.as.heap.ptr[buf.len]; + return &ptr[len]; } RBIMPL_ATTR_ARTIFICIAL() @@ -477,16 +447,7 @@ RSTRING_LENINT(VALUE str) * @param ptrvar Variable where its contents is stored. * @param lenvar Variable where its length is stored. */ -#ifdef HAVE_STMT_AND_DECL_IN_EXPR -# define RSTRING_GETMEM(str, ptrvar, lenvar) \ - __extension__ ({ \ - struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ - (ptrvar) = rbimpl_str.as.heap.ptr; \ - (lenvar) = rbimpl_str.len; \ - }) -#else # define RSTRING_GETMEM(str, ptrvar, lenvar) \ ((ptrvar) = RSTRING_PTR(str), \ (lenvar) = RSTRING_LEN(str)) -#endif /* HAVE_STMT_AND_DECL_IN_EXPR */ #endif /* RBIMPL_RSTRING_H */ diff --git a/include/ruby/internal/core/rstruct.h b/include/ruby/internal/core/rstruct.h index 69be487b59..0028a1bdcd 100644 --- a/include/ruby/internal/core/rstruct.h +++ b/include/ruby/internal/core/rstruct.h @@ -31,18 +31,6 @@ # include "ruby/backward.h" #endif -/** - * @private - * - * @deprecated This macro once was a thing in the old days, but makes no sense - * any longer today. Exists here for backwards compatibility - * only. You can safely forget about it. - * - * @internal - * - * Declaration of rb_struct_ptr() is at include/ruby/backward.h. - */ -#define RSTRUCT_PTR(st) rb_struct_ptr(st) /** @cond INTERNAL_MACRO */ #define RSTRUCT_LEN RSTRUCT_LEN #define RSTRUCT_SET RSTRUCT_SET diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index c7904746fd..ec0794e387 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -37,6 +37,7 @@ #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/fl_type.h" +#include "ruby/internal/static_assert.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value_type.h" @@ -108,11 +109,17 @@ /** @cond INTERNAL_MACRO */ #define RTYPEDDATA_P RTYPEDDATA_P #define RTYPEDDATA_TYPE RTYPEDDATA_TYPE +#define TYPED_DATA_EMBEDDED ((VALUE)1) +#define TYPED_DATA_PTR_MASK (~(TYPED_DATA_EMBEDDED)) +/** @endcond */ + +/** + * Macros to see if each corresponding flag is defined. + */ #define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE #define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 -/** @endcond */ /** * @private @@ -137,6 +144,8 @@ rbimpl_typeddata_flags { */ RUBY_TYPED_FREE_IMMEDIATELY = 1, + RUBY_TYPED_EMBEDDABLE = 2, + /** * This flag has something to do with Ractor. Multiple Ractors run without * protecting each other. Sharing an object among Ractors is basically @@ -151,6 +160,12 @@ rbimpl_typeddata_flags { */ RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE, + // experimental flag + // Similar to RUBY_TYPED_FROZEN_SHAREABLE, but doesn't make shareable + // reachable objects from this T_DATA object on the Ractor.make_shareable. + // If it refers to unshareable objects, simply raise an error. + // RUBY_TYPED_FROZEN_SHAREABLE_NO_REC = RUBY_FL_FINALIZE, + /** * This flag has something to do with our garbage collector. These days * ruby objects are "generational". There are those who are young and @@ -173,9 +188,9 @@ rbimpl_typeddata_flags { RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ /** - * This flag no longer in use + * This flag is used to distinguish RTypedData from deprecated RData objects. */ - RUBY_TYPED_UNUSED = RUBY_FL_UNUSED6, + RUBY_TYPED_FL_IS_TYPED_DATA = RUBY_FL_USERPRIV0, /** * This flag determines whether marking and compaction should be carried out @@ -247,10 +262,15 @@ struct rb_data_type_struct { RUBY_DATA_FUNC dcompact; /** - * This field is reserved for future extension. For now, it must be - * filled with zeros. + * @internal */ - void *reserved[1]; /* For future extension. + void (*handle_weak_references)(void *); + + /** + * This field is reserved for future extension. For now, it must be + * filled with zeros. + */ + void *reserved[7]; /* For future extension. This array *must* be filled with ZERO. */ } function; @@ -348,24 +368,28 @@ struct RTypedData { /** The part that all ruby objects have in common. */ struct RBasic basic; + /** Direct reference to the slots that holds instance variables, if any **/ + VALUE fields_obj; + /** + * This is a `const rb_data_type_t *const` value, with the low bits set: + * + * 1: Set if object is embedded. + * * This field stores various information about how Ruby should handle a * data. This roughly resembles a Ruby level class (apart from method * definition etc.) */ - const rb_data_type_t *const type; - - /** - * This has to be always 1. - * - * @internal - */ - const VALUE typed_flag; + const VALUE type; /** Pointer to the actual C level struct that you want to wrap. */ void *data; }; +#if !defined(__cplusplus) || __cplusplus >= 201103L +RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data)); +#endif + RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((3)) /** @@ -380,6 +404,7 @@ RBIMPL_ATTR_NONNULL((3)) */ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type); +RBIMPL_ATTR_NONNULL((3)) /** * Identical to rb_data_typed_object_wrap(), except it allocates a new data * region internally instead of taking an existing one. The allocation is done @@ -395,6 +420,7 @@ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t * */ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); +RBIMPL_ATTR_NONNULL(()) /** * Checks for the domestic relationship between the two. * @@ -409,6 +435,7 @@ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t */ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); +RBIMPL_ATTR_NONNULL((2)) /** * Checks if the given object is of given kind. * @@ -419,6 +446,7 @@ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t * */ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); +RBIMPL_ATTR_NONNULL((2)) /** * Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead * of returning false. @@ -430,8 +458,49 @@ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); * @post Upon successful return `obj`'s type is guaranteed `data_type`. */ void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +/** + * @private + * + * Fails with the given object's type incompatibility to the type. + * + * This is an implementation detail of Check_Type. People don't use it + * directly. + * + * @param[in] obj The object in question. + * @param[in] expected Name of expected data type of `obj`. + */ +void rb_unexpected_object_type(VALUE obj, const char *expected); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * Fails with the given object's type incompatibility to the type. + * + * This is an implementation detail of #TypedData_Make_Struct. People don't + * use it directly. + * + * @param[in] actual Actual data type. + * @param[in] expected Expected data type. + */ +void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected); RBIMPL_SYMBOL_EXPORT_END() +#if RUBY_DEBUG +# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \ + while (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { \ + rb_unexpected_object_type(obj, "Data"); \ + unreachable; \ + } +#else +# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \ + RBIMPL_ASSERT_NOTHING +#endif + /** * Converts sval, a pointer to your struct, into a Ruby object. * @@ -460,14 +529,13 @@ RBIMPL_SYMBOL_EXPORT_END() */ #define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ - (sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \ + (sval) = RBIMPL_CAST((type *)rbimpl_typeddata_get_data(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) /** * Identical to #TypedData_Wrap_Struct, except it allocates a new data region * internally instead of taking an existing one. The allocation is done using - * ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to - * be anything other than ::RUBY_TYPED_DEFAULT_FREE. + * ruby_calloc(). * * @param klass Ruby level class of the object. * @param type Type name of the C struct. @@ -498,18 +566,37 @@ RBIMPL_SYMBOL_EXPORT_END() sizeof(type)) #endif -/** - * Obtains a C struct from inside of a wrapper Ruby object. - * - * @param obj An instance of ::RTypedData. - * @param type Type name of the C struct. - * @param data_type The data type describing `type`. - * @param sval Variable name of obtained C struct. - * @exception rb_eTypeError `obj` is not a kind of `data_type`. - * @return Unwrapped C struct that `obj` holds. - */ -#define TypedData_Get_Struct(obj,type,data_type,sval) \ - ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) +static inline bool +rbimpl_typeddata_embedded_p(VALUE obj) +{ + return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED; +} + +RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() +static inline bool +RTYPEDDATA_EMBEDDED_P(VALUE obj) +{ + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); + + return rbimpl_typeddata_embedded_p(obj); +} + +static inline void * +rbimpl_typeddata_get_data(VALUE obj) +{ + /* We reuse the data pointer in embedded TypedData. */ + return rbimpl_typeddata_embedded_p(obj) ? + RBIMPL_CAST((void *)&RTYPEDDATA_DATA(obj)) : + RTYPEDDATA_DATA(obj); +} + +static inline void * +RTYPEDDATA_GET_DATA(VALUE obj) +{ + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL)); + + return rbimpl_typeddata_get_data(obj); +} RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() @@ -527,7 +614,28 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_rtypeddata_p(VALUE obj) { - return RTYPEDDATA(obj)->typed_flag == 1; + return FL_TEST_RAW(obj, RUBY_TYPED_FL_IS_TYPED_DATA); +} + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * Identical to rbimpl_rtypeddata_p(), except it is allowed to call on non-data + * objects. + * + * This is an implementation detail of inline functions defined in this file. + * People don't use it directly. + * + * @param[in] obj Object in question + * @retval true `obj` is an instance of ::RTypedData. + * @retval false `obj` is not an instance of ::RTypedData + */ +static inline bool +rbimpl_obj_typeddata_p(VALUE obj) +{ + return RB_TYPE_P(obj, RUBY_T_DATA) && rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() @@ -543,19 +651,14 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool RTYPEDDATA_P(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) { - Check_Type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(false); - } -#endif + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); return rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() -/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ +RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries for the type of given object. * @@ -563,19 +666,77 @@ RBIMPL_ATTR_ARTIFICIAL() * @return Data type struct that corresponds to `obj`. * @pre `obj` must be an instance of ::RTypedData. */ -static inline const struct rb_data_type_struct * +static inline const rb_data_type_t * RTYPEDDATA_TYPE(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) { - rb_unexpected_type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(NULL); + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL)); + + VALUE type = RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK; + const rb_data_type_t *ptr = RBIMPL_CAST((const rb_data_type_t *)type); + RBIMPL_ASSERT_OR_ASSUME(ptr); + return ptr; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL(()) +static inline bool +rbimpl_typeddata_inherited_p_inline(const rb_data_type_t *child, const rb_data_type_t *parent) +{ + do { + if (RB_LIKELY(child == parent)) return true; + } while ((child = child->parent) != NULL); + return false; +} +#define rb_typeddata_inherited_p rbimpl_typeddata_inherited_p_inline + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL((2)) +static inline bool +rbimpl_typeddata_is_kind_of_inline(VALUE obj, const rb_data_type_t *data_type) +{ + if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) return false; + return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type); +} +#define rb_typeddata_is_kind_of rbimpl_typeddata_is_kind_of_inline + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL((2)) +/** + * @private + * + * This is an implementation detail of TypedData_Get_Struct(). Don't use it + * directly. + */ +static inline void * +rbimpl_check_typeddata(VALUE obj, const rb_data_type_t *expected_type) +{ + if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) { + rb_unexpected_object_type(obj, expected_type->wrap_struct_name); } -#endif - return RTYPEDDATA(obj)->type; + const rb_data_type_t *actual_type = RTYPEDDATA_TYPE(obj); + if (RB_UNLIKELY(!rb_typeddata_inherited_p(actual_type, expected_type))){ + rb_unexpected_typeddata(actual_type, expected_type); + } + + return RTYPEDDATA_GET_DATA(obj); } + +/** + * Obtains a C struct from inside of a wrapper Ruby object. + * + * @param obj An instance of ::RTypedData. + * @param type Type name of the C struct. + * @param data_type The data type describing `type`. + * @param sval Variable name of obtained C struct. + * @exception rb_eTypeError `obj` is not a kind of `data_type`. + * @return Unwrapped C struct that `obj` holds. + */ +#define TypedData_Get_Struct(obj,type,data_type,sval) \ + ((sval) = RBIMPL_CAST((type *)rbimpl_check_typeddata((obj), (data_type)))) + +RBIMPL_ATTR_NONNULL((2)) /** * While we don't stop you from using this function, it seems to be an * implementation detail of #TypedData_Make_Struct, which is preferred over @@ -597,12 +758,4 @@ rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, return result; } -RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap")) -/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */ -static inline VALUE -rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) -{ - return rb_data_typed_object_wrap(klass, datap, type); -} - #endif /* RBIMPL_RTYPEDDATA_H */ diff --git a/include/ruby/internal/ctype.h b/include/ruby/internal/ctype.h index 0f7ca6c516..8b24026311 100644 --- a/include/ruby/internal/ctype.h +++ b/include/ruby/internal/ctype.h @@ -498,8 +498,8 @@ RBIMPL_ATTR_ARTIFICIAL() * Our own locale-insensitive version of `tolower(3)`. * * @param[in] c Byte in question to convert. - * @retval c The byte is not listed in in IEEE 1003.1 section - * 7.3.1.1 "upper". + * @retval c The byte is not listed in IEEE 1003.1 section 7.3.1.1 + * "upper". * @retval otherwise Byte converted using the map defined in IEEE 1003.1 * section 7.3.1 "tolower". * @note Not only does this function works under the POSIX Locale, but diff --git a/include/ruby/internal/encoding/coderange.h b/include/ruby/internal/encoding/coderange.h index 7a81208c9e..c89f871518 100644 --- a/include/ruby/internal/encoding/coderange.h +++ b/include/ruby/internal/encoding/coderange.h @@ -79,7 +79,7 @@ RBIMPL_ATTR_CONST() static inline bool RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr) { - return rb_enc_coderange_clean_p(cr); + return rb_enc_coderange_clean_p(RBIMPL_CAST((int)cr)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() diff --git a/include/ruby/internal/encoding/encoding.h b/include/ruby/internal/encoding/encoding.h index dc3e0151f0..a58f9f2b15 100644 --- a/include/ruby/internal/encoding/encoding.h +++ b/include/ruby/internal/encoding/encoding.h @@ -28,6 +28,7 @@ #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" +#include "ruby/internal/encoding/coderange.h" #include "ruby/internal/value.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/fl_type.h" @@ -79,7 +80,7 @@ enum ruby_encoding_consts { static inline void RB_ENCODING_SET_INLINED(VALUE obj, int encindex) { - VALUE f = /* upcast */ encindex; + VALUE f = /* upcast */ RBIMPL_CAST((VALUE)encindex); f <<= RUBY_ENCODING_SHIFT; RB_FL_UNSET_RAW(obj, RUBY_ENCODING_MASK); diff --git a/include/ruby/internal/encoding/string.h b/include/ruby/internal/encoding/string.h index 6ed7ca1c90..2cfa91c01e 100644 --- a/include/ruby/internal/encoding/string.h +++ b/include/ruby/internal/encoding/string.h @@ -30,7 +30,7 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() /** - * Identical to rb_enc_str_new(), except it additionally takes an encoding. + * Identical to rb_str_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the @@ -307,13 +307,13 @@ RBIMPL_ATTR_NONNULL(()) /** * Looks for the passed string in the passed buffer. * - * @param[in] x Buffer that potentially includes `y`. + * @param[in] x Query string. * @param[in] m Number of bytes of `x`. - * @param[in] y Query string. + * @param[in] y Buffer that potentially includes `x`. * @param[in] n Number of bytes of `y`. * @param[in] enc Encoding of both `x` and `y`. * @retval -1 Not found. - * @retval otherwise Found index in `x`. + * @retval otherwise Found index in `y`. * @note This API can match at a non-character-boundary. */ long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc); diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h index 1ce9a30e6f..5bf82bfe7d 100644 --- a/include/ruby/internal/error.h +++ b/include/ruby/internal/error.h @@ -53,6 +53,9 @@ typedef enum { /** Warning is for performance issues (not enabled by -w). */ RB_WARN_CATEGORY_PERFORMANCE, + /** Warning is for checking unused block strictly */ + RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, + RB_WARN_CATEGORY_DEFAULT_BITS = ( (1U << RB_WARN_CATEGORY_DEPRECATED) | (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | @@ -62,6 +65,7 @@ typedef enum { (1U << RB_WARN_CATEGORY_DEPRECATED) | (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | (1U << RB_WARN_CATEGORY_PERFORMANCE) | + (1U << RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK) | 0) } rb_warning_category_t; @@ -417,11 +421,12 @@ void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() /** + * @private + * * Fails with the given object's type incompatibility to the type. * - * It seems this function is visible from extension libraries only because - * RTYPEDDATA_TYPE() uses it on RUBY_DEBUG. So you can basically ignore it; - * use some other fine-grained method instead. + * This is an implementation detail of Check_Type. People don't use it + * directly. * * @param[in] self The object in question. * @param[in] t Expected type of the object. @@ -481,7 +486,7 @@ VALUE *rb_ruby_debug_ptr(void); */ #define ruby_debug (*rb_ruby_debug_ptr()) -/* reports if `-W' specified */ +/* reports if $VERBOSE is true */ RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** @@ -496,7 +501,8 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) * default, the method just emits its passed contents to ::rb_stderr using * rb_io_write(). * - * @note This function is affected by the `-W` flag. + * @note This function is affected by the value of $VERBOSE, it does + * nothing unless $VERBOSE is true. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * * @internal @@ -521,7 +527,7 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) * Issues a compile-time warning that happens at `__file__:__line__`. Purpose * of this function being exposed to CAPI is unclear. * - * @note This function is affected by the `-W` flag. + * @note This function is affected by the value of $VERBOSE. * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. * @param[in] fmt Format specifier string compatible with rb_sprintf(). @@ -534,19 +540,20 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) * Identical to rb_sys_fail(), except it does not raise an exception to render * a warning instead. * - * @note This function is affected by the `-W` flag. + * @note This function is affected by the value of $VERBOSE. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_sys_warning(const char *fmt, ...); -/* reports always */ +/* reports if $VERBOSE is not nil (so if it is true or false) */ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** - * Identical to rb_warning(), except it reports always regardless of runtime - * `-W` flag. + * Identical to rb_warning(), except it reports unless $VERBOSE is nil. * + * @note This function is affected by the value of $VERBOSE, it does + * nothing if $VERBOSE is nil. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_warn(const char *fmt, ...); @@ -555,8 +562,7 @@ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** - * Identical to rb_category_warning(), except it reports always regardless of - * runtime `-W` flag. + * Identical to rb_category_warning(), except it reports unless $VERBOSE is nil. * * @param[in] cat Category e.g. deprecated. * @param[in] fmt Format specifier string compatible with rb_sprintf(). @@ -566,8 +572,7 @@ void rb_category_warn(rb_warning_category_t cat, const char *fmt, ...); RBIMPL_ATTR_NONNULL((1, 3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** - * Identical to rb_compile_warning(), except it reports always regardless of - * runtime `-W` flag. + * Identical to rb_compile_warning(), except it reports unless $VERBOSE is nil. * * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h index 5bcbb97746..23aa1d9580 100644 --- a/include/ruby/internal/eval.h +++ b/include/ruby/internal/eval.h @@ -155,7 +155,8 @@ VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. @@ -189,7 +190,8 @@ VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -261,7 +263,8 @@ VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -307,7 +310,8 @@ VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VAL * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -335,7 +339,8 @@ VALUE rb_call_super(int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No super method are there. * @exception rb_eException Any exceptions happen inside. * @return What the super method evaluates to. diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index f7f5abdd9b..2afb3f1fa3 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -59,10 +59,8 @@ #define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */ #define FL_PROMOTED RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED) /**< @old{RUBY_FL_PROMOTED} */ #define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */ -#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */ #define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */ #define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */ -#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */ #define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */ #define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */ @@ -218,11 +216,11 @@ ruby_fl_type { RUBY_FL_PROMOTED = (1<<5), /** - * This flag is no longer in use + * This flag meaning is type dependent, currently only used by T_DATA. * * @internal */ - RUBY_FL_UNUSED6 = (1<<6), + RUBY_FL_USERPRIV0 = (1<<6), /** * This flag has something to do with finalisers. A ruby object can have @@ -239,16 +237,16 @@ ruby_fl_type { RUBY_FL_FINALIZE = (1<<7), /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards + * @deprecated This flag was an implementation detail that should never have + * no been exposed. Exists here for backwards * compatibility only. You can safely forget about it. */ - RUBY_FL_TAINT + RUBY_FL_EXIVAR #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) + RBIMPL_ATTR_DEPRECATED(("FL_EXIVAR is an outdated implementation detail, it should not be used.")) #elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_TAINT) +# pragma deprecated(RUBY_FL_EXIVAR) #endif = 0, @@ -265,52 +263,19 @@ ruby_fl_type { */ RUBY_FL_SHAREABLE = (1<<8), - /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - */ - RUBY_FL_UNTRUSTED - -#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("trustedness turned out to be a wrong idea.")) -#elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_UNTRUSTED) -#endif - - = 0, - - /** - * This flag has something to do with object IDs. Unlike in the old days, - * an object's object ID (that a user can query using `Object#object_id`) - * is no longer its physical address represented using Ruby level integers. - * It is now a monotonic-increasing integer unrelated to the underlying - * memory arrangement. Object IDs are assigned when necessary; objects are - * born without one, and will eventually have such property when queried. - * The interpreter has to manage which one is which. This is the flag that - * helps the management. Objects with this flag set are the ones with - * object IDs assigned. - * - * @internal - * - * But honestly, @shyouhei doesn't think this flag should be visible from - * 3rd parties. It must be an implementation detail that they should never - * know. Might better be hidden. - */ - RUBY_FL_SEEN_OBJ_ID = (1<<9), + /** + * This object weakly refers to other objects. + * + * @internal + */ + RUBY_FL_WEAK_REFERENCE = (1<<9), - /** - * This flag has something to do with instance variables. 3rd parties need - * not know, but there are several ways to store an object's instance - * variables. Objects with this flag use so-called "generic" backend - * storage. This distinction is purely an implementation detail. People - * need not be aware of this working behind-the-scene. - * - * @internal - * - * As of writing everything except ::RObject and RModule use this scheme. - */ - RUBY_FL_EXIVAR = (1<<10), + /** + * This flag is no longer in use + * + * @internal + */ + RUBY_FL_UNUSED10 = (1<<10), /** * This flag has something to do with data immutability. When this flag is @@ -370,7 +335,7 @@ ruby_fl_type { * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ - RUBY_ELTS_SHARED = RUBY_FL_USER2, + RUBY_ELTS_SHARED = RUBY_FL_USER0, /** * This flag has something to do with an object's class. There are kind of @@ -395,24 +360,7 @@ ruby_fl_type { * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ - RUBY_FL_SINGLETON = RUBY_FL_USER0, -}; - -enum { - /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - */ - RUBY_FL_DUPPED - -#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("It seems there is no actual usage of this enum.")) -#elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_DUPPED) -#endif - - = (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR + RUBY_FL_SINGLETON = RUBY_FL_USER1, }; #undef RBIMPL_HAVE_ENUM_ATTRIBUTE @@ -446,10 +394,8 @@ RB_FL_ABLE(VALUE obj) if (RB_SPECIAL_CONST_P(obj)) { return false; } - else if (RB_TYPE_P(obj, RUBY_T_NODE)) { - return false; - } else { + RBIMPL_ASSERT_OR_ASSUME(!RB_TYPE_P(obj, RUBY_T_NODE)); return true; } } @@ -457,7 +403,7 @@ RB_FL_ABLE(VALUE obj) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_TEST(). 3rd parties need not use + * This is an implementation detail of RB_FL_TEST(). 3rd parties need not use * this. Just always use RB_FL_TEST(). * * @param[in] obj Object in question. @@ -505,7 +451,7 @@ RB_FL_TEST(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_ANY(). 3rd parties need not use + * This is an implementation detail of RB_FL_ANY(). 3rd parties need not use * this. Just always use RB_FL_ANY(). * * @param[in] obj Object in question. @@ -539,7 +485,7 @@ RB_FL_ANY(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_ALL(). 3rd parties need not use + * This is an implementation detail of RB_FL_ALL(). 3rd parties need not use * this. Just always use RB_FL_ALL(). * * @param[in] obj Object in question. @@ -575,7 +521,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use + * This is an implementation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. @@ -595,7 +541,7 @@ rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use + * This is an implementation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. @@ -635,7 +581,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use + * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. @@ -655,7 +601,7 @@ rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use + * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. @@ -690,7 +636,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not + * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. @@ -710,7 +656,7 @@ rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not + * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. @@ -743,130 +689,8 @@ RB_FL_REVERSE(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline bool -RB_OBJ_TAINTABLE(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline VALUE -RB_OBJ_TAINTED_RAW(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline bool -RB_OBJ_TAINTED(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - */ -static inline void -RB_OBJ_TAINT_RAW(VALUE obj) -{ - (void)obj; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - */ -static inline void -RB_OBJ_TAINT(VALUE obj) -{ - (void)obj; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] dst Victim object. - * @param[in] src Infectant object. - */ -static inline void -RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) -{ - (void)dst; - (void)src; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] dst Victim object. - * @param[in] src Infectant object. - */ -static inline void -RB_OBJ_INFECT(VALUE dst, VALUE src) -{ - (void)dst; - (void)src; - return; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -/** - * This is an implenentation detail of RB_OBJ_FROZEN(). 3rd parties need not + * This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not * use this. Just always use RB_OBJ_FROZEN(). * * @param[in] obj Object in question. @@ -905,9 +729,21 @@ RB_OBJ_FROZEN(VALUE obj) } } +RUBY_SYMBOL_EXPORT_BEGIN +/** + * Prevents further modifications to the given object. ::rb_eFrozenError shall + * be raised if modification is attempted. + * + * @param[out] x Object in question. + * @exception rb_eNoMemError Failed to allocate memory for the frozen + * representation of the object. + */ +void rb_obj_freeze_inline(VALUE obj); +RUBY_SYMBOL_EXPORT_END + RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implenentation detail of RB_OBJ_FREEZE(). 3rd parties need not + * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not * use this. Just always use RB_OBJ_FREEZE(). * * @param[out] obj Object in question. @@ -915,11 +751,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { - RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); + rb_obj_freeze_inline(obj); } -RUBY_SYMBOL_EXPORT_BEGIN -void rb_obj_freeze_inline(VALUE obj); -RUBY_SYMBOL_EXPORT_END - #endif /* RBIMPL_FL_TYPE_H */ diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h index 2a5180671c..21c2b670b3 100644 --- a/include/ruby/internal/gc.h +++ b/include/ruby/internal/gc.h @@ -44,10 +44,11 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() -#define REF_EDGE(s, p) (offsetof(struct s, p)) -#define REFS_LIST_PTR(l) ((RUBY_DATA_FUNC)l) +#define RUBY_REF_EDGE(s, p) offsetof(s, p) +#define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(uintptr_t)(l) #define RUBY_REF_END SIZE_MAX -#define RUBY_REFERENCES_START(t) static size_t t[] = { +#define RUBY_REFERENCES(t) static const size_t t[] +#define RUBY_REFERENCES_START(t) RUBY_REFERENCES(t) = { #define RUBY_REFERENCES_END RUBY_REF_END, }; /* gc.c */ @@ -209,22 +210,6 @@ void rb_gc_mark_movable(VALUE obj); VALUE rb_gc_location(VALUE obj); /** - * Asserts that the passed object is no longer needed. Such objects are - * reclaimed sooner or later so this function is not mandatory. But sometimes - * you can know from your application knowledge that an object is surely dead - * at some point. Calling this as a hint can be a polite way. - * - * @param[out] obj Object, dead. - * @pre `obj` have never been passed to this function before. - * @post `obj` could be invalidated. - * @warning It is a failure to pass an object multiple times to this - * function. - * @deprecated This is now a no-op function. - */ -RBIMPL_ATTR_DEPRECATED(("this is now a no-op function")) -void rb_gc_force_recycle(VALUE obj); - -/** * Triggers a GC process. This was the only GC entry point that we had at the * beginning. Over time our GC evolved. Now what this function does is just a * very simplified variation of the entire GC algorithms. A series of diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h index 5a414fc472..9beb215c0c 100644 --- a/include/ruby/internal/globals.h +++ b/include/ruby/internal/globals.h @@ -68,6 +68,7 @@ RUBY_EXTERN VALUE rb_cBasicObject; /**< `BasicObject` class. */ RUBY_EXTERN VALUE rb_cObject; /**< `Object` class. */ RUBY_EXTERN VALUE rb_cArray; /**< `Array` class. */ RUBY_EXTERN VALUE rb_cBinding; /**< `Binding` class. */ +RUBY_EXTERN VALUE rb_cBox; /**< `Ruby::Box` class. */ RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */ RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */ RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */ @@ -91,10 +92,11 @@ RUBY_EXTERN VALUE rb_cRandom; /**< `Random` class. */ RUBY_EXTERN VALUE rb_cRange; /**< `Range` class. */ RUBY_EXTERN VALUE rb_cRational; /**< `Rational` class. */ RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */ +RUBY_EXTERN VALUE rb_cSet; /**< `Set` class. */ RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */ RUBY_EXTERN VALUE rb_cString; /**< `String` class. */ RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */ -RUBY_EXTERN VALUE rb_cSymbol; /**< `Sumbol` class. */ +RUBY_EXTERN VALUE rb_cSymbol; /**< `Symbol` class. */ RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */ RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */ RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */ diff --git a/include/ruby/internal/has/builtin.h b/include/ruby/internal/has/builtin.h index 243ba2a34c..8e7fb173d8 100644 --- a/include/ruby/internal/has/builtin.h +++ b/include/ruby/internal/has/builtin.h @@ -48,6 +48,7 @@ # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */ # define RBIMPL_HAS_BUILTIN(_) (RBIMPL_HAS_BUILTIN_ ## _) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_add_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align RBIMPL_COMPILER_SINCE(GCC, 6, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_assume 0 @@ -75,6 +76,7 @@ # define RBIMPL_HAS_BUILTIN___builtin_rotateright32 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) +# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # /* Note that "0, 0, 0" might be inaccurate. */ @@ -82,6 +84,7 @@ # /* Take config.h definition when available */ # define RBIMPL_HAS_BUILTIN(_) ((RBIMPL_HAS_BUILTIN_ ## _)+0) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW +# define RBIMPL_HAS_BUILTIN___builtin_add_overflow_p HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW_P # define RBIMPL_HAS_BUILTIN___builtin_alloca 0 # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN # define RBIMPL_HAS_BUILTIN___builtin_assume 0 @@ -107,6 +110,7 @@ # define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 # define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW +# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow_p HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW_P # if defined(HAVE___BUILTIN_UNREACHABLE) # define RBIMPL_HAS_BUILTIN___builtin_unreachable 1 # else diff --git a/include/ruby/internal/has/c_attribute.h b/include/ruby/internal/has/c_attribute.h index c5c48867bf..69b0f402cd 100644 --- a/include/ruby/internal/has/c_attribute.h +++ b/include/ruby/internal/has/c_attribute.h @@ -21,11 +21,23 @@ * @brief Defines #RBIMPL_HAS_C_ATTRIBUTE. */ +#include "ruby/internal/has/extension.h" +#include "ruby/internal/has/warning.h" + /** Wraps (or simulates) `__has_c_attribute`. */ #if defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 +#elif RBIMPL_HAS_EXTENSION(c_attributes) +# /* Hmm. It seems Clang 17 has this macro defined even when -std=c99 mode, +# * _and_ fails to compile complaining that attributes are C2X feature. We +# * need to work around this nonsense. */ +# define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) + +#elif RBIMPL_HAS_WARNING("-Wc2x-extensions") +# define RBIMPL_HAS_C_ATTRIBUTE(_) 0 + #elif defined(__has_c_attribute) # define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h index 2262c6f0c6..b2cc6b132d 100644 --- a/include/ruby/internal/intern/array.h +++ b/include/ruby/internal/intern/array.h @@ -144,7 +144,13 @@ void rb_ary_free(VALUE ary); */ void rb_ary_modify(VALUE ary); -/** @alias{rb_obj_freeze} */ +/** + * Freeze an array, preventing further modifications. The underlying buffer may + * be shrunk before freezing to conserve memory. + * + * @param[out] obj Object assumed to be an array to freeze. + * @see RB_OBJ_FREEZE() + */ VALUE rb_ary_freeze(VALUE obj); RBIMPL_ATTR_PURE() @@ -187,7 +193,7 @@ VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs); * : (int i) -> T? * | (int beg, int len) -> ::Array[T]? * | (Range[int] r) -> ::Array[T]? - * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RagneError. + * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RangeError. * end * ``` */ diff --git a/include/ruby/internal/intern/bignum.h b/include/ruby/internal/intern/bignum.h index 43d68018de..c27f77a1fb 100644 --- a/include/ruby/internal/intern/bignum.h +++ b/include/ruby/internal/intern/bignum.h @@ -51,7 +51,7 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_big_new(size_t len, int sign); /** - * Queries if the passed bignum instance is a "bigzro". What is a bigzero? + * Queries if the passed bignum instance is a "bigzero". What is a bigzero? * Well, bignums are for very big integers, but can also represent tiny ones * like -1, 0, 1. Bigzero are instances of bignums whose values are zero. * Knowing if a bignum is bigzero can be handy on occasions, like for instance @@ -793,7 +793,7 @@ size_t rb_absint_size(VALUE val, int *nlz_bits_ret); * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @retval (size_t)-1 Overflowed. * @retval otherwise - `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, + * `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, * where val_numbits is the number of bits of `abs(val)`. * @post If `nlz_bits_ret` is not `NULL` and there is no overflow, * `(return_value * word_numbits - val_numbits)` is stored in diff --git a/include/ruby/internal/intern/class.h b/include/ruby/internal/intern/class.h index 0fb2d001bc..357af5d176 100644 --- a/include/ruby/internal/intern/class.h +++ b/include/ruby/internal/intern/class.h @@ -88,8 +88,8 @@ VALUE rb_define_class_id(ID id, VALUE super); * @post `outer::id` refers the returned class. * @note If a class named `id` is already defined and its superclass is * `super`, the function just returns the defined class. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super); @@ -127,8 +127,8 @@ VALUE rb_define_module_id(ID id); * constant is not a module. * @return The created module. * @post `outer::id` refers the returned module. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_define_module_id_under(VALUE outer, ID id); diff --git a/include/ruby/internal/intern/complex.h b/include/ruby/internal/intern/complex.h index e111bd8ced..1efc093631 100644 --- a/include/ruby/internal/intern/complex.h +++ b/include/ruby/internal/intern/complex.h @@ -87,10 +87,6 @@ VALUE rb_complex_new(VALUE real, VALUE imag); */ VALUE rb_complex_new_polar(VALUE abs, VALUE arg); -RBIMPL_ATTR_DEPRECATED(("by: rb_complex_new_polar")) -/** @old{rb_complex_new_polar} */ -VALUE rb_complex_polar(VALUE abs, VALUE arg); - RBIMPL_ATTR_PURE() /** * Queries the real part of the passed Complex. diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h index 32647f48aa..2d813ceb9d 100644 --- a/include/ruby/internal/intern/cont.h +++ b/include/ruby/internal/intern/cont.h @@ -148,7 +148,8 @@ VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eFiberError `fiber` is terminated etc. * @exception rb_eException Any exceptions happen in `fiber`. * @return Either what was yielded or the last value of the fiber body. @@ -192,7 +193,8 @@ VALUE rb_fiber_yield(int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) */ @@ -247,7 +249,8 @@ VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eFiberError (See above) * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) @@ -275,7 +278,7 @@ VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_spla * @exception rb_eFiberError `fiber` is terminated etc. * @return (See rb_fiber_resume() for details) */ -VALUE rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv); +VALUE rb_fiber_raise(VALUE fiber, int argc, VALUE *argv); RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/internal/intern/enumerator.h b/include/ruby/internal/intern/enumerator.h index 20e5d7c6fc..00804d786a 100644 --- a/include/ruby/internal/intern/enumerator.h +++ b/include/ruby/internal/intern/enumerator.h @@ -100,7 +100,8 @@ VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE * * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling `meth` on `recv` with `argv`. @@ -186,7 +187,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling the current method on `recv` with `argv`. */ @@ -220,7 +222,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @note This macro may return inside. */ #define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ @@ -250,7 +253,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @note This macro may return inside. */ #define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \ diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h index bf8daadd3e..1fd9ec2f51 100644 --- a/include/ruby/internal/intern/error.h +++ b/include/ruby/internal/intern/error.h @@ -237,6 +237,8 @@ RBIMPL_ATTR_NORETURN() */ void rb_error_arity(int argc, int min, int max); +void rb_str_modify(VALUE str); + RBIMPL_SYMBOL_EXPORT_END() /** @@ -244,12 +246,7 @@ RBIMPL_SYMBOL_EXPORT_END() * * Does anyone use this? Remain not deleted for compatibility. */ -#define rb_check_frozen_internal(obj) do { \ - VALUE frozen_obj = (obj); \ - if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \ - rb_error_frozen_object(frozen_obj); \ - } \ - } while (0) +#define rb_check_frozen_internal rb_check_frozen /** @alias{rb_check_frozen} */ static inline void @@ -258,9 +255,16 @@ rb_check_frozen_inline(VALUE obj) if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) { rb_error_frozen_object(obj); } + + /* ref: internal CHILLED_STRING_P() + This is an implementation detail subject to change. */ + if (RB_UNLIKELY(RB_TYPE_P(obj, T_STRING) && FL_TEST_RAW(obj, RUBY_FL_USER2 | RUBY_FL_USER3))) { // STR_CHILLED + rb_str_modify(obj); + } } -/** @alias{rb_check_frozen} */ +/* rb_check_frozen() is available as a symbol, but have + * the inline version take priority for native consumers. */ #define rb_check_frozen rb_check_frozen_inline /** diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h index 79820fdc61..8508b7ab9e 100644 --- a/include/ruby/internal/intern/file.h +++ b/include/ruby/internal/intern/file.h @@ -24,6 +24,9 @@ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" +#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY +# include "ruby/backward.h" +#endif RBIMPL_SYMBOL_EXPORT_BEGIN() diff --git a/include/ruby/internal/intern/hash.h b/include/ruby/internal/intern/hash.h index af8dfd5d8f..504770fa5f 100644 --- a/include/ruby/internal/intern/hash.h +++ b/include/ruby/internal/intern/hash.h @@ -284,20 +284,6 @@ typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); */ VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func); -/* file.c */ - -/** - * This function is mysterious. What it does is not immediately obvious. Also - * what it does seems platform dependent. - * - * @param[in] path A local path. - * @retval 0 The "check" succeeded. - * @retval otherwise The "check" failed. - */ -int rb_path_check(const char *path); - -/* hash.c */ - /** * Destructively removes every environment variables of the running process. * diff --git a/include/ruby/internal/intern/io.h b/include/ruby/internal/intern/io.h index 02c249723e..b9eb258cc1 100644 --- a/include/ruby/internal/intern/io.h +++ b/include/ruby/internal/intern/io.h @@ -385,7 +385,7 @@ VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io); * @param[in] fd Target file descriptor. * @param[in] flags Flags, e.g. `O_CREAT|O_EXCL` * @param[in] path The path of the file that backs `fd`, for diagnostics. - * @return An allocated instance of ::rb_cIO. + * @return An allocated instance of ::rb_cIO with the autoclose flag set. * @note Leave `path` NULL if you don't know. */ VALUE rb_io_fdopen(int fd, int flags, const char *path); diff --git a/include/ruby/internal/intern/load.h b/include/ruby/internal/intern/load.h index 288a16c2ec..9ceb98c2e4 100644 --- a/include/ruby/internal/intern/load.h +++ b/include/ruby/internal/intern/load.h @@ -177,6 +177,43 @@ VALUE rb_f_require(VALUE self, VALUE feature); VALUE rb_require_string(VALUE feature); /** + * Resolves and returns a symbol of a function in the native extension + * specified by the feature and symbol names. Extensions will use this function + * to access the symbols provided by other native extensions. + * + * @param[in] feature Name of a feature, e.g. `"json"`. + * @param[in] symbol Name of a symbol defined by the feature. + * @return The resolved symbol of a function, defined and externed by the + * specified feature. It may be NULL if the feature is not loaded, + * the feature is not extension, or the symbol is not found. + */ +void *rb_ext_resolve_symbol(const char *feature, const char *symbol); + +/** + * This macro is to provide backwards compatibility. It provides a way to + * define function prototypes and resolving function symbols in a safe way. + * + * ```CXX + * // prototypes + * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL + * VALUE *(*other_extension_func)(VALUE,VALUE); + * #else + * VALUE other_extension_func(VALUE); + * #endif + * + * // in Init_xxx() + * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL + * other_extension_func = \ + * (VALUE(*)(VALUE,VALUE))rb_ext_resolve_symbol(fname, sym_name); + * if (other_extension_func == NULL) { + * // raise your own error + * } + * #endif + * ``` + */ +#define HAVE_RB_EXT_RESOLVE_SYMBOL 1 + +/** * @name extension configuration * @{ */ diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h index b9ffa57c06..3897639a0a 100644 --- a/include/ruby/internal/intern/object.h +++ b/include/ruby/internal/intern/object.h @@ -80,7 +80,8 @@ VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `klass`'s allocator is undefined. * @exception rb_eException Any exceptions can happen inside. * @return An allocated new instance of `klass`. @@ -151,13 +152,12 @@ VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass); * @return An allocated, not yet initialised instance of `klass`. * @note It calls the allocator defined by rb_define_alloc_func(). You * cannot use this function to define an allocator. Use - * rb_newobj_of(), #TypedData_Make_Struct or others, instead. + * TypedData_Make_Struct or others, instead. * @note Usually prefer rb_class_new_instance() to rb_obj_alloc() and * rb_obj_call_init(). * @see rb_class_new_instance() * @see rb_obj_call_init() * @see rb_define_alloc_func() - * @see rb_newobj_of() * @see #TypedData_Make_Struct */ VALUE rb_obj_alloc(VALUE klass); diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h index b8c3c5e146..2635d672eb 100644 --- a/include/ruby/internal/intern/proc.h +++ b/include/ruby/internal/intern/proc.h @@ -101,7 +101,8 @@ VALUE rb_proc_call(VALUE recv, VALUE args); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ @@ -141,7 +142,8 @@ VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE pro * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ @@ -245,7 +247,8 @@ VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. @@ -279,7 +282,8 @@ VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE p * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. diff --git a/include/ruby/internal/intern/process.h b/include/ruby/internal/intern/process.h index 7a7b24ed4b..cfa5e13162 100644 --- a/include/ruby/internal/intern/process.h +++ b/include/ruby/internal/intern/process.h @@ -31,6 +31,15 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() /* process.c */ /** + * Wait for the specified process to terminate, reap it, and return its status. + * + * @param[in] pid The process ID to wait for. + * @param[in] flags The flags to pass to waitpid(2). + * @return VALUE An instance of Process::Status. + */ +VALUE rb_process_status_wait(rb_pid_t pid, int flags); + +/** * Sets the "last status", or the `$?`. * * @param[in] status The termination status, as defined in `waitpid(3posix)`. @@ -247,7 +256,7 @@ rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen); * * @internal * - * This function might or might not exist depending on `./confiugre` result. + * This function might or might not exist depending on `./configure` result. * It must be a portability hell. Better not use. */ VALUE rb_proc_times(VALUE _); diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h index fabc287cd1..ba75213618 100644 --- a/include/ruby/internal/intern/select.h +++ b/include/ruby/internal/intern/select.h @@ -72,11 +72,13 @@ struct timeval; * someone else, vastly varies among operating systems. You would better avoid * touching an fd from more than one threads. * + * NOTE: this function is used in native extensions, so change its API with care. + * * @internal * * Although any file descriptors are possible here, it makes completely no * sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know - * the reason for this limitatuon in detail, you might find this thread super + * the reason for this limitation in detail, you might find this thread super * interesting: https://lkml.org/lkml/2004/10/6/117 */ int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); diff --git a/include/ruby/internal/intern/select/win32.h b/include/ruby/internal/intern/select/win32.h index edaf7a8523..b7301e63f3 100644 --- a/include/ruby/internal/intern/select/win32.h +++ b/include/ruby/internal/intern/select/win32.h @@ -206,7 +206,7 @@ rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src) * property we heavily touch the internals of MSVCRT. We `CreateFile` a * `"NUL"` alongside of a socket and directly manipulate its `struct ioinfo`. * This is of course a very dirty hack. If we could design the API today we - * could use `CancellIoEx`. But we are older than that Win32 API. + * could use `CancelIoEx`. But we are older than that Win32 API. */ static inline int rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout) @@ -253,7 +253,7 @@ rb_fd_max(const rb_fdset_t *f) const fd_set *p = f->fdset; RBIMPL_ASSERT_OR_ASSUME(p); - return p->fd_count; + return RBIMPL_CAST((int)p->fd_count); } #endif /* RBIMPL_INTERN_SELECT_WIN32_H */ diff --git a/include/ruby/internal/intern/set.h b/include/ruby/internal/intern/set.h new file mode 100644 index 0000000000..f4ff8665e2 --- /dev/null +++ b/include/ruby/internal/intern/set.h @@ -0,0 +1,111 @@ +#ifndef RBIMPL_INTERN_SET_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SET_H +/** + * @file + * @author Ruby developers <ruby-core@ruby-lang.org> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cSet. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* set.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Iterates over a set. Calls func with each element of the set and the + * argument given. func should return ST_CONTINUE, ST_STOP, or ST_DELETE. + * + * @param[in] set An instance of ::rb_cSet to iterate over. + * @param[in] func Callback function to yield. + * @param[in] arg Passed as-is to `func`. + * @exception rb_eRuntimeError `set` was tampered during iterating. + */ +void rb_set_foreach(VALUE set, int (*func)(VALUE element, VALUE arg), VALUE arg); + +/** + * Creates a new, empty set object. + * + * @return An allocated new instance of ::rb_cSet. + */ +VALUE rb_set_new(void); + +/** + * Identical to rb_set_new(), except it additionally specifies how many elements + * it is expected to contain. This way you can create a set that is large enough + * for your need. For large sets, it means it won't need to be reallocated + * much, improving performance. + * + * @param[in] capa Designed capacity of the set. + * @return An empty Set, whose capacity is `capa`. + */ +VALUE rb_set_new_capa(size_t capa); + +/** + * Whether the set contains the given element. + * + * @param[in] set Set to look into. + * @param[in] element Set element to look for. + * @return true if element is in the set, falst otherwise. + */ +bool rb_set_lookup(VALUE set, VALUE element); + +/** + * Adds element to set. + * + * @param[in] set Target set table to modify. + * @param[in] element Arbitrary Ruby object. + * @exception rb_eFrozenError `set` is frozen. + * @return true if element was not already in set, false otherwise + * @post `element` is in `set`. + */ +bool rb_set_add(VALUE set, VALUE element); + +/** + * Removes all entries from set. + * + * @param[out] set Target to clear. + * @exception rb_eFrozenError `set`is frozen. + * @return The passed `set` + * @post `set` has no elements. + */ +VALUE rb_set_clear(VALUE set); + +/** + * Removes the element from from set. + * + * @param[in] set Target set to modify. + * @param[in] element Key to delete. + * @retval true if element was already in set, false otherwise + * @post `set` does not have `element` as an element. + */ +bool rb_set_delete(VALUE set, VALUE element); + +/** + * Returns the number of elements in the set. + * + * @param[in] set A set object. + * @return The size of the set. + */ +size_t rb_set_size(VALUE set); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_SET_H */ diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h index e5b6d6c3d5..4773788651 100644 --- a/include/ruby/internal/intern/signal.h +++ b/include/ruby/internal/intern/signal.h @@ -97,7 +97,7 @@ RBIMPL_ATTR_NONNULL(()) * - Case #11: When signo and PID are both negative, the behaviour of this * function depends on how `killpg(3)` works. On Linux, it seems such * attempt is strictly prohibited and `Errno::EINVAL` is raised. But on - * macOS, it seems it tries to to send the signal actually to the process + * macOS, it seems it tries to send the signal actually to the process * group. * * @note Above description is in fact different from how `kill(2)` works. diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h index 3083125e56..2ec08fc81f 100644 --- a/include/ruby/internal/intern/string.h +++ b/include/ruby/internal/intern/string.h @@ -412,7 +412,7 @@ VALUE rb_utf8_str_new_static(const char *ptr, long len); /** * Identical to rb_interned_str(), except it takes a Ruby's string instead of - * C's. It can also be seen as a routine identical to to rb_str_new_shared(), + * C's. It can also be seen as a routine identical to rb_str_new_shared(), * except it returns an infamous "f"string. * * @param[in] str An object of ::RString. @@ -444,8 +444,8 @@ VALUE rb_str_to_interned_str(VALUE str); * terminating NUL character. * @exception rb_eArgError `len` is negative. * @return A found or created instance of ::rb_cString, of `len` bytes - * length, of "binary" encoding, whose contents are identical to - * that of `ptr`. + * length, of US-ASCII or "binary" encoding, whose contents are + * identical to that of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. */ @@ -454,7 +454,7 @@ VALUE rb_interned_str(const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_interned_str(), except it assumes the passed pointer is a - * pointer to a C's string. It can also be seen as a routine identical to to + * pointer to a C's string. It can also be seen as a routine identical to * rb_str_to_interned_str(), except it takes a C's string instead of Ruby's. * Or it can also be seen as a routine identical to rb_str_new_cstr(), except * it returns an infamous "f"string. @@ -591,10 +591,9 @@ void rb_must_asciicompat(VALUE obj); VALUE rb_str_dup(VALUE str); /** - * I guess there is no use case of this function in extension libraries, but - * this is a routine identical to rb_str_dup(), except it always creates an - * instance of ::rb_cString regardless of the given object's class. This makes - * the most sense when the passed string is formerly hidden by rb_obj_hide(). + * Like rb_str_dup(), but always create an instance of ::rb_cString + * regardless of the given object's class. This makes the most sense + * when the passed string is formerly hidden by rb_obj_hide(). * * @param[in] str A string, possibly hidden. * @return A duplicated new instance of ::rb_cString. @@ -970,8 +969,8 @@ st_index_t rb_str_hash(VALUE str); * * @param[in] str1 A string. * @param[in] str2 Another string. - * @retval 1 They have identical contents, length, and encodings. - * @retval 0 Otherwise. + * @retval 0 They have identical contents, length, and encodings. + * @retval 1 Otherwise. * @pre Both objects must not be any arbitrary objects except * ::RString. * @@ -1686,10 +1685,10 @@ rbimpl_exc_new_cstr(VALUE exc, const char *str) * Length of a string literal. * * @param[in] str A C String literal. - * @return An integer constant expression that represents `str`'s length, - * in bytes, not including the terminating NUL character. + * @return An integer constant expression that represents the number of + * `str`'s elements, not including the terminating NUL character. */ -#define rb_strlen_lit(str) (sizeof(str "") - 1) +#define rb_strlen_lit(str) ((sizeof(str "") / sizeof(str ""[0])) - 1) /** * Identical to rb_str_new_static(), except it cannot take string variables. diff --git a/include/ruby/internal/intern/struct.h b/include/ruby/internal/intern/struct.h index 4510508d77..16b3fad4e0 100644 --- a/include/ruby/internal/intern/struct.h +++ b/include/ruby/internal/intern/struct.h @@ -54,6 +54,8 @@ VALUE rb_struct_new(VALUE klass, ...); * @post Global toplevel constant `name` is defined. * @note `name` is allowed to be a null pointer. This function creates * an anonymous struct class then. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. * * @internal * @@ -78,6 +80,8 @@ RBIMPL_ATTR_NONNULL((2)) * @post `name` is a constant under `space`. * @note In contrast to rb_struct_define(), it doesn't make any sense to * pass a null pointer to this function. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_struct_define_under(VALUE space, const char *name, ...); @@ -195,6 +199,8 @@ RBIMPL_ATTR_NONNULL((2)) * @post `class_name` is a constant under `outer`. * @note In contrast to rb_struct_define_without_accessor(), it doesn't * make any sense to pass a null name. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); @@ -209,6 +215,8 @@ VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_nam * NULL. Each of which are the name of fields. * @exception rb_eArgError Duplicated field name. * @return The defined class. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_data_define(VALUE super, ...); diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h index 716375acd7..4d87452745 100644 --- a/include/ruby/internal/intern/thread.h +++ b/include/ruby/internal/intern/thread.h @@ -61,10 +61,10 @@ int rb_thread_wait_fd(int fd); int rb_thread_fd_writable(int fd); /** - * Notifies a closing of a file descriptor to other threads. Multiple threads - * can wait for the given file descriptor at once. If such file descriptor is - * closed, threads need to start propagating their exceptions. This is the API - * to kick that process. + * This funciton is now a no-op. It was previously used to interrupt threads + * that were using the given file descriptor and wait for them to finish. + * + * @deprecated Use IO with RUBY_IO_MODE_EXTERNAL and `rb_io_close` instead. * * @param[in] fd A file descriptor. * @note This function blocks until all the threads waiting for such fd diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h index 76af796b54..f0b54c702c 100644 --- a/include/ruby/internal/intern/vm.h +++ b/include/ruby/internal/intern/vm.h @@ -89,7 +89,8 @@ VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @retval RUBY_Qundef `recv` doesn't respond to `mid`. * @retval otherwise What the method evaluates to. */ @@ -106,9 +107,11 @@ VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int k * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `arg`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `arg`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return What the command evaluates to. */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(4.0) VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat); /** @@ -229,8 +232,7 @@ void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func); * restrict creation of an instance of a class. For example it rarely makes * sense for a DB adaptor class to allow programmers creating DB row objects * without querying the DB itself. You can kill sporadic creation of such - * objects then, by nullifying the allocator function using this API. Your - * object shall be allocated using #RB_NEWOBJ_OF() directly. + * objects then, by nullifying the allocator function using this API. * * @param[out] klass The class to modify. * @pre `klass` must be an instance of Class. diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h index 662d39c0ec..a10e7ad2d8 100644 --- a/include/ruby/internal/interpreter.h +++ b/include/ruby/internal/interpreter.h @@ -141,7 +141,7 @@ void ruby_show_copyright(void); * * @param[in] addr A pointer somewhere on the stack, near its bottom. */ -void ruby_init_stack(volatile VALUE *addr); +void ruby_init_stack(void *addr); /** * Initializes the VM and builtin libraries. diff --git a/include/ruby/internal/iterator.h b/include/ruby/internal/iterator.h index 5f706460f8..891045363e 100644 --- a/include/ruby/internal/iterator.h +++ b/include/ruby/internal/iterator.h @@ -265,48 +265,6 @@ int rb_block_given_p(void); */ void rb_need_block(void); -#ifndef __cplusplus -RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) -#endif -/** - * Old way to iterate a block. - * - * @deprecated This is an old API. Use rb_block_call() instead. - * @warning The passed function must at least once call a ruby method - * (to handle interrupts etc.) - * @param[in] func1 A function that could yield a value. - * @param[in,out] data1 Passed to `func1` - * @param[in] proc A function acts as a block. - * @param[in,out] data2 Passed to `proc` as the data2 parameter. - * @return What `func1` returns. - */ -VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); - -#ifdef __cplusplus -namespace ruby { -namespace backward { -/** - * Old way to iterate a block. - * - * @deprecated This is an old API. Use rb_block_call() instead. - * @warning The passed function must at least once call a ruby method - * (to handle interrupts etc.) - * @param[in] iter A function that could yield a value. - * @param[in,out] data1 Passed to `func1` - * @param[in] bl A function acts as a block. - * @param[in,out] data2 Passed to `proc` as the data2 parameter. - * @return What `func1` returns. - */ -static inline VALUE -rb_iterate_deprecated(VALUE (*iter)(VALUE), VALUE data1, rb_block_call_func_t bl, VALUE data2) -{ - return ::rb_iterate(iter, data1, bl, data2); -}}} - -RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) -VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); -#endif - /** * Identical to rb_funcallv(), except it additionally passes a function as a * block. When the method yields, `proc` is called with the yielded value as @@ -337,7 +295,8 @@ VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_cal * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return What `obj.mid` returns. */ VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat); diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h index 6884db195d..cd099f85db 100644 --- a/include/ruby/internal/memory.h +++ b/include/ruby/internal/memory.h @@ -40,7 +40,12 @@ #if defined(_MSC_VER) && defined(_WIN64) # include <intrin.h> +# if defined(_M_AMD64) # pragma intrinsic(_umul128) +# endif +# if defined(_M_ARM64) +# pragma intrinsic(__umulh) +# endif #endif #include "ruby/internal/attr/alloc_size.h" @@ -56,13 +61,14 @@ #include "ruby/internal/has/builtin.h" #include "ruby/internal/stdalign.h" #include "ruby/internal/stdbool.h" +#include "ruby/internal/stdckdint.h" #include "ruby/internal/xmalloc.h" #include "ruby/backward/2/limits.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/assume.h" #include "ruby/defines.h" -/** @cond INTENAL_MACRO */ +/** @cond INTERNAL_MACRO */ /* Make alloca work the best possible way. */ #if defined(alloca) @@ -402,7 +408,8 @@ typedef uint128_t DSIZE_T; /** * @private * - * This is an implementation detail of rbimpl_size_mul_overflow(). + * This is an implementation detail of rbimpl_size_mul_overflow() and + * rbimpl_size_add_overflow(). * * @internal * @@ -410,9 +417,9 @@ typedef uint128_t DSIZE_T; * nothing more than std::variant<std::size_t> if we could use recent C++, but * reality is we cannot. */ -struct rbimpl_size_mul_overflow_tag { - bool left; /**< Whether overflow happened or not. */ - size_t right; /**< Multiplication result. */ +struct rbimpl_size_overflow_tag { + bool overflowed; /**< Whether overflow happened or not. */ + size_t result; /**< Calculation result. */ }; RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -482,6 +489,18 @@ RBIMPL_ATTR_NORETURN() */ void ruby_malloc_size_overflow(size_t x, size_t y); +RBIMPL_ATTR_NORETURN() +/** + * @private + * + * This is an implementation detail. People don't use this directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @exception rb_eArgError `x` + `y` would integer overflow. + */ +void ruby_malloc_add_size_overflow(size_t x, size_t y); + #ifdef HAVE_RB_GC_GUARDED_PTR_VAL volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val); #endif @@ -554,39 +573,46 @@ RBIMPL_ATTR_CONST() * * @param[in] x Arbitrary value. * @param[in] y Arbitrary value. - * @return `{ left, right }`, where `left` is whether there is an integer - * overflow or not, and `right` is a (possibly overflowed) result - * of `x` * `y`. + * @return `{ overflowed, result }`, where `overflowed` is whether there is + * an integer overflow or not, and `result` is a (possibly + * overflowed) result of `x` * `y`. * * @internal * * This is in fact also an implementation detail of ruby_xmalloc2() etc. */ -static inline struct rbimpl_size_mul_overflow_tag +static inline struct rbimpl_size_overflow_tag rbimpl_size_mul_overflow(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; + struct rbimpl_size_overflow_tag ret = { false, 0, }; + +#if defined(ckd_mul) + ret.overflowed = ckd_mul(&ret.result, x, y); -#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) - ret.left = __builtin_mul_overflow(x, y, &ret.right); +#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) + ret.overflowed = __builtin_mul_overflow(x, y, &ret.result); #elif defined(DSIZE_T) RB_GNUC_EXTENSION DSIZE_T dx = x; RB_GNUC_EXTENSION DSIZE_T dy = y; RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; - ret.left = dz > SIZE_MAX; - ret.right = RBIMPL_CAST((size_t)dz); + ret.overflowed = dz > SIZE_MAX; + ret.result = RBIMPL_CAST((size_t)dz); -#elif defined(_MSC_VER) && defined(_WIN64) +#elif defined(_MSC_VER) && defined(_M_AMD64) unsigned __int64 dp = 0; unsigned __int64 dz = _umul128(x, y, &dp); - ret.left = RBIMPL_CAST((bool)dp); - ret.right = RBIMPL_CAST((size_t)dz); + ret.overflowed = RBIMPL_CAST((bool)dp); + ret.result = RBIMPL_CAST((size_t)dz); + +#elif defined(_MSC_VER) && defined(_M_ARM64) + ret.overflowed = __umulh(x, y) != 0; + ret.result = x * y; #else /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ - ret.left = (y != 0) && (x > SIZE_MAX / y); - ret.right = x * y; + ret.overflowed = (y != 0) && (x > SIZE_MAX / y); + ret.result = x * y; #endif return ret; @@ -610,11 +636,11 @@ rbimpl_size_mul_overflow(size_t x, size_t y) static inline size_t rbimpl_size_mul_or_raise(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag size = + struct rbimpl_size_overflow_tag size = rbimpl_size_mul_overflow(x, y); - if (RB_LIKELY(! size.left)) { - return size.right; + if (RB_LIKELY(! size.overflowed)) { + return size.result; } else { ruby_malloc_size_overflow(x, y); @@ -622,6 +648,81 @@ rbimpl_size_mul_or_raise(size_t x, size_t y) } } +#if defined(__DOXYGEN__) +RBIMPL_ATTR_CONSTEXPR(CXX14) +#elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) +RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */ +#elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0) +RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */ +#endif +RBIMPL_ATTR_CONST() +/** + * @private + * + * This is an implementation detail. People don't use this directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @return `{ overflowed, result }`, where `overflowed` is whether there is + * an integer overflow or not, and `result` is a (possibly + * overflowed) result of `x` + `y`. + * + * @internal + */ +static inline struct rbimpl_size_overflow_tag +rbimpl_size_add_overflow(size_t x, size_t y) +{ + struct rbimpl_size_overflow_tag ret = { false, 0, }; + +#if defined(ckd_add) + ret.overflowed = ckd_add(&ret.result, x, y); + +#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow) + ret.overflowed = __builtin_add_overflow(x, y, &ret.result); + +#elif defined(DSIZE_T) + RB_GNUC_EXTENSION DSIZE_T dx = x; + RB_GNUC_EXTENSION DSIZE_T dy = y; + RB_GNUC_EXTENSION DSIZE_T dz = dx + dy; + ret.overflowed = dz > SIZE_MAX; + ret.result = (size_t)dz; + +#else + ret.result = x + y; + ret.overflowed = ret.result < y; + +#endif + + return ret; +} + +/** + * @private + * + * This is an implementation detail. People don't use this directly. + * + * @param[in] x Arbitrary value. + * @param[in] y Arbitrary value. + * @exception rb_eArgError Multiplication could integer overflow. + * @return `x` + `y`. + * + * @internal + */ +static inline size_t +rbimpl_size_add_or_raise(size_t x, size_t y) +{ + struct rbimpl_size_overflow_tag size = + rbimpl_size_add_overflow(x, y); + + if (RB_LIKELY(!size.overflowed)) { + return size.result; + } + else { + ruby_malloc_add_size_overflow(x, y); + RBIMPL_UNREACHABLE_RETURN(0); + } +} + /** * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. @@ -639,7 +740,7 @@ rbimpl_size_mul_or_raise(size_t x, size_t y) static inline void * rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) { - const size_t total_size = rbimpl_size_mul_or_raise(count, elsize); + const size_t total_size = rbimpl_size_mul_or_raise(RBIMPL_CAST((size_t)count), elsize); const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE); return rb_alloc_tmp_buffer_with_count(store, total_size, cnt); } diff --git a/include/ruby/internal/module.h b/include/ruby/internal/module.h index d678dd2102..97b0b2b8b0 100644 --- a/include/ruby/internal/module.h +++ b/include/ruby/internal/module.h @@ -56,8 +56,8 @@ RBIMPL_ATTR_NONNULL(()) * @post Top-level constant named `name` refers the returned class. * @note If a class named `name` is already defined and its superclass is * `super`, the function just returns the defined class. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. * * @internal * @@ -75,8 +75,8 @@ RBIMPL_ATTR_NONNULL(()) * constant is not a module. * @return The created module. * @post Top-level constant named `name` refers the returned module. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move modules returned by this + * function. They are immortal. * * @internal * @@ -103,8 +103,8 @@ RBIMPL_ATTR_NONNULL(()) * @post `outer::name` refers the returned class. * @note If a class named `name` is already defined and its superclass * is `super`, the function just returns the defined class. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move classes returned by this + * function. They are immortal. */ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super); @@ -118,8 +118,8 @@ RBIMPL_ATTR_NONNULL(()) * the constant is not a class. * @return The created module. * @post `outer::name` refers the returned module. - * @note The compaction GC does not move classes returned by this - * function. + * @note The GC does not collect nor move modules returned by this + * function. They are immortal. */ VALUE rb_define_module_under(VALUE outer, const char *name); diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h index ba1d7cbe59..13030ae279 100644 --- a/include/ruby/internal/newobj.h +++ b/include/ruby/internal/newobj.h @@ -29,63 +29,14 @@ #include "ruby/internal/value.h" #include "ruby/assert.h" -/** - * Declares, allocates, then assigns a new object to the given variable. - * - * @param obj Variable name. - * @param type Variable type. - * @exception rb_eNoMemError No space left. - * @return An allocated object, not initialised. - * @note Modern programs tend to use #NEWOBJ_OF instead. - * - * @internal - * - * :FIXME: Should we deprecate it? - */ -#define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj()) - -/** - * Identical to #RB_NEWOBJ, except it also accepts the allocating object's - * class and flags. - * - * @param obj Variable name. - * @param type Variable type. - * @param klass Object's class. - * @param flags Object's flags. - * @exception rb_eNoMemError No space left. - * @return An allocated object, filled with the arguments. - */ -#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags)) - -#define NEWOBJ RB_NEWOBJ /**< @old{RB_NEWOBJ} */ -#define NEWOBJ_OF RB_NEWOBJ_OF /**< @old{RB_NEWOBJ_OF} */ #define OBJSETUP rb_obj_setup /**< @old{rb_obj_setup} */ #define CLONESETUP rb_clone_setup /**< @old{rb_clone_setup} */ #define DUPSETUP rb_dup_setup /**< @old{rb_dup_setup} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** - * This is the implementation detail of #RB_NEWOBJ. - * - * @exception rb_eNoMemError No space left. - * @return An allocated object, not initialised. - */ -VALUE rb_newobj(void); - -/** - * This is the implementation detail of #RB_NEWOBJ_OF. - * - * @param klass Object's class. - * @param flags Object's flags. - * @exception rb_eNoMemError No space left. - * @return An allocated object, filled with the arguments. - */ -VALUE rb_newobj_of(VALUE klass, VALUE flags); - -/** * Fills common fields in the object. * - * @note Prefer rb_newobj_of() to this function. * @param[in,out] obj A Ruby object to be set up. * @param[in] klass `obj` will belong to this class. * @param[in] type One of ::ruby_value_type. @@ -158,42 +109,4 @@ void rb_singleton_class_attached(VALUE klass, VALUE obj); void rb_copy_generic_ivar(VALUE clone, VALUE obj); RBIMPL_SYMBOL_EXPORT_END() -RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works.")) -/** - * @deprecated Not sure exactly when but at some time, the implementation of - * `Object#clone` stopped using this function. It remained - * untouched for a while, and then @shyouhei realised that they - * are no longer doing the same thing. It seems nobody seriously - * uses this function any longer. Let's just abandon it. - * - * @param[out] clone The destination object. - * @param[in] obj The source object. - */ -static inline void -rb_clone_setup(VALUE clone, VALUE obj) -{ - (void)clone; - (void)obj; - return; -} - -RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works.")) -/** - * @deprecated Not sure exactly when but at some time, the implementation of - * `Object#dup` stopped using this function. It remained - * untouched for a while, and then @shyouhei realised that they - * are no longer the same thing. It seems nobody seriously uses - * this function any longer. Let's just abandon it. - * - * @param[out] dup The destination object. - * @param[in] obj The source object. - */ -static inline void -rb_dup_setup(VALUE dup, VALUE obj) -{ - (void)dup; - (void)obj; - return; -} - #endif /* RBIMPL_NEWOBJ_H */ diff --git a/include/ruby/internal/scan_args.h b/include/ruby/internal/scan_args.h index 1ed2bf6368..2dbc1ee7bc 100644 --- a/include/ruby/internal/scan_args.h +++ b/include/ruby/internal/scan_args.h @@ -75,7 +75,7 @@ * Pass keywords if current method is called with keywords, useful for argument * delegation */ -#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p() +#define RB_PASS_CALLED_KEYWORDS !!rb_keyword_given_p() /** @} */ diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h index dc0a6b41d6..1e2636da48 100644 --- a/include/ruby/internal/special_consts.h +++ b/include/ruby/internal/special_consts.h @@ -156,7 +156,7 @@ RB_TEST(VALUE obj) * * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil). */ - return obj & ~RUBY_Qnil; + return obj & RBIMPL_CAST((VALUE)~RUBY_Qnil); } RBIMPL_ATTR_CONST() @@ -226,7 +226,7 @@ RB_NIL_OR_UNDEF_P(VALUE obj) * * NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil. */ - const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil); + const VALUE mask = RBIMPL_CAST((VALUE)~(RUBY_Qundef ^ RUBY_Qnil)); const VALUE common_bits = RUBY_Qundef & RUBY_Qnil; return (obj & mask) == common_bits; } @@ -326,7 +326,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_SPECIAL_CONST_P(VALUE obj) { - return RB_IMMEDIATE_P(obj) || obj == RUBY_Qfalse; + return (obj == RUBY_Qfalse) || RB_IMMEDIATE_P(obj); } RBIMPL_ATTR_CONST() @@ -346,7 +346,7 @@ RBIMPL_ATTR_CONSTEXPR(CXX11) static inline VALUE rb_special_const_p(VALUE obj) { - return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue; + return (unsigned int)RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue; } /** diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h index 594c2b2917..30bfd3bb79 100644 --- a/include/ruby/internal/static_assert.h +++ b/include/ruby/internal/static_assert.h @@ -23,13 +23,14 @@ #include <assert.h> #include "ruby/internal/has/extension.h" #include "ruby/internal/compiler_since.h" +#include "ruby/internal/attr/maybe_unused.h" /** @cond INTERNAL_MACRO */ #if defined(__cplusplus) && defined(__cpp_static_assert) # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_STATIC_ASSERT0 static_assert -#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +#elif defined(__cplusplus) && RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__INTEL_CXX11_MODE__) @@ -71,7 +72,7 @@ #else # define RBIMPL_STATIC_ASSERT(name, expr) \ - typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] + RBIMPL_ATTR_MAYBE_UNUSED() typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] #endif #endif /* RBIMPL_STATIC_ASSERT_H */ diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h index 1ca61136ba..5d9026434b 100644 --- a/include/ruby/internal/stdbool.h +++ b/include/ruby/internal/stdbool.h @@ -27,25 +27,13 @@ #elif defined(__cplusplus) # /* bool is a keyword in C++. */ -# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) -# include <cstdbool> -# endif -# # ifndef __bool_true_false_are_defined # define __bool_true_false_are_defined # endif -#elif defined(HAVE_STDBOOL_H) -# /* Take stdbool.h definition. */ +#else +# /* Take stdbool.h definition. It exists since GCC 3.0 and VS 2015. */ # include <stdbool.h> - -#elif !defined(HAVE__BOOL) -typedef unsigned char _Bool; -# /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ -# define bool _Bool -# define true ((_Bool)+1) -# define false ((_Bool)+0) -# define __bool_true_false_are_defined #endif #endif /* RBIMPL_STDBOOL_H */ diff --git a/include/ruby/internal/stdckdint.h b/include/ruby/internal/stdckdint.h new file mode 100644 index 0000000000..e5b5b8b751 --- /dev/null +++ b/include/ruby/internal/stdckdint.h @@ -0,0 +1,68 @@ +#ifndef RBIMPL_STDCKDINT_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_STDCKDINT_H +/** + * @author Ruby developers <ruby-core@ruby-lang.org> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief C23 shim for <stdckdint.h> + */ +#include "ruby/internal/config.h" +#include "ruby/internal/cast.h" +#include "ruby/internal/has/builtin.h" +#include "ruby/internal/stdbool.h" + +#ifdef __has_include +# if __has_include(<stdckdint.h>) +# /* Conforming C23 situation; e.g. recent clang */ +# define RBIMPL_HAVE_STDCKDINT_H +# endif +#endif + +#ifdef HAVE_STDCKDINT_H +# /* Some OSes (most notably FreeBSD) have this file. */ +# define RBIMPL_HAVE_STDCKDINT_H +#endif + +#ifdef __cplusplus +# /* It seems OS/Compiler provided stdckdint.h tend not support C++ yet. +# * Situations could improve someday but in a meantime let us work around. +# */ +# undef RBIMPL_HAVE_STDCKDINT_H +#endif + +#ifdef RBIMPL_HAVE_STDCKDINT_H +# /* Take that. */ +# include <stdckdint.h> + +#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow) +# define ckd_add(x, y, z) RBIMPL_CAST((bool)__builtin_add_overflow((y), (z), (x))) +# define ckd_sub(x, y, z) RBIMPL_CAST((bool)__builtin_sub_overflow((y), (z), (x))) +# define ckd_mul(x, y, z) RBIMPL_CAST((bool)__builtin_mul_overflow((y), (z), (x))) +# define __STDC_VERSION_STDCKDINT_H__ 202311L + +#/* elif defined(__cplusplus) */ +#/* :TODO: if we assume C++11 we can use `<type_traits>` to implement them. */ + +#else +# /* intentionally leave them undefined */ +# /* to make `#ifdef ckd_add` etc. work as intended. */ +# undef ckd_add +# undef ckd_sub +# undef ckd_mul +# undef __STDC_VERSION_STDCKDINT_H__ +#endif + +#endif /* RBIMPL_STDCKDINT_H */ diff --git a/include/ruby/internal/symbol.h b/include/ruby/internal/symbol.h index 869a31115c..8bfd686fbe 100644 --- a/include/ruby/internal/symbol.h +++ b/include/ruby/internal/symbol.h @@ -101,12 +101,11 @@ ID rb_intern(const char *name); ID rb_intern2(const char *name, long len); /** - * Identical to rb_intern(), except it takes an instance of ::rb_cString. + * Identical to rb_intern(), except it takes a `T_STRING` object. * * @param[in] str The name of the id. - * @pre `str` must either be an instance of ::rb_cSymbol, or an instance - * of ::rb_cString, or responds to `#to_str` method. - * @exception rb_eTypeError Can't convert `str` into ::rb_cString. + * @pre `rb_type(str)` must be `T_STRING`. + * @exception rb_eEncodingError `str` contains invalid character(s). * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given str. * @note These days Ruby internally has two kinds of symbols @@ -121,10 +120,17 @@ ID rb_intern_str(VALUE str); * Retrieves the name mapped to the given id. * * @param[in] id An id to query. - * @retval NULL No such id ever existed in the history. + * @retval NULL Unknown id. * @retval otherwise A name that the id represents. * @note The return value is managed by the interpreter. Don't pass it * to free(). + * @note The underlying name can contain internal NUL bytes, so the return + * value might be a truncated representation due to the nature of C + * strings. + * @note This C string is backed by an underlying Ruby string. The Ruby + * string may move during GC compaction which would make this + * C string point to invalid memory. Do not use the return value + * of this function after a potential GC entry point. */ const char *rb_id2name(ID id); @@ -159,34 +165,40 @@ RBIMPL_ATTR_NONNULL(()) * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. - * @exception rb_eEncodingError Given string is non-ASCII. + * @exception rb_eEncodingError Given string contains invalid character(s). * @retval 0 No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. + * @see rb_str_to_str * @see https://bugs.ruby-lang.org/issues/5072 - * - * @internal - * - * @shyouhei doesn't know why this has to raise rb_eEncodingError. */ ID rb_check_id(volatile VALUE *namep); /** - * @copydoc rb_intern_str() - * - * @internal + * Identical to rb_intern_str(), except it tries to convert the parameter object + * to an instance of ::rb_cString or its subclasses. * - * :FIXME: Can anyone tell us what is the difference between this one and - * rb_intern_str()? As far as @shyouhei reads the implementation it seems what - * rb_to_id() does is is just waste some CPU time, then call rb_intern_str(). - * He hopes he is wrong. + * @param[in] str The name of the id. + * @pre `str` must either be an instance of ::rb_cSymbol, or an instance + * of ::rb_cString, or responds to `#to_str` method. + * @exception rb_eTypeError Can't convert `str` into ::rb_cString. + * @exception rb_eEncodingError Given string contains invalid character(s). + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given str. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become static ones; i.e. would never be garbage collected. It + * is up to you to avoid memory leaks. Think twice before using + * it. + * @see rb_str_to_str */ ID rb_to_id(VALUE str); /** - * Identical to rb_id2name(), except it returns a Ruby's String instead of C's. + * Identical to rb_id2name(), except it returns a frozen Ruby String instead of + * a C String. * * @param[in] id An id to query. * @retval RUBY_Qfalse No such id ever existed in the history. @@ -201,14 +213,14 @@ ID rb_to_id(VALUE str); VALUE rb_id2str(ID id); /** - * Identical to rb_id2str(), except it takes an instance of ::rb_cSymbol rather - * than an ::ID. + * Obtain a frozen string representation of a symbol (not including the leading + * colon). Done without any object allocations. * - * @param[in] id An id to query. - * @retval RUBY_Qfalse No such id ever existed in the history. - * @retval otherwise An instance of ::rb_cString with the name of id. + * @param[in] symbol A ::rb_cSymbol instance to query. + * @return A frozen instance of ::rb_cString with the name of `symbol`. + * @note This does not create a permanent ::ID using the symbol. */ -VALUE rb_sym2str(VALUE id); +VALUE rb_sym2str(VALUE symbol); /** * Identical to rb_intern_str(), except it generates a dynamic symbol if @@ -237,17 +249,14 @@ RBIMPL_ATTR_NONNULL(()) * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. - * @exception rb_eEncodingError Given string is non-ASCII. + * @exception rb_eEncodingError Given string contains invalid character(s). * @retval RUBY_Qnil No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. * @see https://bugs.ruby-lang.org/issues/5072 - * - * @internal - * - * @shyouhei doesn't know why this has to raise rb_eEncodingError. + * @see rb_str_to_str */ VALUE rb_check_symbol(volatile VALUE *namep); RBIMPL_SYMBOL_EXPORT_END() @@ -308,8 +317,9 @@ rbimpl_intern_const(ID *ptr, const char *str) } /** - * Old implementation detail of rb_intern(). - * @deprecated Does anyone use it? Preserved for backward compat. + * Returns the cached ID for the given str in var, in compiler + * independent manner. Use this instead of GCC specific rb_intern() + * when you want to cache the ID on all platforms certainly. */ #define RUBY_CONST_ID(var, str) \ do { \ @@ -318,7 +328,8 @@ rbimpl_intern_const(ID *ptr, const char *str) } while (0) #if defined(HAVE_STMT_AND_DECL_IN_EXPR) -/* __builtin_constant_p and statement expression is available +/* GCC specific shorthand for RUBY_CONST_ID(). + * __builtin_constant_p and statement expression is available * since gcc-2.7.2.3 at least. */ #define rb_intern(str) \ (RBIMPL_CONSTANT_P(str) ? \ diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h index 977f60a009..b47d8afb97 100644 --- a/include/ruby/internal/value_type.h +++ b/include/ruby/internal/value_type.h @@ -96,10 +96,11 @@ #define RB_TYPE_P RB_TYPE_P #define Check_Type Check_Type -#if !RUBY_DEBUG -# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t))) +#ifdef RBIMPL_VA_OPT_ARGS +# define RBIMPL_ASSERT_TYPE(v, t) \ + RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t), "actual type: %d", rb_type(v)) #else -# define RBIMPL_ASSERT_TYPE Check_Type +# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t)) #endif /** @endcond */ @@ -129,8 +130,8 @@ ruby_value_type { RUBY_T_RATIONAL = 0x0f, /**< @see struct ::RRational */ RUBY_T_NIL = 0x11, /**< @see ::RUBY_Qnil */ - RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qfalse */ - RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qtrue */ + RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qtrue */ + RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qfalse */ RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */ RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */ RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */ @@ -443,7 +444,7 @@ Check_Type(VALUE v, enum ruby_value_type t) } unexpected_type: - rb_unexpected_type(v, t); + rb_unexpected_type(v, RBIMPL_CAST((int)t)); } #endif /* RBIMPL_VALUE_TYPE_H */ diff --git a/include/ruby/internal/warning_push.h b/include/ruby/internal/warning_push.h index f5981633f8..91d62cb00d 100644 --- a/include/ruby/internal/warning_push.h +++ b/include/ruby/internal/warning_push.h @@ -79,7 +79,7 @@ */ #define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/ # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) diff --git a/include/ruby/internal/xmalloc.h b/include/ruby/internal/xmalloc.h index 57552e4e7d..132bc478ce 100644 --- a/include/ruby/internal/xmalloc.h +++ b/include/ruby/internal/xmalloc.h @@ -283,110 +283,6 @@ void ruby_xfree(void *ptr) RBIMPL_ATTR_NOEXCEPT(free(ptr)) ; -#if USE_GC_MALLOC_OBJ_INFO_DETAILS -# define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__) -# define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__) -# define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__) -# define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__) -# define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__) - -RBIMPL_ATTR_NODISCARD() -RBIMPL_ATTR_RESTRICT() -RBIMPL_ATTR_RETURNS_NONNULL() -RBIMPL_ATTR_ALLOC_SIZE((1)) -void *ruby_xmalloc_body(size_t size) -RBIMPL_ATTR_NOEXCEPT(malloc(size)) -; - -RBIMPL_ATTR_NODISCARD() -RBIMPL_ATTR_RESTRICT() -RBIMPL_ATTR_RETURNS_NONNULL() -RBIMPL_ATTR_ALLOC_SIZE((1,2)) -void *ruby_xmalloc2_body(size_t nelems, size_t elemsiz) -RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) -; - -RBIMPL_ATTR_NODISCARD() -RBIMPL_ATTR_RESTRICT() -RBIMPL_ATTR_RETURNS_NONNULL() -RBIMPL_ATTR_ALLOC_SIZE((1,2)) -void *ruby_xcalloc_body(size_t nelems, size_t elemsiz) -RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) -; - -RBIMPL_ATTR_NODISCARD() -RBIMPL_ATTR_RETURNS_NONNULL() -RBIMPL_ATTR_ALLOC_SIZE((2)) -void *ruby_xrealloc_body(void *ptr, size_t newsiz) -RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) -; - -RBIMPL_ATTR_NODISCARD() -RBIMPL_ATTR_RETURNS_NONNULL() -RBIMPL_ATTR_ALLOC_SIZE((2,3)) -void *ruby_xrealloc2_body(void *ptr, size_t newelems, size_t newsiz) -RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) -; - -RUBY_EXTERN const char *ruby_malloc_info_file; -RUBY_EXTERN int ruby_malloc_info_line; - -static inline void * -ruby_xmalloc_with_location(size_t s, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xmalloc_body(s); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xmalloc2_body(s1, s2); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line) -{ - void *ptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - ptr = ruby_xcalloc_body(s1, s2); - ruby_malloc_info_file = NULL; - return ptr; -} - -static inline void * -ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line) -{ - void *rptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - rptr = ruby_xrealloc_body(ptr, s); - ruby_malloc_info_file = NULL; - return rptr; -} - -static inline void * -ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line) -{ - void *rptr; - ruby_malloc_info_file = file; - ruby_malloc_info_line = line; - rptr = ruby_xrealloc2_body(ptr, s1, s2); - ruby_malloc_info_file = NULL; - return rptr; -} -#endif - RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_XMALLOC_H */ |
