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

ruby-changes:16362

From: nobu <ko1@a...>
Date: Wed, 16 Jun 2010 18:20:31 +0900 (JST)
Subject: [ruby-changes:16362] Ruby:r28339 (trunk): * parse.y (warn_unused_var): warn unused variables.

nobu	2010-06-16 18:20:14 +0900 (Wed, 16 Jun 2010)

  New Revision: 28339

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=28339

  Log:
    * parse.y (warn_unused_var): warn unused variables.
      [ruby-dev:41620]

  Modified files:
    trunk/ChangeLog
    trunk/parse.y
    trunk/test/ruby/test_rubyoptions.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 28338)
+++ ChangeLog	(revision 28339)
@@ -1,3 +1,8 @@
+Wed Jun 16 18:20:00 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (warn_unused_var): warn unused variables.
+	  [ruby-dev:41620]
+
 Wed Jun 16 15:40:53 2010  NAKAMURA Usaku  <usa@r...>
 
 	* error.c (rb_bug): existance of _set_abort_behavior() depends on
Index: parse.y
===================================================================
--- parse.y	(revision 28338)
+++ parse.y	(revision 28339)
@@ -99,6 +99,7 @@
 struct local_vars {
     struct vtable *args;
     struct vtable *vars;
+    struct vtable *used;
     struct local_vars *prev;
 };
 
@@ -167,7 +168,7 @@
     if (POINTER_P(tbl)) {
         for (i = 0; i < tbl->pos; i++) {
             if (tbl->tbl[i] == id) {
-                return 1;
+                return i+1;
             }
         }
     }
@@ -8916,6 +8917,27 @@
     ruby_sourceline = saved_line;
     return node;
 }
+
+#define LVAR_USED (1UL << (sizeof(ID) * CHAR_BIT - 1))
+
+static void
+warn_unused_var(struct parser_params *parser, struct local_vars *local)
+{
+    int i, cnt;
+    ID *v, *u;
+
+    if (!local->used) return;
+    v = local->vars->tbl;
+    u = local->used->tbl;
+    cnt = local->used->pos;
+    if (cnt != local->vars->pos) {
+	rb_bug("local->used->pos != local->vars->pos");
+    }
+    for (i = 0; i < cnt; ++i) {
+	if (!v[i] || (u[i] & LVAR_USED)) continue;
+	rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable %s", rb_id2name(v[i]));
+    }
+}
 #endif /* !RIPPER */
 
 static void
@@ -8927,6 +8949,7 @@
     local->prev = lvtbl;
     local->args = vtable_alloc(0);
     local->vars = vtable_alloc(inherit_dvars ? DVARS_INHERIT : DVARS_TOPSCOPE);
+    local->used = RTEST(ruby_verbose) ? vtable_alloc(0) : 0;
     lvtbl = local;
 }
 
@@ -8934,6 +8957,10 @@
 local_pop_gen(struct parser_params *parser)
 {
     struct local_vars *local = lvtbl->prev;
+    if (lvtbl->used) {
+	warn_unused_var(parser, lvtbl);
+	vtable_free(lvtbl->used);
+    }
     vtable_free(lvtbl->args);
     vtable_free(lvtbl->vars);
     xfree(lvtbl);
@@ -8982,28 +9009,37 @@
 local_var_gen(struct parser_params *parser, ID id)
 {
     vtable_add(lvtbl->vars, id);
+    if (lvtbl->used) {
+	vtable_add(lvtbl->used, (ID)ruby_sourceline);
+    }
     return vtable_size(lvtbl->vars) - 1;
 }
 
 static int
 local_id_gen(struct parser_params *parser, ID id)
 {
-    struct vtable *vars, *args;
+    struct vtable *vars, *args, *used;
 
     vars = lvtbl->vars;
     args = lvtbl->args;
+    used = lvtbl->used;
 
     while (vars && POINTER_P(vars->prev)) {
 	vars = vars->prev;
 	args = args->prev;
+	if (used) used = used->prev;
     }
 
     if (vars && vars->prev == DVARS_INHERIT) {
 	return rb_local_defined(id);
     }
+    else if (vtable_included(args, id)) {
+	return 1;
+    }
     else {
-	return (vtable_included(args, id) ||
-		vtable_included(vars, id));
+	int i = vtable_included(vars, id);
+	if (i && used) used->tbl[i-1] |= LVAR_USED;
+	return i != 0;
     }
 }
 
@@ -9012,6 +9048,9 @@
 {
     lvtbl->args = vtable_alloc(lvtbl->args);
     lvtbl->vars = vtable_alloc(lvtbl->vars);
+    if (lvtbl->used) {
+	lvtbl->used = vtable_alloc(lvtbl->used);
+    }
     return lvtbl->args;
 }
 
@@ -9020,6 +9059,11 @@
 {
     struct vtable *tmp;
 
+    if ((tmp = lvtbl->used) != 0) {
+	warn_unused_var(parser, lvtbl);
+	lvtbl->used = lvtbl->used->prev;
+	vtable_free(tmp);
+    }
     tmp = lvtbl->args;
     lvtbl->args = lvtbl->args->prev;
     vtable_free(tmp);
@@ -9051,20 +9095,24 @@
 static int
 dvar_defined_gen(struct parser_params *parser, ID id)
 {
-    struct vtable *vars, *args;
+    struct vtable *vars, *args, *used;
+    int i;
 
     args = lvtbl->args;
     vars = lvtbl->vars;
+    used = lvtbl->used;
 
     while (POINTER_P(vars)) {
 	if (vtable_included(args, id)) {
 	    return 1;
 	}
-	if (vtable_included(vars, id)) {
+	if ((i = vtable_included(vars, id)) != 0) {
+	    if (used) used->tbl[i-1] |= LVAR_USED;
 	    return 1;
 	}
 	args = args->prev;
 	vars = vars->prev;
+	if (used) used = used->prev;
     }
 
     if (vars == DVARS_INHERIT) {
Index: test/ruby/test_rubyoptions.rb
===================================================================
--- test/ruby/test_rubyoptions.rb	(revision 28338)
+++ test/ruby/test_rubyoptions.rb	(revision 28339)
@@ -415,4 +415,10 @@
   ensure
     t.close(true) if t
   end
+
+  def test_unused_variable
+    feature3446 = '[ruby-dev:41620]'
+    assert_in_out_err(["-we", "a=1"], "", [], ["-e:1: warning: assigned but unused variable a"], feature3446)
+    assert_in_out_err(["-we", "1.times do\n  a=1\nend"], "", [], ["-e:2: warning: assigned but unused variable a"], feature3446)
+  end
 end

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

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