summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-10-12 17:39:29 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-10-12 17:39:29 +0000
commit37d0c873f6c9fabebf2ea44a28f843a99f082b07 (patch)
tree6369d79547e2579a157548d85e909283e3f45fcb
parent7fa39b27621122b336db3f17ae77bb10a577d1d7 (diff)
parse.y: should not eliminate value nodes
* parse.y (remove_duplicate_keys): should not simply eliminate all value nodes, which may have side effects. [ruby-core:65625] [Bug #10315] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47894 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--parse.y29
-rw-r--r--test/ruby/test_syntax.rb15
3 files changed, 36 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 4e0dca223e..b1955c3582 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Oct 13 02:39:26 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (remove_duplicate_keys): should not simply eliminate all
+ value nodes, which may have side effects.
+ [ruby-core:65625] [Bug #10315]
+
Sun Oct 12 10:39:16 2014 Zachary Scott <e@zzak.io>
* vm.c: [DOC] fix typo by @yui-knk [Fixes GH-738]
diff --git a/parse.y b/parse.y
index 2c3df8f3d1..af0f362847 100644
--- a/parse.y
+++ b/parse.y
@@ -9601,9 +9601,6 @@ append_literal_keys(st_data_t k, st_data_t v, st_data_t h)
{
NODE *node = (NODE *)v;
NODE **result = (NODE **)h;
- node->nd_alen = 2;
- node->nd_next->nd_end = node->nd_next;
- node->nd_next->nd_next = 0;
if (*result)
list_concat(*result, node);
else
@@ -9618,21 +9615,25 @@ remove_duplicate_keys(struct parser_params *parser, NODE *hash)
NODE *result = 0;
while (hash && hash->nd_head && hash->nd_next) {
NODE *head = hash->nd_head;
- VALUE key = 0;
+ NODE *value = hash->nd_next;
+ NODE *next = value->nd_next;
+ VALUE key = (VALUE)head;
st_data_t data;
- if (nd_type(head) == NODE_LIT) {
- key = head->nd_lit;
- if (st_lookup(literal_keys, key, &data)) {
- rb_compile_warn(ruby_sourcefile, nd_line((NODE *)data),
- "duplicated key at line %d ignored: %+"PRIsVALUE,
- nd_line(head), head->nd_lit);
- }
+ hash->nd_alen = 2;
+ value->nd_end = value;
+ value->nd_next = 0;
+ if (nd_type(head) == NODE_LIT &&
+ st_lookup(literal_keys, (key = head->nd_lit), &data)) {
+ rb_compile_warn(ruby_sourcefile, nd_line((NODE *)data),
+ "duplicated key at line %d ignored: %+"PRIsVALUE,
+ nd_line(head), head->nd_lit);
+ head = ((NODE *)data)->nd_next;
+ head->nd_head = block_append(head->nd_head, value->nd_head);
}
else {
- key = (VALUE)head;
+ st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
}
- st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
- hash = hash->nd_next->nd_next;
+ hash = next;
}
st_foreach(literal_keys, append_literal_keys, (st_data_t)&result);
st_free_table(literal_keys);
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 5a7d2f8a62..797d559b02 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -120,6 +120,21 @@ class TestSyntax < Test::Unit::TestCase
assert_raise(ArgumentError) {o.kw(**h)}
h = {"k1"=>11, k2: 12}
assert_raise(TypeError) {o.kw(**h)}
+
+ bug10315 = '[ruby-core:65625] [Bug #10315]'
+ a = []
+ def a.add(x) push(x); x; end
+ def a.f(k:) k; end
+ a.clear
+ r = nil
+ assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), k: a.add(2))")}
+ assert_equal(2, r)
+ assert_equal([1, 2], a, bug10315)
+ a.clear
+ r = nil
+ assert_warn(/duplicated/) {r = eval("a.f({k: a.add(1), k: a.add(2)})")}
+ assert_equal(2, r)
+ assert_equal([1, 2], a, bug10315)
end
def test_keyword_self_reference