diff --git a/compiler2/AST.cc b/compiler2/AST.cc
index 3f57d065e5d7c6a3e70f24ae8691186a8eef1288..291f03c0382eb409a00068a51309c2287645abc8 100644
--- a/compiler2/AST.cc
+++ b/compiler2/AST.cc
@@ -177,7 +177,8 @@ namespace Common {
     // run delayed Type::chk_coding() calls
     if (!delayed_type_enc_v.empty()) {
       for (size_t i = 0; i < delayed_type_enc_v.size(); ++i) {
-        delayed_type_enc_v[i]->t->chk_coding(delayed_type_enc_v[i]->enc, true);
+        delayed_type_enc_v[i]->t->chk_coding(delayed_type_enc_v[i]->enc,
+          delayed_type_enc_v[i]->mod, true);
         delete delayed_type_enc_v[i];
       }
       delayed_type_enc_v.clear();
@@ -303,10 +304,11 @@ namespace Common {
     }
   }
   
-  void Modules::delay_type_encode_check(Type* p_type, bool p_encode)
+  void Modules::delay_type_encode_check(Type* p_type, Module* p_module, bool p_encode)
   {
     for (size_t i = 0; i < delayed_type_enc_v.size(); ++i) {
       if (delayed_type_enc_v[i]->t == p_type &&
+          delayed_type_enc_v[i]->mod == p_module &&
           delayed_type_enc_v[i]->enc == p_encode) {
         // it's already in the list of delayed checks
         return;
@@ -314,6 +316,7 @@ namespace Common {
     }
     type_enc_t* elem = new type_enc_t;
     elem->t = p_type;
+    elem->mod = p_module;
     elem->enc = p_encode;
     delayed_type_enc_v.add(elem);
   }
diff --git a/compiler2/AST.hh b/compiler2/AST.hh
index f92c90a625345134f996cae6efc8ea5d90994ff4..4a7c5a05841a8cf24d442ecb0add82658f4661cc 100644
--- a/compiler2/AST.hh
+++ b/compiler2/AST.hh
@@ -100,6 +100,7 @@ namespace Common {
     /** Contains info needed for delayed type encoding checks */
     struct type_enc_t {
       Type* t;
+      Module* mod;
       bool enc;
     };
     static vector<type_enc_t> delayed_type_enc_v;
@@ -152,12 +153,12 @@ namespace Common {
       * info related to each type */
     void generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs);
     
-    /** Called if a Type::chk_coding() call could not be resolved (because the
-      * needed custom coding function was not found yet, but it might be among
-      * the functions that have not been checked yet).
+    /** Called if a Type::chk_coding() call could not be resolved (the check for
+      * custom and PER coding requires the checks of all external functions to
+      * be completed).
       * This stores the info needed to call the function again after everything
       * else has been checked. */
-    static void delay_type_encode_check(Type* p_type, bool p_encode);
+    static void delay_type_encode_check(Type* p_type, Module* p_module, bool p_encode);
   };
 
   /**
diff --git a/compiler2/Type.cc b/compiler2/Type.cc
index 58e901530dd551122c9733484dd0108a075992ed..94757c41f73e6a92e7c485802519f4f888d44c0e 100644
--- a/compiler2/Type.cc
+++ b/compiler2/Type.cc
@@ -4428,16 +4428,32 @@ namespace Common {
     }
   }
 
-  void Type::chk_coding(bool encode, bool delayed /* = false */) {
+  void Type::chk_coding(bool encode, Module* usage_mod, bool delayed /* = false */) {
     coding_t& coding = encode ? default_encoding : default_decoding;
     switch (coding.type) {
     case CODING_BY_FUNCTION:
+      {
+        Module* func_mod = coding.function_def->get_my_scope()->get_scope_mod();
+        if (usage_mod != func_mod) {
+          // add a phantom import for the coder function's module, to make sure
+          // it is visible from the module that requested the coding
+          Ttcn::Module* usage_mod_ttcn = dynamic_cast<Ttcn::Module*>(usage_mod);
+          if (usage_mod_ttcn == NULL) {
+            FATAL_ERROR("Type::chk_coding");
+          }
+          Ttcn::ImpMod* new_imp = new Ttcn::ImpMod(func_mod->get_modid().clone());
+          new_imp->set_mod(func_mod);
+          new_imp->set_imptype(Ttcn::ImpMod::I_DEPENDENCY);
+          usage_mod_ttcn->get_imports().add_impmod(new_imp);
+        }
+      }
+      // fall through
     case CODING_BUILT_IN:
       if (!delayed) {
         // a coding method has been set by an external function's checker,
         // but there might still be unchecked external functions out there;
         // delay this function until everything else has been checked
-        Modules::delay_type_encode_check(this, encode);
+        Modules::delay_type_encode_check(this, usage_mod, encode);
       }
       return;
     case CODING_UNSET:
@@ -4550,7 +4566,7 @@ namespace Common {
         // the type has a custom encoding attribute, but no external coder
         // function with that encoding has been found yet;
         // delay this function until everything else has been checked
-        Modules::delay_type_encode_check(this, encode);
+        Modules::delay_type_encode_check(this, usage_mod, encode);
         // set the coding type back to UNSET for delayed call
         coding.type = CODING_UNSET;
       }
@@ -4562,7 +4578,7 @@ namespace Common {
     else { // ASN.1 type
       // delay this function until everything else has been checked, in case
       // there is an encoder/decoder external function out there for this type
-      Modules::delay_type_encode_check(this, encode);
+      Modules::delay_type_encode_check(this, usage_mod, encode);
     }
   }
 
diff --git a/compiler2/Type.hh b/compiler2/Type.hh
index b24291fb35159d6638d432780c246c98a54e5c6e..759b8742764eb801b43c82143152897d0619e506 100644
--- a/compiler2/Type.hh
+++ b/compiler2/Type.hh
@@ -692,7 +692,7 @@ namespace Common {
       * @note Because this check depends on the checks of other AST elements
       * (external functions), it is sometimes delayed to the end of the semantic
       * analysis. */
-    void chk_coding(bool encode, bool delayed = false);
+    void chk_coding(bool encode, Module* usage_mod, bool delayed = false);
     
     /** Indicates whether the type is encoded/decoded by a function or by a
       * built-in codec. */
diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc
index 3ab69888c8ff543ad6bcb72a555e53dd6ee463fb..1e6028737cae7f08b5a3b3ea882640c0cd1788a8 100644
--- a/compiler2/Type_chk.cc
+++ b/compiler2/Type_chk.cc
@@ -5782,7 +5782,8 @@ bool Type::chk_this_template_Str(Template *t, namedbool implicit_omit,
         target->get_Template(), (target->get_DerivedRef() != NULL) ?
         INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED,
         OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs);
-      target_type->get_type_refd_last()->chk_coding(false);
+      target_type->get_type_refd_last()->chk_coding(false,
+        t->get_my_scope()->get_scope_mod());
     }
     {
       Value* str_enc = t->get_string_encoding();
diff --git a/compiler2/Value.cc b/compiler2/Value.cc
index 470a6870f73b8189194caa5b7337453160f033de..7e48312eeec7e266a202a2b12a901cef1775dc4c 100644
--- a/compiler2/Value.cc
+++ b/compiler2/Value.cc
@@ -5658,7 +5658,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     }*/
 
     if(!disable_attribute_validation()) {
-      t_type->chk_coding(true);
+      t_type->chk_coding(true, my_scope->get_scope_mod());
     }
     
     switch (t_type->get_typetype()) {
@@ -5810,7 +5810,7 @@ error:
     }
 
     if(!disable_attribute_validation()) {
-      t_type->chk_coding(false);
+      t_type->chk_coding(false, my_scope->get_scope_mod());
     }
 
     return;
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index 008b08571330784769452c8f0c3637521fe9d726..fdd64d15229f945d321e17be690ab86de53c6ca8 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -1288,6 +1288,10 @@ namespace Ttcn {
 
   void ImpMod::chk_imp(ReferenceChain& refch, vector<Common::Module>& moduleStack)
   {
+      if (imptype == I_DEPENDENCY) {
+        // these are added during semantic analysis, including their module pointer
+        return;
+      }
       Error_Context cntxt(this, "In import definition");
 
       if (!modules->has_mod_withId(*modid)) {
@@ -1399,6 +1403,8 @@ namespace Ttcn {
 
         break;
       }
+      case I_DEPENDENCY:
+        return false;
       default:
         FATAL_ERROR("ImpMod::get_imported_def");
       }
@@ -1489,6 +1495,8 @@ namespace Ttcn {
           return result;
         break;
       }
+      case I_DEPENDENCY:
+        return NULL;
       default:
         FATAL_ERROR("ImpMod::get_imported_def");
       }
@@ -1579,6 +1587,16 @@ namespace Ttcn {
   void Imports::add_impmod(ImpMod *p_impmod)
   {
     if (!p_impmod) FATAL_ERROR("Ttcn::Imports::add_impmod()");
+    if (p_impmod->get_imptype() == ImpMod::I_DEPENDENCY) {
+      // this is just an extra dependency, not an actual 'import' in TTCN-3 code,
+      // only insert it if it's needed
+      for (size_t i = 0; i < impmods_v.size(); ++i) {
+        if (p_impmod->get_mod() == impmods_v[i]->get_mod()) {
+          delete p_impmod;
+          return;
+        }
+      }
+    }
     impmods_v.add(p_impmod);
     p_impmod->set_my_mod(my_mod);
   }
diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh
index d98e435642ce75fed5a946268d6ab1e9ba6c1507..dd1cda7c3f05063d9d489e90bfe63e9e4acf42f0 100644
--- a/compiler2/ttcn3/AST_ttcn3.hh
+++ b/compiler2/ttcn3/AST_ttcn3.hh
@@ -646,7 +646,7 @@ namespace Ttcn {
     void set_with_attr(MultiWithAttrib* p_attrib);
     WithAttribPath* get_attrib_path();
     void set_parent_path(WithAttribPath* p_path);
-    const Imports& get_imports() const { return *imp; }
+    Imports& get_imports() { return *imp; }
 
     bool is_visible(const Identifier& id, visibility_t visibility);
     
@@ -719,7 +719,14 @@ namespace Ttcn {
       I_ERROR,
       I_ALL,
       I_IMPORTSPEC,
-      I_IMPORTIMPORT
+      I_IMPORTIMPORT,
+      /** Phantom import for when the 'include' is needed in the generated C++
+        * code, but the TTCN-3 'import' statement is optional.
+        * Currently this can only happen when using coding values of a type that
+        * has custom or PER coder functions set (the module containing the coder
+        * function declarations does not have to be imported to the module that
+        * contains the coding operation). */
+      I_DEPENDENCY
     };
   private:
     /** Points to the target (imported) module. This is initially NULL;
diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index a10b05ba7302b165f5955110fa91e15f3f1c249a..a111df363f46a5d0e058f248a9602e3b53d68345 100644
--- a/compiler2/ttcn3/Statement.cc
+++ b/compiler2/ttcn3/Statement.cc
@@ -8939,7 +8939,8 @@ error:
     if (!error_flag && t_var_type != NULL) {
       // make sure the variable's type has a decoding type set, and store it
       t_parass->set_dec_type(t_var_type->get_type_refd());
-      t_parass->get_dec_type()->chk_coding(false);
+      t_parass->get_dec_type()->chk_coding(false,
+        t_parass->get_ref()->get_my_scope()->get_scope_mod());
     }
   }
   else {
@@ -9745,7 +9746,8 @@ error:
               // store the variable type in case it's decoded (since this cannot
               // be extracted from the value type with the sub-references)
               v[i]->set_dec_type(var_type->get_type_refd());
-              v[i]->get_dec_type()->chk_coding(false);
+              v[i]->get_dec_type()->chk_coding(false,
+                v[i]->get_var_ref()->get_my_scope()->get_scope_mod());
             }
           }
           else {
diff --git a/regression_test/customEncoding/Coders.cc b/regression_test/customEncoding/Coders.cc
index 4318f4ed87d9a6496486ed4cd8d93119bd9eeac1..93da8c5ea3ba444aed7e4f12b4ffccca5b2fc959 100644
--- a/regression_test/customEncoding/Coders.cc
+++ b/regression_test/customEncoding/Coders.cc
@@ -161,3 +161,50 @@ INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y)
 }
 
 } // namespace Custom1
+
+namespace Custom5 {
+
+BITSTRING f__enc__set(const Custom3::Set& x)
+{
+  return int2bit(x.num(), 8);
+}
+
+INTEGER f__dec__set(BITSTRING& b, Custom3::Set& x)
+{
+  x.num() = bit2int(b);
+  x.str() = "c++";
+  b = BITSTRING(0, NULL);
+  return 0;
+}
+
+BITSTRING f__enc__setof(const Types::SetOf& x)
+{
+  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
+  TTCN_Buffer buf;
+  x.encode(Types::SetOf_descr_, buf, TTCN_EncDec::CT_JSON, false);
+  OCTETSTRING tmp;
+  buf.get_string(tmp);
+  return oct2bit(tmp);
+}
+
+INTEGER f__dec__setof(BITSTRING& x, Types::SetOf& y)
+{
+  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
+  TTCN_Buffer buf(bit2oct(x));
+  y.decode(Types::SetOf_descr_, buf, TTCN_EncDec::CT_JSON);
+  switch (TTCN_EncDec::get_last_error_type()) {
+  case TTCN_EncDec::ET_NONE: {
+    buf.cut();
+    OCTETSTRING tmp;
+    buf.get_string(tmp);
+    x = oct2bit(tmp);
+    return 0; }
+  case TTCN_EncDec::ET_INCOMPL_MSG:
+  case TTCN_EncDec::ET_LEN_ERR:
+    return 2;
+  default:
+    return 1;
+  }
+}
+
+} // namespace Custom5
diff --git a/regression_test/customEncoding/Coders.hh b/regression_test/customEncoding/Coders.hh
index ca2af2acf901afb62790ad063a4e338915741973..9902fa454473e5a306553a01c35e731732a0513d 100644
--- a/regression_test/customEncoding/Coders.hh
+++ b/regression_test/customEncoding/Coders.hh
@@ -13,6 +13,7 @@
 
 #include "Custom2.hh"
 #include "Custom1.hh"
+#include "Custom5.hh"
 
 #ifndef CODERS_HH
 #define CODERS_HH
@@ -27,6 +28,7 @@ INTEGER f__dec__rec(BITSTRING& b, Custom3::Rec& x);
 BITSTRING f__enc__uni(const Custom1::Uni& x);
 INTEGER f__dec__uni(BITSTRING& b, Custom1::Uni& x);
 
+// Coding functions for the bitstring type in test 4
 BITSTRING f__enc__bs(const BITSTRING& x);
 INTEGER f__dec__bs(BITSTRING& b, BITSTRING& x);
 
@@ -45,4 +47,16 @@ extern INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y);
 
 }
 
+namespace Custom5 {
+
+// Coding functions for the set type in test 5
+BITSTRING f__enc__set(const Custom3::Set& x);
+INTEGER f__dec__set(BITSTRING& b, Custom3::Set& x);
+
+// "PER" coder functions, using the built-in JSON codec
+extern BITSTRING f__enc__setof(const Types::SetOf& x);
+extern INTEGER f__dec__setof(BITSTRING& x, Types::SetOf& y);
+
+}
+
 #endif
diff --git a/regression_test/customEncoding/Custom1.ttcn b/regression_test/customEncoding/Custom1.ttcn
index 4832eadb9123a958fa788834e725a21fe3940025..e6f8357c3f397860fe6fc5b6b19698d4d1d18264 100644
--- a/regression_test/customEncoding/Custom1.ttcn
+++ b/regression_test/customEncoding/Custom1.ttcn
@@ -165,6 +165,30 @@ testcase tc_custom4() runs on CT
 }
 
 // Test 5.
+// The encoded type is a set defined in another module
+// The coding functions are declared in a 3rd module (which is not imported in this module)
+testcase tc_custom5() runs on CT
+{
+  var Set x := { num := 3, str := "ttcn" };
+  var bitstring enc_exp := int2bit(x.num, 8);
+  var Set dec_exp := { num := 3, str := "c++" };
+  
+  var bitstring enc := encvalue(x);
+  if (enc != enc_exp) {
+    setverdict(fail, "Expected: ", enc_exp, ", got: ", enc);
+  }
+  var Set dec;
+  var integer res := decvalue(enc_exp, dec);
+  if (res != 0) {
+    setverdict(fail, "Failed to decode ", enc_exp);
+  }
+  if (dec != dec_exp) {
+    setverdict(fail, "Expected: ", dec_exp, ", got: ", dec);
+  }
+  setverdict(pass);
+}
+
+// Test 6.
 // Using encvalue on templates and template variables
 // Same type and encoding function as test 1
 testcase tc_custom_temp() runs on CT
@@ -185,7 +209,7 @@ testcase tc_custom_temp() runs on CT
   setverdict(pass);
 }
 
-// Test 6.
+// Test 7.
 // Same as test 2, but with encvalue_unichar and decvalue_unichar.
 // The input RecOf has also been adjusted, so it doesn't cause problems for the UTF-8 decoder.
 testcase tc_custom_unichar() runs on CT
@@ -209,7 +233,7 @@ testcase tc_custom_unichar() runs on CT
   setverdict(pass);
 }
 
-// Test 7.
+// Test 8.
 // Using custom encoding on a decoded parameter redirect.
 // Same input value as in test 5.
 testcase tc_custom_param_redirect() runs on CT
@@ -240,7 +264,7 @@ testcase tc_custom_param_redirect() runs on CT
   }
 }
 
-// Test 8.
+// Test 9.
 // Using custom encoding in a template with decoded content matching.
 // Same input as test 3.
 testcase tc_custom_decmatch() runs on CT
@@ -272,7 +296,7 @@ external function f_enc_seq(in Seq x) return octetstring
 external function f_dec_seq(in octetstring x) return Seq
   with { extension "prototype(convert) decode(JSON)" };
   
-// Test 9.
+// Test 10.
 // Using encvalue and decvalue on the ASN.1 type Seq (with JSON encoding).
 testcase tc_asn() runs on CT
 {
@@ -295,7 +319,31 @@ testcase tc_asn() runs on CT
   setverdict(pass);
 }
 
-// Test 10.
+// Test 11.
+// Using encvalue and decvalue on the ASN.1 type Set (with JSON encoding).
+// The external functions indicating the type's coding are in a different module, which is not imported.
+testcase tc_asn2() runs on CT
+{
+  var Set2 x := { num := 10, str := "abc" };
+  var bitstring enc_exp := oct2bit(char2oct("{\"num\":10,\"str\":\"abc\"}"));
+  var Set2 dec_exp := x;
+  
+  var bitstring enc := encvalue(x);
+  if (enc != enc_exp) {
+    setverdict(fail, "Expected: ", enc_exp, ", got: ", enc);
+  }
+  var Set2 dec;
+  var integer res := decvalue(enc_exp, dec);
+  if (res != 0) {
+    setverdict(fail, "Failed to decode ", enc_exp);
+  }
+  if (dec != dec_exp) {
+    setverdict(fail, "Expected: ", dec_exp, ", got: ", dec);
+  }
+  setverdict(pass);
+}
+
+// Test 12.
 // The redirected parameter is decoded into a value of ASN.1 type Seq.
 // Same input value as in test 8.
 testcase tc_asn_param_redirect() runs on CT
@@ -326,7 +374,7 @@ testcase tc_asn_param_redirect() runs on CT
   }
 }
 
-// Test 11.
+// Test 13.
 // Decoded content matching against a value of ASN.1 type Seq.
 // Same input value as in test 8.
 testcase tc_asn_decmatch() runs on CT
@@ -359,7 +407,7 @@ external function f_enc_seqof(in SeqOf x) return bitstring
 external function f_dec_seqof(inout bitstring x, out SeqOf y) return integer
   with { extension "prototype(sliding) decode(PER)" };
   
-// Test 12.
+// Test 14.
 // PER coder with encvalue and decvalue.
 testcase tc_per() runs on CT
 {
@@ -383,7 +431,32 @@ testcase tc_per() runs on CT
   setverdict(pass);
 }
 
-// Test 13.
+// Test 15.
+// PER coder with encvalue and decvalue.
+// The PER coder functions are declared in a module, which is not imported into this one.
+testcase tc_per2() runs on CT
+{
+  var SetOf x := { 1, 2, 3 };
+  // the manually written "PER" coder for this module uses the built-in JSON coder
+  var bitstring enc_exp := oct2bit(char2oct("[1,2,3]"));
+  var SetOf dec_exp := x;
+  
+  var bitstring enc := encvalue(x);
+  if (enc != enc_exp) {
+    setverdict(fail, "Expected: ", enc_exp, ", got: ", enc);
+  }
+  var SetOf dec;
+  var integer res := decvalue(enc_exp, dec);
+  if (res != 0) {
+    setverdict(fail, "Failed to decode ", enc_exp);
+  }
+  if (dec != dec_exp) {
+    setverdict(fail, "Expected: ", dec_exp, ", got: ", dec);
+  }
+  setverdict(pass);
+}
+
+// Test 16.
 // The redirected parameter is decoded using the PER coder.
 // Same input value as in test 11.
 testcase tc_per_param_redirect() runs on CT
@@ -414,7 +487,7 @@ testcase tc_per_param_redirect() runs on CT
   }
 }
 
-// Test 14.
+// Test 17.
 // Decoded content matching with the PER coder.
 // Same input value as in test 11.
 testcase tc_per_decmatch() runs on CT
@@ -447,7 +520,7 @@ external function f_enc_choice(in Choice x) return bitstring
 external function f_dec_choice(inout bitstring x, out Choice y) return integer
   with { extension "prototype(sliding) decode(PER)" };
 
-// Test 15.
+// Test 18.
 // Encoding an ASN.1 type with JSON (built-in) and decoding the same type with PER (manual).
 testcase tc_asn_mixed() runs on CT
 {
@@ -478,14 +551,17 @@ control {
   execute(tc_custom2());
   execute(tc_custom3());
   execute(tc_custom4());
+  execute(tc_custom5());
   execute(tc_custom_temp());
   execute(tc_custom_unichar());
   execute(tc_custom_param_redirect());
   execute(tc_custom_decmatch());
   execute(tc_asn());
+  execute(tc_asn2());
   execute(tc_asn_param_redirect());
   execute(tc_asn_decmatch());
   execute(tc_per());
+  execute(tc_per2());
   execute(tc_per_param_redirect());
   execute(tc_per_decmatch());
   execute(tc_asn_mixed());
diff --git a/regression_test/customEncoding/Custom3.ttcn b/regression_test/customEncoding/Custom3.ttcn
index bd3db629b5523279f59087913e32758753c811f1..2b876d4e3c619a94d96d8c0d5b97862e02e9d001 100644
--- a/regression_test/customEncoding/Custom3.ttcn
+++ b/regression_test/customEncoding/Custom3.ttcn
@@ -22,4 +22,13 @@ with {
   encode "localCustom";
 }
 
+// Set type for test 5
+type set Set {
+  integer num,
+  charstring str
+}
+with {
+  encode "localCustom";
+}
+
 }
diff --git a/regression_test/customEncoding/Custom4.ttcn b/regression_test/customEncoding/Custom4.ttcn
index aa9cec62b677fa8160b8172abf16d7e209c7d9f7..5eb3a78272ecb0fda87fd611799199fb674e3b79 100644
--- a/regression_test/customEncoding/Custom4.ttcn
+++ b/regression_test/customEncoding/Custom4.ttcn
@@ -19,7 +19,7 @@ import from Custom2 all;
 import from Custom3 all;
 import from Types all;
 
-// Test 16 (RT2 only).
+// Test 19 (RT2 only).
 // Using custom encoding on a decoded value redirect.
 // Same input value as in test 1.
 testcase tc_custom_value_redirect() runs on CT
@@ -50,7 +50,7 @@ testcase tc_custom_value_redirect() runs on CT
   }
 }
 
-// Test 17 (RT2 only).
+// Test 20 (RT2 only).
 // The redirected value is decoded into a value of ASN.1 type Seq.
 // Same input value as in test 8.
 testcase tc_asn_value_redirect() runs on CT
@@ -80,7 +80,7 @@ testcase tc_asn_value_redirect() runs on CT
   }
 }
 
-// Test 18 (RT2 only).
+// Test 21 (RT2 only).
 // The redirected value is decoded using the PER coder.
 // Same input value as in test 11.
 testcase tc_per_value_redirect() runs on CT
diff --git a/regression_test/customEncoding/Custom5.ttcn b/regression_test/customEncoding/Custom5.ttcn
new file mode 100644
index 0000000000000000000000000000000000000000..a15dc54be4c56588e8ef8628d54f6877d6abb376
--- /dev/null
+++ b/regression_test/customEncoding/Custom5.ttcn
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * Copyright (c) 2000-2016 Ericsson Telecom AB
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Baranyi, Botond
+ *
+ ******************************************************************************/
+
+module Custom5 {
+
+import from Custom3 all;
+import from Types all;
+
+// Coding function declarations for test 5
+external function f_enc_set(in Set x) return bitstring
+  with { extension "prototype(convert) encode(localCustom)" }
+  
+external function f_dec_set(inout bitstring b, out Set x) return integer
+  with { extension "prototype(sliding) decode(localCustom)" }
+
+// these let encvalue and decvalue know which encoding to use for the ASN.1 type
+external function f_enc_set2(in Set2 x) return octetstring
+  with { extension "prototype(convert) encode(JSON)" };
+  
+external function f_dec_set2(in octetstring x) return Set2
+  with { extension "prototype(convert) decode(JSON)" };
+
+// PER coder functions, these need to be implemented manually, just like custom
+// coder functions
+external function f_enc_setof(in SetOf x) return bitstring
+  with { extension "prototype(convert) encode(PER)" };
+  
+external function f_dec_setof(inout bitstring x, out SetOf y) return integer
+  with { extension "prototype(sliding) decode(PER)" };
+
+}
diff --git a/regression_test/customEncoding/Makefile b/regression_test/customEncoding/Makefile
index fee2198833b40b7655a1230a50cd0bb7655a999a..d5918ca7a2e932fe641f236287116ed815951592 100644
--- a/regression_test/customEncoding/Makefile
+++ b/regression_test/customEncoding/Makefile
@@ -19,7 +19,7 @@ include $(TOPDIR)/Makefile.regression
 
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
-TTCN3_MODULES = Custom1.ttcn Custom2.ttcn Custom3.ttcn
+TTCN3_MODULES = Custom1.ttcn Custom2.ttcn Custom3.ttcn Custom5.ttcn
 ASN1_MODULES = Types.asn
 
 ifdef RT2
diff --git a/regression_test/customEncoding/Types.asn b/regression_test/customEncoding/Types.asn
index 19381f6f7671fb6209bb9e5a1e1e153b1b297ba7..985b9be590bdf0247abb33646bd33f13d71019d6 100644
--- a/regression_test/customEncoding/Types.asn
+++ b/regression_test/customEncoding/Types.asn
@@ -23,8 +23,15 @@ Seq ::= SEQUENCE {
   str VisibleString
 }
 
+Set2 ::= SET {
+  num INTEGER,
+  str VisibleString
+}
+
 SeqOf ::= SEQUENCE OF INTEGER
 
+SetOf ::= SEQUENCE OF INTEGER
+
 Choice ::= CHOICE {
   num INTEGER,
   str VisibleString
diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc
index bcc45dba3bec8710cc977b1a0f89f11f560850f0..15fc4ee927bfaf29d17338f71fc9d0a6530809b7 100644
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ