ruby-changes:23408
From: ko1 <ko1@a...>
Date: Tue, 24 Apr 2012 18:20:52 +0900 (JST)
Subject: [ruby-changes:23408] ko1:r35459 (trunk): * compile.c: fix to output warning when the same literals
ko1 2012-04-24 18:20:42 +0900 (Tue, 24 Apr 2012) New Revision: 35459 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35459 Log: * compile.c: fix to output warning when the same literals are available as a condition of same case clause. And remove infomation ('#n') because we can find duplicated condition with explicit line numbers. [ruby-core:38343] [Ruby 1.9 - Bug #5068] * test/ruby/test_syntax.rb: add a test for above. Modified files: trunk/ChangeLog trunk/compile.c trunk/test/ruby/test_syntax.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 35458) +++ ChangeLog (revision 35459) @@ -1,3 +1,13 @@ +Tue Apr 24 18:12:13 2012 Koichi Sasada <ko1@a...> + + * compile.c: fix to output warning when the same literals + are available as a condition of same case clause. + And remove infomation ('#n') because we can find duplicated + condition with explicit line numbers. + [ruby-core:38343] [Ruby 1.9 - Bug #5068] + + * test/ruby/test_syntax.rb: add a test for above. + Tue Apr 24 17:03:51 2012 NAKAMURA Usaku <usa@r...> * win32/win32.c (waitpid): need to check the return value of Index: compile.c =================================================================== --- compile.c (revision 35458) +++ compile.c (revision 35459) @@ -1309,6 +1309,21 @@ cdhash_hash, }; +struct cdhash_set_label_struct { + VALUE hash; + int pos; + int len; +}; + +static int +cdhash_set_label_i(VALUE key, VALUE val, void *ptr) +{ + struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr; + LABEL *lobj = (LABEL *)(val & ~1); + rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len))); + return ST_CONTINUE; +} + /** ruby insn object list -> raw instruction sequence */ @@ -1427,41 +1442,19 @@ if (lobj->sp == -1) { lobj->sp = sp; } - generated_iseq[pos + 1 + j] = - lobj->position - (pos + len); + generated_iseq[pos + 1 + j] = lobj->position - (pos + len); break; } case TS_CDHASH: { - /* - * [obj, label, ...] - */ - int i; - VALUE lits = operands[j]; - VALUE map = rb_hash_new(); - RHASH_TBL(map)->type = &cdhash_type; + VALUE map = operands[j]; + struct cdhash_set_label_struct data = { + map, pos, len, + }; + rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data); - for (i=0; i < RARRAY_LEN(lits); i+=2) { - VALUE obj = rb_ary_entry(lits, i); - VALUE lv = rb_ary_entry(lits, i+1); - lobj = (LABEL *)(lv & ~1); - - if (!lobj->set) { - rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, - "unknown label"); - } - if (!st_lookup(rb_hash_tbl(map), obj, 0)) { - rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len))); - } - else { - int n = i/2 + 1; - rb_compile_warning(RSTRING_PTR(iseq->filename), iobj->line_no, - "duplicated when clause (#%d) is ignored", n); - } - } hide_obj(map); generated_iseq[pos + 1 + j] = map; - iseq_add_mark_object(iseq, map); break; } case TS_LINDEX: @@ -2428,25 +2421,26 @@ case NODE_STR: return node->nd_lit; } - return Qfalse; + return Qundef; } -static VALUE -when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE special_literals) +static int +when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals) { while (vals) { - VALUE lit; - NODE* val; + NODE* val = vals->nd_head; + VALUE lit = case_when_optimizable_literal(val); - val = vals->nd_head; - - if (special_literals && - (lit = case_when_optimizable_literal(val)) != Qfalse) { - rb_ary_push(special_literals, lit); - rb_ary_push(special_literals, (VALUE)(l1) | 1); + if (lit == Qundef) { + only_special_literals = 0; } else { - special_literals = Qfalse; + if (rb_hash_lookup(literals, lit) != Qnil) { + rb_compile_warning(RSTRING_PTR(iseq->filename), nd_line(val), "duplicated when clause is ignored"); + } + else { + rb_hash_aset(literals, lit, (VALUE)(l1) | 1); + } } if (nd_type(val) == NODE_STR) { @@ -2462,7 +2456,7 @@ ADD_INSNL(cond_seq, nd_line(val), branchif, l1); vals = vals->nd_next; } - return special_literals; + return only_special_literals; } static int @@ -3152,11 +3146,15 @@ DECL_ANCHOR(head); DECL_ANCHOR(body_seq); DECL_ANCHOR(cond_seq); - VALUE special_literals = rb_ary_tmp_new(1); + int only_special_literals = 1; + VALUE literals = rb_hash_new(); INIT_ANCHOR(head); INIT_ANCHOR(body_seq); INIT_ANCHOR(cond_seq); + + RHASH_TBL(literals)->type = &cdhash_type; + if (node->nd_head == 0) { COMPILE_(ret, "when", node->nd_body, poped); break; @@ -3188,12 +3186,12 @@ if (vals) { switch (nd_type(vals)) { case NODE_ARRAY: - special_literals = when_vals(iseq, cond_seq, vals, l1, special_literals); + only_special_literals = when_vals(iseq, cond_seq, vals, l1, only_special_literals, literals); break; case NODE_SPLAT: case NODE_ARGSCAT: case NODE_ARGSPUSH: - special_literals = 0; + only_special_literals = 0; COMPILE(cond_seq, "when/cond splat", vals); ADD_INSN1(cond_seq, nd_line(vals), checkincludearray, Qtrue); ADD_INSNL(cond_seq, nd_line(vals), branchif, l1); @@ -3230,11 +3228,11 @@ ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel); } - if (special_literals) { + if (only_special_literals) { + iseq_add_mark_object(iseq, literals); + ADD_INSN(ret, nd_line(tempnode), dup); - ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, - special_literals, elselabel); - iseq_add_mark_object_compile_time(iseq, special_literals); + ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel); } ADD_SEQ(ret, cond_seq); Index: test/ruby/test_syntax.rb =================================================================== --- test/ruby/test_syntax.rb (revision 35458) +++ test/ruby/test_syntax.rb (revision 35459) @@ -128,6 +128,29 @@ assert_not_label(:foo, 'class Foo < not_label:foo; end', bug6347) end + def test_duplicated_when + w = 'warning: duplicated when clause is ignored' + assert_warn(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){ + eval %q{ + case 1 + when 1, 1 + when 1, 1 + when 1, 1 + end + } + } + assert_warn(/#{w}/){#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){ + a = 1 + eval %q{ + case 1 + when 1, 1 + when 1, a + when 1, 1 + end + } + } + end + private def not_label(x) @result = x; @not_label ||= nil end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/