summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-22 05:01:32 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-04-22 05:01:32 +0000
commit01828cf45ab6d002b2d9f2907581db5e841cb57f (patch)
tree09daaad900fb9b2839c2c0b1254342762b4e10ed
parent8f93c59ecab7b7279a78324db869f1cac78319d9 (diff)
merge revision(s) 53495: [Backport #11970]
* compile.c (compile_massign_lhs): when index ends with splat, append rhs value to it like POSTARG, since VM_CALL_ARGS_SPLAT splats the last argument only. [ruby-core:72777] [Bug #11970] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@54671 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--compile.c46
-rw-r--r--test/ruby/test_assignment.rb8
-rw-r--r--version.h8
4 files changed, 57 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index f5998e2111..a147d27643 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Fri Apr 22 13:41:38 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * compile.c (compile_massign_lhs): when index ends with splat,
+ append rhs value to it like POSTARG, since VM_CALL_ARGS_SPLAT
+ splats the last argument only. [ruby-core:72777] [Bug #11970]
+
Thu Mar 31 05:06:02 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* sprintf.c (rb_str_format): fix buffer overflow, length must be
diff --git a/compile.c b/compile.c
index a316cbbf0a..e0cc38abd2 100644
--- a/compile.c
+++ b/compile.c
@@ -187,11 +187,20 @@ r_value(VALUE value)
#define ADD_INSN(seq, line, insn) \
ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
+/* insert an instruction before prev */
+#define INSERT_BEFORE_INSN(prev, line, insn) \
+ INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line), BIN(insn), 0))
+
/* add an instruction with some operands (1, 2, 3, 5) */
#define ADD_INSN1(seq, line, insn, op1) \
ADD_ELEM((seq), (LINK_ELEMENT *) \
new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
+/* insert an instruction with some operands (1, 2, 3, 5) before prev */
+#define INSERT_BEFORE_INSN1(prev, line, insn, op1) \
+ INSERT_ELEM_PREV(&(prev)->link, (LINK_ELEMENT *) \
+ new_insn_body(iseq, (line), BIN(insn), 1, (VALUE)(op1)))
+
/* add an instruction with label operand (alias of ADD_INSN1) */
#define ADD_INSNL(seq, line, insn, label) ADD_INSN1(seq, line, insn, label)
@@ -737,6 +746,20 @@ compile_data_alloc_adjust(rb_iseq_t *iseq)
}
/*
+ * elem1, elemX => elemX, elem2, elem1
+ */
+static void
+INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2)
+{
+ elem2->prev = elem1->prev;
+ elem2->next = elem1;
+ elem1->prev = elem2;
+ if (elem2->prev) {
+ elem2->prev->next = elem2;
+ }
+}
+
+/*
* elem1, elemX => elem1, elem2, elemX
*/
static void
@@ -782,6 +805,12 @@ FIRST_ELEMENT(LINK_ANCHOR *anchor)
}
static LINK_ELEMENT *
+LAST_ELEMENT(LINK_ANCHOR *anchor)
+{
+ return anchor->last;
+}
+
+static LINK_ELEMENT *
POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
{
LINK_ELEMENT *elem = anchor->last;
@@ -2663,19 +2692,22 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
INSN *iobj;
rb_call_info_t *ci;
VALUE dupidx;
+ int line = nd_line(node);
COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node);
- POP_ELEMENT(ret); /* pop pop insn */
- iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */
+ iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */
ci = (rb_call_info_t *)iobj->operands[0];
- ci->orig_argc += 1; ci->argc = ci->orig_argc;
+ ci->orig_argc += 1;
dupidx = INT2FIX(ci->orig_argc);
- ADD_INSN1(ret, nd_line(node), topn, dupidx);
- ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
- ADD_INSN(ret, nd_line(node), pop); /* result */
- ADD_INSN(ret, nd_line(node), pop); /* rhs */
+ INSERT_BEFORE_INSN1(iobj, line, topn, dupidx);
+ if (ci->flag & VM_CALL_ARGS_SPLAT) {
+ --ci->orig_argc;
+ INSERT_BEFORE_INSN1(iobj, line, newarray, INT2FIX(1));
+ INSERT_BEFORE_INSN(iobj, line, concatarray);
+ }
+ ADD_INSN(ret, line, pop); /* result */
break;
}
case NODE_MASGN: {
diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb
index 9c0fd48725..81ae3b0d25 100644
--- a/test/ruby/test_assignment.rb
+++ b/test/ruby/test_assignment.rb
@@ -757,4 +757,12 @@ class TestAssignmentGen < Test::Unit::TestCase
o = bug9448.new
assert_equal("ok", o['current'] = "ok")
end
+
+ def test_massign_aref_lhs_splat
+ bug11970 = '[ruby-core:72777] [Bug #11970]'
+ h = {}
+ k = [:key]
+ h[*k], = ["ok", "ng"]
+ assert_equal("ok", h[:key], bug11970)
+ end
end
diff --git a/version.h b/version.h
index 10b5108260..355b8265df 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.2.5"
-#define RUBY_RELEASE_DATE "2016-03-31"
-#define RUBY_PATCHLEVEL 292
+#define RUBY_RELEASE_DATE "2016-04-22"
+#define RUBY_PATCHLEVEL 293
#define RUBY_RELEASE_YEAR 2016
-#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 31
+#define RUBY_RELEASE_MONTH 4
+#define RUBY_RELEASE_DAY 22
#include "ruby/version.h"