[前][次][番号順一覧][スレッド一覧]

ruby-changes:57603

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Fri, 6 Sep 2019 16:12:45 +0900 (JST)
Subject: [ruby-changes:57603] a569bc09e2 (master): add include/ruby/backward/cxxanyargs.hpp

https://git.ruby-lang.org/ruby.git/commit/?id=a569bc09e2

From a569bc09e25a2ba813d0bec1228d9ff65330a3db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Thu, 5 Sep 2019 23:50:45 +0900
Subject: add include/ruby/backward/cxxanyargs.hpp

Compilation of extension libraries written in C++ are reportedly
broken due to https://github.com/ruby/ruby/pull/2404

The root cause of this issue was that the definition of ANYARGS
differ between C and C++, and that of C++ is incompatible with the
updated ones.

We are using the incompatibility against itself.  In C++ two distinct
function prototypes can be overloaded.  We provide the old, ANYARGSed
prototypes in addition to the current granular ones; and let the
older ones warn about types.

diff --git a/eval.c b/eval.c
index eb34c35..1b62498 100644
--- a/eval.c
+++ b/eval.c
@@ -948,12 +948,26 @@ VALUE https://github.com/ruby/ruby/blob/trunk/eval.c#L948
 rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
            VALUE (* r_proc) (VALUE, VALUE), VALUE data2, ...)
 {
+    va_list ap;
+    va_start(ap, data2);
+    return rb_vrescue2(b_proc, data1, r_proc, data2, ap);
+    va_end(ap);
+}
+
+/*!
+ * \copydoc rb_rescue2
+ * \param[in] args exception classes, terminated by 0.
+ */
+VALUE
+rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
+            VALUE (* r_proc) (VALUE, VALUE), VALUE data2,
+            va_list args)
+{
     enum ruby_tag_type state;
     rb_execution_context_t * volatile ec = GET_EC();
     rb_control_frame_t *volatile cfp = ec->cfp;
     volatile VALUE result = Qfalse;
     volatile VALUE e_info = ec->errinfo;
-    va_list args;
 
     EC_PUSH_TAG(ec);
     if ((state = EC_EXEC_TAG()) == TAG_NONE) {
@@ -976,14 +990,12 @@ rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1, https://github.com/ruby/ruby/blob/trunk/eval.c#L990
 	    int handle = FALSE;
 	    VALUE eclass;
 
-	    va_init_list(args, data2);
 	    while ((eclass = va_arg(args, VALUE)) != 0) {
 		if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
 		    handle = TRUE;
 		    break;
 		}
 	    }
-	    va_end(args);
 
 	    if (handle) {
 		result = Qnil;
diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp
new file mode 100644
index 0000000..70191a9
--- /dev/null
+++ b/include/ruby/backward/cxxanyargs.hpp
@@ -0,0 +1,376 @@ https://github.com/ruby/ruby/blob/trunk/include/ruby/backward/cxxanyargs.hpp#L1
+#ifndef RUBY_BACKWARD_CXXANYARGS_HPP // -*- C++ -*-
+#define RUBY_BACKWARD_CXXANYARGS_HPP
+/// @file
+/// @brief      Provides old prototypes for C++ programs.
+/// @author     \@shyouhei
+/// @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.
+/// @note       DO NOT  MODERNIZE THIS FILE!   As the  file name implies  it is
+///             meant to  be a backwards  compatibility shim.  Please  stick to
+///             C++ 98 and never use newer features, like `constexpr`.
+
+/// @brief  The main namespace.
+/// @note   The name  "ruby" might  already be  taken, but that  must not  be a
+///         problem because namespaces are allowed to reopen.
+namespace ruby {
+
+/// @brief  Backwards compatibility layer.
+namespace backward {
+
+/// @brief  Provides ANYARGS deprecation warnings.
+///
+/// In C,  ANYARGS means there  is no function prototype.   Literally anything,
+/// even including  nothing, can be  a valid  ANYARGS.  So passing  a correctly
+/// prototyped function pointer  to an ANYARGS-ed function  parameter is valid,
+/// at the same time passing an ANYARGS-ed function pointer to a granular typed
+/// function  parameter is  also  valid.  However  on the  other  hand in  C++,
+/// ANYARGS doesn't actually mean any number of arguments.  C++'s ANYARGS means
+/// _variadic_ number of arguments.  This is incompatible with ordinal, correct
+/// function prototypes.
+///
+/// Luckily, function  prototypes being distinct  each other means they  can be
+/// overloaded.  We can provide a compatibility layer for older Ruby APIs which
+/// used to have ANYARGS.  This namespace includes such attempts.
+namespace cxxanyargs {
+
+/// @brief ANYARGS-ed function type.
+typedef VALUE type(ANYARGS);
+
+/// @brief ANYARGS-ed function type, void variant.
+typedef void void_type(ANYARGS);
+
+/// @brief ANYARGS-ed function type, int variant.
+typedef int int_type(ANYARGS);
+
+/// @name Hooking global variables
+/// @{
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       Define a function-backended global variable.
+/// @param[in]   q  Name of the variable.
+/// @param[in]   w  Getter function.
+/// @param[in]   e  Setter function.
+/// @note        Both functions can be nullptr.
+/// @see         rb_define_hooked_variable()
+/// @deprecated  Use glanular typed overload instead.
+inline void
+rb_define_virtual_variable(const char *q, type *w, void_type *e)
+{
+    rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t*>(w);
+    rb_gvar_setter_t *t = reinterpret_cast<rb_gvar_setter_t*>(e);
+    ::rb_define_virtual_variable(q, r, t);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       Define a function-backended global variable.
+/// @param[in]   q  Name of the variable.
+/// @param[in]   w  Variable storage.
+/// @param[in]   e  Getter function.
+/// @param[in]   r  Setter function.
+/// @note        Both functions can be nullptr.
+/// @see         rb_define_virtual_variable()
+/// @deprecated  Use glanular typed overload instead.
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
+{
+    rb_gvar_getter_t *t = reinterpret_cast<rb_gvar_getter_t*>(e);
+    rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t*>(r);
+    ::rb_define_hooked_variable(q, w, t, y);
+}
+
+/// @}
+/// @name Exceptions and tag jumps
+/// @{
+
+DEPRECATED_BY(::rb_block_call,)
+/// @brief       Old way to implement iterators.
+/// @param[in]   q  A function that can yield.
+/// @param[in]   w  Passed to `q`.
+/// @param[in]   e  What is to be yielded.
+/// @param[in]   r  Passed to `e`.
+/// @return      The return value of `q`.
+/// @note        `e` can be nullptr.
+/// @deprecated  This function is obsolated since  long before 2.x era.  Do not
+///              use it any longer.  rb_block_call() is provided instead.
+inline VALUE
+rb_iterate(VALUE(*q)(VALUE), VALUE w, type *e, VALUE r)
+{
+    rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e);
+    return ::rb_iterate(q, w, t, r);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       Call a method with a block.
+/// @param[in]   q  The self.
+/// @param[in]   w  The method.
+/// @param[in]   e  The 3 of elems of `r`
+/// @param[in]   r  The arguments.
+/// @param[in]   t  What is to be yielded.
+/// @param[in]   y  Passed to `t`
+/// @return      Return value of `q#w(*r,&t)`
+/// @note        't' can be nullptr.
+/// @deprecated  Use glanular typed overload instead.
+inline VALUE
+rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
+{
+    rb_block_call_func_t u = reinterpret_cast<rb_block_call_func_t>(t);
+    return ::rb_block_call(q, w, e, r, u, y);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       An equivalent of `rescue` clause.
+/// @param[in]   q  A function that can raise.
+/// @param[in]   w  Passed to `q`.
+/// @param[in]   e  A function that cleans-up.
+/// @param[in]   r  Passed to `e`.
+/// @return      The return value of `q` if  no exception occurs, or the return
+///              value of `e` if otherwise.
+/// @note        `e` can be nullptr.
+/// @see         rb_ensure()
+/// @see         rb_rescue2()
+/// @see         rb_protect()
+/// @deprecated  Use glanular typed overload instead.
+inline VALUE
+rb_rescue(type *q, VALUE w, type *e, VALUE r)
+{
+    typedef VALUE func1_t(VALUE);
+    typedef VALUE func2_t(VALUE, VALUE);
+    func1_t *t = reinterpret_cast<func1_t*>(q);
+    func2_t *y = reinterpret_cast<func2_t*>(e);
+    return ::rb_rescue(t, w, y, r);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       An equivalent of `rescue` clause.
+/// @param[in]   q    A function that can raise.
+/// @param[in]   w    Passed to `q`.
+/// @param[in]   e    A function that cleans-up.
+/// @param[in]   r    Passed to `e`.
+/// @param[in]   ...  0-terminated list of subclass of @ref rb_eException.
+/// @return      The return value of `q` if  no exception occurs, or the return
+///              value of `e` if otherwise.
+/// @note        `e` can be nullptr.
+/// @see         rb_ensure()
+/// @see         rb_rescue()
+/// @see         rb_protect()
+/// @deprecated  Use glanular typed overload instead.
+inline VALUE
+rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...)
+{
+    typedef VALUE func1_t(VALUE);
+    typedef VALUE func2_t(VALUE, VALUE);
+    func1_t *t = reinterpret_cast<func1_t*>(q);
+    func2_t *y = reinterpret_cast<func2_t*>(e);
+    va_list ap;
+    va_start(ap, r);
+    return ::rb_vrescue2(t, w, y, r, ap);
+    va_end(ap);
+}
+
+DEPRECATED_TYPE(("Use of ANYARGS in this function is deprected"),)
+/// @brief       An equivalent of `ensure` clause.
+/// @param[in]   q  A function that can raise.
+/// @param[in]   w  Passed to `q`.
+/// @param[in]   e  A function that ensures.
+/// @param[in]   r  Passed to `e`.
+/// @return      The return value of `q`.
+/// @note        It makes no sense to pass nullptr to `e`.
+/// @see         rb_rescue()
+/// @see         rb_rescue2()
+/// @see         rb_protect()
+/// @deprecated  Use glanular typed overload instead.
+inline VALUE
+rb_ensure(type *q, VALUE w, type *e, VALUE r)
+{
+    typedef VALUE func1_t(VALUE);
+    func1_t *t = reinterpret_cast<func1_t*>(q);
+    func1_t * (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]