summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2019-08-28 17:11:23 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2019-08-29 18:34:09 +0900
commit9ef51b0b89a10c8c401cb9f2337e47a25be72cbe (patch)
tree511f7b67ffb9a22c9028aef0c9f4346835348578 /class.c
parent48e346a088395924298163941d4b4cdd8243e377 (diff)
drop-in type check for rb_define_method
The rb_define_method function takes a pointer to ANYARGS-ed functions, which in fact varies 18 different prototypes. We still need to preserve ANYARGS for storages but why not check the consistencies if possible. Q&As: Q: Where did the magic number "18" came from in the description above? A: Count the case branch of vm_method.c:call_cfunc_invoker_func(). Note also that the 18 branches has lasted for at least 25 years. See also 200e0ee2fd3c1c006c528874a88f684447215524. Q: What is this __weakref__ thing? A: That is a kind of function overloading mechanism that GCC provides. In this case for instance rb_define_method0 is an alias of rb_define_method, with a strong type. Q: What is this __transparent_union__ thing? A: That is another kind of function overloading mechanism that GCC provides. In this case the attributed function pointer is either VALUE(*)(int,VALUE*,VALUE) or VALUE(*)(int,const VALUE*,VALUE). This is better than void* or ANYARGS because we can reject all other possibilities than the two. Q: What does this rb_define_method macro mean? A: It selects appropriate alias of the rb_define_method function, depending on the arity. Q: Why the prototype change of rb_f_notimplement? A: Function pointer to rb_f_notimplement is special cased in vm_method.c:rb_add_method_cfunc(). That should be handled by the __builtin_choose_expr chain inside of rb_define_method macro expansion. In order to do so, comparison like (func == rb_f_notimplement) is inappropriate for __builtin_choose_expr's expression (which must be a compile-time integer constant but the address of rb_f_notimplement is not fixed until the linker). So instead we are using __builtin_types_compatible_p, and in doing so we need to distinguish rb_f_notimplement from others, by type.
Diffstat (limited to 'class.c')
-rw-r--r--class.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/class.c b/class.c
index c9f36c8..f35e9bb 100644
--- a/class.c
+++ b/class.c
@@ -1540,6 +1540,9 @@ rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
rb_add_method_cfunc(klass, mid, func, argc, METHOD_VISI_PUBLIC);
}
+#ifdef rb_define_method
+#undef rb_define_method
+#endif
void
rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{