diff options
| -rw-r--r-- | src/class.c | 37 | ||||
| -rw-r--r-- | test/t/class.rb | 76 |
2 files changed, 84 insertions, 29 deletions
diff --git a/src/class.c b/src/class.c index f0393c7ec..6efc9f5e7 100644 --- a/src/class.c +++ b/src/class.c @@ -187,30 +187,39 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { - struct RClass *c = 0; + struct RClass *c, *s; if (mrb_const_defined(mrb, outer, id)) { mrb_value v = mrb_const_get(mrb, outer, id); + mrb_check_type(mrb, v, MRB_TT_CLASS); c = mrb_class_ptr(v); - if (!mrb_nil_p(super) && (c->tt != MRB_TT_CLASS || c->super != mrb_class_ptr(super))) { - c = 0; + if (!mrb_nil_p(super)) { + if (mrb_type(super) != MRB_TT_CLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); + } + + if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass mismatch for class %s", mrb_sym2name(mrb, id)); + } } + + return c; } - if (!c) { - struct RClass *s = 0; - if (!mrb_nil_p(super)) { - mrb_check_type(mrb, super, MRB_TT_CLASS); - s = mrb_class_ptr(super); - } - if (!s) { - s = mrb->object_class; + if (!mrb_nil_p(super)) { + if (mrb_type(super) != MRB_TT_CLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "superclass must be a Class (%s given)", mrb_obj_classname(mrb, super)); } - c = mrb_class_new(mrb, s); - setup_class(mrb, outer, c, id); - mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); + s = mrb_class_ptr(super); } + else { + s = mrb->object_class; + } + + c = mrb_class_new(mrb, s); + setup_class(mrb, outer, c, id); + mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); return c; } diff --git a/test/t/class.rb b/test/t/class.rb index 1b809a832..d6c4715dd 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -47,36 +47,82 @@ end # Not ISO specified assert('Class 1') do - class C; end - C.class == Class + class C1; end + C1.class == Class end assert('Class 2') do - class C; end - C.new.class == C + class C2; end + C2.new.class == C2 end assert('Class 3') do - class C; end - C.new.class.class == Class + class C3; end + C3.new.class.class == Class end assert('Class 4') do - class A; end - class C < A; end - C.class == Class + class C4_A; end + class C4 < C4_A; end + C4.class == Class end assert('Class 5') do - class A; end - class C < A; end - C.new.class == C + class C5_A; end + class C5 < C5_A; end + C5.new.class == C5 end assert('Class 6') do - class A; end - class C < A; end - C.new.class.class == Class + class C6_A; end + class C6 < C6_A; end + C6.new.class.class == Class +end + +assert('Class 7') do + class C7_A; end + class C7_B; end + + class C7 < C7_A; end + + error = false + begin + # Different superclass. + class C7 < C7_B; end + rescue TypeError + error = true + end + + error +end + +assert('Class 8') do + class C8_A; end + + class C8; end # superclass is Object + + error = false + begin + # Different superclass. + class C8 < C8_A; end + rescue TypeError + error = true + end + + error +end + +assert('Class 9') do + Class9Const = "a" + + error = false + begin + class Class9Const; end + rescue TypeError + error = true + end + + error end assert('Class Module 1') do |
