[Feature:trunk] unused variable warning

e$B$J$+$@$G$9!#e(B

Ruby で変数宣言がほしい、とな? - kなんとかの日記 e$B$K$"$k!"L$;HMQe(B
e$BJQ?t$KBP$9$k7Y9p$r<BAu$7$F$_$^$7$?!#e(B

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

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:41620] [Feature:trunk] unused variable
warning”
on Wed, 16 Jun 2010 17:44:02 +0900, Nobuyoshi N.
[email protected] writes:

|Ruby で変数宣言がほしい、とな? - kなんとかの日記 e$B$K$"$k!"L$;HMQe(B
|e$BJQ?t$KBP$9$k7Y9p$r<BAu$7$F$_$^$7$?!#e(B

e$B%3%_%C%H$7$F$/$@$5$$$^$;$s$+!#e(B

e$B%A%1%C%He(B #3446 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

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.


http://redmine.ruby-lang.org/issues/show/3446