diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-28 06:24:12 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-28 06:24:12 +0000 |
commit | 72ff61f4a8ae7a8bf05b0bd6f91b3b290645627c (patch) | |
tree | 731069832b17cffaafc9fdcdd394f1976c7ec576 | |
parent | 7a929727f6a4e45a0ebf0542650ff122b16264ad (diff) | |
download | ruby-72ff61f4a8ae7a8bf05b0bd6f91b3b290645627c.tar.gz |
NameError#receiver of uninitialized constant
* error.c (name_err_mesg_to_str): quote the name if unprintable.
* object.c (check_setter_id): use rb_check_id to convert names.
* variable.c (uninitialized_constant): use NameError::message to
keep the receiver of uninitialized constant. [Feature #10881]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52321 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | error.c | 2 | ||||
-rw-r--r-- | eval_error.c | 60 | ||||
-rw-r--r-- | method.h | 4 | ||||
-rw-r--r-- | object.c | 146 | ||||
-rw-r--r-- | proc.c | 45 | ||||
-rw-r--r-- | range.c | 2 | ||||
-rw-r--r-- | struct.c | 25 | ||||
-rw-r--r-- | test/ruby/test_exception.rb | 4 | ||||
-rw-r--r-- | variable.c | 138 | ||||
-rw-r--r-- | vm_method.c | 8 |
11 files changed, 206 insertions, 237 deletions
@@ -1,4 +1,11 @@ -Wed Oct 28 15:23:14 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> +Wed Oct 28 15:24:09 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * error.c (name_err_mesg_to_str): quote the name if unprintable. + + * object.c (check_setter_id): use rb_check_id to convert names. + + * variable.c (uninitialized_constant): use NameError::message to + keep the receiver of uninitialized constant. [Feature #10881] * error.c (rb_name_err_new): new function to create NameError exception instance. [Feature #10881] @@ -1264,7 +1264,7 @@ name_err_mesg_to_str(VALUE obj) else { c = s = FAKE_CSTR(&s_str, ""); } - args[0] = ptr[NAME_ERR_MESG__NAME]; + args[0] = QUOTE(rb_obj_as_string(ptr[NAME_ERR_MESG__NAME])); args[1] = d; args[2] = s; args[3] = c; diff --git a/eval_error.c b/eval_error.c index e907d7ee88..82a69033b6 100644 --- a/eval_error.c +++ b/eval_error.c @@ -208,47 +208,53 @@ ruby_error_print(void) error_print(); } -static const char * -method_visibility_name(rb_method_visibility_t visi) -{ - switch (visi) { - case METHOD_VISI_UNDEF: - case METHOD_VISI_PUBLIC: return ""; - case METHOD_VISI_PRIVATE: return " private"; - case METHOD_VISI_PROTECTED: return " protected"; - } - rb_bug("method_visibility_name: unreachable (%d)", (int)visi); -} +#define undef_mesg_for(v, k) rb_fstring_cstr("undefined"v" method `%1$s' for "k" `%$s'") +#define undef_mesg(v) ( \ + is_mod ? \ + undef_mesg_for(v, "module") : \ + undef_mesg_for(v, "class")) void rb_print_undef(VALUE klass, ID id, int visi) { - const char *v = method_visibility_name(visi); - - rb_name_error(id, "undefined%s method `%"PRIsVALUE"' for %s `% "PRIsVALUE"'", v, - QUOTE_ID(id), - (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", - rb_class_name(klass)); + const int is_mod = RB_TYPE_P(klass, T_MODULE); + VALUE mesg; + switch (visi & METHOD_VISI_MASK) { + case METHOD_VISI_UNDEF: + case METHOD_VISI_PUBLIC: mesg = undef_mesg(""); break; + case METHOD_VISI_PRIVATE: mesg = undef_mesg(" private"); break; + case METHOD_VISI_PROTECTED: mesg = undef_mesg(" protected"); break; + default: UNREACHABLE; + } + rb_name_err_raise_str(mesg, klass, ID2SYM(id)); } void rb_print_undef_str(VALUE klass, VALUE name) { - rb_name_error_str(name, "undefined method `%"PRIsVALUE"' for %s `% "PRIsVALUE"'", - QUOTE(name), - (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", - rb_class_name(klass)); + const int is_mod = RB_TYPE_P(klass, T_MODULE); + rb_name_err_raise_str(undef_mesg(""), klass, name); } +#define inaccessible_mesg_for(v, k) rb_fstring_cstr("method `%1$s' for "k" `%2$s' is "v) +#define inaccessible_mesg(v) ( \ + is_mod ? \ + inaccessible_mesg_for(v, "module") : \ + inaccessible_mesg_for(v, "class")) + void rb_print_inaccessible(VALUE klass, ID id, rb_method_visibility_t visi) { - const char *v = method_visibility_name(visi); - rb_name_error(id, "method `%"PRIsVALUE"' for %s `% "PRIsVALUE"' is %s", - QUOTE_ID(id), - (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class", - rb_class_name(klass), - v); + const int is_mod = RB_TYPE_P(klass, T_MODULE); + VALUE mesg; + switch (visi & METHOD_VISI_MASK) { + case METHOD_VISI_UNDEF: + case METHOD_VISI_PUBLIC: mesg = inaccessible_mesg(""); break; + case METHOD_VISI_PRIVATE: mesg = inaccessible_mesg(" private"); break; + case METHOD_VISI_PROTECTED: mesg = inaccessible_mesg(" protected"); break; + default: UNREACHABLE; + } + rb_name_err_raise_str(mesg, klass, ID2SYM(id)); } static int @@ -27,7 +27,9 @@ typedef enum { METHOD_VISI_UNDEF = 0x00, METHOD_VISI_PUBLIC = 0x01, METHOD_VISI_PRIVATE = 0x02, - METHOD_VISI_PROTECTED = 0x03 + METHOD_VISI_PROTECTED = 0x03, + + METHOD_VISI_MASK = 0x03 } rb_method_visibility_t; typedef struct rb_scope_visi_struct { @@ -1900,29 +1900,21 @@ rb_class_get_superclass(VALUE klass) return RCLASS(klass)->super; } -#define id_for_setter(name, type, message) \ - check_setter_id(name, rb_is_##type##_sym, rb_is_##type##_name, message) +#define id_for_var(obj, name, part, type) \ + id_for_setter(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name") +#define id_for_setter(obj, name, type, message) \ + check_setter_id(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message)) static ID -check_setter_id(VALUE name, int (*valid_sym_p)(VALUE), int (*valid_name_p)(VALUE), - const char *message) +check_setter_id(VALUE obj, VALUE *pname, + int (*valid_id_p)(ID), int (*valid_name_p)(VALUE), + const char *message, size_t message_len) { - ID id; - if (SYMBOL_P(name)) { - if (!valid_sym_p(name)) { - rb_name_error_str(name, message, QUOTE(rb_sym2str(name))); - } - id = SYM2ID(name); - } - else { - VALUE str = rb_check_string_type(name); - if (NIL_P(str)) { - rb_raise(rb_eTypeError, "% "PRIsVALUE" is not a symbol or string", - name); - } - if (!valid_name_p(str)) { - rb_name_error_str(str, message, QUOTE(str)); - } - id = rb_intern_str(str); + ID id = rb_check_id(pname); + VALUE name = *pname; + + if (id ? !valid_id_p(id) : !valid_name_p(name)) { + rb_name_err_raise_str(rb_fstring_new(message, message_len), + obj, name); } return id; } @@ -1934,17 +1926,20 @@ rb_is_attr_name(VALUE name) } static int -rb_is_attr_sym(VALUE sym) +rb_is_attr_id(ID id) { - return rb_is_local_sym(sym) || rb_is_const_sym(sym); + return rb_is_local_id(id) || rb_is_const_id(id); } -static const char invalid_attribute_name[] = "invalid attribute name `%"PRIsVALUE"'"; +static const char wrong_constant_name[] = "wrong constant name %1$s"; +static const char invalid_attribute_name[] = "invalid attribute name `%1$s'"; static ID -id_for_attr(VALUE name) +id_for_attr(VALUE obj, VALUE name) { - return id_for_setter(name, attr, invalid_attribute_name); + ID id = id_for_setter(obj, name, attr, invalid_attribute_name); + if (!id) id = rb_intern_str(name); + return id; } /* @@ -1966,7 +1961,7 @@ rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass) int i; for (i=0; i<argc; i++) { - rb_attr(klass, id_for_attr(argv[i]), TRUE, FALSE, TRUE); + rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, FALSE, TRUE); } return Qnil; } @@ -1976,7 +1971,7 @@ rb_mod_attr(int argc, VALUE *argv, VALUE klass) { if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) { rb_warning("optional boolean argument is obsoleted"); - rb_attr(klass, id_for_attr(argv[0]), 1, RTEST(argv[1]), TRUE); + rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE); return Qnil; } return rb_mod_attr_reader(argc, argv, klass); @@ -1998,7 +1993,7 @@ rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass) int i; for (i=0; i<argc; i++) { - rb_attr(klass, id_for_attr(argv[i]), FALSE, TRUE, TRUE); + rb_attr(klass, id_for_attr(klass, argv[i]), FALSE, TRUE, TRUE); } return Qnil; } @@ -2026,7 +2021,7 @@ rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass) int i; for (i=0; i<argc; i++) { - rb_attr(klass, id_for_attr(argv[i]), TRUE, TRUE, TRUE); + rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, TRUE, TRUE); } return Qnil; } @@ -2102,7 +2097,7 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) if (p >= pend || !*p) { wrong_name: - rb_name_error_str(name, "wrong constant name % "PRIsVALUE, name); + rb_name_err_raise(wrong_constant_name, mod, name); } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { @@ -2137,8 +2132,8 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) part = rb_str_subseq(name, beglen, len); OBJ_FREEZE(part); if (!ISUPPER(*pbeg) || !rb_is_const_name(part)) { - rb_name_error_str(part, "wrong constant name %"PRIsVALUE, - QUOTE(part)); + name = part; + goto wrong_name; } else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) { part = rb_str_intern(part); @@ -2146,14 +2141,12 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) continue; } else { - rb_name_error_str(part, "uninitialized constant %"PRIsVALUE"% "PRIsVALUE, - rb_str_subseq(name, 0, beglen), - part); + rb_name_err_raise("uninitialized constant %2$s::%1$s", mod, part); } } if (!rb_is_const_id(id)) { - rb_name_error(id, "wrong constant name %"PRIsVALUE, - QUOTE_ID(id)); + name = ID2SYM(id); + goto wrong_name; } mod = RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id); } @@ -2183,7 +2176,8 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod) static VALUE rb_mod_const_set(VALUE mod, VALUE name, VALUE value) { - ID id = id_for_setter(name, const, "wrong constant name %"PRIsVALUE); + ID id = id_for_setter(mod, name, const, wrong_constant_name); + if (!id) id = rb_intern_str(name); rb_const_set(mod, id, value); return value; } @@ -2260,7 +2254,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) if (p >= pend || !*p) { wrong_name: - rb_name_error_str(name, "wrong constant name % "PRIsVALUE, name); + rb_name_err_raise(wrong_constant_name, mod, name); } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { @@ -2290,16 +2284,16 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) part = rb_str_subseq(name, beglen, len); OBJ_FREEZE(part); if (!ISUPPER(*pbeg) || !rb_is_const_name(part)) { - rb_name_error_str(part, "wrong constant name %"PRIsVALUE, - QUOTE(part)); + name = part; + goto wrong_name; } else { return Qfalse; } } if (!rb_is_const_id(id)) { - rb_name_error(id, "wrong constant name %"PRIsVALUE, - QUOTE_ID(id)); + name = ID2SYM(id); + goto wrong_name; } if (RTEST(recur)) { if (!rb_const_defined(mod, id)) @@ -2347,20 +2341,10 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod) static VALUE rb_obj_ivar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = id_for_var(obj, iv, an, instance); if (!id) { - if (rb_is_instance_name(iv)) { - return Qnil; - } - else { - rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE(iv)); - } - } - if (!rb_is_instance_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE_ID(id)); + return Qnil; } return rb_ivar_get(obj, id); } @@ -2391,7 +2375,8 @@ rb_obj_ivar_get(VALUE obj, VALUE iv) static VALUE rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val) { - ID id = id_for_setter(iv, instance, "`%"PRIsVALUE"' is not allowed as an instance variable name"); + ID id = id_for_var(obj, iv, an, instance); + if (!id) id = rb_intern_str(iv); return rb_ivar_set(obj, id, val); } @@ -2418,20 +2403,10 @@ rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_obj_ivar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = id_for_var(obj, iv, an, instance); if (!id) { - if (rb_is_instance_name(iv)) { - return Qfalse; - } - else { - rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE(iv)); - } - } - if (!rb_is_instance_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE_ID(id)); + return Qfalse; } return rb_ivar_defined(obj, id); } @@ -2455,21 +2430,11 @@ rb_obj_ivar_defined(VALUE obj, VALUE iv) static VALUE rb_mod_cvar_get(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = id_for_var(obj, iv, a, class); if (!id) { - if (rb_is_class_name(iv)) { - rb_name_error_str(iv, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"", - iv, rb_class_name(obj)); - } - else { - rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name", - QUOTE(iv)); - } - } - if (!rb_is_class_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name", - QUOTE_ID(id)); + rb_name_err_raise("uninitialized class variable %1$s in %2$s", + obj, iv); } return rb_cvar_get(obj, id); } @@ -2497,7 +2462,8 @@ rb_mod_cvar_get(VALUE obj, VALUE iv) static VALUE rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val) { - ID id = id_for_setter(iv, class, "`%"PRIsVALUE"' is not allowed as a class variable name"); + ID id = id_for_var(obj, iv, a, class); + if (!id) id = rb_intern_str(iv); rb_cvar_set(obj, id, val); return val; } @@ -2521,20 +2487,10 @@ rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val) static VALUE rb_mod_cvar_defined(VALUE obj, VALUE iv) { - ID id = rb_check_id(&iv); + ID id = id_for_var(obj, iv, a, class); if (!id) { - if (rb_is_class_name(iv)) { - return Qfalse; - } - else { - rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name", - QUOTE(iv)); - } - } - if (!rb_is_class_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name", - QUOTE_ID(id)); + return Qfalse; } return rb_cvar_defined(obj, id); } @@ -405,18 +405,19 @@ static ID check_local_id(VALUE bindval, volatile VALUE *pname) { ID lid = rb_check_id(pname); - VALUE name = *pname, sym = name; + VALUE name = *pname; if (lid) { if (!rb_is_local_id(lid)) { - name = rb_id2str(lid); - wrong: - rb_name_error_str(sym, "wrong local variable name `% "PRIsVALUE"' for %"PRIsVALUE, - name, bindval); + rb_name_err_raise("wrong local variable name `%1$s' for %2$s", + bindval, ID2SYM(lid)); } } else { - if (!rb_is_local_name(sym)) goto wrong; + if (!rb_is_local_name(name)) { + rb_name_err_raise("wrong local variable name `%1$s' for %2$s", + bindval, name); + } return 0; } return lid; @@ -481,9 +482,10 @@ bind_local_variable_get(VALUE bindval, VALUE sym) GetBindingPtr(bindval, bind); if ((ptr = get_local_variable_ptr(bind->env, lid)) == NULL) { + sym = ID2SYM(lid); undefined: - rb_name_error_str(sym, "local variable `%"PRIsVALUE"' not defined for %"PRIsVALUE, - sym, bindval); + rb_name_err_raise("local variable `%1$s' not defined for %2$s", + bindval, sym); } return *ptr; @@ -1495,24 +1497,30 @@ method_owner(VALUE obj) void rb_method_name_error(VALUE klass, VALUE str) { - const char *s0 = " class"; +#define MSG(s) rb_fstring_cstr("undefined method `%1$s' for"s" `%2$s'") VALUE c = klass; + VALUE s; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_ivar_get(klass, attached); - switch (TYPE(obj)) { + switch (BUILTIN_TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; - s0 = ""; + s = MSG(""); } + goto normal_class; } else if (RB_TYPE_P(c, T_MODULE)) { - s0 = " module"; + s = MSG(" module"); + } + else { + normal_class: + s = MSG(" class"); } - rb_name_error_str(str, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'", - QUOTE(str), s0, rb_class_name(c)); + rb_name_err_raise_str(s, c, str); +#undef MSG } static VALUE @@ -1616,14 +1624,15 @@ rb_obj_singleton_method(VALUE obj, VALUE vid) id = rb_intern_str(vid); return mnew_missing(klass, obj, id, id, rb_cMethod); } - rb_name_error_str(vid, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'", - QUOTE(vid), obj); + undef: + rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'", + obj, vid); } if (NIL_P(klass = rb_singleton_class_get(obj)) || UNDEFINED_METHOD_ENTRY_P(me = rb_method_entry_at(klass, id)) || UNDEFINED_REFINED_METHOD_P(me->def)) { - rb_name_error(id, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'", - QUOTE_ID(id), obj); + vid = ID2SYM(id); + goto undef; } return mnew_from_me(me, klass, obj, id, rb_cMethod, FALSE); } @@ -83,7 +83,7 @@ range_modify(VALUE range) { /* Ranges are immutable, so that they should be initialized only once. */ if (RANGE_EXCL(range) != Qnil) { - rb_name_error(idInitialize, "`initialize' called twice"); + rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize)); } } @@ -201,13 +201,6 @@ rb_struct_members_m(VALUE obj) return rb_struct_s_members_m(rb_obj_class(obj)); } -NORETURN(static void not_a_member(ID id)); -static void -not_a_member(ID id) -{ - rb_name_error(id, "`%"PRIsVALUE"' is not a struct member", QUOTE_ID(id)); -} - VALUE rb_struct_getmember(VALUE obj, ID id) { @@ -216,7 +209,7 @@ rb_struct_getmember(VALUE obj, ID id) if (i != -1) { return RSTRUCT_GET(obj, i); } - not_a_member(id); + rb_name_err_raise("`%1$s' is not a struct member", obj, ID2SYM(id)); UNREACHABLE; } @@ -272,8 +265,8 @@ new_struct(VALUE name, VALUE super) ID id; name = rb_str_to_str(name); if (!rb_is_const_name(name)) { - rb_name_error_str(name, "identifier %"PRIsVALUE" needs to be constant", - QUOTE(name)); + rb_name_err_raise("identifier %1$s needs to be constant", + super, name); } id = rb_to_id(name); if (rb_const_defined_at(super, id)) { @@ -830,7 +823,7 @@ rb_struct_aref_sym(VALUE s, VALUE name) if (pos != -1) { return RSTRUCT_GET(s, pos); } - rb_name_error_str(name, "no member '% "PRIsVALUE"' in struct", name); + rb_name_err_raise("no member '%1$s' in struct", s, name); UNREACHABLE; } @@ -863,8 +856,8 @@ rb_struct_aref(VALUE s, VALUE idx) else if (RB_TYPE_P(idx, T_STRING)) { ID id = rb_check_id(&idx); if (!id) { - rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", - QUOTE(idx)); + rb_name_err_raise("no member '%1$s' in struct", + s, idx); } return rb_struct_aref_sym(s, ID2SYM(id)); } @@ -890,7 +883,7 @@ rb_struct_aset_sym(VALUE s, VALUE name, VALUE val) return val; } - rb_name_error_str(name, "no member '% "PRIsVALUE"' in struct", name); + rb_name_err_raise("no member '%1$s' in struct", s, name); UNREACHABLE; } @@ -925,8 +918,8 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE val) if (RB_TYPE_P(idx, T_STRING)) { ID id = rb_check_id(&idx); if (!id) { - rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", - QUOTE(idx)); + rb_name_err_raise("no member '%1$s' in struct", + s, idx); } return rb_struct_aset_sym(s, ID2SYM(id), val); } diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index af69d86d6b..a3b392ae00 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -672,6 +672,10 @@ end.join } assert_equal(:Object, e.name) e = assert_raise(NameError) { + BasicObject::X + } + assert_same(BasicObject, e.receiver) + e = assert_raise(NameError) { obj.instance_eval {foo} } assert_equal(:foo, e.name) diff --git a/variable.c b/variable.c index 84eaf172c6..97c0932e34 100644 --- a/variable.c +++ b/variable.c @@ -1691,6 +1691,27 @@ rb_obj_instance_variables(VALUE obj) return ary; } +#define rb_is_constant_id rb_is_const_id +#define rb_is_constant_name rb_is_const_name +#define id_for_var(obj, name, part, type) \ + id_for_var_message(obj, name, type, "`%1$s' is not allowed as "#part" "#type" variable name") +#define id_for_var_message(obj, name, type, message) \ + check_id_type(obj, &(name), rb_is_##type##_id, rb_is_##type##_name, message, strlen(message)) +static ID +check_id_type(VALUE obj, VALUE *pname, + int (*valid_id_p)(ID), int (*valid_name_p)(VALUE), + const char *message, size_t message_len) +{ + ID id = rb_check_id(pname); + VALUE name = *pname; + + if (id ? !valid_id_p(id) : !valid_name_p(name)) { + rb_name_err_raise_str(rb_fstring_new(message, message_len), + obj, name); + } + return id; +} + /* * call-seq: * obj.remove_instance_variable(symbol) -> obj @@ -1717,25 +1738,14 @@ VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name) { VALUE val = Qnil; - const ID id = rb_check_id(&name); + const ID id = id_for_var(obj, name, an, instance); st_data_t n, v; struct st_table *iv_index_tbl; st_data_t index; rb_check_frozen(obj); if (!id) { - if (rb_is_instance_name(name)) { - rb_name_error_str(name, "instance variable %"PRIsVALUE" not defined", - name); - } - else { - rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE(name)); - } - } - if (!rb_is_instance_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name", - QUOTE_ID(id)); + goto not_defined; } switch (BUILTIN_TYPE(obj)) { @@ -1766,8 +1776,10 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) } break; } - rb_name_error(id, "instance variable %"PRIsVALUE" not defined", QUOTE_ID(id)); + not_defined: + rb_name_err_raise("instance variable %1$s not defined", + obj, name); UNREACHABLE; } @@ -1776,11 +1788,11 @@ static void uninitialized_constant(VALUE klass, VALUE name) { if (klass && rb_class_real(klass) != rb_cObject) - rb_name_error_str(name, "uninitialized constant %"PRIsVALUE"::% "PRIsVALUE"", - rb_class_name(klass), name); - else { - rb_name_error_str(name, "uninitialized constant % "PRIsVALUE"", name); - } + rb_name_err_raise("uninitialized constant %2$s::%1$s", + klass, name); + else + rb_name_err_raise("uninitialized constant %1$s", + klass, name); } VALUE @@ -2152,8 +2164,8 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) while ((ce = rb_const_lookup(tmp, id))) { if (visibility && RB_CONST_PRIVATE_P(ce)) { - rb_name_error(id, "private constant %"PRIsVALUE"::%"PRIsVALUE" referenced", - rb_class_name(klass), QUOTE_ID(id)); + rb_name_err_raise("private constant %2$s::%1$s referenced", + klass, ID2SYM(id)); } if (RB_CONST_DEPRECATED_P(ce)) { if (klass == rb_cObject) { @@ -2239,21 +2251,11 @@ rb_public_const_get_at(VALUE klass, ID id) VALUE rb_mod_remove_const(VALUE mod, VALUE name) { - const ID id = rb_check_id(&name); + const ID id = id_for_var(mod, name, a, constant); if (!id) { - if (rb_is_const_name(name)) { - rb_name_error_str(name, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", - rb_class_name(mod), name); - } - else { - rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as a constant name", - QUOTE(name)); - } - } - if (!rb_is_const_id(id)) { - rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a constant name", - QUOTE_ID(id)); + rb_name_err_raise("constant %2$s::%1$s not defined", + mod, name); } return rb_const_remove(mod, id); } @@ -2267,11 +2269,11 @@ rb_const_remove(VALUE mod, ID id) rb_check_frozen(mod); if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %"PRIsVALUE"::%"PRIsVALUE"", - rb_class_name(mod), QUOTE_ID(id)); + rb_name_err_raise("cannot remove %2$s::%1$s", + mod, ID2SYM(id)); } - rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", - rb_class_name(mod), QUOTE_ID(id)); + rb_name_err_raise("constant %2$s::%1$s not defined", + mod, ID2SYM(id)); } rb_clear_constant_cache(); @@ -2616,8 +2618,8 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv, rb_clear_constant_cache(); } - rb_name_error_str(val, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", - rb_class_name(mod), QUOTE(val)); + rb_name_err_raise("constant %2$s::%1$s not defined", + mod, val); } if ((ce = rb_const_lookup(mod, id))) { ce->flag &= ~mask; @@ -2627,8 +2629,8 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv, if (i > 0) { rb_clear_constant_cache(); } - rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", - rb_class_name(mod), QUOTE_ID(id)); + rb_name_err_raise("constant %2$s::%1$s not defined", + mod, ID2SYM(id)); } } rb_clear_constant_cache(); @@ -2751,8 +2753,8 @@ rb_cvar_get(VALUE klass, ID id) tmp = klass; CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;}); if (!target) { - rb_name_error(id, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"", - QUOTE_ID(id), rb_class_name(tmp)); + rb_name_err_raise("uninitialized class variable %1$s in %2$s", + tmp, ID2SYM(id)); } if (front && target != front) { st_data_t did = id; @@ -2777,34 +2779,35 @@ rb_cvar_defined(VALUE klass, ID id) return Qfalse; } -void -rb_cv_set(VALUE klass, const char *name, VALUE val) +static ID +cv_intern(VALUE klass, const char *name) { ID id = rb_intern(name); if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", name); + rb_name_err_raise("wrong class variable name %1$s", + klass, rb_str_new_cstr(name)); } + return id; +} + +void +rb_cv_set(VALUE klass, const char *name, VALUE val) +{ + ID id = cv_intern(klass, name); rb_cvar_set(klass, id, val); } VALUE rb_cv_get(VALUE klass, const char *name) { - ID id = rb_intern(name); - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", name); - } + ID id = cv_intern(klass, name); return rb_cvar_get(klass, id); } void rb_define_class_variable(VALUE klass, const char *name, VALUE val) { - ID id = rb_intern(name); - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", name); - } + ID id = cv_intern(klass, name); rb_cvar_set(klass, id, val); } @@ -2931,33 +2934,22 @@ rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod) VALUE rb_mod_remove_cvar(VALUE mod, VALUE name) { - const ID id = rb_check_id(&name); + const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s"); st_data_t val, n = id; if (!id) { - if (rb_is_class_name(name)) { - rb_name_error_str(name, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"", - name, rb_class_name(mod)); - } - else { - rb_name_error_str(name, "wrong class variable name %"PRIsVALUE"", QUOTE(name)); - } - } - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %"PRIsVALUE"", QUOTE_ID(id)); + not_defined: + rb_name_err_raise("class variable %1$s not defined for %2$s", + mod, name); } rb_check_frozen(mod); if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { return (VALUE)val; } if (rb_cvar_defined(mod, id)) { - rb_name_error(id, "cannot remove %"PRIsVALUE" for %"PRIsVALUE"", - QUOTE_ID(id), rb_class_name(mod)); + rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id)); } - rb_name_error(id, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"", - QUOTE_ID(id), rb_class_name(mod)); - - UNREACHABLE; + goto not_defined; } VALUE diff --git a/vm_method.c b/vm_method.c index f61c1b7d96..4059312953 100644 --- a/vm_method.c +++ b/vm_method.c @@ -918,8 +918,8 @@ remove_method(VALUE klass, ID mid) !(me = (rb_method_entry_t *)data) || (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF) || UNDEFINED_REFINED_METHOD_P(me->def)) { - rb_name_error(mid, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE, - rb_id2str(mid), rb_class_path(klass)); + rb_name_err_raise("method `%1$s' not defined in %2$s", + klass, ID2SYM(mid)); } rb_id_table_delete(RCLASS_M_TBL(klass), mid); @@ -965,8 +965,8 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) VALUE v = argv[i]; ID id = rb_check_id(&v); if (!id) { - rb_name_error_str(v, "method `%"PRIsVALUE"' not defined in %"PRIsVALUE, - v, rb_obj_class(mod)); + rb_name_err_raise("method `%1$s' not defined in %2$s", + mod, v); } remove_method(mod, id); } |