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

ruby-changes:48610

From: ko1 <ko1@a...>
Date: Thu, 9 Nov 2017 14:22:57 +0900 (JST)
Subject: [ruby-changes:48610] ko1:r60725 (trunk): fix backtrace on argment error.

ko1	2017-11-09 14:22:51 +0900 (Thu, 09 Nov 2017)

  New Revision: 60725

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60725

  Log:
    fix backtrace on argment error.
    
    * vm_backtrace.c (rb_backtrace_use_iseq_first_lineno_for_last_location):
      added. It modifies last location's line as corresponding iseq's first line
      number.
    
    * vm_args.c (raise_argument_error): use added function.

  Modified files:
    trunk/test/ruby/test_method.rb
    trunk/vm_args.c
    trunk/vm_backtrace.c
Index: vm_backtrace.c
===================================================================
--- vm_backtrace.c	(revision 60724)
+++ vm_backtrace.c	(revision 60725)
@@ -585,6 +585,25 @@ rb_backtrace_to_str_ary(VALUE self) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L585
     return bt->strary;
 }
 
+void
+rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
+{
+    const rb_backtrace_t *bt;
+    const rb_iseq_t *iseq;
+    rb_backtrace_location_t *loc;
+
+    GetCoreDataFromValue(self, rb_backtrace_t, bt);
+    VM_ASSERT(bt->backtrace_size > 0);
+
+    loc = &bt->backtrace[bt->backtrace_size - 1];
+    iseq = loc->body.iseq.iseq;
+
+    VM_ASSERT(loc->type == LOCATION_TYPE_ISEQ);
+
+    loc->body.iseq.lineno.lineno = FIX2INT(iseq->body->location.first_lineno);
+    loc->type = LOCATION_TYPE_ISEQ_CALCED;
+}
+
 static VALUE
 location_create(rb_backtrace_location_t *srcloc, void *btobj)
 {
Index: vm_args.c
===================================================================
--- vm_args.c	(revision 60724)
+++ vm_args.c	(revision 60725)
@@ -687,6 +687,8 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L687
     return opt_pc;
 }
 
+void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self); /* vm_backtrace.c */
+
 static void
 raise_argument_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const VALUE exc)
 {
@@ -698,6 +700,7 @@ raise_argument_error(rb_execution_contex https://github.com/ruby/ruby/blob/trunk/vm_args.c#L700
 		      iseq->body->iseq_encoded,
 		      ec->cfp->sp, 0, 0 /* stack_max */);
 	at = rb_ec_backtrace_object(ec);
+	rb_backtrace_use_iseq_first_lineno_for_last_location(at);
 	rb_vm_pop_frame(ec);
     }
     else {
Index: test/ruby/test_method.rb
===================================================================
--- test/ruby/test_method.rb	(revision 60724)
+++ test/ruby/test_method.rb	(revision 60725)
@@ -990,4 +990,31 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L990
     assert_equal('1', obj.foo(1))
     assert_equal('1', obj.bar(1))
   end
+
+  def test_argument_error_location
+    body = <<-'END_OF_BODY'
+    eval <<-'EOS'
+    $line_lambda = __LINE__; $f = lambda do
+      _x = 1
+    end
+    $line_method = __LINE__; def foo
+      _x = 1
+    end
+    begin
+      $f.call(1)
+    rescue ArgumentError => e
+      assert_equal "(eval):#{$line_lambda.to_s}:in `block in <main>'", e.backtrace.first
+    end
+    begin
+      foo(1)
+    rescue ArgumentError => e
+      assert_equal "(eval):#{$line_method}:in `foo'", e.backtrace.first
+    end
+    EOS
+    END_OF_BODY
+
+    assert_separately [], body
+    # without trace insn
+    assert_separately [], "RubyVM::InstructionSequence.compile_option = {trace_instruction: false}\n" + body
+  end
 end

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

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