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

ruby-changes:20638

From: nobu <ko1@a...>
Date: Wed, 27 Jul 2011 01:05:48 +0900 (JST)
Subject: [ruby-changes:20638] nobu:r32686 (trunk): * eval_error.c (rb_print_undef_str): new function to raise

nobu	2011-07-27 01:05:35 +0900 (Wed, 27 Jul 2011)

  New Revision: 32686

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

  Log:
    * eval_error.c (rb_print_undef_str): new function to raise
      NameError for undefined method.
    * load.c (rb_mod_autoload_p), object.c (rb_mod_const_get),
      variable.c (rb_f_untrace_var, set_const_visibility), vm_method.c
      (rb_mod_{remove,undef,alias}_method, set_method_visibility):
      remove inadvertent symbol creation.  based on the first patch by
      Jeremy Evans at [ruby-core:38447].  [Feature #5089]

  Modified files:
    trunk/ChangeLog
    trunk/eval_error.c
    trunk/eval_intern.h
    trunk/load.c
    trunk/object.c
    trunk/proc.c
    trunk/test/ruby/test_module.rb
    trunk/test/ruby/test_symbol.rb
    trunk/variable.c
    trunk/vm_method.c

Index: eval_intern.h
===================================================================
--- eval_intern.h	(revision 32685)
+++ eval_intern.h	(revision 32686)
@@ -198,9 +198,12 @@
 VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
 VALUE rb_make_exception(int argc, VALUE *argv);
 
+NORETURN(void rb_method_name_error(VALUE, VALUE));
+
 NORETURN(void rb_fiber_start(void));
 
 NORETURN(void rb_print_undef(VALUE, ID, int));
+NORETURN(void rb_print_undef_str(VALUE, VALUE));
 NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
 NORETURN(void rb_vm_jump_tag_but_local_jump(int, VALUE));
 NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 32685)
+++ ChangeLog	(revision 32686)
@@ -1,5 +1,14 @@
-Wed Jul 27 01:05:28 2011  Nobuyoshi Nakada  <nobu@r...>
+Wed Jul 27 01:05:32 2011  Nobuyoshi Nakada  <nobu@r...>
 
+	* eval_error.c (rb_print_undef_str): new function to raise
+	  NameError for undefined method.
+
+	* load.c (rb_mod_autoload_p), object.c (rb_mod_const_get),
+	  variable.c (rb_f_untrace_var, set_const_visibility), vm_method.c
+	  (rb_mod_{remove,undef,alias}_method, set_method_visibility):
+	  remove inadvertent symbol creation.  based on the first patch by
+	  Jeremy Evans at [ruby-core:38447].  [Feature #5089]
+
 	* vm_method.c (obj_respond_to): fix the respond_to_missing? override
 	  case.  based on the patch by Jeremy Evans at [ruby-core:38417].
 	  [Feature #5072]
Index: variable.c
===================================================================
--- variable.c	(revision 32685)
+++ variable.c	(revision 32686)
@@ -634,7 +634,10 @@
 
     rb_secure(4);
     rb_scan_args(argc, argv, "11", &var, &cmd);
-    id = rb_to_id(var);
+    id = rb_check_id(&var);
+    if (!id) {
+	rb_name_error_str(var, "undefined global variable %s", RSTRING_PTR(var));
+    }
     if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
 	rb_name_error(id, "undefined global variable %s", rb_id2name(id));
     }
@@ -1972,7 +1975,11 @@
     }
 
     for (i = 0; i < argc; i++) {
-	id = rb_to_id(argv[i]);
+	VALUE val = argv[i];
+	id = rb_check_id(&val);
+	if (!id) {
+	    rb_name_error_str(val, "constant %s::%s not defined", rb_class2name(mod), RSTRING_PTR(val));
+	}
 	if (RCLASS_CONST_TBL(mod) && st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) {
 	    ((rb_const_entry_t*)v)->flag = flag;
 	    return;
Index: eval_error.c
===================================================================
--- eval_error.c	(revision 32685)
+++ eval_error.c	(revision 32686)
@@ -206,6 +206,15 @@
 		  rb_class2name(klass));
 }
 
+void
+rb_print_undef_str(VALUE klass, VALUE name)
+{
+    rb_name_error_str(name, "undefined method `%s' for %s `%s'",
+		      RSTRING_PTR(name),
+		      (TYPE(klass) == T_MODULE) ? "module" : "class",
+		      rb_class2name(klass));
+}
+
 static int
 sysexit_status(VALUE err)
 {
Index: object.c
===================================================================
--- object.c	(revision 32685)
+++ object.c	(revision 32686)
@@ -35,6 +35,7 @@
 
 static ID id_eq, id_eql, id_match, id_inspect;
 static ID id_init_copy, id_init_clone, id_init_dup;
+static ID id_const_missing;
 
 /*
  *  call-seq:
@@ -1774,7 +1775,23 @@
     else {
 	rb_scan_args(argc, argv, "11", &name, &recur);
     }
-    id = rb_to_id(name);
+    id = rb_check_id(&name);
+    if (!id) {
+	if (!rb_is_const_name(name)) {
+	    rb_name_error_str(name, "wrong constant name %s", RSTRING_PTR(name));
+	}
+	else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
+	    id = rb_to_id(name);
+	}
+	else if (mod && rb_class_real(mod) != rb_cObject) {
+	    rb_name_error_str(name, "uninitialized constant %s::%s",
+			      rb_class2name(mod),
+			      RSTRING_PTR(name));
+	}
+	else {
+	    rb_name_error_str(name, "uninitialized constant %s", RSTRING_PTR(name));
+	}
+    }
     if (!rb_is_const_id(id)) {
 	rb_name_error(id, "wrong constant name %s", rb_id2name(id));
     }
@@ -2813,6 +2830,7 @@
     id_init_copy = rb_intern("initialize_copy");
     id_init_clone = rb_intern("initialize_clone");
     id_init_dup = rb_intern("initialize_dup");
+    id_const_missing = rb_intern("const_missing");
 
     for (i=0; conv_method_names[i].method; i++) {
 	conv_method_names[i].id = rb_intern(conv_method_names[i].method);
Index: load.c
===================================================================
--- load.c	(revision 32685)
+++ load.c	(revision 32686)
@@ -705,7 +705,11 @@
 static VALUE
 rb_mod_autoload_p(VALUE mod, VALUE sym)
 {
-    return rb_autoload_p(mod, rb_to_id(sym));
+    ID id = rb_check_id(&sym);
+    if (!id) {
+	return Qnil;
+    }
+    return rb_autoload_p(mod, id);
 }
 
 /*
Index: proc.c
===================================================================
--- proc.c	(revision 32685)
+++ proc.c	(revision 32686)
@@ -1144,7 +1144,7 @@
     return data->me->klass;
 }
 
-static void
+void
 rb_method_name_error(VALUE klass, VALUE str)
 {
     const char *s0 = " class";
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 32685)
+++ vm_method.c	(revision 32686)
@@ -485,7 +485,13 @@
     int i;
 
     for (i = 0; i < argc; i++) {
-	remove_method(mod, rb_to_id(argv[i]));
+	VALUE v = argv[i];
+	ID id = rb_check_id(&v);
+	if (!id) {
+	    rb_name_error_str(v, "method `%s' not defined in %s",
+			      RSTRING_PTR(v), rb_class2name(mod));
+	}
+	remove_method(mod, id);
     }
     return mod;
 }
@@ -693,7 +699,12 @@
 {
     int i;
     for (i = 0; i < argc; i++) {
-	rb_undef(mod, rb_to_id(argv[i]));
+	VALUE v = argv[i];
+	ID id = rb_check_id(&v);
+	if (!id) {
+	    rb_method_name_error(mod, v);
+	}
+	rb_undef(mod, id);
     }
     return mod;
 }
@@ -952,7 +963,11 @@
 static VALUE
 rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
 {
-    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
+    ID oldid = rb_check_id(&oldname);
+    if (!oldid) {
+	rb_print_undef_str(mod, oldname);
+    }
+    rb_alias(mod, rb_to_id(newname), oldid);
     return mod;
 }
 
@@ -971,7 +986,12 @@
     int i;
     secure_visibility(self);
     for (i = 0; i < argc; i++) {
-	rb_export_method(self, rb_to_id(argv[i]), ex);
+	VALUE v = argv[i];
+	ID id = rb_check_id(&v);
+	if (!id) {
+	    rb_print_undef_str(self, v);
+	}
+	rb_export_method(self, id, ex);
     }
     rb_clear_cache_by_class(self);
 }
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 32685)
+++ test/ruby/test_module.rb	(revision 32686)
@@ -472,6 +472,9 @@
     assert_raise(NameError) { c2::Bar }
     assert_raise(NameError) { c2.const_get(:Bar) }
     assert_raise(NameError) { c2.const_get(:Bar, false) }
+    assert_raise(NameError) { c2.const_get("Bar", false) }
+    assert_raise(NameError) { c2.const_get("BaR11", false) }
+    assert_raise(NameError) { Object.const_get("BaR11", false) }
 
     c1.instance_eval do
       def const_missing(x)
@@ -483,7 +486,12 @@
     assert_equal(:Bar, c2::Bar)
     assert_equal(:Bar, c2.const_get(:Bar))
     assert_equal(:Bar, c2.const_get(:Bar, false))
+    assert_equal(:Bar, c2.const_get("Bar"))
+    assert_equal(:Bar, c2.const_get("Bar", false))
 
+    v = c2.const_get("Bar11", false)
+    assert_equal("Bar11".to_sym, v)
+
     assert_raise(NameError) { c1.const_get(:foo) }
   end
 
Index: test/ruby/test_symbol.rb
===================================================================
--- test/ruby/test_symbol.rb	(revision 32685)
+++ test/ruby/test_symbol.rb	(revision 32686)
@@ -197,4 +197,37 @@
       assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
     end
   end
+
+  def test_no_inadvertent_symbol_creation3
+    feature5089 = '[ruby-core:38447]'
+    c = Class.new do
+      def self.alias_method(str)
+        super(:puts, str)
+      end
+    end
+    s = "gadzoooks"
+    {:alias_method => ["#{s}1", NameError],
+     :autoload? => ["#{s}2", nil],
+     :const_get => ["A#{s}3", NameError],
+     :private_class_method => ["#{s}4", NameError],
+     :private_constant => ["#{s}5", NameError],
+     :private => ["#{s}6", NameError],
+     :protected => ["#{s}7", NameError],
+     :public => ["#{s}8", NameError],
+     :public_class_method => ["#{s}9", NameError],
+     :public_constant => ["#{s}10", NameError],
+     :remove_method => ["#{s}11", NameError],
+     :undef_method => ["#{s}12", NameError],
+     :untrace_var => ["#{s}13", NameError],
+    }.each do |meth, arr|
+      str, ret = arr
+      msg = "#{meth}(#{str}) #{feature5089}"
+      if ret.is_a?(Class) && (ret < Exception)
+        assert_raises(ret){c.send(meth, str)}
+      else
+        assert(c.send(meth, str) == ret, msg)
+      end
+      assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
+    end
+  end
 end

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

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