diff --git a/compile.c b/compile.c
index 09e966d..027ea31 100644
--- a/compile.c
+++ b/compile.c
@@ -4848,9 +4848,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 		rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)),
 		ISEQ_TYPE_CLASS, nd_line(node));
 	VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
+	int define_type = VM_DEFINE_TYPE_CLASS;
+	if (!noscope) define_type |= VM_DEFINE_FLAG_SCOPED;
+	if (node->nd_super) define_type |= VM_DEFINE_FLAG_HAS_SUPERCLASS;
 	COMPILE(ret, "super", node->nd_super);
 	ADD_INSN3(ret, nd_line(node), defineclass,
-		  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(noscope ? 3 : 0));
+		  ID2SYM(node->nd_cpath->nd_mid), iseqval,
+		  INT2FIX(define_type));
 
 	if (poped) {
 	    ADD_INSN(ret, nd_line(node), pop);
@@ -4864,9 +4868,12 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	    ISEQ_TYPE_CLASS, nd_line(node));
 
 	VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath);
+	int define_type = VM_DEFINE_TYPE_MODULE;
+	if (!noscope) define_type |= VM_DEFINE_FLAG_SCOPED;
 	ADD_INSN (ret, nd_line(node), putnil); /* dummy */
 	ADD_INSN3(ret, nd_line(node), defineclass,
-		  ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(noscope ? 5 : 2));
+		  ID2SYM(node->nd_cpath->nd_mid), iseqval,
+		  INT2FIX(define_type));
 	if (poped) {
 	    ADD_INSN(ret, nd_line(node), pop);
 	}
@@ -4882,7 +4889,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	ADD_INSN (ret, nd_line(node), putnil);
 	CONST_ID(singletonclass, "singletonclass");
 	ADD_INSN3(ret, nd_line(node), defineclass,
-		  ID2SYM(singletonclass), iseqval, INT2FIX(1));
+		  ID2SYM(singletonclass), iseqval,
+		  INT2FIX(VM_DEFINE_TYPE_SINGLETON_CLASS));
 
 	if (poped) {
 	    ADD_INSN(ret, nd_line(node), pop);
diff --git a/insns.def b/insns.def
index 7ada586..235043c 100644
--- a/insns.def
+++ b/insns.def
@@ -885,17 +885,24 @@ trace
  */
 DEFINE_INSN
 defineclass
-(ID id, ISEQ class_iseq, rb_num_t define_type)
+(ID id, ISEQ class_iseq, rb_num_t define_flags)
 (VALUE cbase, VALUE super)
 (VALUE val)
 {
     VALUE klass;
+    rb_vm_define_type_t type = VM_DEFINE_TYPE(define_flags);
 
-    switch ((int)define_type) {
-      case 0: /* scoped:   class Foo::Bar */
-      case 3: /* no scope: class Bar */
+    switch (type) {
+      case VM_DEFINE_TYPE_CLASS:
 	/* val is dummy.  classdef returns class scope value */
 
+	if (VM_DEFINE_HAS_SUPERCLASS_P(define_flags)) {
+	    if (!RB_TYPE_P(super, T_CLASS)) {
+		rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
+			 rb_obj_classname(super));
+	    }
+	}
+
 	if (super == Qnil) {
 	    super = rb_cObject;
 	}
@@ -906,7 +913,7 @@ defineclass
 	rb_autoload_load(cbase, id);
 	if ((klass = vm_search_const_defined_class(cbase, id)) != 0) {
 	    /* already exist */
-	    klass = define_type == 0 ? rb_public_const_get_at(klass, id) : rb_const_get_at(klass, id);
+	    klass = VM_DEFINE_SCOPED_P(define_flags) ? rb_public_const_get_at(klass, id) : rb_const_get_at(klass, id);
 	    if (!RB_TYPE_P(klass, T_CLASS)) {
 		rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
 	    }
@@ -929,13 +936,12 @@ defineclass
 	    rb_class_inherited(super, klass);
 	}
 	break;
-      case 1:
+      case VM_DEFINE_TYPE_SINGLETON_CLASS:
 	/* val is dummy.  classdef returns class scope value */
 	/* super is dummy */
 	klass = rb_singleton_class(cbase);
 	break;
-      case 2: /* scoped:   module Foo::Bar  or  module ::Bar */
-      case 5: /* no scope: module Bar */
+      case VM_DEFINE_TYPE_MODULE:
 	/* val is dummy.  classdef returns class scope value */
 	/* super is dummy */
 
@@ -943,7 +949,7 @@ defineclass
 
 	/* find klass */
 	if ((klass = vm_search_const_defined_class(cbase, id)) != 0) {
-	    klass = define_type == 2 ? rb_public_const_get_at(klass, id) : rb_const_get_at(klass, id);
+	    klass = VM_DEFINE_SCOPED_P(define_flags) ? rb_const_get_at(klass, id) : rb_public_const_get_at(klass, id);
 	    /* already exist */
 	    if (!RB_TYPE_P(klass, T_MODULE)) {
 		rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(id));
@@ -957,7 +963,7 @@ defineclass
 	}
 	break;
       default:
-	rb_bug("unknown defineclass type: %d", (int)define_type);
+	rb_bug("unknown defineclass type: %d", (int)type);
     }
 
     COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index 0ac29b3..fa50d2f 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -299,4 +299,41 @@ class TestClass < Test::Unit::TestCase
     assert_equal 1, m::C
     assert_equal 1, m.m
   end
+
+  def test_invalid_superclass
+    assert_raise(TypeError) do
+      eval <<-EOF
+        class C < nil
+        end
+      EOF
+    end
+
+    assert_raise(TypeError) do
+      eval <<-EOF
+        class C < false
+        end
+      EOF
+    end
+
+    assert_raise(TypeError) do
+      eval <<-EOF
+        class C < true
+        end
+      EOF
+    end
+
+    assert_raise(TypeError) do
+      eval <<-EOF
+        class C < 0
+        end
+      EOF
+    end
+
+    assert_raise(TypeError) do
+      eval <<-EOF
+        class C < ""
+        end
+      EOF
+    end
+  end
 end
diff --git a/vm_core.h b/vm_core.h
index 87076f3..6cc3b0a 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -612,6 +612,20 @@ typedef struct rb_thread_struct {
     unsigned long running_time_us;
 } rb_thread_t;
 
+typedef enum {
+    VM_DEFINE_TYPE_CLASS           = 0x00,
+    VM_DEFINE_TYPE_SINGLETON_CLASS = 0x01,
+    VM_DEFINE_TYPE_MODULE          = 0x02,
+    /* 0x03..0x06 is reserved */
+    VM_DEFINE_TYPE_MASK            = 0x07,
+} rb_vm_define_type_t;
+
+#define VM_DEFINE_TYPE(x) ((x) & VM_DEFINE_TYPE_MASK)
+#define VM_DEFINE_FLAG_SCOPED         0x08
+#define VM_DEFINE_FLAG_HAS_SUPERCLASS 0x10
+#define VM_DEFINE_SCOPED_P(x) ((x) & VM_DEFINE_FLAG_SCOPED)
+#define VM_DEFINE_HAS_SUPERCLASS_P(x) ((x) & VM_DEFINE_FLAG_HAS_SUPERCLASS)
+
 /* iseq.c */
 #if defined __GNUC__ && __GNUC__ >= 4
 #pragma GCC visibility push(default)
