From ccdf75c1c208212a703e025d1043f959199249d7 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 31 May 2023 08:31:13 +0900 Subject: [PATCH] error.c: a new function `mrb_check_frozen_value()` --- include/mruby.h | 2 +- src/class.c | 13 ++++++++----- src/error.c | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/mruby.h b/include/mruby.h index 12be6faf8..3ecea7029 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1434,7 +1434,7 @@ MRB_INLINE void mrb_check_frozen(mrb_state *mrb, void *o) { if (mrb_frozen_p((struct RBasic*)o)) mrb_frozen_error(mrb, o); } - +MRB_API void mrb_check_frozen_value(mrb_state *mrb, mrb_value v); MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *c, const char *a, const char *b); MRB_API void mrb_define_alias_id(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b); MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass); diff --git a/src/class.c b/src/class.c index 326f16e40..e30102e10 100644 --- a/src/class.c +++ b/src/class.c @@ -756,7 +756,13 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_ MRB_CLASS_ORIGIN(c); h = c->mt; - mrb_check_frozen(mrb, c); + if (c->tt == MRB_TT_SCLASS && mrb_frozen_p(c)) { + mrb_value v = mrb_iv_get(mrb, mrb_obj_value(c), MRB_SYM(__attached__)); + mrb_check_frozen_value(mrb, v); + } + else { + mrb_check_frozen(mrb, c); + } if (!h) h = c->mt = mt_new(mrb); if (MRB_METHOD_PROC_P(m)) { struct RProc *p = MRB_METHOD_PROC(m); @@ -1011,10 +1017,7 @@ get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list *ap) if (i < argc) { pickarg = &argv[i++]; if (needmodify && !mrb_nil_p(*pickarg)) { - if (mrb_immediate_p(*pickarg)) { - mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", *pickarg); - } - mrb_check_frozen(mrb, mrb_obj_ptr(*pickarg)); + mrb_check_frozen_value(mrb, *pickarg); } } else { diff --git a/src/error.c b/src/error.c index 0b20ec541..7a2a30530 100644 --- a/src/error.c +++ b/src/error.c @@ -518,10 +518,24 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, mrb_exc_raise(mrb, exc); } +static mrb_noreturn void +frozen_error(mrb_state *mrb, mrb_value v) +{ + mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", v); +} + MRB_API mrb_noreturn void mrb_frozen_error(mrb_state *mrb, void *frozen_obj) { - mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %t", mrb_obj_value(frozen_obj)); + frozen_error(mrb, mrb_obj_value(frozen_obj)); +} + +MRB_API void +mrb_check_frozen_value(mrb_state *mrb, mrb_value v) +{ + if (mrb_immediate_p(v) || mrb_frozen_p(mrb_basic_ptr(v))) { + frozen_error(mrb, v); + } } MRB_API mrb_noreturn void