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

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/

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