summaryrefslogtreecommitdiff
path: root/vm_args.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-27 10:15:47 (GMT)
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-27 10:15:47 (GMT)
commit6115f65d7dd29561710c3e84bb27180e5bab4380 (patch)
tree637d955e548699811e54d3044b9bdfa4113a3ba2 /vm_args.c
parent955c7f0698d2229f72ae9b9d2a49a1cbecb606e9 (diff)
* vm_args.c: fix backtrace location for keyword related exceptions.
For example, the following program def foo(k1: 1); end # line 1 foo(k2: 2) # line 2 causes "unknown keyword: k2 (ArgumentError)". Before this patch, the backtrace location is only line 2. However, error should be located at line 1 (over line 2 in stack trace). This patch fix this problem. * class.c (rb_keyword_error_new): separate exception creation logic from rb_keyword_error(), to use in vm_args.c. * vm_insnhelper.c (rb_arg_error_new): rename to rb_arity_error_new(). * vm_args.c (argument_arity_error): rename to argument_arity_error(). * vm_args.c (arugment_kw_error): added to fix backtrace. * test/ruby/test_keyword.rb: add tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48608 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_args.c')
-rw-r--r--vm_args.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/vm_args.c b/vm_args.c
index 207d3ff..fa91ed6 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -8,6 +8,11 @@
**********************************************************************/
+NORETURN(static void raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc));
+NORETURN(static void argument_arity_error(rb_thread_t *th, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc));
+NORETURN(static void arugment_kw_error(rb_thread_t *th, const rb_iseq_t *iseq, const char *error, const VALUE keys));
+VALUE rb_keyword_error_new(const char *error, VALUE keys); /* class.c */
+
struct args_info {
/* basic args info */
rb_call_info_t *ci;
@@ -359,8 +364,6 @@ make_unused_kw_hash(const ID *passed_keywords, int passed_keyword_len, const VAL
return obj;
}
-void rb_keyword_error(const char *error, VALUE keys);
-
static inline int
args_setup_kw_parameters_lookup(const ID key, VALUE *ptr, const ID * const passed_keywords, VALUE *passed_values, const int passed_keyword_len)
{
@@ -401,7 +404,7 @@ args_setup_kw_parameters(VALUE* const passed_values, const int passed_keyword_le
}
}
- if (missing) rb_keyword_error("missing", missing);
+ if (missing) arugment_kw_error(GET_THREAD(), iseq, "missing", missing);
for (di=0; i<key_num; i++, di++) {
if (args_setup_kw_parameters_lookup(acceptable_keywords[i], &locals[i], passed_keywords, passed_values, passed_keyword_len)) {
@@ -442,7 +445,7 @@ args_setup_kw_parameters(VALUE* const passed_values, const int passed_keyword_le
else {
if (found != passed_keyword_len) {
VALUE keys = make_unused_kw_hash(passed_keywords, passed_keyword_len, passed_values, TRUE);
- rb_keyword_error("unknown", keys);
+ arugment_kw_error(GET_THREAD(), iseq, "unknown", keys);
}
}
@@ -495,29 +498,6 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr)
return ST_CONTINUE;
}
-NORETURN(static void argument_error(const rb_iseq_t *iseq, int miss_argc, int min_argc, int max_argc));
-static void
-argument_error(const rb_iseq_t *iseq, int miss_argc, int min_argc, int max_argc)
-{
- rb_thread_t *th = GET_THREAD();
- VALUE exc = rb_arg_error_new(miss_argc, min_argc, max_argc);
- VALUE at;
-
- if (iseq) {
- vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, Qnil /* self */, Qnil /* klass */, Qnil /* specval*/,
- iseq->iseq_encoded, th->cfp->sp, 0 /* local_size */, 0 /* me */, 0 /* stack_max */);
- at = rb_vm_backtrace_object();
- vm_pop_frame(th);
- }
- else {
- at = rb_vm_backtrace_object();
- }
-
- rb_iv_set(exc, "bt_locations", at);
- rb_funcall(exc, rb_intern("set_backtrace"), 1, at);
- rb_exc_raise(exc);
-}
-
static int
setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, rb_call_info_t * const ci,
VALUE * const locals, const enum arg_setup_type arg_setup_type)
@@ -599,7 +579,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r
args_extend(args, min_argc);
}
else {
- argument_error(iseq, given_argc, min_argc, max_argc);
+ argument_arity_error(th, iseq, given_argc, min_argc, max_argc);
}
}
}
@@ -619,7 +599,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r
given_argc = max_argc;
}
else {
- argument_error(iseq, given_argc, min_argc, max_argc);
+ argument_arity_error(th, iseq, given_argc, min_argc, max_argc);
}
}
@@ -684,6 +664,38 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r
return opt_pc;
}
+static void
+raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc)
+{
+ VALUE at;
+
+ if (iseq) {
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, Qnil /* self */, Qnil /* klass */, Qnil /* specval*/,
+ iseq->iseq_encoded, th->cfp->sp, 0 /* local_size */, 0 /* me */, 0 /* stack_max */);
+ at = rb_vm_backtrace_object();
+ vm_pop_frame(th);
+ }
+ else {
+ at = rb_vm_backtrace_object();
+ }
+
+ rb_iv_set(exc, "bt_locations", at);
+ rb_funcall(exc, rb_intern("set_backtrace"), 1, at);
+ rb_exc_raise(exc);
+}
+
+static void
+argument_arity_error(rb_thread_t *th, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc)
+{
+ raise_argument_error(th, iseq, rb_arity_error_new(miss_argc, min_argc, max_argc));
+}
+
+static void
+arugment_kw_error(rb_thread_t *th, const rb_iseq_t *iseq, const char *error, const VALUE keys)
+{
+ raise_argument_error(th, iseq, rb_keyword_error_new(error, keys));
+}
+
static inline void
vm_caller_setup_arg_splat(rb_control_frame_t *cfp, rb_call_info_t *ci)
{