diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index c7acd995d7ee52..91a3571ad4235d 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -79,7 +79,7 @@ jobs: || contains(github.event.head_commit.message, '[DOC]') || contains(github.event.pull_request.title, '[DOC]') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event.pull_request.user.login == 'dependabot[bot]' && !startsWith(github.head_ref, 'dependabot/vcpkg')) + || (github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: diff --git a/NEWS.md b/NEWS.md index e043d15bea9742..943dbcb870dfa1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -100,7 +100,7 @@ releases. * error_highlight 0.7.2 * ipaddr 1.2.9 * 1.2.8 to [v1.2.9][ipaddr-v1.2.9] -* json 2.21.0 +* json 2.21.1 * 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2], [v2.19.3][json-v2.19.3], [v2.19.4][json-v2.19.4], [v2.19.5][json-v2.19.5], [v2.19.6][json-v2.19.6], [v2.19.7][json-v2.19.7], [v2.19.8][json-v2.19.8], [v2.19.9][json-v2.19.9], [v2.20.0][json-v2.20.0], [v2.21.0][json-v2.21.0] * openssl 4.0.2 * 4.0.0 to [v4.0.1][openssl-v4.0.1], [v4.0.2][openssl-v4.0.2] diff --git a/benchmark/README.md b/benchmark/README.md index 9f9192685e97bb..02b6373f810dc2 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -62,8 +62,7 @@ make benchmark ITEM=vm # Run some limited benchmarks in ITEM-matched files make benchmark ITEM=vm OPTS=--filter=block -# You can specify the benchmark by an exact filename instead of using the default argument: -# ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb') +# You can specify the benchmark by exact filenames instead of matching ITEM: make benchmark ARGS=benchmark/erb_render.yml # You can specify any option via $OPTS diff --git a/bignum.c b/bignum.c index 89b35dd1e1275c..d1a2001f5db6ee 100644 --- a/bignum.c +++ b/bignum.c @@ -3440,9 +3440,6 @@ absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_num INTEGER_PACK_NATIVE_BYTE_ORDER); if (sign == 2) { -#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4) - *nlz_bits_ret = 0; -#endif return (size_t)-1; } *nlz_bits_ret = nlz_bits; diff --git a/common.mk b/common.mk index 9e3697ece84822..20e6a7d98f9916 100644 --- a/common.mk +++ b/common.mk @@ -1316,7 +1316,7 @@ $(MAINOBJ): $(srcdir)/$(MAINSRC) probes.dmyh: $(BASERUBY) $(tooldir)/gen_dummy_probes.rb $(srcdir)/probes.d > $@ -probes.h: {$(VPATH)}probes.$(DTRACE_EXT) +probes.h: {$(VPATH)}probes.$(DTRACE_EXT) $(srcdir)/vm_opts.h prereq: incs srcs preludes PHONY @@ -1440,15 +1440,26 @@ COMPARE_RUBY = $(BASERUBY) BENCH_RUBY = $(RUNRUBY) BENCH_OPTS = --output=markdown --output-compare -v ITEM = -ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '$(ITEM)' -o -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb' | sort) +ARGS = OPTS = -# See benchmark/README.md for details. +# Select the benchmark files with Ruby instead of `find | sort`, so the +# recipe runs on any platform regardless of the shell. When ARGS is +# empty, collect the files matching ITEM under benchmark/. Executables +# are passed with forward slashes because benchmark-driver splits them +# with Shellwords, which eats backslashes. See benchmark/README.md. benchmark: miniruby$(EXEEXT) update-benchmark-driver PHONY - $(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \ - --executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \ - --executables="built-ruby::$(BENCH_RUBY) --disable-gem" \ - $(BENCH_OPTS) $(ARGS) $(OPTS) + $(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib \ + -e "files = %w[$(ARGS)]" \ + -e "files = Dir.glob(['$(ITEM)', '*$(ITEM)*.yml', '*$(ITEM)*.rb'], base: '$(srcdir)/benchmark').reject(&:empty?).sort.uniq.map {|f| '$(srcdir)/benchmark/' + f} if files.empty?" \ + -e "if sep = File::ALT_SEPARATOR" \ + -e "ARGV.map! {|a| a.start_with?('--executables') ? a.gsub(sep, '/') : a}" \ + -e "end" \ + -e "ARGV.concat(files)" \ + -e "load '$(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver'" -- \ + --executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \ + --executables="built-ruby::$(BENCH_RUBY) --disable-gem" \ + $(BENCH_OPTS) $(OPTS) run.gdb: echo set breakpoint pending on > run.gdb diff --git a/configure.ac b/configure.ac index 562d9262f837f1..a88cd219b9fffc 100644 --- a/configure.ac +++ b/configure.ac @@ -1683,8 +1683,9 @@ RUBY_REPLACE_TYPE(clockid_t, [], CLOCKID, [@%:@ifdef HAVE_TIME_H @%:@endif]) # __VA_ARGS__ is also tested in AC_PROG_CC_C99 since autoconf 2.60a (around -# 2006). The check below is redundant and should always success. Remain not -# deleted for backward compat. +# 2006). The check below is redundant and should always success. However, +# when using the script generated by autoconf 2.71 cannot detect any of the +# C89/C99/C11 features in clang-20. AC_CACHE_CHECK(for variable length macro, rb_cv_va_args_macro, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ int foo(const char*); @@ -1694,6 +1695,8 @@ int foo(const char*); rb_cv_va_args_macro=no)]) AS_IF([test "$rb_cv_va_args_macro" = yes], [ AC_DEFINE(HAVE_VA_ARGS_MACRO) +], [ + AC_MSG_ERROR([C99 compiler is needed]) ]) # We want C11's `_Alignof`. GCC (and alike) have `__alignof__`, which behave diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 5f3c9478f75296..1099806f96e8e2 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -550,7 +550,7 @@ nogvl_getch(void *p) /* * call-seq: - * io.getch(min: nil, time: nil, intr: nil) -> char + * io.getch(min: nil, time: nil, intr: nil) -> char or nil * * Reads and returns a character in raw mode. * @@ -1776,7 +1776,7 @@ console_dev(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * io.getch(min: nil, time: nil, intr: nil) -> char + * io.getch(min: nil, time: nil, intr: nil) -> char or nil * * See IO#getch. */ diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index 5c24d0c514dd83..e8483db94bd536 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.21.0' + VERSION = '2.21.1' end diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb index 9e141a72685da0..a0358ccc6b02a4 100644 --- a/ext/json/parser/extconf.rb +++ b/ext/json/parser/extconf.rb @@ -15,22 +15,6 @@ have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1 -def have_builtin_func(name, check_expr, opt = "", &b) - checking_for checking_message(name.funcall_style, nil, opt) do - if try_compile(<= (level) && ruby_rgengc_debug >= (level)) -#elif defined(HAVE_VA_ARGS_MACRO) -# define RGENGC_DEBUG_ENABLED(level) ((RGENGC_DEBUG) >= (level)) #else -# define RGENGC_DEBUG_ENABLED(level) 0 +# define RGENGC_DEBUG_ENABLED(level) ((RGENGC_DEBUG) >= (level)) #endif int ruby_rgengc_debug; @@ -1334,12 +1332,8 @@ static inline void gc_prof_set_heap_info(rb_objspace_t *); #define gc_prof_record(objspace) (objspace)->profile.current_record #define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record) -#ifdef HAVE_VA_ARGS_MACRO -# define gc_report(level, objspace, ...) \ +#define gc_report(level, objspace, ...) \ if (!RGENGC_DEBUG_ENABLED(level)) {} else gc_report_body(level, objspace, __VA_ARGS__) -#else -# define gc_report if (!RGENGC_DEBUG_ENABLED(0)) {} else gc_report_body -#endif PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4); static void gc_finalize_deferred(void *dmy); @@ -4136,10 +4130,6 @@ gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap) } } -#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 -__attribute__((noinline)) -#endif - #if GC_CAN_COMPILE_COMPACTION static void gc_sort_heap_by_compare_func(rb_objspace_t *objspace, gc_compact_compare_func compare_func); static int compare_pinned_slots(const void *left, const void *right, void *d); diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h index 0818ad60112c42..8e78f23788f980 100644 --- a/include/ruby/internal/anyargs.h +++ b/include/ruby/internal/anyargs.h @@ -91,8 +91,8 @@ # 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 +# /* prior to C99: unsupported */ +# error __VA_ARGS__ macro is not available #else # /** @cond INTERNAL_MACRO */ diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h index 34862ded6e55c2..44de06a6eaac1a 100644 --- a/include/ruby/internal/config.h +++ b/include/ruby/internal/config.h @@ -124,10 +124,7 @@ #endif /* Detection of __VA_OPT__ */ -#if ! defined(HAVE_VA_ARGS_MACRO) -# undef HAVE___VA_OPT__ - -#elif defined(__cplusplus) +#if defined(__cplusplus) # if __cplusplus > 201703L # define HAVE___VA_OPT__ # else diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index ca794bcaeb508d..6be5fbf3af818d 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -393,7 +393,7 @@ rb_orig_errno_ptr(void) /** @cond INTERNAL_MACRO */ #if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") # /* Skip it; clang -pedantic doesn't like the following */ -#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) +#elif defined(__GNUC__) && defined(__OPTIMIZE__) # define rb_yield_values(argc, ...) \ __extension__({ \ const int rb_yield_values_argc = (argc); \ diff --git a/parse.y b/parse.y index b6fc74c5a0af3a..a65d689916ba0d 100644 --- a/parse.y +++ b/parse.y @@ -1755,18 +1755,10 @@ extern const ID id_warn, id_warning, id_gets, id_assoc; # define PRIsWARN PRIsVALUE # define WARN_ARGS(fmt,n) p->value, id_warn, n, rb_usascii_str_new_lit(fmt) # define WARN_ARGS_L(l,fmt,n) WARN_ARGS(fmt,n) -# ifdef HAVE_VA_ARGS_MACRO # define WARN_CALL(...) rb_funcall(__VA_ARGS__) -# else -# define WARN_CALL rb_funcall -# endif # define WARNING_ARGS(fmt,n) p->value, id_warning, n, rb_usascii_str_new_lit(fmt) # define WARNING_ARGS_L(l, fmt,n) WARNING_ARGS(fmt,n) -# ifdef HAVE_VA_ARGS_MACRO # define WARNING_CALL(...) rb_funcall(__VA_ARGS__) -# else -# define WARNING_CALL rb_funcall -# endif # define compile_error ripper_compile_error #else # define WARN_S_L(s,l) s diff --git a/template/Makefile.in b/template/Makefile.in index 7d4b798a838170..e87f52589e285e 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -521,7 +521,21 @@ _PREFIXED_SYMBOL = TOKEN_PASTE($(SYMBOL_PREFIX),name) shift; \ $(Q1:0=:) set -x; \ $(DTRACE) "$$@" -s $< - $(Q) sed -e 's/RUBY_/RUBY_DTRACE_/g' -e 's/PROBES_H_TMP/RUBY_PROBES_H/' -e 's/(char \*/(const char */g' -e 's/, char \*/, const char */g' $@.tmp > $@ + $(Q) { \ + echo '#ifdef __clang__'; \ + echo '#pragma clang diagnostic push'; \ + echo '#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"'; \ + echo '#pragma clang diagnostic ignored "-Wgnu-statement-expression-from-macro-expansion"'; \ + echo '#endif'; \ + sed -e 's/RUBY_/RUBY_DTRACE_/g' \ + -e 's/PROBES_H_TMP/RUBY_PROBES_H/' \ + -e 's/(char \*/(const char */g' -e 's/, char \*/, const char */g' \ + -e 's/({/RB_GNUC_EXTENSION&/g' \ + $@.tmp; \ + echo '#ifdef __clang__'; \ + echo '#pragma clang diagnostic pop'; \ + echo '#endif'; \ + } > $@ $(Q) $(RM) $@.tmp .dmyh.h: diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index a66d248ff5a3d2..71a21de62817c9 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -1108,7 +1108,7 @@ def setup_options(parser, options) super parser.separator "load path options:" parser.on '-Idirectory', 'Add library load path' do |dirs| - dirs.split(':').each { |d| $LOAD_PATH.unshift d } + dirs.split(File::PATH_SEPARATOR).each { |d| $LOAD_PATH.unshift d } end end end diff --git a/tool/test/testunit/test_load_path.rb b/tool/test/testunit/test_load_path.rb new file mode 100644 index 00000000000000..eb50350ea62017 --- /dev/null +++ b/tool/test/testunit/test_load_path.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: false +require 'test/unit' +require 'optparse' + +class TestLoadPathOption < Test::Unit::TestCase + # Representative absolute paths that never contain the platform's + # File::PATH_SEPARATOR, so joining them with it round-trips exactly. + # On Windows the separator is ";", so drive-letter paths (which embed + # a colon) are the case the old hardcoded split(":") used to break. + def sample_dirs + if File::PATH_SEPARATOR == ";" + ["V:/foo/lib", "C:/bar/lib"] + else + ["/foo/lib", "/bar/lib"] + end + end + + def build_parser + base = Class.new do + def setup_options(parser, options); end + end + klass = Class.new(base) do + prepend Test::Unit::LoadPathOption + end + parser = OptionParser.new + klass.new.setup_options(parser, {}) + parser + end + + def parse_load_path(argv) + saved = $LOAD_PATH.dup + build_parser.parse(argv) + $LOAD_PATH - saved + ensure + $LOAD_PATH.replace(saved) + end + + def test_single_directory_kept_intact + dir = sample_dirs.first + assert_equal([dir], parse_load_path(["-I#{dir}"]), + "a single -I directory must be added verbatim") + end + + def test_multiple_directories_split_on_path_separator + dirs = sample_dirs + joined = dirs.join(File::PATH_SEPARATOR) + # unshift reverses insertion order, so compare as a set. + assert_equal(dirs.sort, parse_load_path(["-I#{joined}"]).sort, + "-I must split only on File::PATH_SEPARATOR") + end +end diff --git a/vm.c b/vm.c index 58eb41d9113acb..07d03c864ae6f8 100644 --- a/vm.c +++ b/vm.c @@ -5194,15 +5194,6 @@ usage_analysis_register_clear(VALUE self) return usage_analysis_clear(self, usage_hash); } -#else - -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = 0; -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = 0; -MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = 0; - -#endif - -#if VM_COLLECT_USAGE_DETAILS /* @param insn instruction number */ static void vm_collect_usage_insn(int insn) diff --git a/vm_callinfo.h b/vm_callinfo.h index 612f8024640303..3ce2f4a3916d29 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -648,8 +648,8 @@ vm_cc_check_cme(const struct rb_callcache *cc, const rb_callable_method_entry_t fprintf(stderr, "iseq_overload:%d, cme:%p (def:%p), cm_cc_cme(cc):%p (def:%p)\n", (int)cme->def->iseq_overload, - cme, cme->def, - vm_cc_cme(cc), vm_cc_cme(cc)->def); + (void *)cme, (void *)cme->def, + (void *)vm_cc_cme(cc), (void *)vm_cc_cme(cc)->def); rp(cme); rp(vm_cc_cme(cc)); rp(rb_vm_lookup_overloaded_cme(cme)); diff --git a/vm_core.h b/vm_core.h index fba04b7f56ac5c..320d4cc7eb3f1d 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1736,7 +1736,7 @@ VM_BH_ISEQ_BLOCK_P(VALUE block_handler) if (!imemo_type_p(captured->code.val, imemo_iseq)) { rb_bug("not imemo_iseq. captured:%p IMEMO_P(captured->code.val):%d, " "flags:%.*" PRIxVALUE, - captured, + (void *)captured, RB_TYPE_P(captured->code.val, T_IMEMO), (int)(sizeof(VALUE) * CHAR_BIT / 4), RBASIC(captured->code.val)->flags); } diff --git a/win32/configure.bat b/win32/configure.bat index e8d6b5f95b64c1..f0103a2cb879d6 100644 --- a/win32/configure.bat +++ b/win32/configure.bat @@ -118,7 +118,7 @@ goto :loop ; echo>>%confargs% "--target=%arg:$=$$%" \ goto :loop ; :program_name - for /f "delims=- tokens=1,*" %I in ("%opt%") do set "var=%%J" + for /f "delims=- tokens=1,*" %%I in ("%opt%") do set "var=%%J" if "%var%" == "prefix" (set "var=PROGRAM_PREFIX" & goto :name) if "%var%" == "suffix" (set "var=PROGRAM_SUFFIX" & goto :name) if "%var%" == "name" (set "var=RUBY_INSTALL_NAME" & goto :name) @@ -188,7 +188,7 @@ goto :loop ; :ntver ::- For version constants, see ::- https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt#remarks - if "%eq%" == "" (set "NTVER=%~1" & call :shift) else (set "NTVER=%arg%") + set "NTVER=%arg%" if /i not "%NTVER:~0,2%" == "0x" if /i not "%NTVER:~0,13%" == "_WIN32_WINNT_" ( for %%i in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do ( call :set NTVER=%%NTVER:%%i=%%i%%