summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--error.c109
-rw-r--r--internal.h1
-rw-r--r--test/ruby/test_exception.rb16
-rw-r--r--vm_eval.c20
4 files changed, 80 insertions, 66 deletions
diff --git a/error.c b/error.c
index c8b9404c63..6dce0c8601 100644
--- a/error.c
+++ b/error.c
@@ -916,6 +916,15 @@ rb_exc_new_str(VALUE etype, VALUE str)
return rb_class_new_instance(1, &str, etype);
}
+static VALUE
+exc_init(VALUE exc, VALUE mesg)
+{
+ rb_ivar_set(exc, id_mesg, mesg);
+ rb_ivar_set(exc, id_bt, Qnil);
+
+ return exc;
+}
+
/*
* call-seq:
* Exception.new(msg = nil) -> exception
@@ -930,10 +939,7 @@ exc_initialize(int argc, VALUE *argv, VALUE exc)
VALUE arg;
rb_scan_args(argc, argv, "01", &arg);
- rb_ivar_set(exc, id_mesg, arg);
- rb_ivar_set(exc, id_bt, Qnil);
-
- return exc;
+ return exc_init(exc, arg);
}
/*
@@ -1421,7 +1427,17 @@ rb_name_error_str(VALUE str, const char *fmt, ...)
rb_exc_raise(exc);
}
-static VALUE name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options);
+static VALUE
+name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
+{
+ const rb_execution_context_t *ec = GET_EC();
+ rb_control_frame_t *cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp);
+ cfp = rb_vm_get_ruby_level_next_cfp(ec, cfp);
+ rb_ivar_set(exc, id_name, method);
+ if (recv != Qundef) rb_ivar_set(exc, id_receiver, recv);
+ if (cfp) rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
+ return exc;
+}
/*
* call-seq:
@@ -1435,40 +1451,32 @@ static VALUE name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALU
static VALUE
name_err_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE options;
- argc = rb_scan_args(argc, argv, "*:", NULL, &options);
- return name_err_initialize_options(argc, argv, self, options);
-}
-
-static VALUE
-name_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options)
-{
ID keywords[1];
- VALUE values[numberof(keywords)];
- VALUE name;
- VALUE iseqw = Qnil;
- int i;
+ VALUE values[numberof(keywords)], name, options;
+ argc = rb_scan_args(argc, argv, "*:", NULL, &options);
keywords[0] = id_receiver;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
name = (argc > 1) ? argv[--argc] : Qnil;
rb_call_super(argc, argv);
- rb_ivar_set(self, id_name, name);
- for (i = 0; i < numberof(keywords); ++i) {
- if (values[i] != Qundef) {
- rb_ivar_set(self, keywords[i], values[i]);
- }
- }
- {
- const rb_execution_context_t *ec = GET_EC();
- rb_control_frame_t *cfp =
- rb_vm_get_ruby_level_next_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
- if (cfp) iseqw = rb_iseqw_new(cfp->iseq);
- }
- rb_ivar_set(self, id_iseq, iseqw);
+ name_err_init_attr(self, values[0], name);
return self;
}
+static VALUE
+name_err_init(VALUE exc, VALUE mesg, VALUE recv, VALUE method)
+{
+ exc_init(exc, rb_name_err_mesg_new(mesg, recv, method));
+ return name_err_init_attr(exc, recv, method);
+}
+
+VALUE
+rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
+{
+ VALUE exc = rb_obj_alloc(rb_eNameError);
+ return name_err_init(exc, mesg, recv, method);
+}
+
/*
* call-seq:
* name_error.name -> string or nil
@@ -1506,7 +1514,13 @@ name_err_local_variables(VALUE self)
return vars;
}
-static VALUE nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options);
+static VALUE
+nometh_err_init_attr(VALUE exc, VALUE args, int priv)
+{
+ rb_ivar_set(exc, id_args, args);
+ rb_ivar_set(exc, id_private_call_p, priv ? Qtrue : Qfalse);
+ return exc;
+}
/*
* call-seq:
@@ -1521,20 +1535,22 @@ static VALUE nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VA
static VALUE
nometh_err_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE options;
+ int priv;
+ VALUE args, options;
argc = rb_scan_args(argc, argv, "*:", NULL, &options);
- return nometh_err_initialize_options(argc, argv, self, options);
+ priv = (argc > 3) && (--argc, RTEST(argv[argc]));
+ args = (argc > 2) ? argv[--argc] : Qnil;
+ if (!NIL_P(options)) argv[argc++] = options;
+ rb_call_super(argc, argv);
+ return nometh_err_init_attr(self, args, priv);
}
-static VALUE
-nometh_err_initialize_options(int argc, VALUE *argv, VALUE self, VALUE options)
+VALUE
+rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv)
{
- VALUE priv = (argc > 3) && (--argc, RTEST(argv[argc])) ? Qtrue : Qfalse;
- VALUE args = (argc > 2) ? argv[--argc] : Qnil;
- name_err_initialize_options(argc, argv, self, options);
- rb_ivar_set(self, id_args, args);
- rb_ivar_set(self, id_private_call_p, priv);
- return self;
+ VALUE exc = rb_obj_alloc(rb_eNoMethodError);
+ name_err_init(exc, mesg, recv, method);
+ return nometh_err_init_attr(exc, args, priv);
}
/* :nodoc: */
@@ -1584,17 +1600,6 @@ rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
return result;
}
-VALUE
-rb_name_err_new(VALUE mesg, VALUE recv, VALUE method)
-{
- VALUE exc = rb_obj_alloc(rb_eNameError);
- rb_ivar_set(exc, id_mesg, rb_name_err_mesg_new(mesg, recv, method));
- rb_ivar_set(exc, id_bt, Qnil);
- rb_ivar_set(exc, id_name, method);
- rb_ivar_set(exc, id_receiver, recv);
- return exc;
-}
-
/* :nodoc: */
static VALUE
name_err_mesg_equal(VALUE obj1, VALUE obj2)
diff --git a/internal.h b/internal.h
index 9b6a213151..cc5f4b7e99 100644
--- a/internal.h
+++ b/internal.h
@@ -1220,6 +1220,7 @@ VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
rb_exc_raise(rb_name_err_new(mesg, recv, name))
#define rb_name_err_raise(mesg, recv, name) \
rb_name_err_raise_str(rb_fstring_cstr(mesg), (recv), (name))
+VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
#define rb_key_err_raise(mesg, recv, name) \
rb_exc_raise(rb_key_err_new(mesg, recv, name))
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 43115de3bd..8dafa45120 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -1320,4 +1320,20 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end;
assert_in_out_err([], code, [], /Bug14566/, success: false, timeout: 1)
end
+
+ def test_super_in_method_missing
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Object
+ def method_missing(name, *args, &block)
+ super
+ end
+ end
+
+ bug14670 = '[ruby-dev:50522] [Bug #14670]'
+ assert_raise_with_message(NoMethodError, /`foo'/, bug14670) do
+ Object.new.foo
+ end
+ end;
+ end
end
diff --git a/vm_eval.c b/vm_eval.c
index 2fb339c662..e87f9fdac0 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -643,26 +643,18 @@ MJIT_FUNC_EXPORTED VALUE
rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
int argc, const VALUE *argv, int priv)
{
- int n = 0;
- enum {
- arg_mesg,
- arg_name,
- arg_args,
- arg_priv,
- args_size
- };
- VALUE args[args_size];
+ VALUE name = argv[0];
if (!format) {
format = rb_fstring_cstr("undefined method `%s' for %s%s%s");
}
- args[n++] = rb_name_err_mesg_new(format, obj, argv[0]);
- args[n++] = argv[0];
if (exc == rb_eNoMethodError) {
- args[n++] = rb_ary_new4(argc - 1, argv + 1);
- args[n++] = priv ? Qtrue : Qfalse;
+ VALUE args = rb_ary_new4(argc - 1, argv + 1);
+ return rb_nomethod_err_new(format, obj, name, args, priv);
+ }
+ else {
+ return rb_name_err_new(format, obj, name);
}
- return rb_class_new_instance(n, args, exc);
}
#endif /* #ifndef MJIT_HEADER */