From 47fb01e35bda888642efa577b08c3626a1eb199f Mon Sep 17 00:00:00 2001 From: nobu Date: Sun, 20 Jun 2010 05:41:07 +0000 Subject: [PATCH] * parse.y (shadowing_lvar_gen): get rid of adding extra name for shadowing local variable. [ruby-dev:41628] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@28364 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 ++++++++ parse.y | 61 +++++++++++++++++++++++++++++++---- test/ruby/test_rubyoptions.rb | 6 ++++ version.h | 4 +-- 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7179f3f806..ff18c20005 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Jun 20 14:40:50 2010 Nobuyoshi Nakada + + * parse.y (shadowing_lvar_gen): get rid of adding extra name for + shadowing local variable. [ruby-dev:41628] + Sat Jun 19 11:11:37 2010 Yukihiro Matsumoto * lib/irb.rb: remove double exclamation marks. a patch from Diego @@ -75,6 +80,15 @@ Thu Jun 17 18:37:47 2010 NAKAMURA Usaku * transcode.c (rb_str_encode): should return new string always. fixed #3444. +Wed Jun 16 18:34:54 2010 NAKAMURA Usaku + + * parse.y: ripper needs warn_unused_var(), too. + +Wed Jun 16 18:20:00 2010 Nobuyoshi Nakada + + * parse.y (warn_unused_var): warn unused variables. + [ruby-dev:41620] + Wed Jun 16 15:40:53 2010 NAKAMURA Usaku * error.c (rb_bug): existence of _set_abort_behavior() depends on diff --git a/parse.y b/parse.y index ebe9fef233..2b8bd7ecf9 100644 --- a/parse.y +++ b/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; } } } @@ -8238,7 +8239,6 @@ shadowing_lvar_gen(struct parser_params *parser, ID name) } else if (dvar_defined(name) || local_id(name)) { rb_warningS("shadowing outer local variable - %s", rb_id2name(name)); - vtable_add(lvtbl->vars, name); } } else { @@ -8918,6 +8918,27 @@ new_args_gen(struct parser_params *parser, NODE *m, NODE *o, ID r, NODE *p, ID b } #endif /* !RIPPER */ +#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])); + } +} + static void local_push_gen(struct parser_params *parser, int inherit_dvars) { @@ -8927,6 +8948,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 +8956,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 +9008,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 +9047,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 +9058,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 +9094,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 a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 683677c160..65e692ecc0 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -415,4 +415,10 @@ class TestRubyOptions < Test::Unit::TestCase 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 diff --git a/version.h b/version.h index b90e4d8cb9..4610505832 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #define RUBY_VERSION "1.9.3" -#define RUBY_RELEASE_DATE "2010-06-19" +#define RUBY_RELEASE_DATE "2010-06-20" #define RUBY_PATCHLEVEL -1 #define RUBY_BRANCH_NAME "trunk" @@ -8,7 +8,7 @@ #define RUBY_VERSION_TEENY 1 #define RUBY_RELEASE_YEAR 2010 #define RUBY_RELEASE_MONTH 6 -#define RUBY_RELEASE_DAY 19 +#define RUBY_RELEASE_DAY 20 #include "ruby/version.h"