void rb_check_frozen(VALUE obj) { if (OBJ_FROZEN(obj)) rb_error_frozen(rb_obj_classname(obj)); }
static rb_method_entry_t * rb_add_method_def(VALUE klass, ID mid, rb_method_type_t type, rb_method_definition_t *def, rb_method_flag_t noex) { rb_method_entry_t *me; st_table *mtbl; st_data_t data; if (NIL_P(klass)) { klass = rb_cObject; } if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_UNTRUSTED(klass))) { rb_raise(rb_eSecurityError, "Insecure: can't define method"); } if (!FL_TEST(klass, FL_SINGLETON) && type != VM_METHOD_TYPE_NOTIMPLEMENTED && type != VM_METHOD_TYPE_ZSUPER && (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) { noex = NOEX_PRIVATE | noex; } else if (FL_TEST(klass, FL_SINGLETON) && type == VM_METHOD_TYPE_CFUNC && mid == rb_intern("allocate")) { rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()", rb_class2name(rb_ivar_get(klass, attached))); mid = ID_ALLOCATOR; } if (OBJ_FROZEN(klass)) { rb_error_frozen("class/module"); } mtbl = RCLASS_M_TBL(klass); /* check re-definition */ if (st_lookup(mtbl, mid, &data)) { rb_method_entry_t *old_me = (rb_method_entry_t *)data; rb_method_definition_t *old_def = old_me->def; if (rb_method_definition_eq(old_def, def)) return old_me; rb_vm_check_redefinition_opt_method(old_me); if (RTEST(ruby_verbose) && type != VM_METHOD_TYPE_UNDEF && old_def->alias_count == 0 && old_def->type != VM_METHOD_TYPE_UNDEF && old_def->type != VM_METHOD_TYPE_ZSUPER) { extern rb_iseq_t *rb_proc_get_iseq(VALUE proc, int *is_proc); rb_iseq_t *iseq = 0; rb_warning("method redefined; discarding old %s", rb_id2name(mid)); switch (old_def->type) { case VM_METHOD_TYPE_ISEQ: iseq = old_def->body.iseq; break; case VM_METHOD_TYPE_BMETHOD: iseq = rb_proc_get_iseq(old_def->body.proc, 0); break; default: break; } if (iseq && !NIL_P(iseq->filename)) { int line = iseq->insn_info_table ? rb_iseq_first_lineno(iseq) : 0; rb_compile_warning(RSTRING_PTR(iseq->filename), line, "previous definition of %s was here", rb_id2name(old_def->original_id)); } } rb_free_method_entry(old_me); } rb_clear_cache_by_id(mid); me = ALLOC(rb_method_entry_t); me->flag = NOEX_WITH_SAFE(noex); me->called_id = mid; me->klass = klass; me->def = def; if (def) def->alias_count++; /* check mid */ if (klass == rb_cObject && mid == idInitialize) { rb_warn("redefining Object#initialize may cause infinite loop"); } /* check mid */ if (mid == object_id || mid == id__send__) { if (type == VM_METHOD_TYPE_ISEQ) { rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid)); } } st_insert(mtbl, mid, (st_data_t) me); return me; }