diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc
index 8b47f46b54987c7655f263025279ff48bd79113f..dda0e6eb1813175f77f6145266600543dc428220 100644
--- a/compiler2/Type_chk.cc
+++ b/compiler2/Type_chk.cc
@@ -3731,7 +3731,7 @@ void Type::chk_Fat()
       Error_Context cntxt2(u.fatref.return_type, "In return type");
       u.fatref.return_type->chk();
       u.fatref.return_type->chk_as_return_type(!u.fatref.returns_template,
-        "function type");
+        " function type");
       if (u.fatref.is_startable && u.fatref.return_type->get_type_refd_last()
           ->get_typetype() == T_DEFAULT) u.fatref.is_startable = false;
 
@@ -3920,7 +3920,7 @@ void Type::chk_as_return_type(bool as_value, const char* what)
   Type *t = get_type_refd_last();
   switch(t->get_typetype()) {
   case Type::T_PORT:
-    error("Port type `%s' cannot be the return type of a %s"
+    error("Port type `%s' cannot be the return type of a%s"
       , t->get_fullname().c_str(), what);
     break;
   case Type::T_SIGNATURE:
@@ -6000,21 +6000,15 @@ void Type::chk_this_value_class(Value* value)
   switch(v->get_valuetype()) {
   case Value::V_TTCN3_NULL:
     break; // OK
-  case Value::V_REFD:
-    // TODO
-    break;
   case Value::V_EXPR:
-    switch (v->get_optype()) {
-    case Value::OPTYPE_CLASS_CREATE:
-      // TODO
-      break;
-    default:
-      // error
+    if (v->get_optype() == Value::OPTYPE_CLASS_CREATE) {
+      // OK
       break;
     }
-    break;
+    // else fall through
   default:
     // error
+    v->error("class value was expected");
     break;
   }
 }
diff --git a/compiler2/Value.cc b/compiler2/Value.cc
index 6204546b29dfc033201d55337563a91883f08cf7..2d8a79be3515a404ec1c9b74598709c84dcc9c61 100644
--- a/compiler2/Value.cc
+++ b/compiler2/Value.cc
@@ -4063,8 +4063,11 @@ namespace Common {
         goto error;
       case Assignment::A_TYPE:
         if (ass->get_Type()->get_type_refd_last()->get_typetype() == Type::T_CLASS) {
-          tmp_type = ass->get_Type();
-          break;
+          Ttcn::Reference* ttcn_ref = static_cast<Ttcn::Reference*>(u.ref.ref);
+          if (ttcn_ref->get_reftype() == Ref_simple::REF_THIS) {
+            tmp_type = ass->get_Type();
+            break;
+          }
         }
         // else fall through
       default:
@@ -8201,8 +8204,12 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     case OPTYPE_CLASS_CREATE: { // r1 t_list2
       Type* t = chk_expr_operand_undef_create();
       if (u.expr.v_optype == OPTYPE_CLASS_CREATE) {
-        Ttcn::FormalParList* fp_list = t->get_class_type_body()->get_constructor()
-          ->get_FormalParList();
+        Ttcn::ClassTypeBody* class_ = t->get_class_type_body();
+        if (class_->is_abstract()) {
+          error("Cannot create an instance of abstract class type `%s'",
+            class_->get_my_def()->get_Type()->get_typename().c_str());
+        }
+        Ttcn::FormalParList* fp_list = class_->get_constructor()->get_FormalParList();
         Ttcn::ActualParList* parlist = new Ttcn::ActualParList;
         bool is_erroneous = fp_list->chk_actual_parlist(u.expr.t_list2->get_tis(), parlist);
         if (is_erroneous) {
@@ -9602,8 +9609,11 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
             break;
           case Assignment::A_TYPE:
             if (ass->get_Type()->get_type_refd_last()->get_typetype() == Type::T_CLASS) {
-              u.ref.refd_last = this;
-              break;
+              Ttcn::Reference* ttcn_ref = static_cast<Ttcn::Reference*>(u.ref.ref);
+              if (ttcn_ref->get_reftype() == Ref_simple::REF_THIS) {
+                u.ref.refd_last = this;
+                break;
+              }
             }
             // else fall through
           default:
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index 2448f1ba490474ee2d462bf852f710c2ebb7fffe..4ea2bde4f99fa552baf3480f56f93aab0143a3ed 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -844,7 +844,6 @@ namespace Ttcn {
         }
       }
       else { // params != NULL
-        FormalParList *fplist = NULL;
         if (ass->get_asstype() == Common::Assignment::A_TYPE) {
           Def_Type* def = dynamic_cast<Def_Type*>(ass);
           if (def == NULL) {
@@ -854,14 +853,10 @@ namespace Ttcn {
           if (type->get_typetype() == Common::Type::T_CLASS) {
             // if the referred assignment is a class type, then the reference and
             // its parameters are meant for the constructor instead
-            fplist = type->get_class_type_body()->get_constructor()->
-              get_FormalParList();
+            ass = type->get_class_type_body()->get_constructor();
           }
         }
-        if (fplist == NULL) {
-          // if it's not a class type, retrieve the formal parameter list normally
-          fplist = ass->get_FormalParList();
-        }
+        FormalParList* fplist = ass->get_FormalParList();
         if (fplist != NULL) {
           Error_Context cntxt(params, "In actual parameter list of %s",
             ass->get_description().c_str());
@@ -6769,7 +6764,7 @@ namespace Ttcn {
     if (return_type) {
       Error_Context cntxt2(return_type, "In return type");
       return_type->chk();
-      return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,"function");
+      return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL," function");
     }
     
     if (w_attrib_path) {
@@ -7454,7 +7449,7 @@ namespace Ttcn {
       Error_Context cntxt2(return_type, "In return type");
       return_type->chk();
       return_type->chk_as_return_type(asstype == A_EXT_FUNCTION_RVAL,
-        "external function");
+        " external function");
     }
     if (!semantic_check_only) fp_list->set_genname(get_genname());
     if (w_attrib_path) {
@@ -8031,7 +8026,84 @@ namespace Ttcn {
   
   void Def_AbsFunction::chk()
   {
-    // TODO
+    if (checked) {
+      return;
+    }
+    checked = true;
+    Error_Context cntxt(this, "In abstract function definition `%s'",
+      id->get_dispname().c_str());
+    ClassTypeBody* my_class = my_scope->get_scope_class();
+    if (my_class == NULL) {
+      FATAL_ERROR("Def_AbsFunction::chk");
+    }
+    if (!my_class->is_abstract()) {
+      error("Concrete class type `%s' cannot have abstract methods",
+        my_class->get_my_def()->get_Type()->get_typename().c_str());
+    }
+    fp_list->chk(asstype);
+    if (return_type != NULL) {
+      Error_Context cntxt2(return_type, "In return type");
+      return_type->chk();
+      return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,
+        "n abstract function");
+    }
+    if (!semantic_check_only) {
+      fp_list->set_genname(get_genname());
+    }
+    // TODO: with attributes
+  }
+  
+  void Def_AbsFunction::chk_implementation(Common::Assignment* p_ass, Location* p_loc)
+  {
+    switch (p_ass->get_asstype()) {
+    case A_FUNCTION:
+    case A_FUNCTION_RVAL:
+    case A_FUNCTION_RTEMP: {
+      Def_Function* def_func = dynamic_cast<Def_Function*>(p_ass);
+      if (def_func == NULL) {
+        // it's an abstract function, which means it hasn't been implemented
+        p_loc->error("Missing implementation of abstract method `%s'",
+          get_fullname().c_str());
+      }
+      else {
+        // check whether they're identical
+        bool match = true;
+        if (asstype != p_ass->get_asstype()) {
+          match = false;
+        }
+        else if (return_type != NULL &&
+                 !def_func->get_return_type()->is_identical(return_type)) {
+          match = false;
+        }
+        else {
+          FormalParList* other_fp_list = def_func->get_FormalParList();
+          if (other_fp_list->get_nof_fps() != fp_list->get_nof_fps()) {
+            match = false;
+          }
+          else {
+            for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
+              FormalPar* fp1 = fp_list->get_fp_byIndex(i);
+              FormalPar* fp2 = other_fp_list->get_fp_byIndex(i);
+              if (fp1->get_asstype() != fp2->get_asstype() ||
+                  !fp1->get_Type()->is_identical(fp2->get_Type()) ||
+                  fp1->get_id().get_name() != fp2->get_id().get_name()) {
+                match = false;
+              }
+            }
+          }
+        }
+        if (!match) {
+          p_ass->error("The prototype of method `%s' is not identical to that "
+            "of inherited abstract method `%s'",
+            def_func->get_id().get_dispname().c_str(), get_fullname().c_str());
+        }
+      }
+      break; }
+    default:
+      p_ass->error("%s shadows inherited abstract method `%s'",
+        p_ass->get_description().c_str(), get_fullname().c_str());
+      break;
+    }
   }
   
   void Def_AbsFunction::generate_code(output_struct* target, bool)
@@ -8746,9 +8818,39 @@ namespace Ttcn {
     
     fp_list->chk(asstype);
     
+    ClassTypeBody* my_class = my_scope->get_scope_class();
+    ClassTypeBody* base_class = my_class->get_base_class();
     if (base_call != NULL) {
-      Common::Assignment* base_type_ass = base_call->get_refd_assignment(true);
-      // TODO
+      Error_Context cntxt2(this, "In super-constructor call");
+      if (base_class == NULL) {
+        base_call->error("Class type `%s' does not have a superclass",
+          my_class->get_my_def()->get_Type()->get_typename().c_str());
+      }
+      else {
+        Common::Assignment* base_call_ass = base_call->get_refd_assignment(true);
+        if (base_call_ass != NULL) {
+          if (base_call_ass->get_asstype() != Common::Assignment::A_CONSTRUCTOR) {
+            base_call->error("Reference to constructor was expected instead of %s",
+              base_call_ass->get_assname());
+          }
+          else {
+            ClassTypeBody* base_call_class = base_call_ass->get_my_scope()->get_scope_class();
+            if (base_call_class != base_class) {
+              base_call->error("expected call to constructor of class type `%s', "
+                "instead of class type `%s'",
+              my_class->get_base_type()->get_typename().c_str(),
+              base_call_class->get_my_def()->get_Type()->get_typename().c_str());
+            }
+          }
+        }
+      }
+    }
+    else if (base_class != NULL) {
+      Def_Constructor* base_constructor = base_class->get_constructor();
+      if (base_constructor != NULL &&
+          !base_constructor->get_FormalParList()->has_only_default_values()) {
+        error("Missing super-constructor call");
+      }
     }
     
     block->chk();
diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh
index 09987327fbce4ae95bb5ee6b652a7ac2ec5c7e53..c7e856fe38fbf6495490f88eb91f0a9a15d330e5 100644
--- a/compiler2/ttcn3/AST_ttcn3.hh
+++ b/compiler2/ttcn3/AST_ttcn3.hh
@@ -1385,8 +1385,12 @@ namespace Ttcn {
     Type *get_input_type();
     Type *get_output_type();
     Type* get_return_type() const { return return_type; }
+    //virtual Type *get_RunsOnType();
     template_restriction_t get_template_restriction()
       { return template_restriction; }
+    /** Checks and returns whether the function is startable.
+     * Reports the appropriate error message(s) if not. */
+    //bool chk_startable(Location* caller_location);
   };
 
   /**
@@ -1611,8 +1615,8 @@ namespace Ttcn {
     virtual ~Def_AbsFunction();
     virtual Definition* clone() const;
     virtual void chk();
+    void chk_implementation(Common::Assignment* p_ass, Location* p_loc);
     virtual void generate_code(output_struct* target, bool clean_up = false);
-    // TODO
   };
 
   /**
diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index 37443c049c13ea331605c91acef2803d63fa6a7a..4cc52b8e13bc7d60ef15e824b52d86b7602ab466 100644
--- a/compiler2/ttcn3/Statement.cc
+++ b/compiler2/ttcn3/Statement.cc
@@ -11512,7 +11512,8 @@ error:
     Common::Assignment::asstype_t asstype = t_ass->get_asstype();
     switch (asstype) {
     case Common::Assignment::A_TYPE:
-      if (t_ass->get_Type()->get_typetype() != Common::Type::T_CLASS) {
+      if (t_ass->get_Type()->get_typetype() != Common::Type::T_CLASS ||
+          ref->get_reftype() != Common::Ref_simple::REF_THIS) {
         ref->error("Reference to a value, template, timer, port or class object "
           "was expected instead of %s", t_ass->get_description().c_str());
         return;
diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc
index 52faefb9850f724a84248748050e6f89dd18b688..69c31a23dc5af6e5573102fa3c9fc34aa77a04c2 100644
--- a/compiler2/ttcn3/Ttcnstuff.cc
+++ b/compiler2/ttcn3/Ttcnstuff.cc
@@ -2986,7 +2986,7 @@ namespace Ttcn {
                                Reference* p_runs_on_ref, Reference* p_mtc_ref, Reference* p_system_ref,
                                Definitions* p_members, StatementBlock* p_finally_block)
   : Scope(), Location(), class_id(p_class_id), my_def(NULL), external(p_external), final(p_final),
-    abstract(p_abstract), built_in(FALSE), base_type(p_base_type),
+    abstract(p_abstract), built_in(FALSE), base_type(p_base_type), base_class(NULL),
     runs_on_ref(p_runs_on_ref), runs_on_type(NULL), mtc_ref(p_mtc_ref),
     mtc_type(NULL), system_ref(p_system_ref), system_type(NULL),
     members(p_members), finally_block(p_finally_block), constructor(NULL), checked(false),
@@ -3000,7 +3000,7 @@ namespace Ttcn {
   
   ClassTypeBody::ClassTypeBody()
   : Scope(), Location(), class_id(NULL), my_def(NULL), external(FALSE), final(FALSE),
-    abstract(TRUE), built_in(TRUE), base_type(NULL),
+    abstract(TRUE), built_in(TRUE), base_type(NULL), base_class(NULL),
     runs_on_ref(NULL), runs_on_type(NULL), mtc_ref(NULL),
     mtc_type(NULL), system_ref(NULL), system_type(NULL),
     members(NULL), finally_block(NULL), constructor(NULL), checked(false),
@@ -3018,6 +3018,7 @@ namespace Ttcn {
     final = p.final;
     abstract = p.abstract;
     base_type = p.base_type != NULL ? p.base_type->clone() : NULL;
+    base_class = p.base_class;
     runs_on_ref = p.runs_on_ref != NULL ? p.runs_on_ref->clone() : NULL;
     mtc_ref = p.mtc_ref != NULL ? p.mtc_ref->clone() : NULL;
     system_ref = p.system_ref != NULL ? p.system_ref->clone() : NULL;
@@ -3047,6 +3048,7 @@ namespace Ttcn {
     if (default_constructor) {
       delete constructor;
     }
+    abstract_functions.clear();
   }
   
   void ClassTypeBody::set_fullname(const string& p_fullname)
@@ -3067,7 +3069,7 @@ namespace Ttcn {
     if (system_ref != NULL) {
       system_ref->set_fullname(p_fullname + ".<system_type>");
     }
-    members->set_fullname(p_fullname + ".<members>");
+    members->set_fullname(p_fullname);
     if (finally_block != NULL) {
       finally_block->set_fullname(p_fullname + ".<finally_block>");
     }
@@ -3133,6 +3135,14 @@ namespace Ttcn {
     return constructor;
   }
   
+  ClassTypeBody* ClassTypeBody::get_base_class()
+  {
+    if (!checked) {
+      chk();
+    }
+    return base_class;
+  }
+  
   Type* ClassTypeBody::get_RunsOnType()
   {
     if (!checked) {
@@ -3157,30 +3167,33 @@ namespace Ttcn {
     return system_type;
   }
   
-  bool ClassTypeBody::is_parent_class(const ClassTypeBody* p_class) const
+  bool ClassTypeBody::is_parent_class(const ClassTypeBody* p_class)
   {
+    if (!checked) {
+      chk();
+    }
     if (this == p_class || p_class->built_in) {
       return true;
     }
-    if (base_type == NULL) {
+    if (base_class == NULL) {
       return false;
     }
-    return base_type->get_type_refd_last()->get_class_type_body()->
-      is_parent_class(p_class);
+    return base_class->is_parent_class(p_class);
   }
   
   bool ClassTypeBody::has_local_ass_withId(const Identifier& p_id)
   {
+    if (!checked) {
+      chk();
+    }
     if (built_in) {
       return false;
     }
-    chk();
     if (members->has_local_ass_withId(p_id)) {
       return true;
     }
     if (base_type != NULL) {
-      return base_type->get_type_refd_last()->get_class_type_body()->
-        has_local_ass_withId(p_id);
+      return base_class->has_local_ass_withId(p_id);
     }
     else {
       return false;
@@ -3192,14 +3205,15 @@ namespace Ttcn {
     if (built_in) {
       FATAL_ERROR("ClassTypeBody::get_local_ass_byId");
     }
-    chk();
+    if (!checked) {
+      chk();
+    }
     Common::Assignment* ass = NULL;
     if (members->has_local_ass_withId(p_id)) {
       ass = members->get_local_ass_byId(p_id);
     }
-    if (ass == NULL && base_type != NULL) {
-      ass = base_type->get_type_refd_last()->get_class_type_body()->
-        get_local_ass_byId(p_id);
+    if (ass == NULL && base_class != NULL) {
+      ass = base_class->get_local_ass_byId(p_id);
     }
     return ass;
   }
@@ -3216,8 +3230,8 @@ namespace Ttcn {
       return true;
     }
 
-    const ClassTypeBody* ref_scope_class = usage_scope->get_scope_class();
-    const ClassTypeBody* ass_scope_class = ass->get_my_scope()->get_scope_class();
+    ClassTypeBody* ref_scope_class = usage_scope->get_scope_class();
+    ClassTypeBody* ass_scope_class = ass->get_my_scope()->get_scope_class();
     if (ass_scope_class == NULL) {
       FATAL_ERROR("ClassTypeBody::chk_visibility()");
     }
@@ -3258,8 +3272,7 @@ namespace Ttcn {
         else {
           // send the reference to the base type, with the reftype changed to 'this'
           p_ref->set_reftype(Ref_simple::REF_THIS);
-          Common::Assignment* ass = base_type->get_type_refd_last()->
-            get_class_type_body()->get_ass_bySRef(p_ref);
+          Common::Assignment* ass = base_class->get_ass_bySRef(p_ref);
           p_ref->set_reftype(Ref_simple::REF_SUPER);
           return ass;
         }
@@ -3294,7 +3307,10 @@ namespace Ttcn {
       return;
     }
     checked = true;
-    // TODO: external? final? abstract?
+    if (final && abstract) {
+      error("Final classes cannot be abstract");
+    }
+    // TODO: external?
     if (base_type != NULL) {
       Error_Context cntxt(base_type, "In superclass definition");
       base_type->chk();
@@ -3306,11 +3322,14 @@ namespace Ttcn {
         delete base_type;
         base_type = NULL;
       }
-      // TODO: additional checks for the base type
+      else {
+        base_class = base_type->get_type_refd_last()->get_class_type_body();
+        if (base_class->final) {
+          base_type->error("The superclass cannot be final");
+        }
+      }
     }
-
-    ClassTypeBody* base_class = base_type != NULL ? 
-      base_type->get_type_refd_last()->get_class_type_body() : NULL;
+    
     if (runs_on_ref != NULL) {
       Error_Context cntxt(runs_on_ref, "In `runs on' clause");
       runs_on_type = runs_on_ref->chk_comptype_ref();
@@ -3375,7 +3394,6 @@ namespace Ttcn {
     for (size_t i = 0; i < members->get_nof_asss(); ++i) {
       Common::Assignment* ass = members->get_ass_byIndex(i, false);
       if (ass->get_asstype() == Common::Assignment::A_CONSTRUCTOR) {
-        // TODO: check for multiple constructors, or is that handled by previous checks?
         constructor = dynamic_cast<Def_Constructor*>(ass);
         if (constructor == NULL) {
           FATAL_ERROR("ClassTypeBody::chk");
@@ -3453,6 +3471,46 @@ namespace Ttcn {
     if (finally_block != NULL) {
       finally_block->chk();
     }
+    
+    if (abstract) {
+      // create a map of all abstract functions (including inherited ones)
+      if (base_class != NULL && base_class->abstract) {
+        for (size_t i = 0; i < base_class->abstract_functions.size(); ++i) {
+          abstract_functions.add(base_class->abstract_functions.get_nth_key(i),
+            base_class->abstract_functions.get_nth_elem(i));
+        }
+      }
+      for (size_t i = 0; i < members->get_nof_asss(); ++i) {
+        Common::Assignment* ass = members->get_ass_byIndex(i, false);
+        switch (ass->get_asstype()) {
+        case Common::Assignment::A_FUNCTION:
+        case Common::Assignment::A_FUNCTION_RVAL:
+        case Common::Assignment::A_FUNCTION_RTEMP: {
+          Def_AbsFunction* def_abs_func = dynamic_cast<Def_AbsFunction*>(ass);
+          if (def_abs_func != NULL) {
+            const string& def_name = def_abs_func->get_id().get_name();
+            if (abstract_functions.has_key(def_name)) {
+              // TODO
+            }
+            else {
+              abstract_functions.add(def_name, def_abs_func);
+            }
+          }
+          break; }
+        default:
+          break;
+        }
+      }
+    }
+    
+    if (!abstract && base_class != NULL && base_class->abstract) {
+      // all abstract methods from the base class have to be implemented in this class
+      for (size_t i = 0; i < base_class->abstract_functions.size(); ++i) {
+        Def_AbsFunction* def_abs_func = base_class->abstract_functions.get_nth_elem(i);
+        def_abs_func->chk_implementation(get_local_ass_byId(def_abs_func->get_id()), this);
+      }
+    }
+    // todo: name clashes with defs in the base class?
   }
   
   void ClassTypeBody::chk_recursions(ReferenceChain& refch)
diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh
index d6a7669c07a6704d8cc4ba6a7fdf7832fcf271c9..7e4c71cf4b1b8c3a46fcf2a85eebc3efca6812f1 100644
--- a/compiler2/ttcn3/Ttcnstuff.hh
+++ b/compiler2/ttcn3/Ttcnstuff.hh
@@ -756,12 +756,13 @@ public:
 
 class ClassTypeBody : public Common::Scope, public Common::Location {
   Common::Identifier* class_id; // not owned
-  Definition* my_def; // pointer to the class type definition (not owned)
+  Def_Type* my_def; // pointer to the class type definition (not owned)
   boolean external;
   boolean final;
   boolean abstract;
   boolean built_in;
   Common::Type* base_type;
+  ClassTypeBody* base_class; // not owned
   Reference* runs_on_ref;
   Type* runs_on_type;
   Reference* mtc_ref;
@@ -773,6 +774,7 @@ class ClassTypeBody : public Common::Scope, public Common::Location {
   /** set during semantic analysis to either a pointer to the constructor in
     * 'members', or the actual default constructor (if no constructor is defined) */
   Def_Constructor* constructor;
+  map<string, Def_AbsFunction> abstract_functions;
   bool checked;
   bool default_constructor; /// true if the class uses a default constructor
   
@@ -786,7 +788,9 @@ public:
   ClassTypeBody* clone() const;
   virtual ~ClassTypeBody();
   
-  void set_my_def(Definition* p_def) { my_def = p_def; }
+  void set_my_def(Def_Type* p_def) { my_def = p_def; }
+  Def_Type* get_my_def() { return my_def; }
+  boolean is_abstract() const { return abstract; }
   
   void set_fullname(const string& p_fullname);
   void set_my_scope(Scope* p_scope);
@@ -797,13 +801,14 @@ public:
   Common::Identifier* get_id() const { return class_id; }
   Def_Constructor* get_constructor();
   Common::Type* get_base_type() const { return base_type; }
+  ClassTypeBody* get_base_class();
   boolean is_built_in() const { return built_in; }
   
   Type* get_RunsOnType();
   Type* get_MtcType();
   Type* get_SystemType();
   
-  bool is_parent_class(const ClassTypeBody* p_class) const;
+  bool is_parent_class(const ClassTypeBody* p_class);
   bool has_local_ass_withId(const Identifier& p_id);
   Common::Assignment* get_local_ass_byId(const Identifier& p_id);
   Common::Assignment* get_ass_bySRef(Common::Ref_simple* p_ref);
diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
index b2213a0ffae5f8cf324798d4151d10b224056fce..caea0ac18accd844afc4a0815db2d994c585ff74 100644
--- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn
+++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
@@ -275,6 +275,113 @@ function f_no_comp_usage() { //^In function definition//
 }
 
 
+type class C15 {
+  public var integer v;
+  public function f() { }
+  public function g() return boolean { return true; }
+}
+
+function f_access_with_class_name() { //^In function definition//
+  log(C5.v); //^In log statement// //Reference to a value, template, timer, port or class object was expected instead of type `@oop_SE.C5'//
+  log(C5.g()); //^In log statement// //Reference to a value, template, timer, port or class object was expected instead of type `@oop_SE.C5'//
+  C5.f(); //Reference to a function or altstep was expected instead of type `@oop_SE.C5', which cannot be invoked//
+  C5.g(); //Reference to a function or altstep was expected instead of type `@oop_SE.C5', which cannot be invoked//
+  if (C5.g()) { log(1); } //^In if statement// //Reference to a value was expected instead of type `@oop_SE.C5'//
+  if (C5.v == 1) { log(2); } //^In if statement// //Reference to a value was expected instead of type `@oop_SE.C5'//
+  var integer x1 := C5.v + 1; //^In variable definition// //^In the left operand of operation// //Reference to a value was expected instead of type `@oop_SE.C5'//
+  var boolean x2 := C5.g(); //^In variable definition// //Reference to a value was expected instead of type `@oop_SE.C5'//
+}
+
+
+function f_init_values() { //^In function definition//
+  var integer v_int := 3;
+  var template integer vt_int := (1..10);
+  var C4 v1 := 1; //^In variable definition// //class value was expected//
+  var C4 v2 := v_int; //^In variable definition// //Type mismatch\: a value of type `@oop_SE.C4' was expected instead of `integer'//
+  var C4 v3 := valueof(vt_int) + v_int; //^In variable definition// //Incompatible value\: `@oop_SE.C4' value was expected//
+  var C4 v4 := CT_RunsOn.create; //^In variable definition// //Incompatible value\: `@oop_SE.C4' value was expected//
+  var C4 v5 := C11.create; //^In variable definition// //Incompatible class types\: operation `create' should refer to `@oop_SE.C4' instead of `@oop_SE.C11'//
+}
+
+
+type class C16 extends C15 { //^In type definition//
+  create() : C15(1) { } //Previous definition of `create' is here//
+  create(in integer p) : C15(p) { } //Duplicate definition with name `create'//
+}
+
+type class C17 { //^In type definition//
+  create() : C15(1) { } //^In constructor definition// //^In super-constructor call// //Class type `@oop_SE.C17' does not have a superclass//
+}
+
+type class C18 extends C15 { //^In type definition//
+  create() : C16() { } //^In constructor definition// //^In super-constructor call// //expected call to constructor of class type `@oop_SE.C15', instead of class type `@oop_SE.C16'//
+}
+
+type class C19 extends C15 { //^In type definition//
+  create() { } //^In constructor definition// //Missing super-constructor call//
+}
+
+type class C20 extends C15 { //^In type definition//
+  create() : f_embedded_types() { } //^In constructor definition// //^In super-constructor call// //Reference to constructor was expected instead of function//
+}
+
+
+type class @final @abstract C21 { } //^In type definition// //Final classes cannot be abstract//
+
+type class @final C22 { }
+
+type class C23 extends C22 { } //^In type definition// //^In superclass definition// //The superclass cannot be final//
+
+type class @abstract C24 { //^In type definition//
+  public function @abstract f1(in Nonexistent a); //^In abstract function definition// //^In formal parameter list// //^In parameter// //There is no local or imported definition with name `Nonexistent'//
+  public function @abstract f2() return template Nonexistent; //^In abstract function definition// //^In return type// //There is no local or imported definition with name `Nonexistent'//
+  public function @abstract f3() return Port; //^In abstract function definition// //^In return type// //Port type `@oop_SE.Port' cannot be the return type of an abstract function//
+}
+
+function f_inst_abstract() { //^In function definition//
+  var C24 x := C24.create; //^In variable definition// //Cannot create an instance of abstract class type `@oop_SE.C24'//
+}
+
+type class @abstract C25 {
+  public function @abstract f_abs() return integer;
+}
+
+type class @abstract C26 extends C25 {
+  public function @abstract f_abs2(inout template integer p);
+}
+
+type class C27 extends C26 { } //^In type definition// //Missing implementation of abstract method `@oop_SE.C25.f_abs'// //Missing implementation of abstract method `@oop_SE.C26.f_abs2'//
+
+type class C28 extends C25 { //^In type definition//
+  public var integer f_abs; //variable `@oop_SE.C28.f_abs' shadows inherited abstract method `@oop_SE.C25.f_abs'//
+}
+
+type class C29 extends C26 { //^In type definition// //Missing implementation of abstract method `@oop_SE.C25.f_abs'//
+  public function f_abs2(inout template integer p) { }
+}
+
+type class C30 extends C26 {
+  public function f_abs() return integer { return 1; }
+  public function f_abs2(inout template integer p) { }
+}
+
+type class C31 extends C25 { //^In type definition//
+  public function f_abs(in template integer p) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
+}
+
+type class C32 extends C25 { //^In type definition//
+  public function f_abs(inout integer p) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
+}
+
+type class C33 extends C25 { //^In type definition//
+  public function f_abs(inout template integer q) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
+}
+
+type class C34 extends C25 { //^In type definition//
+  public function f_abs(inout template integer p) return boolean { return false; } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
+}
+
+
 control { //^In control part//
   var C11 x := C11.create; //^In variable definition// //A definition without `runs on' clause cannot create a value of class type `@oop_SE.C11', which runs on component type `@oop_SE.CT_RunsOn'// //Cannot create value of class type `@oop_SE.C11', which has an `mtc' clause, in the control part.// //Cannot create value of class type `@oop_SE.C11', which has a `system' clause, in the control part.//
 }
diff --git a/regression_test/oop/oop.ttcn b/regression_test/oop/oop.ttcn
index 63601f402adac2a579339c4dfbbcccffb78501d6..047ceadb4c1943d864e86aba03e88db72ceecc29 100644
--- a/regression_test/oop/oop.ttcn
+++ b/regression_test/oop/oop.ttcn
@@ -460,6 +460,17 @@ testcase tc_order() runs on CT {
   }
 }
 
+testcase tc_abstract() runs on CT {
+  var AbstractClass v := ConcreteClass.create;
+  var integer x := 0;
+  if (v.f_abs(x) and x == 1) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
 
 control {
   execute(tc_members_and_methods());
@@ -471,6 +482,7 @@ control {
   execute(tc_function_pars_and_retval());
   execute(tc_object());
   execute(tc_order());
+  execute(tc_abstract());
 }
 
 }