Feature #3446
closedunused variable warning
Description
=begin
なかだです。
http://d.hatena.ne.jp/kwatch/20100616/1276650107 にある、未使用
変数に対する警告を実装してみました。
diff --git i/parse.y w/parse.y
index ebe9fef..8dbbacf 100644
--- i/parse.y
+++ w/parse.y
@@ -99,6 +99,7 @@ struct vtable {
struct local_vars {
struct vtable *args;
struct vtable *vars;
- struct vtable *used;
 struct local_vars *prev;
 };
@@ -167,7 +168,7 @@ vtable_included(const struct vtable * tbl, ID id)
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 @@ new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b
 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_push_gen(struct parser_params *parser, int inherit_dvars)
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 @@ static void
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 @@ static int
 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 @@ dyna_push_gen(struct parser_params *parser)
{
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 @@ dyna_pop_1(struct parser_params *parser)
{
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 @@ dyna_in_block_gen(struct parser_params *parser)
 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) { 
 diff --git i/test/ruby/test_rubyoptions.rb w/test/ruby/test_rubyoptions.rb
 index 683677c..0d70357 100644
 --- i/test/ruby/test_rubyoptions.rb
 +++ w/test/ruby/test_rubyoptions.rb
 @@ -415,4 +415,9 @@ class TestRubyOptions < Test::Unit::TestCase
 ensure
 t.close(true) if t
 end
- 
def test_unused_variable 
- 
assert_in_out_err(["-we", "a=1"], "", [], ["-e:1: warning: assigned but unused variable a"]) 
- 
assert_in_out_err(["-we", "1.times do\n a=1\nend"], "", [], ["-e:2: warning: assigned but unused variable a"]) 
- 
end 
 end
 
--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦
=end
        
           Updated by matz (Yukihiro Matsumoto) over 15 years ago
          Updated by matz (Yukihiro Matsumoto) over 15 years ago
          
          
        
        
      
      =begin
まつもと ゆきひろです
In message "Re: [ruby-dev:41620] [Feature:trunk] unused variable warning"
on Wed, 16 Jun 2010 17:44:02 +0900, Nobuyoshi Nakada nobu@ruby-lang.org writes:
|http://d.hatena.ne.jp/kwatch/20100616/1276650107 にある、未使用
|変数に対する警告を実装してみました。
コミットしてくださいませんか。
=end
        
           Updated by nobu (Nobuyoshi Nakada) over 15 years ago
          Updated by nobu (Nobuyoshi Nakada) over 15 years ago
          
          
        
        
      
      - Status changed from Open to Closed
- % Done changed from 0 to 100
=begin
This issue was solved with changeset r28339.
Nobuyoshi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
=end