diff --git a/compiler2/compiler.1 b/compiler2/compiler.1
index b9b71c86c55a1547c22553fcb6b197d240d0226b..936d98e9c9935f6df15ebf0248888e7e1b054eae 100644
--- a/compiler2/compiler.1
+++ b/compiler2/compiler.1
@@ -3,7 +3,7 @@
 compiler \- TTCN-3 and ASN.1 to C++ translator
 .SH SYNOPSIS
 .B compiler
-.RB "[\| " \-abcdDeEfFgiIjlLMnNpqrRsStuwxXyY0 " \|]"
+.RB "[\| " \-abcdDeEfFgiIjklLMnNpqrRsStuwxXyY0 " \|]"
 .RB "[\| " \-V
 .IR " verb_level" " \|]"
 .RB "[\| " \-J
@@ -131,6 +131,9 @@ Disables JSON encoder/decoder functions.
 .BI \-J " file"
 Read a list of input files from the provided file.
 .TP
+.B \-k
+Enables object-oriented features.
+.TP
 .BI \-K " file"
 Enables selective code coverage.
 .TP
diff --git a/compiler2/main.cc b/compiler2/main.cc
index b02afb24f55e3457b4bcbf2856892ae908fb6dfd..14d57207a0ef299605f40c95cae40e941e68345d 100644
--- a/compiler2/main.cc
+++ b/compiler2/main.cc
@@ -395,7 +395,7 @@ static boolean is_valid_asn1_filename(const char* file_name)
 static void usage()
 {
   fprintf(stderr, "\n"
-    "usage: %s [-abcdDeEfFgiIjlLMnNOpqrRsStuwxXyY0] [-J file] [-K file] [-z file] [-V verb_level]\n"
+    "usage: %s [-abcdDeEfFgiIjklLMnNOpqrRsStuwxXyY0] [-J file] [-K file] [-z file] [-V verb_level]\n"
     "	[-o dir] [-U none|type|'number'] [-P modulename.top_level_pdu_name] [-Q number] ...\n"
     "	[-T] module.ttcn [-A] module.asn ...\n"
     "	or  %s -v\n"
@@ -417,6 +417,7 @@ static void usage()
     "	-I:		enable real-time testing features\n"
     "	-j:		disable JSON encoder/decoder functions\n"
     "	-J file:	read input files from file\n"
+    "	-k:		enable object-oriented features\n"
     "	-K file:	enable selective code coverage\n"
     "	-l:		include source line info in C++ code\n"
     "	-L:		add source line info for logging\n"
diff --git a/compiler2/makefile.c b/compiler2/makefile.c
index 8189852d47b44b5cb2712626464b4a63f5f3a957..d975d77f896f37b097debf67249f3c46b8df6778 100644
--- a/compiler2/makefile.c
+++ b/compiler2/makefile.c
@@ -276,6 +276,7 @@ struct makefile_struct {
   boolean enable_legacy_encoding;
   boolean disable_userinfo;
   boolean realtime_features;
+  boolean oop_features;
   struct string_list* solspeclibraries; /* not owned */
   struct string_list* sol8speclibraries; /* not owned */
   struct string_list* linuxspeclibraries; /* not owned */
@@ -348,6 +349,7 @@ static void init_makefile_struct(struct makefile_struct *makefile)
   makefile->enable_legacy_encoding = FALSE;
   makefile->disable_userinfo = FALSE;
   makefile->realtime_features = FALSE;
+  makefile->oop_features = FALSE;
   makefile->solspeclibraries = NULL;
   makefile->sol8speclibraries = NULL;
   makefile->linuxspeclibraries = NULL;
@@ -2255,7 +2257,7 @@ static void print_makefile(struct makefile_struct *makefile)
           "AR = ar\n"
           "ARFLAGS = \n\n"
           "# Flags for the TTCN-3 and ASN.1 compiler:\n"
-          "COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n"
+          "COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n"
           "# Execution mode: (either ttcn3 or ttcn3-parallel)\n"
           "TTCN3_LIB = ttcn3%s%s%s\n\n"
 #ifdef LICENSE
@@ -2304,6 +2306,7 @@ static void print_makefile(struct makefile_struct *makefile)
           (makefile->profiled_file_list ? " -z $(PROFILED_FILE_LIST)" : ""),
           (makefile->disable_userinfo ? " -D" : ""),
           (makefile->realtime_features ? " -I" : ""),
+          (makefile->oop_features ? " -k" : ""),
           /* end of COMPILER FLAGS */
           (makefile->use_runtime_2 ? "-rt2"    : ""), /* TTCN3_LIB */
           (makefile->single_mode   ? ""        : "-parallel"),
@@ -4685,7 +4688,7 @@ static void generate_makefile(size_t n_arguments, char *arguments[],
   boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings,
   boolean outparamboundness, boolean omit_in_value_list, boolean warnings_for_bad_variants, boolean activate_debugger,
   boolean ignore_untagged_on_top_union, boolean disable_predef_ext_folder, boolean enable_legacy_encoding, boolean disable_userinfo,
-  boolean realtime_features, struct string_list* solspeclibraries, struct string_list* sol8speclibraries,
+  boolean realtime_features, boolean oop_features, struct string_list* solspeclibraries, struct string_list* sol8speclibraries,
   struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries,
   struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries,
   struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput,
@@ -4746,6 +4749,7 @@ static void generate_makefile(size_t n_arguments, char *arguments[],
   makefile.enable_legacy_encoding = enable_legacy_encoding;
   makefile.disable_userinfo = disable_userinfo;
   makefile.realtime_features = realtime_features;
+  makefile.oop_features = oop_features;
   makefile.solspeclibraries = solspeclibraries;
   makefile.sol8speclibraries = sol8speclibraries;
   makefile.linuxspeclibraries = linuxspeclibraries;
@@ -4912,6 +4916,7 @@ static void usage(void)
     "	-i:		enable real-time testing features\n"
     "	-I path:	Add path to the search paths when using TPD files\n"
     "	-J file:	The names of files taken from file instead of command line\n"
+    "	-k:		enable object-oriented features\n"
     "	-K file:	enable selective code coverage\n"
     "	-l:		use dynamic linking\n"
     "	-L:		create makefile with library archive as the default target\n"
@@ -4967,7 +4972,7 @@ int main(int argc, char *argv[])
     Sflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE,
     djflag = FALSE, doerflag = FALSE, Zflag = FALSE, Hflag = FALSE, Mflag = FALSE,
     diflag = FALSE, zflag = FALSE, Eflag = FALSE, nflag = FALSE,
-    Nflag = FALSE, Gflag = FALSE, duflag = FALSE, iflag = FALSE;
+    Nflag = FALSE, Gflag = FALSE, duflag = FALSE, iflag = FALSE, kflag = FALSE;
   boolean error_flag = FALSE;
   char *output_file = NULL;
   char *ets_name = NULL;
@@ -5028,7 +5033,7 @@ int main(int argc, char *argv[])
   }
 
   for ( ; ; ) {
-    int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgGiI:J:K:o:lLmMnNpP:rRsSt:TU:vVwWXYz:ZH");
+    int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgGiI:J:kK:o:lLmMnNpP:rRsSt:TU:vVwWXYz:ZH");
     if (c == -1) break;
     switch (c) {
     case 'O':
@@ -5200,6 +5205,9 @@ int main(int argc, char *argv[])
     case 'Z':
       SET_FLAG(Z);
       break;
+    case 'k':
+      SET_FLAG(k);
+      break;
     default:
       error_flag = TRUE;
       break;
@@ -5212,7 +5220,7 @@ int main(int argc, char *argv[])
     if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag
       || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag || Gflag
       || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag
-      || Zflag || Hflag || Mflag || zflag || Eflag || nflag || iflag
+      || Zflag || Hflag || Mflag || zflag || Eflag || nflag || iflag || kflag
       || n_other_files > 0 || n_search_paths > 0)
       error_flag = TRUE;
   }
@@ -5417,7 +5425,7 @@ int main(int argc, char *argv[])
       create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csmode,
       &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &linkerOptions, &semantic_check_only, &disable_attibute_validation,
       &dbflag, &drflag, &dtflag, &dxflag, &djflag, &doerflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag,
-      &asflag, &temp_wflag, &Yflag, &Mflag, &Eflag, &nflag, &Nflag, &diflag, &Gflag, &duflag, &iflag,
+      &asflag, &temp_wflag, &Yflag, &Mflag, &Eflag, &nflag, &Nflag, &diflag, &Gflag, &duflag, &iflag, &kflag,
       solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep,
       linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag,
       &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs, &profiled_file_list, search_paths, n_search_paths, &makefileScript);
@@ -5468,7 +5476,7 @@ int main(int argc, char *argv[])
       cxxcompiler, optlevel, optflags, linkerOptions,
       semantic_check_only, disable_attibute_validation, dbflag, drflag, dtflag, dxflag, djflag, doerflag,
       fxflag, doflag, gfflag, lnflag, isflag, asflag, wflag, Yflag, Mflag, Eflag, nflag, Nflag, diflag,
-      Gflag, duflag, iflag, solspeclibraries, sol8speclibraries, linuxspeclibraries,
+      Gflag, duflag, iflag, kflag, solspeclibraries, sol8speclibraries, linuxspeclibraries,
       freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects,
       linkerlibsearchpath, generatorCommandOutput, target_placement_list);
     if (makefileScript != NULL) {
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index ec8d800244e8ef17aa929341afb8689c29d7e38b..75ec17a8a0571d31da58318cd2e57ec5d0c2c534 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -7475,6 +7475,9 @@ namespace Ttcn {
     checked = true;
     Error_Context cntxt(this, "In external function definition `%s'",
       id->get_dispname().c_str());
+    if (!ext_keyword && my_scope->get_scope_class()->is_external()) {
+      error("Missing function body or `external' keyword");
+    }
     fp_list->chk(asstype);
     if (return_type) {
       Error_Context cntxt2(return_type, "In return type");
diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh
index 6eab20d65864a237040de8dafd2bd9988412a525..f72f0825238ecaecda6e1a660992c7629384474a 100644
--- a/compiler2/ttcn3/AST_ttcn3.hh
+++ b/compiler2/ttcn3/AST_ttcn3.hh
@@ -1550,6 +1550,7 @@ namespace Ttcn {
     // pretty or compact printing for json or xml
     Ttcn::PrintingType *printing;
     bool deterministic;
+    bool ext_keyword;
     /// Copy constructor disabled
     Def_ExtFunction(const Def_ExtFunction& p);
     /// %Assignment disabled
@@ -1568,12 +1569,12 @@ 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)
+      template_restriction_t p_template_restriction, bool p_ext_keyword)
       : Def_Function_Base(true, p_id, p_fpl, p_return_type, returns_template,
           p_template_restriction),
       function_type(EXTFUNC_MANUAL), encoding_type(Type::CT_UNDEF),
       encoding_options(0), eb_list(0), printing(0),
-      deterministic(p_deterministic) { }
+      deterministic(p_deterministic), ext_keyword(p_ext_keyword) { }
     ~Def_ExtFunction();
     virtual Def_ExtFunction *clone() const;
     virtual void set_fullname(const string& p_fullname);
diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc
index f2c91c87c906319510fbcf13fca4a9f6dcfabd87..1a1355fca76a684c380c35d915833e110e5b1bfb 100644
--- a/compiler2/ttcn3/Ttcnstuff.cc
+++ b/compiler2/ttcn3/Ttcnstuff.cc
@@ -3318,7 +3318,9 @@ namespace Ttcn {
     if (final && abstract) {
       error("Final classes cannot be abstract");
     }
-    // TODO: external?
+    if (external && abstract) {
+      error("External classes cannot be abstract");
+    }
     if (base_type != NULL) {
       Error_Context cntxt(base_type, "In superclass definition");
       base_type->chk();
@@ -3335,6 +3337,9 @@ namespace Ttcn {
         if (base_class->final) {
           base_type->error("The superclass cannot be final");
         }
+        if (external && !base_class->external) {
+          base_type->error("An external class cannot extend an internal class");
+        }
       }
     }
     
@@ -3480,6 +3485,25 @@ namespace Ttcn {
       finally_block->chk();
     }
     
+    if (external) {
+      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_EXT_FUNCTION:
+        case Common::Assignment::A_EXT_FUNCTION_RVAL:
+        case Common::Assignment::A_EXT_FUNCTION_RTEMP:
+          // OK
+          break;
+        default:
+          ass->error("An external class cannot contain a %s", ass->get_assname());
+          break;
+        }
+      }
+      if (finally_block != NULL) {
+        finally_block->error("An external class cannot have a destructor");
+      }
+    }
+    
     if (abstract) {
       // create a map of all abstract functions (including inherited ones)
       if (base_class != NULL && base_class->abstract) {
diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh
index 8929e67919bc4ddee6a29d888fc63f1d6feed69a..68a35806b3dab20e652676ee14f20039a919da5b 100644
--- a/compiler2/ttcn3/Ttcnstuff.hh
+++ b/compiler2/ttcn3/Ttcnstuff.hh
@@ -791,6 +791,7 @@ public:
   void set_my_def(Def_Type* p_def);
   Def_Type* get_my_def() { return my_def; }
   boolean is_abstract() const { return abstract; }
+  boolean is_external() const { return external; }
   
   void set_fullname(const string& p_fullname);
   void set_my_scope(Scope* p_scope);
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index bc755755919d7c2611b2350d4efe562ace7f1f0b..046d41c420c4626cffcc2e6020f7d461d5e8f7be 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -3654,12 +3654,20 @@ ClassFunctionDef:
       $9.template_restriction);
     $$->set_location(infile, @$);
   }
-| ExtKeyword FunctionKeyword optFinalModifier optAbstractModifier
+| ExtKeyword FunctionKeyword optFinalModifier
   optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
   optReturnType
   {
-    $$ = new Def_ExtFunction($5, $6, $8, $10.type, $10.returns_template,
-      $10.template_restriction);
+    $$ = new Def_ExtFunction($4, $5, $7, $9.type, $9.returns_template,
+      $9.template_restriction, true);
+    $$->set_location(infile, @$);
+  }
+| FunctionKeyword optFinalModifier
+  optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
+  optReturnType
+  {
+    $$ = new Def_ExtFunction($3, $4, $6, $8.type, $8.returns_template,
+      $8.template_restriction, false);
     $$->set_location(infile, @$);
   }
 ;
@@ -5634,7 +5642,7 @@ ExtFunctionDef: // 276
   {
     $6->set_location(infile, @5, @7);
     $$ = new Def_ExtFunction($3, $4, $6, $8.type, $8.returns_template,
-                             $8.template_restriction);
+                             $8.template_restriction, true);
     $$->set_location(infile, @$);
   }
 ;
diff --git a/compiler2/ttcn3_makefilegen.1 b/compiler2/ttcn3_makefilegen.1
index 4c5d0427b70169fe3da4772903684a624ff31935..ddf97d01936a7717af6b0cfea256bfaddb2efd14 100644
--- a/compiler2/ttcn3_makefilegen.1
+++ b/compiler2/ttcn3_makefilegen.1
@@ -3,7 +3,7 @@
 ttcn3_makefilegen \- Makefile Generator
 .SH SYNOPSIS
 .B ttcn3_makefilegen
-.RB "[\| " \-acdEfgilMnpRsSw " \|]"
+.RB "[\| " \-acdEfgiklMnpRsSw " \|]"
 .RB "[\| " \-e
 .IR " ETS_name" " \|]"
 .RB "[\| " \-o
@@ -86,6 +86,9 @@ during search. However if the tpdName attribute is missing then the value
 of the name attribute is taken with the .tpd suffix and used during the
 search.
 .TP
+.B \-k
+Enables object-oriented features.
+.TP
 .BI \-o " dir|file"
 Write the Makefile to the given directory or file.
 The current working directory is the default otherwise.
diff --git a/compiler2/xpather.cc b/compiler2/xpather.cc
index 646a83c3a46c4e6bd646e218c9171fb471134ec7..3b9c43b6c5224f7bad809c0d85154f82bdff970a 100644
--- a/compiler2/xpather.cc
+++ b/compiler2/xpather.cc
@@ -1270,7 +1270,7 @@ static tpd_result process_tpd_internal(const char **p_tpd_name, char* tpdName, c
   boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, boolean* p_doerflag,
   boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
   boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean *p_Eflag, boolean* p_nflag, boolean* p_Nflag,
-  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features,
+  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features, boolean* p_oop_features,
   struct string_list* solspeclibs, struct string_list* sol8speclibs,
   struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
   struct string_list* linkerlibs, struct string_list* additionalObjects, struct string_list* linkerlibsearchp, boolean Vflag, boolean Dflag,
@@ -1292,7 +1292,7 @@ extern "C" tpd_result process_tpd(const char **p_tpd_name, const char *actcfg,
   boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, boolean* p_doerflag,
   boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
   boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean* p_Eflag, boolean* p_nflag, boolean* p_Nflag,
-  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features,
+  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features, boolean* p_oop_features,
   struct string_list* solspeclibs, struct string_list* sol8speclibs,
   struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
   string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag,
@@ -1325,7 +1325,7 @@ extern "C" tpd_result process_tpd(const char **p_tpd_name, const char *actcfg,
       p_fxflag, p_doflag, p_gfflag, p_lnflag, p_isflag,
       p_asflag, p_swflag, p_Yflag, p_Mflag, p_Eflag, p_nflag, p_Nflag,
       p_diflag, p_enable_legacy_encoding, p_disable_userinfo,
-      p_realtime_features, solspeclibs, sol8speclibs,
+      p_realtime_features, p_oop_features, solspeclibs, sol8speclibs,
       linuxspeclibs, freebsdspeclibs, win32speclibs, ttcn3prep,
       linkerlibs, additionalObjects, linkerlibsearchp, Vflag, Dflag, p_Zflag,
       p_Hflag, generatorCommandOutput, target_placement_list, prefix_workdir, 
@@ -1356,7 +1356,7 @@ extern "C" tpd_result process_tpd(const char **p_tpd_name, const char *actcfg,
       p_fxflag, p_doflag, p_gfflag, p_lnflag, p_isflag,
       p_asflag, p_swflag, p_Yflag, p_Mflag, p_Eflag, p_nflag, p_Nflag,
       p_diflag, p_enable_legacy_encoding, p_disable_userinfo,
-      p_realtime_features, solspeclibs, sol8speclibs,
+      p_realtime_features, p_oop_features, solspeclibs, sol8speclibs,
       linuxspeclibs, freebsdspeclibs, win32speclibs, ttcn3prep,
       linkerlibs, additionalObjects, linkerlibsearchp, Vflag, Dflag, p_Zflag,
       p_Hflag, generatorCommandOutput, target_placement_list, prefix_workdir, 
@@ -1462,7 +1462,7 @@ static tpd_result process_tpd_internal(const char **p_tpd_name, char *tpdName, c
   boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag, boolean* p_djflag, boolean* p_doerflag,
   boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
   boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean* p_Eflag, boolean* p_nflag, boolean* p_Nflag,
-  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features,
+  boolean* p_diflag, boolean* p_enable_legacy_encoding, boolean* p_disable_userinfo, boolean* p_realtime_features, boolean* p_oop_features,
   struct string_list* solspeclibs, struct string_list* sol8speclibs,
   struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
   string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag,
@@ -2074,6 +2074,7 @@ static tpd_result process_tpd_internal(const char **p_tpd_name, char *tpdName, c
   xsdbool2boolean(xpathCtx, actcfg, "enableLegacyEncoding", p_enable_legacy_encoding);
   xsdbool2boolean(xpathCtx, actcfg, "disableUserInformation", p_disable_userinfo);
   xsdbool2boolean(xpathCtx, actcfg, "enableRealtimeTesting", p_realtime_features);
+  xsdbool2boolean(xpathCtx, actcfg, "enableOOP", p_oop_features);
 
   projDesc = projGenHelper.getTargetOfProject(*p_project_name);
   if (projDesc) projDesc->setLinkingStrategy(*p_lflag);
@@ -2981,6 +2982,7 @@ static tpd_result process_tpd_internal(const char **p_tpd_name, char *tpdName, c
           my_duflag = 0;
         boolean my_enable_legacy_encoding = 0;
         boolean my_realtime_features = 0;
+        boolean my_oop_features = 0;
 
         char *my_ets = NULL;
         char *my_proj_name = NULL;
@@ -3033,7 +3035,7 @@ static tpd_result process_tpd_internal(const char **p_tpd_name, char *tpdName, c
           &my_quflag, &my_dsflag, cxxcompiler, optlevel, optflags, linkerOptions, semantic_check_only, disable_attibute_validation,
           &my_dbflag, &my_drflag, &my_dtflag, &my_dxflag, &my_djflag, &my_doerflag, &my_fxflag, &my_doflag,
           &my_gfflag, &my_lnflag, &my_isflag, &my_asflag, &my_swflag, &my_Yflag, &my_Mflag, &my_Eflag, &my_nflag, &my_Nflag, &my_diflag,
-          &my_enable_legacy_encoding, &my_duflag, &my_realtime_features, solspeclibs, sol8speclibs, linuxspeclibs, freebsdspeclibs, win32speclibs,
+          &my_enable_legacy_encoding, &my_duflag, &my_realtime_features, &my_oop_features, solspeclibs, sol8speclibs, linuxspeclibs, freebsdspeclibs, win32speclibs,
           ttcn3prep, linkerlibs, additionalObjects, linkerlibsearchp, Vflag, FALSE, &my_Zflag, 
           &my_Hflag, NULL, NULL, prefix_workdir, run_command_list, seen_tpd_files, required_configs, profiled_file_list,
           search_paths, n_search_paths, makefileScript, all_configs);
diff --git a/compiler2/xpather.h b/compiler2/xpather.h
index bc05747dcdd6745e851b595967d5c96e41efa462..da32a106b50328035809a20fd6383c35c8f1b5be 100644
--- a/compiler2/xpather.h
+++ b/compiler2/xpather.h
@@ -289,7 +289,7 @@ tpd_result process_tpd(const char **p_tpd_name, const char *actcfg,
   boolean *forcexerinasn, boolean *defaultasomit, boolean *gccmessageformat,
   boolean *linenumber, boolean *includesourceinfo, boolean *addsourcelineinfo, boolean *suppresswarnings,
   boolean *outparamboundness, boolean *omit_in_value_list, boolean *warnings_for_bad_variants, boolean *activate_debugger, boolean* ignore_untagged_union,
-  boolean *disable_predef_exp_folder, boolean* enable_legacy_encoding, boolean* disable_userinfo, boolean* realtime_features,
+  boolean *disable_predef_exp_folder, boolean* enable_legacy_encoding, boolean* disable_userinfo, boolean* realtime_features, boolean* oop_features,
   struct string_list* solspeclibs, struct string_list* sol8speclibs,
   struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs,
   char** ttcn3preprocessor, struct string_list* linkerlibs, struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, boolean Vflag, boolean Dflag,
diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
index 52beefad3a03c7d73632a9dddd5440ce788990df..9fdeb7c3a209ceaa043fa3ede9e2db5ace8e9547 100644
--- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn
+++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn
@@ -398,7 +398,7 @@ type class C37 {
   create() {}
 }
 
-function f_left_hand_side() { //^In function definition//
+function f_global_left_hand_side() { //^In function definition//
   var C37 x := C37.create;
   x.c := 2; //^In variable assignment// //Reference to a variable or template variable was expected instead of constant `@oop_SE.C37.c'//
   x.t := *; //^In variable assignment// //Reference to a variable or template variable was expected instead of template `@oop_SE.C37.t'//
@@ -407,18 +407,59 @@ function f_left_hand_side() { //^In function definition//
   x.f2() := "x"; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C37.f2'//
 }
 
+type class C38 extends C37 { //^In type definition//
+  public function f1() return Rec { return { 3, "b" }; }
+  public function f2() return template charstring { return omit; }
+  function f_class_left_hand_side() { //^In function definition//
+    this := null; //^In variable assignment// //Reference to a variable or template variable was expected instead of type `@oop_SE.C38'//
+    this.c := 4; //^In variable assignment// //Reference to a variable or template variable was expected instead of constant `@oop_SE.C37.c'//
+    this.t := ?; //^In variable assignment// //Reference to a variable or template variable was expected instead of template `@oop_SE.C37.t'//
+    this.f1().str := "x"; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C38.f1'//
+    this.f2() := ?; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C38.f2//
+    super.f1().str := "x"; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C38.f1'//
+    super.f2() := ?; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C38.f2//
+  }
+}
 
-type class C38 {
+
+type class C39 {
   public function f_def(in integer p := 3) return integer { return p; }
 }
 
 function f_default() { //^In function definition//
-  var C38 x := C38.create;
-  var integer ret1 := x.f_def; //^In variable definition// //Invalid reference to method `f_def' in class type `@oop_SE.C38', reference to a member was expected instead//
+  var C39 x := C39.create;
+  var integer ret1 := x.f_def; //^In variable definition// //Invalid reference to method `f_def' in class type `@oop_SE.C39', reference to a member was expected instead//
   var integer ret2 := x.f_def();
 }
 
 
+type external class C40 { //^In type definition//
+  function f1(in integer p) return octetstring; //^In external function definition// //Missing function body or `external' keyword//
+  external function f2();
+}
+
+type external class C41 { //^In type definition//
+  const charstring c := "a"; //An external class cannot contain a constant//
+  template charstring t := "b"; //An external class cannot contain a template//
+  var charstring v; //An external class cannot contain a variable//
+  var template charstring vt; //An external class cannot contain a template variable//
+  timer tmr; //An external class cannot contain a timer//
+  function f1() { } //An external class cannot contain a function//
+  function f2(in charstring x) return charstring { return x; } //An external class cannot contain a function//
+  function f3() return template charstring { return ?; } //An external class cannot contain a function//
+}
+
+type external class @abstract C42 { //^In type definition// //External classes cannot be abstract//
+  function @abstract f(); //An external class cannot contain a function//
+}
+
+type external class C43 extends C39 { } //^In type definition// //^In superclass definition// //An external class cannot extend an internal class//
+
+type class C44 extends C40 {
+  external function f();
+}
+
+
 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/compileonly/mfgen-tpd/Makefile b/regression_test/compileonly/mfgen-tpd/Makefile
index 9529314bc483558b099956d702ded6d768956b57..7e67c9c5209fe8ce2a3be3c5e7fc7f1be0eed46d 100644
--- a/regression_test/compileonly/mfgen-tpd/Makefile
+++ b/regression_test/compileonly/mfgen-tpd/Makefile
@@ -33,7 +33,7 @@ DIRLIST := buildconfig_param invalid_buildconfig_param invalid_buildconfig_tpd \
 	HP79745 HQ56829 HQ56834 HQ56848 library HR30356 flagTest HR30365 dependency_check \
 	required_config required_config_v2  disablePredefinedExternalFolder \
 	makefileScript diff_tpd_name_error enable_legacy_encoding disable_oer \
-	disableUserInformation freeTextLinkerOptions
+	disableUserInformation freeTextLinkerOptions oop_features
 
 ifdef DYN
 DIRS += required_config_v3 splitting compile_once
diff --git a/regression_test/compileonly/mfgen-tpd/oop_features/.gitignore b/regression_test/compileonly/mfgen-tpd/oop_features/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f6fc81065bc4adef1cf0824a65310d53348e079c
--- /dev/null
+++ b/regression_test/compileonly/mfgen-tpd/oop_features/.gitignore
@@ -0,0 +1,3 @@
+bin/
+bin2/
+bin3/
diff --git a/regression_test/compileonly/mfgen-tpd/oop_features/Makefile b/regression_test/compileonly/mfgen-tpd/oop_features/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..bb88871d27fedfc170cd4934d61bf5a2322f2d45
--- /dev/null
+++ b/regression_test/compileonly/mfgen-tpd/oop_features/Makefile
@@ -0,0 +1,62 @@
+##############################################################################
+# Copyright (c) 2000-2020 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
+#
+##############################################################################
+TOPDIR := ../../..
+include $(TOPDIR)/Makefile.regression
+
+ifdef LCOV
+COVERAGE_FLAG := -C
+endif
+
+# ${MAKEPROG} has the same content as the built-in ${MAKE},
+# except the special handling of ${MAKE} does not apply.
+# If we used ${MAKE} in the rules below, 'make -n' would succeed once,
+# then fail on every subsequent invocation until a 'make clean' is done. 
+
+MAKEPROG := ${MAKE}
+
+all: CheckTpdTrue CheckTpdFalse CheckTpdMissing
+
+BuildTpdTrue:
+	$(TTCN3_DIR)/bin/ttcn3_makefilegen -f $(MFGEN_FLAGS) $(COVERAGE_FLAG) \
+	-t a.tpd
+
+CheckTpdTrue: BuildTpdTrue
+	if [ ! -f "./bin/Makefile" ] \
+	|| [ `grep -c "COMPILER_FLAGS = -L  -k" ./bin/Makefile` -ne 1 ]; \
+	then echo "Makefilegen enable_legacy_encoding test: Overall verdict: fail" && exit 1; fi
+
+BuildTpdFalse:
+	$(TTCN3_DIR)/bin/ttcn3_makefilegen -f $(MFGEN_FLAGS) $(COVERAGE_FLAG) \
+	-t a.tpd -b False
+
+CheckTpdFalse: BuildTpdFalse
+	if [ ! -f "./bin2/Makefile" ] \
+	|| [ `grep -c "COMPILER_FLAGS = -L  -k" ./bin2/Makefile` -ne 0 ]; \
+	then echo "Makefilegen enable_legacy_encoding test: Overall verdict: fail" && exit 1; fi
+
+BuildTpdMissing:
+	$(TTCN3_DIR)/bin/ttcn3_makefilegen -f $(MFGEN_FLAGS) $(COVERAGE_FLAG) \
+	-t a.tpd -b Missing
+
+CheckTpdMissing: BuildTpdMissing
+	if [ ! -f "./bin3/Makefile" ] \
+	|| [ `grep -c "COMPILER_FLAGS = -L  -k" ./bin3/Makefile` -ne 0 ]; \
+	then echo "Makefilegen enable_legacy_encoding test: Overall verdict: fail" && exit 1; fi
+
+clean:
+	-rm -rf bin bin2 bin3
+
+distclean: clean
+	-rm -f *.out
+
+.PHONY: all clean distclean CheckTpdTrue CheckTpdFalse CheckTpdMissing BuildTpdTrue BuildTpdFalse BuildTpdMissing
+
diff --git a/regression_test/compileonly/mfgen-tpd/oop_features/a.tpd b/regression_test/compileonly/mfgen-tpd/oop_features/a.tpd
new file mode 100644
index 0000000000000000000000000000000000000000..096a99a459afe9cf0be787631ab12aeabe1ea48f
--- /dev/null
+++ b/regression_test/compileonly/mfgen-tpd/oop_features/a.tpd
@@ -0,0 +1,51 @@
+<!--
+ Copyright (c) 2000-2020 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 – initial implementation
+-->
+<TITAN_Project_File_Information version="1.0">
+  <ProjectName>a</ProjectName>
+  <ActiveConfiguration>Default</ActiveConfiguration>
+  <Configurations>
+    <Configuration name="Default">
+      <ProjectProperties>
+        <MakefileSettings>
+          <GNUMake>true</GNUMake>
+          <targetExecutable>bin</targetExecutable>
+          <enableOOP>true</enableOOP>
+        </MakefileSettings>
+        <LocalBuildSettings>
+          <workingDirectory>bin</workingDirectory>
+        </LocalBuildSettings>
+      </ProjectProperties>
+    </Configuration>
+    <Configuration name="False">
+      <ProjectProperties>
+        <MakefileSettings>
+          <GNUMake>true</GNUMake>
+          <targetExecutable>bin2</targetExecutable>
+          <enableOOP>false</enableOOP>
+        </MakefileSettings>
+        <LocalBuildSettings>
+          <workingDirectory>bin2</workingDirectory>
+        </LocalBuildSettings>
+      </ProjectProperties>
+    </Configuration>
+    <Configuration name="Missing">
+      <ProjectProperties>
+        <MakefileSettings>
+          <GNUMake>true</GNUMake>
+          <targetExecutable>bin3</targetExecutable>
+        </MakefileSettings>
+        <LocalBuildSettings>
+          <workingDirectory>bin3</workingDirectory>
+        </LocalBuildSettings>
+      </ProjectProperties>
+    </Configuration>
+  </Configurations>
+</TITAN_Project_File_Information>