Project

General

Profile

Bug #21293

Updated by alanwu (Alan Wu) 5 days ago

GCC 15 defaults to `-std=gnu23`, which breaks rb_define_method() in some corner cases: 

 ```diff 
 diff --git a/object.c b/object.c 
 index 5a379e9..958f421 100644 
 --- a/object.c 
 +++ b/object.c 
 @@ -4613,7 +4613,8 @@ InitVM_Object(void) 
      rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); 
      rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding()); 
      rb_vm_register_global_object(rb_cFalseClass_to_s); 
 -      rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, 0); 
 +      int zero = 0; 
 +      rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, zero); 
      rb_define_alias(rb_cFalseClass, "inspect", "to_s"); 
      rb_define_method(rb_cFalseClass, "&", false_and, 1); 
      rb_define_method(rb_cFalseClass, "|", false_or, 1); 
 ``` 

 Applying the above is fine prior to C23, but on GCC 15 it triggers a build error: 

 ```text 
 compiling object.c 
 In file included from ./include/ruby/ruby.h:27, 
                  from constant.h:13, 
                  from object.c:22: 
 object.c: In function 'InitVM_Object': 
 ./include/ruby/internal/anyargs.h:288:135: error: passing argument 3 of 'rb_define_method_m3' from incompatible pointer type [-Wincompatible-pointer-types] 
   288 | #define rb_define_method(klass, mid, func, arity)             RBIMPL_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity)) 
       |                                                                                                                                         ^~~~~~ 
       |                                                                                                                                         | 
       |                                                                                                                                         VALUE (*)(VALUE) {aka long unsigned int (*)(long unsigned int)} 
 object.c:4617:5: note: in expansion of macro 'rb_define_method' 
  4617 |       rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, kek); 
       |       ^~~~~~~~~~~~~~~~ 
 ./include/ruby/internal/anyargs.h:277:21: note: expected 'VALUE (*)(void)' {aka 'long unsigned int (*)(void)'} but argument is of type 'VALUE (*)(VALUE)' {aka 'long unsigned int (*)(long unsigned int)'} 
   277 | RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) 
       |                       ^~~~~~~~~~~~~~~~ 
 ./include/ruby/internal/anyargs.h:252:41: note: in definition of macro 'RBIMPL_ANYARGS_DECL' 
   252 | RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ 
       |                                           ^~~ 
 object.c:1605:1: note: 'rb_false_to_s' declared here 
  1605 | rb_false_to_s(VALUE obj) 
       | ^~~~~~~~~~~~~ 
 At top level: 
 cc1: note: unrecognized command-line option '-Wno-self-assign' may have been intended to silence earlier diagnostics 
 cc1: note: unrecognized command-line option '-Wno-parentheses-equality' may have been intended to silence earlier diagnostics 
 cc1: note: unrecognized command-line option '-Wno-constant-logical-operand' may have been intended to silence earlier diagnostics 
 make: *** [Makefile:464: object.o] Error 1 
 ``` 

 This also happens for C method that takes a large number of arguments. 

 This is because in C23 `void foo();` no longers means "foo takes an unspecified number of arguments", and there is no way to implement a working `ANYARGS` AFAIK. 

 Not something people would run into in practice, I hope. 

 (related: #21286 but this one is not Windows specific)

Back