diff --git a/compiler2/SigParam.cc b/compiler2/SigParam.cc
index 148920d04686e1a43c90e8fd361cfe169d83c40e..702e5a1f4e6e54d590e724fade302cb24d580464 100644
--- a/compiler2/SigParam.cc
+++ b/compiler2/SigParam.cc
@@ -14,6 +14,7 @@
 
 #include "Type.hh"
 #include "CompilerError.hh"
+#include "AST.hh"
 
 namespace Common {
 
@@ -251,6 +252,47 @@ void SignatureExceptions::chk(Type *p_signature)
   }
 }
 
+void SignatureExceptions::chk(Assignment* p_def)
+{
+  Error_Context cntxt(this, "In exception list");
+  for (size_t i = 0; i < exc_v.size(); i++) {
+    Type* type = exc_v[i];
+    type->set_genname(p_def->get_id().get_name(), string("_exception_") + Int2string(i + 1));
+    type->chk();
+    if (type->get_typetype() == Type::T_ERROR) continue;
+    Type* type_last = type->get_type_refd_last();
+    bool type_error = false;
+    char* error_msg_start = NULL;
+    switch (type_last->get_typetype()) {
+    case Type::T_PORT:
+      type_error = true;
+      error_msg_start = mprintf("Port type `%s'", type_last->get_typename().c_str());
+      break;
+    case Type::T_SIGNATURE:
+      type_error = true;
+      error_msg_start = mprintf("Signature `%s'", type_last->get_typename().c_str());
+      break;
+    case Type::T_DEFAULT:
+      type_error = true;
+      error_msg_start = mcopystr("Default type");
+      break;
+    default:
+      break;
+    }
+    if (type_error) {
+      type->error("%s cannot be on the exception list of a%s %s",
+        error_msg_start, p_def->get_asstype() == Assignment::A_FUNCTION ? "" : "n", p_def->get_assname());
+    }
+    Free(error_msg_start);
+    const string& type_name = type->get_exception_name();
+    if (exc_m.has_key(type_name)) {
+      type->error("Duplicate type in exception list");
+      exc_m[type_name]->note("Type `%s' is already given here",
+        type_name.c_str());
+    } else exc_m.add(type_name, type);
+  }
+}
+
 void SignatureExceptions::set_fullname(const string& p_fullname)
 {
   Node::set_fullname(p_fullname);
diff --git a/compiler2/SigParam.hh b/compiler2/SigParam.hh
index 91436af4de8daa944ba155d69e5eabea7f9a707a..e518f3c600f3670b41fcce7c6b1c86709d1957d5 100644
--- a/compiler2/SigParam.hh
+++ b/compiler2/SigParam.hh
@@ -83,7 +83,7 @@ public:
 };
 
 /**
- * Signature exception-list
+ * Signature or OOP exception-list
  */
 class SignatureExceptions : public Node, public Location {
   vector<Type> exc_v;
@@ -106,7 +106,10 @@ public:
   Type *get_type_byName(const string& p_typename) const
    { return exc_m[p_typename]; }
 
+  /** Semantic check for a signature exception list */
   void chk(Type *p_signature);
+  /** Semantic check for a function, external function or altstep exception list (as part of the OOP features) */
+  void chk(Assignment* p_def);
   virtual void set_fullname(const string& p_fullname);
   virtual void set_my_scope(Scope *p_scope);
   virtual void dump(unsigned level) const;
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index a37e008b8090d021fed183bf5d07a342d6c01275..8d140be73f16725285563e03bab9960ec5aa3dd3 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -47,6 +47,7 @@
 #include "../CodeGenHelper.hh"
 #include "../../common/JSON_Tokenizer.hh"
 #include "../DebuggerStuff.hh"
+#include "../SigParam.hh"
 #include <limits.h>
 
 // implemented in coding_attrib_p.y
@@ -5367,21 +5368,27 @@ namespace Ttcn {
   void Def_Var::chk()
   {
     if(checked) return;
-    Error_Context cntxt(this, "In variable definition `%s'",
-      id->get_dispname().c_str());
+    Error_Context cntxt(this, "In %s definition `%s'",
+      asstype == A_EXCEPTION ? "exception" : "variable", id->get_dispname().c_str());
     type->set_genname(_T_, get_genname());
     type->chk();
     checked = true;
     Type *t = type->get_type_refd_last();
     switch (t->get_typetype()) {
     case Type::T_PORT:
-      error("Variable cannot be defined for port type `%s'",
-        t->get_fullname().c_str());
+      error("%s cannot be defined for port type `%s'",
+        asstype == A_EXCEPTION ? "Exception" : "Variable", t->get_fullname().c_str());
       break;
     case Type::T_SIGNATURE:
-      error("Variable cannot be defined for signature `%s'",
-        t->get_fullname().c_str());
+      error("%s cannot be defined for signature `%s'",
+        asstype == A_EXCEPTION ? "Exception" : "Variable", t->get_fullname().c_str());
       break;
+    case Type::T_DEFAULT:
+      if (asstype == A_EXCEPTION) {
+        error("Exception cannot be defined for the default type");
+        break;
+      }
+      // else fall through
     default:
     if (initial_value) {
       initial_value->set_my_governor(type);
@@ -6609,7 +6616,7 @@ namespace Ttcn {
 
   Def_Function_Base::Def_Function_Base(const Def_Function_Base& p)
     : Definition(p), prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
-    final(p.final)
+    final(p.final), exceptions(p.exceptions)
   {
     fp_list = p.fp_list->clone();
     fp_list->set_my_def(this);
@@ -6619,11 +6626,13 @@ namespace Ttcn {
 
   Def_Function_Base::Def_Function_Base(bool is_external, Identifier *p_id,
     FormalParList *p_fpl, Type *p_return_type, bool returns_template,
-    template_restriction_t p_template_restriction, bool p_final)
+    template_restriction_t p_template_restriction, bool p_final,
+    Common::SignatureExceptions* p_exceptions)
     : Definition(determine_asstype(is_external, p_return_type != 0,
         returns_template), p_id), fp_list(p_fpl), return_type(p_return_type),
         prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
-        template_restriction(p_template_restriction), final(p_final)
+        template_restriction(p_template_restriction), final(p_final),
+        exceptions(p_exceptions)
   {
     if (!p_fpl) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
     fp_list->set_my_def(this);
@@ -6634,6 +6643,7 @@ namespace Ttcn {
   {
     delete fp_list;
     delete return_type;
+    delete exceptions;
   }
 
   void Def_Function_Base::set_fullname(const string& p_fullname)
@@ -6641,6 +6651,9 @@ namespace Ttcn {
     Definition::set_fullname(p_fullname);
     fp_list->set_fullname(p_fullname + ".<formal_par_list>");
     if (return_type) return_type->set_fullname(p_fullname + ".<return_type>");
+    if (exceptions != NULL) {
+      exceptions->set_fullname(p_fullname + ".<exceptions>");
+    }
   }
 
   void Def_Function_Base::set_my_scope(Scope *p_scope)
@@ -6648,6 +6661,9 @@ namespace Ttcn {
     Definition::set_my_scope(p_scope);
     fp_list->set_my_scope(p_scope);
     if (return_type) return_type->set_my_scope(p_scope);
+    if (exceptions != NULL) {
+      exceptions->set_my_scope(p_scope);
+    }
   }
 
   Type *Def_Function_Base::get_Type()
@@ -6837,6 +6853,20 @@ namespace Ttcn {
         return false;
       }
     }
+    if (exceptions != NULL || p_other->exceptions != NULL) {
+      if (exceptions == NULL || p_other->exceptions == NULL) {
+        // one of them has exceptions, the other doesn't
+        return false;
+      }
+      if (exceptions->get_nof_types() != p_other->exceptions->get_nof_types()) {
+        return false;
+      }
+      for (size_t i = 0; i < exceptions->get_nof_types(); ++i) {
+        if (!p_other->exceptions->has_type(exceptions->get_type_byIndex(i))) {
+          return false;
+        }
+      }
+    }
     return true;
   }
 
@@ -6851,9 +6881,9 @@ namespace Ttcn {
                              Type *p_return_type,
                              bool returns_template,
                              template_restriction_t p_template_restriction,
-                             bool p_final, StatementBlock *p_block)
+                             bool p_final, Common::SignatureExceptions* p_exceptions, StatementBlock *p_block)
     : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
-        p_template_restriction, p_final),
+        p_template_restriction, p_final, p_exceptions),
         runs_on_ref(p_runs_on_ref), runs_on_type(0),
         mtc_ref(p_mtc_ref), mtc_type(0),
         system_ref(p_system_ref), system_type(0),
@@ -7101,6 +7131,9 @@ namespace Ttcn {
         break;
       }
     }
+    if (exceptions != NULL) {
+      exceptions->chk(this);
+    }
     if (!semantic_check_only) {
       fp_list->set_genname(get_genname());
       block->set_code_section(GovernedSimple::CS_INLINE);
@@ -7345,6 +7378,10 @@ namespace Ttcn {
     DEBUG(level + 1, "Deterministic: %s", deterministic ? "true" : "false");
     if (prototype != PROTOTYPE_NONE)
       DEBUG(level + 1, "Prototype: %s", get_prototype_name());
+    if (exceptions != NULL) {
+      DEBUG(level + 1, "Exceptions:");
+      exceptions->dump(level + 2);
+    }
     //DEBUG(level + 1, "Statement block:");
     block->dump(level + 1);
   }
@@ -7797,6 +7834,13 @@ namespace Ttcn {
         (Type::CT_JSON != encoding_type && Type::CT_XER != encoding_type))) {
       error("Attribute 'printing' is only allowed for JSON and XER encoding functions.");
     }
+    
+    if (exceptions != NULL) {
+      exceptions->chk(this);
+      if (function_type != EXTFUNC_MANUAL) {
+        error("Exception list is only allowed for manually written external functions");
+      }
+    }
   }
 
   char *Def_ExtFunction::generate_code_encode(char *str)
@@ -8157,6 +8201,10 @@ namespace Ttcn {
         DEBUG(level + 2, "Encoding options: %s", encoding_options->c_str());
     }
     if (eb_list) eb_list->dump(level + 1);
+    if (exceptions != NULL) {
+      DEBUG(level + 1, "Exceptions:");
+      exceptions->dump(level + 2);
+    }
   }
   
   void Def_ExtFunction::generate_json_schema_ref(map<Type*, JSON_Tokenizer>& json_refs)
@@ -8312,6 +8360,9 @@ namespace Ttcn {
       return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,
         "n abstract function");
     }
+    if (exceptions != NULL) {
+      exceptions->chk(this);
+    }
     if (!semantic_check_only) {
       fp_list->set_genname(get_genname());
     }
@@ -8355,10 +8406,10 @@ namespace Ttcn {
   Def_Altstep::Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
                            Reference *p_runs_on_ref, Reference *p_mtc_ref,
                            Reference *p_system_ref, StatementBlock *p_sb,
-                           AltGuards *p_ags)
+                           AltGuards *p_ags, Common::SignatureExceptions* p_exceptions)
     : Definition(A_ALTSTEP, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
       runs_on_type(0), mtc_ref(p_mtc_ref), mtc_type(0),
-      system_ref(p_system_ref), system_type(0), sb(p_sb), ags(p_ags)
+      system_ref(p_system_ref), system_type(0), sb(p_sb), ags(p_ags), exceptions(p_exceptions)
   {
     if (!p_fpl || !p_sb || !p_ags)
       FATAL_ERROR("Def_Altstep::Def_Altstep()");
@@ -8376,6 +8427,7 @@ namespace Ttcn {
     delete system_ref;
     delete sb;
     delete ags;
+    delete exceptions;
   }
 
   Def_Altstep *Def_Altstep::clone() const
@@ -8392,6 +8444,9 @@ namespace Ttcn {
     if (system_ref) system_ref->set_fullname(p_fullname + ".<system_type>");
     sb->set_fullname(p_fullname+".<block>");
     ags->set_fullname(p_fullname + ".<guards>");
+    if (exceptions != NULL) {
+      exceptions->set_fullname(p_fullname + ".<exceptions>");
+    }
   }
 
   void Def_Altstep::set_my_scope(Scope *p_scope)
@@ -8406,6 +8461,9 @@ namespace Ttcn {
     if (system_ref) system_ref->set_my_scope(&bridgeScope);
     sb->set_my_scope(fp_list);
     ags->set_my_scope(sb);
+    if (exceptions != NULL) {
+      exceptions->set_my_scope(&bridgeScope);
+    }
   }
 
   Type *Def_Altstep::get_RunsOnType()
@@ -8479,6 +8537,9 @@ namespace Ttcn {
       w_attrib_path->chk_global_attrib();
       w_attrib_path->chk_no_qualif();
     }
+    if (exceptions != NULL) {
+      exceptions->chk(this);
+    }
   }
 
   void Def_Altstep::generate_code(output_struct *target, bool)
@@ -8635,6 +8696,10 @@ namespace Ttcn {
       DEBUG(level + 1, "System clause:");
       system_ref->dump(level + 2);
     }
+    if (exceptions != NULL) {
+      DEBUG(level + 1, "Exceptions:");
+      exceptions->dump(level + 2);
+    }
     /*
     DEBUG(level + 1, "Local definitions:");
     sb->dump(level + 2);
diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh
index 5f70a1b9337c967b472880eb4e7d5ab9e219db7c..5d6dd9aa371753a40471fd74749815aa2ac2b28b 100644
--- a/compiler2/ttcn3/AST_ttcn3.hh
+++ b/compiler2/ttcn3/AST_ttcn3.hh
@@ -1384,6 +1384,7 @@ namespace Ttcn {
     /** optional template restriction on return template value */
     template_restriction_t template_restriction;
     bool final;
+    Common::SignatureExceptions* exceptions;
 
     static asstype_t determine_asstype(bool is_external, bool has_return_type,
       bool returns_template);
@@ -1404,7 +1405,8 @@ namespace Ttcn {
      */
     Def_Function_Base(bool is_external, Identifier *p_id,
       FormalParList *p_fpl, Type *p_return_type, bool returns_template,
-      template_restriction_t p_template_restriction, bool p_final);
+      template_restriction_t p_template_restriction, bool p_final, 
+      Common::SignatureExceptions* p_exceptions);
     virtual ~Def_Function_Base();
     virtual void set_fullname(const string& p_fullname);
     virtual void set_my_scope(Scope *p_scope);
@@ -1502,7 +1504,7 @@ namespace Ttcn {
                  Reference *p_system_ref, Reference *p_port_ref,
                  Type *p_return_type, bool returns_template,
                  template_restriction_t p_template_restriction,
-                 bool p_final, StatementBlock *p_block);
+                 bool p_final, Common::SignatureExceptions* p_exceptions, StatementBlock *p_block);
     virtual ~Def_Function();
     virtual Def_Function *clone() const;
     virtual void set_fullname(const string& p_fullname);
@@ -1598,9 +1600,10 @@ namespace Ttcn {
      */
     Def_ExtFunction(bool p_deterministic, Identifier *p_id, FormalParList *p_fpl,
       Type *p_return_type, bool returns_template,
-      template_restriction_t p_template_restriction, bool p_final, bool p_ext_keyword)
+      template_restriction_t p_template_restriction, bool p_final,
+      Common::SignatureExceptions* p_exceptions, bool p_ext_keyword)
       : Def_Function_Base(true, p_id, p_fpl, p_return_type, returns_template,
-          p_template_restriction, p_final),
+          p_template_restriction, p_final, p_exceptions),
       function_type(EXTFUNC_MANUAL), encoding_type(Type::CT_UNDEF),
       encoding_options(0), eb_list(0), printing(0),
       deterministic(p_deterministic), ext_keyword(p_ext_keyword) { }
@@ -1643,9 +1646,9 @@ namespace Ttcn {
   public:
     Def_AbsFunction(bool p_deterministic, Identifier* p_id, FormalParList* p_fpl,
       Type* p_return_type, bool returns_template,
-      template_restriction_t p_template_restriction)
+      template_restriction_t p_template_restriction, Common::SignatureExceptions* p_exceptions)
     : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
-      p_template_restriction, false) { }
+      p_template_restriction, false, p_exceptions) { }
     virtual ~Def_AbsFunction();
     virtual Definition* clone() const;
     virtual void chk();
@@ -1686,6 +1689,7 @@ namespace Ttcn {
     Type *system_type;
     StatementBlock *sb; /**< contains the local definitions */
     AltGuards *ags;
+    Common::SignatureExceptions* exceptions;
 
     NameBridgingScope bridgeScope;
 
@@ -1697,7 +1701,7 @@ namespace Ttcn {
     Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
                 Reference *p_runs_on_ref, Reference *p_mtc_ref,
                 Reference *p_system_ref, StatementBlock *p_sb,
-                AltGuards *p_ags);
+                AltGuards *p_ags, Common::SignatureExceptions* p_exceptions);
     virtual ~Def_Altstep();
     virtual Def_Altstep *clone() const;
     virtual void set_fullname(const string& p_fullname);
diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index b606bc4926fd1542e1feca2ced775c4d3524de2a..19661463caa5e9fa8aad53591ec1bec28aa57089 100644
--- a/compiler2/ttcn3/Statement.cc
+++ b/compiler2/ttcn3/Statement.cc
@@ -283,12 +283,29 @@ namespace Ttcn {
     p_finally->exception_handling = EH_OOP_FINALLY;
     finally_block = p_finally;
   }
+  
+  boolean StatementBlock::is_in_finally_block() const
+  {
+    if (exception_handling == EH_OOP_FINALLY) {
+      return TRUE;
+    }
+    if (my_sb != NULL) {
+      return my_sb->is_in_finally_block();
+    }
+    return FALSE;
+  }
+  
+  boolean StatementBlock::is_empty() const
+  {
+    return stmts.size() == 0 && exception_handling == StatementBlock::EH_NONE &&
+      catch_blocks.size() == 0 && finally_block == NULL;
+  }
 
   StatementBlock::returnstatus_t StatementBlock::has_return() const
   {
     returnstatus_t ret_val = RS_NO;
     size_t nof_stmts = stmts.size();
-    for (size_t i = 0; i < nof_stmts; i++) {
+    for (size_t i = 0; i < nof_stmts && ret_val != RS_YES; i++) {
       Statement *stmt = stmts[i];
       if (stmt->get_statementtype() == Statement::S_GOTO) {
 	if (stmt->goto_jumps_forward()) {
@@ -300,7 +317,7 @@ namespace Ttcn {
 	    if (stmt->get_statementtype() == Statement::S_LABEL &&
 		stmt->label_is_used()) break;
 	  }
-	} else return RS_YES;
+	} else ret_val = RS_YES;
       } else if (stmt->get_statementtype()==Statement::S_BLOCK && stmt->get_block()->exception_handling!=EH_NONE) {
         switch (stmt->get_block()->exception_handling) {
         case EH_TRY: // the i-th statement is a try{} statement block, the (i+1)-th must be a catch{} block
@@ -311,9 +328,11 @@ namespace Ttcn {
             if (try_block_rs==catch_block_rs) {
               switch (try_block_rs) {
               case RS_YES:
-                return RS_YES;
+                ret_val = RS_YES;
+                break;
               case RS_MAYBE:
                 ret_val = RS_MAYBE;
+                break;
               default:
                 break;
               }
@@ -333,14 +352,28 @@ namespace Ttcn {
       } else {
 	switch (stmt->has_return()) {
 	case RS_YES:
-	  return RS_YES;
+	  ret_val = RS_YES;
+	  break;
 	case RS_MAYBE:
 	  ret_val = RS_MAYBE;
+	  break;
 	default:
 	  break;
 	}
       }
     }
+    for (size_t i = 0; i < catch_blocks.size(); ++i) {
+      // all 'catch' blocks must also have return for the statement block to have return
+      switch(catch_blocks[i]->has_return()) {
+      case RS_YES:
+        break; // OK, keep checking
+      case RS_MAYBE:
+        return RS_MAYBE;
+      case RS_NO:
+        ret_val = (ret_val == RS_NO) ? RS_NO : RS_MAYBE;
+        break;
+      }
+    }
     return ret_val;
   }
 
@@ -418,9 +451,25 @@ namespace Ttcn {
     }
     chk_trycatch_blocks(prev_stmt, 0);
     chk_unused_labels();
+    map<string, Definition> catch_types;
     for (size_t i = 0; i < catch_blocks.size(); ++i) {
-      catch_blocks[i]->chk();
+      if (oop_features) {
+        catch_blocks[i]->chk();
+        Definition* def_exc = catch_blocks[i]->get_stmt_byIndex(0)->get_def();
+        string catch_type_str = def_exc->get_Type()->get_exception_name();
+        if (catch_types.has_key(catch_type_str)) {
+          def_exc->error("Duplicate catch block definition for exception type `%s'", catch_type_str.c_str());
+          catch_types[catch_type_str]->note("Catch block for the same exception type already defined here");
+        }
+        else {
+          catch_types.add(catch_type_str, def_exc);
+        }
+      }
+      else {
+        catch_blocks[i]->error("The compiler option `-k' must be activated to use object-oriented features such as catch clauses.");
+      }
     }
+    catch_types.clear();
     if (finally_block != NULL) {
       finally_block->chk();
     }
@@ -531,9 +580,14 @@ namespace Ttcn {
           tmp_id.c_str());
       }
       str = mputprintf(str,
-        "~%s_finally() {\n", tmp_id.c_str());
+        "~%s_finally() {\n"
+        "try {\n", tmp_id.c_str());
       str = finally_block->generate_code(str, def_glob_vars, src_glob_vars);
       str = mputprintf(str,
+        "} catch (...) {\n"
+        "fprintf(stderr, \"Unhandled exception or dynamic test case error in a finally block. Terminating application.\\n\");\n"
+        "exit(EXIT_FAILURE);\n"
+        "}\n"
         "}\n"
         "};\n"
         "%s_finally %s%s;\n",
@@ -3819,6 +3873,10 @@ error:
             "It is allowed only in functions and altsteps");
       goto error;
     }
+    if (my_sb->is_in_finally_block()) {
+      error("Return statement cannot be used inside a finally block or the destructor of a class.");
+      goto error;
+    }
     switch (my_def->get_asstype()) {
     case Definition::A_FUNCTION:
       if (returnexpr.t) {
@@ -6353,38 +6411,60 @@ error:
   void Statement::chk_raise_oop()
   {
     Error_Context cntxt(this, "In raise statement");
+    if (!oop_features) {
+      error("The compiler option `-k' must be activated to use object-oriented features such as raise statements.");
+    }
+    Definition *my_def = my_sb->get_my_def();
+    if (!my_def) {
+      error("Raise statement cannot be used in the control part. "
+            "It is allowed only in functions, altsteps and testcases.");
+    }
+    if (my_sb->is_in_finally_block()) {
+      error("Raise statement cannot be used inside a finally block or the destructor of a class.");
+    }
     Common::Type* exc_type = raise_op.ti->get_expr_governor(Common::Type::EXPECTED_DYNAMIC_VALUE);
     if (exc_type == NULL) {
       raise_op.ti->get_Template()->set_lowerid_to_ref();
       exc_type = raise_op.ti->get_expr_governor(Common::Type::EXPECTED_DYNAMIC_VALUE);
     }
     if (exc_type == NULL) {
-      // TODO
-    }
-    else {
-      if (raise_op.ti->get_Type() == exc_type) {
-        // don't use the type indicator of the TemplateInstance
-        // (i.e. the 'type:' part of the in-line template)
-        // as the exception's governor, because it will be deleted
-        if (exc_type->is_ref()) {
-          exc_type = exc_type->get_type_refd();
-        }
-        else {
-          exc_type = Type::get_pooltype(exc_type->get_typetype());
-        }
+      if (raise_op.ti->get_Template()->get_templatetype() != Template::TEMPLATE_ERROR &&
+          (raise_op.ti->get_Template()->get_templatetype() != Template::SPECIFIC_VALUE ||
+           raise_op.ti->get_Template()->get_specific_value()->get_valuetype() != Common::Value::V_ERROR)) {
+        error("Cannot determine the type of the raised exception.");
       }
-      raise_op.ti->chk(exc_type);
-      if (!raise_op.ti->get_Template()->is_Value()) {
-        // TODO: error
-        delete raise_op.ti;
-        raise_op.v = new Common::Value(Common::Value::V_ERROR);
+      exc_type = Type::get_pooltype(Type::T_ERROR);
+    }
+    switch (exc_type->get_type_refd_last()->get_typetype()) {
+    case Common::Type::T_DEFAULT:
+    case Common::Type::T_SIGNATURE:
+    //case Common::Type::T_PORT: // this case is handled by Template::get_expr_governor
+      error("Cannot raise an exception of type %s", exc_type->get_typename().c_str());
+      break;
+    default:
+      break;
+    }
+    if (raise_op.ti->get_Type() == exc_type) {
+      // don't use the type indicator of the TemplateInstance
+      // (i.e. the 'type:' part of the in-line template)
+      // as the exception's governor, because it will be deleted
+      if (exc_type->is_ref()) {
+        exc_type = exc_type->get_type_refd();
       }
       else {
-        Common::Value* val = raise_op.ti->get_Template()->get_Value();
-        delete raise_op.ti;
-        raise_op.v = val;
+        exc_type = Type::get_pooltype(exc_type->get_typetype());
       }
-      // TODO
+    }
+    raise_op.ti->chk(exc_type);
+    if (!raise_op.ti->get_Template()->is_Value()) {
+      error("A specific value without matching symbols or a reference to a value was expected for a raised exception.");
+      delete raise_op.ti;
+      raise_op.v = new Common::Value(Common::Value::V_ERROR);
+    }
+    else {
+      Common::Value* val = raise_op.ti->get_Template()->get_Value();
+      delete raise_op.ti;
+      raise_op.v = val;
     }
     raise_op.checked = true;
   }
@@ -7179,7 +7259,7 @@ error:
     default:
       FATAL_ERROR("Statement::generate_code_block()");
     }
-    if (block->get_nof_stmts() > 0 || block->get_exception_handling()!=StatementBlock::EH_NONE) {
+    if (!block->is_empty()) {
       str = mputstr(str, "{\n");
       if (debugger_active) {
         str = mputstr(str, "TTCN3_Debug_Scope debug_scope;\n");
diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh
index 773ee00f3a23fe5127e769cde19f7562573ccefd..b90976b09758477909d620a3253e57f81c697d36 100644
--- a/compiler2/ttcn3/Statement.hh
+++ b/compiler2/ttcn3/Statement.hh
@@ -132,6 +132,8 @@ namespace Ttcn {
     void set_my_laic_stmt(AltGuards *p_ags, Statement *p_loop_stmt);
     void add_catch_block(StatementBlock* p_catch);
     void set_finally_block(StatementBlock* p_finally);
+    boolean is_in_finally_block() const;
+    boolean is_empty() const;
     returnstatus_t has_return() const;
     /** Used when generating code for interleaved statement. If has
      *  not recv stmt, then the general code generation can be used
diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc
index 8934d5563e80af882d9230107c9276e89bcd901e..32c3d9255bcf156905cabc3220b3b2b62e631818 100644
--- a/compiler2/ttcn3/Ttcnstuff.cc
+++ b/compiler2/ttcn3/Ttcnstuff.cc
@@ -3081,6 +3081,9 @@ namespace Ttcn {
     if (members == NULL) {
       FATAL_ERROR("ClassTypeBody::ClassTypeBody");
     }
+    if (finally_block != NULL) {
+      finally_block->set_exception_handling(StatementBlock::EH_OOP_FINALLY);
+    }
   }
   
   ClassTypeBody::ClassTypeBody()
@@ -3663,6 +3666,7 @@ namespace Ttcn {
     }
 
     if (finally_block != NULL) {
+      Error_Context cntxt(finally_block, "In class destructor");
       finally_block->chk();
     }
     
@@ -3886,7 +3890,7 @@ namespace Ttcn {
         local_struct->source.methods = mputprintf(local_struct->source.methods,
           "} catch (...) {\n"
           "fprintf(stderr, \"Unhandled exception or dynamic test case error in "
-          "destructor of class `%s'\");\n"
+          "the destructor of class `%s'. Terminating application.\\n\");\n"
           "exit(EXIT_FAILURE);\n"
           "}\n"
           "}\n\n", class_id->get_name().c_str());
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index 8601873c1918ce61a81b941e664c800f65164bd2..42954a696f6cc14ff9b8733e55d55dbd4a302d73 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -3681,34 +3681,34 @@ ClassMember:
 ClassFunctionDef:
   FunctionKeyword optFinalModifier
   optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
-  optReturnType optError StatementBlock
+  optReturnType optExceptionSpec optError StatementBlock
   {
     $$ = new Def_Function($3, $4, $6, NULL, NULL, NULL, NULL, $8.type,
-      $8.returns_template, $8.template_restriction, $2, $10);
+      $8.returns_template, $8.template_restriction, $2, $9, $11);
     $$->set_location(infile, @$);
   }
 | FunctionKeyword optFinalModifier AbstractKeyword
   optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
-  optReturnType optError
+  optReturnType optExceptionSpec optError
   {
     $$ = new Def_AbsFunction($4, $5, $7, $9.type, $9.returns_template,
-      $9.template_restriction);
+      $9.template_restriction, $10);
     $$->set_location(infile, @$);
   }
 | ExtKeyword FunctionKeyword optFinalModifier
   optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
-  optReturnType
+  optReturnType optExceptionSpec
   {
     $$ = new Def_ExtFunction($4, $5, $7, $9.type, $9.returns_template,
-      $9.template_restriction, $3, true);
+      $9.template_restriction, $3, $10, true);
     $$->set_location(infile, @$);
   }
 | FunctionKeyword optFinalModifier
   optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
-  optReturnType
+  optReturnType optExceptionSpec
   {
     $$ = new Def_ExtFunction($3, $4, $6, $8.type, $8.returns_template,
-      $8.template_restriction, $2, false);
+      $8.template_restriction, $2, $9, false);
     $$->set_location(infile, @$);
   }
 ;
@@ -4578,11 +4578,11 @@ ValueofOp: // 162
 
 FunctionDef: // 164
   FunctionKeyword optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
-  optRunsOnSpec AltOrTcConfigSpec optPortSpec optReturnType optError StatementBlock
+  optRunsOnSpec AltOrTcConfigSpec optPortSpec optReturnType optExceptionSpec optError StatementBlock
   {
     $5->set_location(infile, @4, @6);
     $$ = new Def_Function($2, $3, $5, $7, $8.mtcref, $8.systemref, $9, $10.type, $10.returns_template,
-                          $10.template_restriction, false, $12);
+                          $10.template_restriction, false, $11, $13);
     $$->set_location(infile, @$);
   }
 ;
@@ -5232,25 +5232,25 @@ TestcaseActualPar:
 
 AltstepDef: // 211
   AltstepKeyword IDentifier '(' optAltstepFormalParList ')' optRunsOnSpec
-  AltOrTcConfigSpec optError '{' AltstepLocalDefList AltGuardList optError '}'
+  AltOrTcConfigSpec optExceptionSpec optError '{' AltstepLocalDefList AltGuardList optError '}'
   optCatchBlockList optFinallyDef
   {
     StatementBlock *sb = new StatementBlock;
-    for (size_t i = 0; i < $10.nElements; i++) {
-      Statement *stmt = new Statement(Statement::S_DEF, $10.elements[i]);
-      stmt->set_location(*$10.elements[i]);
+    for (size_t i = 0; i < $11.nElements; i++) {
+      Statement *stmt = new Statement(Statement::S_DEF, $11.elements[i]);
+      stmt->set_location(*$11.elements[i]);
       sb->add_stmt(stmt);
     }
-    Free($10.elements);
-    for (size_t i = 0; i < $14.nElements; ++i) {
-      sb->add_catch_block($14.elements[i]);
+    Free($11.elements);
+    for (size_t i = 0; i < $15.nElements; ++i) {
+      sb->add_catch_block($15.elements[i]);
     }
-    Free($14.elements);
-    if ($15 != NULL) {
-      sb->set_finally_block($15);
+    Free($15.elements);
+    if ($16 != NULL) {
+      sb->set_finally_block($16);
     }
     $4->set_location(infile, @4);
-    $$ = new Def_Altstep($2, $4, $6, $7.mtcref, $7.systemref, sb, $11);
+    $$ = new Def_Altstep($2, $4, $6, $7.mtcref, $7.systemref, sb, $12, $8);
     $$->set_location(infile, @$);
   }
 ;
@@ -5733,11 +5733,11 @@ GroupIdentifier: // 274 (followed by) 275.
 
 ExtFunctionDef: // 276
   ExtKeyword FunctionKeyword optDeterministicModifier IDentifier
-  '(' optFunctionFormalParList ')' optReturnType
+  '(' optFunctionFormalParList ')' optReturnType optExceptionSpec
   {
     $6->set_location(infile, @5, @7);
     $$ = new Def_ExtFunction($3, $4, $6, $8.type, $8.returns_template,
-                             $8.template_restriction, false, true);
+                             $8.template_restriction, false, $9, true);
     $$->set_location(infile, @$);
   }
 ;
diff --git a/core/OOP.hh b/core/OOP.hh
index 2d11e25f86b6474bbdb918d078bf0139ef89291f..de12f7c8c49753cc2ca1452baf5ed9a8d6755e0b 100644
--- a/core/OOP.hh
+++ b/core/OOP.hh
@@ -292,7 +292,13 @@ public:
   FINALLY(const std::function<void(void)> &p_functor) : functor(p_functor) {}
   ~FINALLY()
   {
-    functor();
+    try {
+      functor();
+    }
+    catch (...) {
+      fprintf(stderr, "Unhandled exception or dynamic test case error in a finally block. Terminating application.\n");
+      exit(EXIT_FAILURE);
+    }
   }
 };
 #endif // C++11
diff --git a/function_test/Makefile b/function_test/Makefile
index bef0203ef8bc77714eaae619e89e0cdaf3cc7d5b..af8d1b1f27d3923503e326fb731f85bb5f067423 100644
--- a/function_test/Makefile
+++ b/function_test/Makefile
@@ -17,7 +17,7 @@
 #
 ##############################################################################
 # Makefile to run the non-interactive tests
-DIRS := Semantic_Analyser Semantic_Analyser_Csaba Config_Parser
+DIRS := Semantic_Analyser Semantic_Analyser_Csaba Config_Parser OOP
 
 SCRIPTFLAGS :=
 
@@ -93,6 +93,9 @@ Semantic_Analyser_Csaba:
 
 Config_Parser:
 	cd $@; if [ ! -f perl ] ; then ln -s `which perl` perl; fi; ./run_test $(SCRIPTFLAGS)
+	
+OOP:
+	cd $@; if [ ! -f perl ] ; then ln -s `which perl` perl; fi; ./run_test $(SCRIPTFLAGS)
 
 profile: $(DIRS)
 	make all
diff --git a/function_test/OOP/.gitignore b/function_test/OOP/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..9be6a06c3f1ab53b46e99da8f5f44e0705ca9923
--- /dev/null
+++ b/function_test/OOP/.gitignore
@@ -0,0 +1,9 @@
+*.report
+compile
+core
+Temp*
+*.gcda
+*.gcno
+Makefile
+perl
+perl.lnk
diff --git a/function_test/OOP/NonOOP_negtest.script b/function_test/OOP/NonOOP_negtest.script
new file mode 100644
index 0000000000000000000000000000000000000000..86d233c282113200502eb5c747bf784f1e5fafee
--- /dev/null
+++ b/function_test/OOP/NonOOP_negtest.script
@@ -0,0 +1,112 @@
+.******************************************************************************
+.* Copyright (c) 2000-2021 Ericsson Telecom AB
+.* All rights reserved. This program and the accompanying materials
+.* are made available under the terms of the Eclipse Public License v2.0
+.* which accompanies this distribution, and is available at
+.* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+.*
+.* Contributors:
+.*   Baranyi, Botond
+.*
+.******************************************************************************/
+:text.
+:lang eng.
+.*---------------------------------------------------------------------*
+:h1.Test cases
+.*---------------------------------------------------------------------*
+.*---------------------------------------------------------------------*
+:h3.Raise and catch without '-k' flag
+.*---------------------------------------------------------------------*
+:xmp tab=0.
+
+<TC - Raise and catch without '-k' flag>
+
+<COMPILE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+type component CT {
+  var integer counter := 0;
+  timer tmr;
+}
+
+function f() runs on CT return integer {
+  counter := counter + 1;
+  return counter;
+}
+
+altstep as() runs on CT {
+  var integer local := f();
+  [] tmr.timeout { log(counter); raise 3; }
+}
+
+testcase tc() runs on CT {
+  tmr.start(2.0);
+  alt {
+    [] as();
+  }
+}
+catch (integer x) {
+  log(x);
+}
+
+control {
+  execute(tc());
+}
+
+}
+<END_MODULE>
+<RESULT>
+The compiler option `-k' must be activated to use object-oriented features such as raise statements.
+<END_RESULT>
+<RESULT>
+The compiler option `-k' must be activated to use object-oriented features such as catch clauses.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+.*---------------------------------------------------------------------*
+:h3.Class and finally without '-k' flag
+.*---------------------------------------------------------------------*
+.Note: 'class' and 'finally' are treated as keywords by the parser and a warning
+.is issued for both. The actual parsing error is caused by the parser interpreting
+.a class definition as a type alias definition for a type called 'class'.
+:xmp tab=0.
+
+<TC - Class and finally without '-k' flag>
+
+<COMPILE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+type class MyClass {
+  var integer m_int;
+  public function get_int() return integer { return m_int; }
+  public function set_int(integer p_int) { m_int := p_int; }
+}
+
+type component CT { }
+
+function f() { }
+finally {
+  log("finally");
+}
+
+}
+<END_MODULE>
+<RESULT>
+Keyword 'class' is treated as an identifier. Activate compiler option '-k' to use object-oriented features.
+<END_RESULT>
+<RESULT>
+at or before token `var': syntax error, unexpected VarKeyword, expecting '\{'
+<END_RESULT>
+<RESULT>
+Keyword 'finally' is treated as an identifier. Activate compiler option '-k' to use object-oriented features.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+:etext.
+
diff --git a/function_test/OOP/OOP_negtest.script b/function_test/OOP/OOP_negtest.script
new file mode 100644
index 0000000000000000000000000000000000000000..ee18c91841fa5a53ced37837abd57b6b132951d3
--- /dev/null
+++ b/function_test/OOP/OOP_negtest.script
@@ -0,0 +1,230 @@
+.******************************************************************************
+.* Copyright (c) 2000-2021 Ericsson Telecom AB
+.* All rights reserved. This program and the accompanying materials
+.* are made available under the terms of the Eclipse Public License v2.0
+.* which accompanies this distribution, and is available at
+.* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+.*
+.* Contributors:
+.*   Baranyi, Botond
+.*
+.******************************************************************************/
+:text.
+:lang eng.
+.*---------------------------------------------------------------------*
+:h1.Test cases
+.*---------------------------------------------------------------------*
+.*---------------------------------------------------------------------*
+:h3.Unhandled exception
+.*---------------------------------------------------------------------*
+:xmp tab=0.
+
+<TC - Unhandled exception>
+
+<EXECUTE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+type component CT {}
+
+testcase tc() runs on CT {
+  raise 1;
+}
+
+control {
+	execute (tc());
+}
+
+}
+<END_MODULE>
+<MODULE CFG Temp Temp.cfg>
+[EXECUTE]
+Temp
+<END_MODULE>
+<RESULT>
+Unhandled exception: 1
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+.*---------------------------------------------------------------------*
+:h3.Exception in the destructor
+.*---------------------------------------------------------------------*
+.Note: This test causes memory leaks, because the test executor terminates prematurely.
+:xmp tab=0.
+
+<TC - Exception in the destructor>
+
+<EXECUTE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+function f() {
+  raise 1;
+}
+
+type class C { }
+finally {
+  f();
+}
+
+type component CT {}
+
+testcase tc() runs on CT {
+  var C x := C.create;
+}
+
+control {
+	execute(tc());
+}
+
+}
+<END_MODULE>
+<MODULE CFG Temp Temp.cfg>
+[EXECUTE]
+Temp
+<END_MODULE>
+<RESULT>
+Unhandled exception or dynamic test case error in the destructor of class `C'. Terminating application.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+.*---------------------------------------------------------------------*
+:h3.DTE in the destructor
+.*---------------------------------------------------------------------*
+.Note: This test causes memory leaks, because the test executor terminates prematurely.
+:xmp tab=0.
+
+<TC - DTE in the destructor>
+
+<EXECUTE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+function f() {
+  var integer x := 0;
+  var integer y := 1 / x;
+}
+
+type class C { }
+finally {
+  f();
+}
+
+type component CT {}
+
+testcase tc() runs on CT {
+  var C x := C.create;
+}
+
+control {
+	execute(tc());
+}
+
+}
+<END_MODULE>
+<MODULE CFG Temp Temp.cfg>
+[EXECUTE]
+Temp
+<END_MODULE>
+<RESULT>
+Unhandled exception or dynamic test case error in the destructor of class `C'. Terminating application.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+.*---------------------------------------------------------------------*
+:h3.Exception in the finally block
+.*---------------------------------------------------------------------*
+.Note: This test causes memory leaks, because the test executor terminates prematurely.
+:xmp tab=0.
+
+<TC - Exception in the finally block>
+
+<EXECUTE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+function f() {
+  raise 1;
+}
+
+type component CT {}
+
+testcase tc() runs on CT {
+  {
+  }
+  finally {
+    f();
+  }
+}
+
+
+control {
+	execute(tc());
+}
+
+}
+<END_MODULE>
+<MODULE CFG Temp Temp.cfg>
+[EXECUTE]
+Temp
+<END_MODULE>
+<RESULT>
+Unhandled exception or dynamic test case error in a finally block. Terminating application.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+.*---------------------------------------------------------------------*
+:h3.DTE in the finally block
+.*---------------------------------------------------------------------*
+.Note: This test causes memory leaks, because the test executor terminates prematurely.
+:xmp tab=0.
+
+<TC - DTE in the finally block>
+
+<EXECUTE>
+<MODULE TTCN Temp Temp.ttcn>
+module Temp {
+
+function f() {
+  var integer x := 0;
+  var integer y := 1 / x;
+}
+
+type component CT {}
+
+testcase tc() runs on CT {
+  {
+  }
+  finally {
+    f();
+  }
+}
+
+
+control {
+	execute(tc());
+}
+
+}
+<END_MODULE>
+<MODULE CFG Temp Temp.cfg>
+[EXECUTE]
+Temp
+<END_MODULE>
+<RESULT>
+Unhandled exception or dynamic test case error in a finally block. Terminating application.
+<END_RESULT>
+<END_TC>
+
+:exmp.
+
+:etext.
+
diff --git a/function_test/OOP/run_test b/function_test/OOP/run_test
new file mode 100755
index 0000000000000000000000000000000000000000..7474b517f738242c395891d3ea2c3de2745ff0b6
--- /dev/null
+++ b/function_test/OOP/run_test
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+SCRIPTFLAGS=
+while [ $# -gt 0 ]; do
+case $1 in
+"-coverage") SCRIPTFLAGS+=" -coverage"; shift 1 ;;
+"-rt2") SCRIPTFLAGS=" -rt2"; shift 1 ;;
+*) echo "Usage: $0 [-rt2] [-coverage]"; exit 1 ;;
+esac
+done
+
+echo "Batch execution of OOP tests: creating 1 report for each script file"
+echo "You must have a symlink in this directory named perl and pointing to perl 5.6.0 or higher"
+
+# OOP_negtest needs to be run with OOP enabled ('-k' flag) and memory leaks need to be ignored
+echo "./perl ../Tools/SAtester.pl $SCRIPTFLAGS -oop -imemleaks -log OOP_negtest.report OOP_negtest.script"
+./perl ../Tools/SAtester.pl $SCRIPTFLAGS -oop -imemleaks -log OOP_negtest.report OOP_negtest.script
+
+# NonOOP_negtest needs to be run with OOP disabled (no '-k' flag)
+echo "./perl ../Tools/SAtester.pl $SCRIPTFLAGS -log NonOOP_negtest.report NonOOP_negtest.script"
+./perl ../Tools/SAtester.pl $SCRIPTFLAGS -log NonOOP_negtest.report NonOOP_negtest.script
+
+echo "Finished. Reports are generated with .report extension."
+
diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
index b5a49e641ad9697a8633d0b3d7b34accd6825637..02872e813e5366e06481b60de24699fa607b03e6 100644
--- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn
+++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
@@ -15,6 +15,7 @@ module oop_SE { //^In TTCN-3 module//
 type component Comp {
   var integer cv_comp;
   const integer cc_comp := -1;
+  timer c_timer;
 }
 
 type port Port message {
@@ -29,8 +30,23 @@ type record Rec {
   charstring str
 }
 
+type record of integer RoI;
+
+type union Uni {
+  integer i,
+  float f
+}
+
+signature Sig(inout integer p);
+
+type integer SmallNumber (-100..100);
+
+type enumerated Enum { E1, E2, E3 };
+
 const integer c := 3;
 
+template integer t := 4;
+
 type class C0 { }
 
 type class C1 extends Nonexistent { } //^In type definition// //^In superclass definition// //There is no local or imported definition with name `Nonexistent'//
@@ -550,8 +566,99 @@ function f_aliases() {
 }
 
 
+function f_exception1(in integer p) return integer exception(integer, charstring, Rec, C0) { return p; }
+function f_exception2() exception(boolean, verdicttype, integer, SmallNumber, RoI, Uni, anytype, Comp, RoI[-], Rec.num, Uni.i, Enum) { }
+external function ef_exception1(in integer p) return integer exception(integer, charstring, Rec, C0);
+altstep a_exception1(in integer p) runs on Comp exception(integer, charstring, Rec, C0) {
+  [] c_timer.timeout { }
+}
+
+function f_exception3() //^In function definition//
+  exception (float, //^In exception list//
+  default, //Default type cannot be on the exception list of a function//
+  bitstring,
+  Port, //Port type `@oop_SE.Port' cannot be on the exception list of a function//
+  hexstring,
+  Sig, //Signature `@oop_SE.Sig' cannot be on the exception list of a function//
+  octetstring) { }
+external function ef_exception2() //^In external function definition// 
+  exception (universal charstring, //^In exception list// //Type `universal charstring' is already given here//
+  integer,
+  universal charstring); //Duplicate type in exception list//
+
+
+function f_raise(in integer p, inout template integer p2) runs on CT_Mtc { //^In function definition// //Previous definition with identifier `p' in higher scope unit is here//
+  if (p == 0) { raise 3; }
+  if (p == 1) { raise Enum: E2; }
+  if (p == 2) { raise int2char(p + 1); }
+  if (p == 3) { raise omit; } //^In if statement// //^In raise statement// //Cannot determine the type of the raised exception.//
+  if (p == 4) { raise null; } //^In if statement// //^In raise statement// //Cannot determine the type of the raised exception.//
+  if (p == 5) { raise pattern "ab?c"; } //^In if statement// //^In raise statement// //A specific value without matching symbols or a reference to a value was expected for a raised exception.//
+  var default def := null;
+  if (p == 6) { raise def; } //^In if statement// //^In raise statement// //Cannot raise an exception of type default//
+  if (p == 7) { raise Sig: { p }; } //^In if statement// //^In raise statement// //Cannot raise an exception of type @oop_SE.Sig//
+  if (p == 8) { raise pt; } //^In if statement// //^In raise statement// //Reference to a value was expected instead of port `@oop_SE.CT_Mtc.pt'//
+  var template charstring vt := ? length (3);
+  if (p == 9) { raise vt; } //^In if statement// //^In raise statement// //A specific value without matching symbols or a reference to a value was expected for a raised exception.//
+  if (p == 10) { raise c; }
+  if (p == 11) { raise t; } //^In if statement// //^In raise statement// //A specific value without matching symbols or a reference to a value was expected for a raised exception.//
+  if (p == 12) { raise p2; } //^In if statement// //^In raise statement// //A specific value without matching symbols or a reference to a value was expected for a raised exception.//
+}
+catch (integer x) { } //Catch block for the same exception type already defined here//
+catch (integer y) { } //Duplicate catch block definition for exception type `integer'//
+catch (SmallNumber x) { }
+catch (RoI[-] x) { }
+catch (Rec.num x) { }
+catch (charstring p) { } //Definition with identifier `p' is not unique in the scope hierarchy//
+catch (default x) { } //^In exception definition// //Exception cannot be defined for the default type//
+catch (Sig x) { } //^In exception definition// //Exception cannot be defined for signature `@oop_SE.Sig'//
+catch (Port x) { } //^In exception definition// //Exception cannot be defined for port type `@oop_SE.Port'//
+catch (octetstring x) { return; }
+finally {
+  raise 3; //^In raise statement// //Raise statement cannot be used inside a finally block or the destructor of a class.//
+}
+
+function f_return1(in integer p) return integer { //^In function definition//
+  if (p > 0) {
+    return 0;
+  }
+  else {
+    raise 0;
+  }
+}
+catch (integer x) {
+  return x;
+}
+finally {
+  return -1; //^In return statement// //Return statement cannot be used inside a finally block or the destructor of a class.//
+}
+
+function f_return2(in integer p) return integer { //^In function definition// //The function has return type, but control might leave it without reaching a return statement//
+  if (p > 0) {
+    return f_return1(p);
+  }
+  catch (integer x) {
+    log(x);
+  }
+  else {
+    raise 0;
+  }
+}
+
+type class C50 { } //^In type definition//
+finally { //^In class destructor//
+  return; //^In return statement// //Return statement cannot be used inside a finally block or the destructor of a class.//
+}
+
+type class C51 { } //^In type definition//
+finally { //^In class destructor//
+  raise 1.0; //^In raise statement// //Raise statement cannot be used inside a finally block or the destructor of a class.//
+}
+
+
 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.//
+  raise "abc"; //^In raise statement// //Raise statement cannot be used in the control part. It is allowed only in functions, altsteps and testcases.//
 }
 
 }
diff --git a/function_test/Tools/SAtester.pl b/function_test/Tools/SAtester.pl
index 00c23c14c54f68df22f1573dc0d9a63827c8aeb9..de9e76a9b856d44c4e43d611acaf3d38a8c0a3bd 100755
--- a/function_test/Tools/SAtester.pl
+++ b/function_test/Tools/SAtester.pl
@@ -56,6 +56,10 @@ my $sa_printHelp_doc = 0;
 my $sa_titanRuntime2 = 0;
 # Enable coverage or not
 my $sa_coverageEnabled = 0;
+# Enable object-oriented features
+my $sa_titanOOP = 0;
+# Ignore memory leaks
+my $sa_ignoreMemLeaks = 0;
 # Files existed before a test case execution
 my %sa_existedFiles;
 # Store input TD files from which TCs are collected
@@ -389,6 +393,8 @@ sub sa_processCommandLine() {
                           'help'      => \$sa_printHelp_cmd,
                           'doc'       => \$sa_printHelp_doc,
                           'rt2'       => \$sa_titanRuntime2,
+                          'oop'       => \$sa_titanOOP,
+                          'imemleaks' => \$sa_ignoreMemLeaks,
                           'coverage'  => \$sa_coverageEnabled,
                           'log=s'     => \$sa_logFile,
                           'timeout=s' => \$sa_timeout,
@@ -683,10 +689,12 @@ sub sa_compileTC(\@) {
    sa_log( "Compiling sources...\n");
    my $runtimeOption = '';
    if ($sa_titanRuntime2) { $runtimeOption = '-R'; }
+   my $oopOption = '';
+   if ($sa_titanOOP) { $oopOption = '-k'; }
    do {
       if ($cycles) { sleep(60 * 10); }
       $cycles++;
-      ($res, $subRes) = sa_executeCommand("$sa_compilerCmd $runtimeOption $modules2compile");
+      ($res, $subRes) = sa_executeCommand("$sa_compilerCmd $runtimeOption $oopOption $modules2compile");
       # Purify message, when no floating license available. Sleep for a while
       # and retry.
       # -continue-without-license=yes
@@ -696,12 +704,12 @@ sub sa_compileTC(\@) {
    if ($root->[1] eq "COMPILE") { return (0, $resultBuffer); }
 
    sa_log( "Generating test port skeletons...\n");
-   ($res, $subRes) = sa_executeCommand("$sa_compilerCmd $runtimeOption -t -f $modules2compile");
+   ($res, $subRes) = sa_executeCommand("$sa_compilerCmd $runtimeOption $oopOption -t -f $modules2compile");
    if ($res) { return (1, $subRes); }
    $resultBuffer .= $subRes;
 
    sa_log( "Generating Makefile...\n");
-   ($res, $subRes) = sa_executeCommand("$sa_mfgenCmd $runtimeOption -s -f $modules2compile *.cc*");
+   ($res, $subRes) = sa_executeCommand("$sa_mfgenCmd $runtimeOption $oopOption -s -f $modules2compile *.cc*");
    if ($res) { return (1, $subRes); }
    $resultBuffer .= $subRes;
    if (not (-e 'Makefile')) {
@@ -803,7 +811,7 @@ sub sa_checkTCResult(\@$) {
       }
    }
    # Check if there is any memory leak in compiler
-   if ($resultBuffer =~ /${sa_re_MemoryLeak}/mi) {
+   if (not $sa_ignoreMemLeaks and $resultBuffer =~ /${sa_re_MemoryLeak}/mi) {
       sa_log( "WARNING: Memory leak detected in compiler, setting verdict to 'FAIL'\n");
       $root->[7] = 'memory leak detected';
       $result = 'FAIL';