diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index 9d99ad0c76872c89b618cb4bc50bcc59b82c45b0..7f28142f93c4af69d62ddc72b270f6a9af725dbc 100644
--- a/compiler2/ttcn3/Statement.cc
+++ b/compiler2/ttcn3/Statement.cc
@@ -8540,7 +8540,16 @@ error:
           // then the parameter redirect class should use the decoding result 
           // from the template instead of decoding the parameter again
           needs_decode = false;
-          if (par->get_type()->get_type_refd_last()->get_typetype_ttcn3() == Type::T_USTR) {
+          Type* decmatch_type = matched_temp->get_decode_target()->get_expr_governor(
+            Type::EXPECTED_TEMPLATE)->get_type_refd_last();
+          if (ve->get_dec_type() != decmatch_type) {
+            // the decmatch template and this parameter redirect decode two
+            // different types, so just decode the parameter
+            needs_decode = true;
+            use_decmatch_result = false;
+          }
+          else if (par->get_type()->get_type_refd_last()->get_typetype_ttcn3() ==
+                   Type::T_USTR) {
             // for universal charstrings the situation could be trickier
             // compare the string encodings
             bool different_ustr_encodings = false;
@@ -8618,7 +8627,12 @@ error:
               set_params_str = mputstr(set_params_str, redir_coding_expr.preamble);
             }
             set_params_str = mputprintf(set_params_str,
-              "if (ptr_matched_temp->%s().get_selection() == DECODE_MATCH",
+              "if (ptr_matched_temp->%s().get_selection() == DECODE_MATCH && "
+              // the type the parameter was decoded to in the template must be the same
+              // as the type this parameter redirect would decode the redirected parameter to
+              // (this is checked by comparing the addresses of the type descriptors)
+              "&%s_descr_ == ptr_matched_temp->%s().get_decmatch_type_descr()",
+              par_name, ve->get_dec_type()->get_genname_typedescriptor(scope).c_str(),
               par_name);
             if (redir_coding_expr.expr != NULL) {
               set_params_str = mputprintf(set_params_str,
@@ -9171,7 +9185,16 @@ error:
           // then the value redirect class should use the decoding result 
           // from the template instead of decoding the value again
           needs_decode = false;
-          if (redir_type->get_type_refd_last()->get_typetype_ttcn3() == Type::T_USTR) {
+          Type* decmatch_type = matched_temp->get_decode_target()->get_expr_governor(
+            Type::EXPECTED_TEMPLATE)->get_type_refd_last();
+          if (v[i]->get_dec_type() != decmatch_type) {
+            // the decmatch template and this value redirect decode two
+            // different types, so just decode the value
+            needs_decode = true;
+            use_decmatch_result = false;
+          }
+          else if (redir_type->get_type_refd_last()->get_typetype_ttcn3() ==
+                   Type::T_USTR) {
             // for universal charstrings the situation could be trickier
             // compare the string encodings
             bool different_ustr_encodings = false;
@@ -9270,7 +9293,14 @@ error:
             }
             Free(current_ref);
             set_values_str = mputprintf(set_values_str,
-              "(*ptr_matched_temp)%s.get_selection() == DECODE_MATCH", subrefs_str);
+              "(*ptr_matched_temp)%s.get_selection() == DECODE_MATCH && "
+              // the type the value was decoded to in the template must be the same
+              // as the type this value redirect would decode the redirected value to
+              // (this is checked by comparing the addresses of the type descriptors)
+              "&%s_descr_ == (*ptr_matched_temp)%s.get_decmatch_type_descr()",
+              subrefs_str,
+              v[i]->get_dec_type()->get_genname_typedescriptor(scope).c_str(),
+              subrefs_str);
             if (redir_coding_expr.expr != NULL) {
               set_values_str = mputprintf(set_values_str,
                 " && %s == (*ptr_matched_temp)%s.get_decmatch_str_enc()",
diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc
index ec66171a119ede7f4ac2b9ce6157422aa1f8b7fe..c2ed63a683728d6873b5021a61dc291ac130d02e 100644
--- a/compiler2/ttcn3/TtcnTemplate.cc
+++ b/compiler2/ttcn3/TtcnTemplate.cc
@@ -4582,6 +4582,9 @@ compile_time:
       // retrieves the decoding result from the last successful matching
       // (used for optimizing decoded value and parameter redirects)
       "void* get_dec_res() const { return dec_val; }\n"
+      // returns a pointer to the type descriptor used in the decoding
+      // (used for the runtime type check for decoded value and parameter redirects)
+      "const TTCN_Typedescriptor_t* get_type_descr() const { return &%s_descr_; }\n"
       "};\n"
       "%s.set_type(DECODE_MATCH);\n"
       "{\n", class_tmp_id.c_str(),
@@ -4591,7 +4594,8 @@ compile_time:
       target_type->get_genname_value(my_scope).c_str(),
       target_type->get_genname_typedescriptor(my_scope).c_str(),
       target_type->get_coding(false).c_str(),
-      omit_in_value_list ? ", TRUE" : "", type_name.c_str(), name);
+      omit_in_value_list ? ", TRUE" : "", type_name.c_str(),
+      target_type->get_genname_typedescriptor(my_scope).c_str(), name);
     
     // generate the decoding target into a temporary
     string target_tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id();
diff --git a/core/Basetype.hh b/core/Basetype.hh
index 06794c0c0062ee756110b864ebe5f359836902c4..1809b33b13a4761a7ad89c7759a4088a1b73625a 100644
--- a/core/Basetype.hh
+++ b/core/Basetype.hh
@@ -1103,6 +1103,10 @@ public:
     * the function returns a void pointer (since the decoding could result in a
     * value of any type), which is converted to the required type when used */
   virtual void* get_dec_res() const = 0;
+  /** this returns the decoded type's descriptor, which may be used by value and
+    * parameter redirect classes to determine whether the redirected value would
+    * be decoded into the same type as the type used in this decmatch template */
+  virtual const TTCN_Typedescriptor_t* get_type_descr() const = 0;
   virtual ~Dec_Match_Interface() {}
 };
 
diff --git a/core/Bitstring.cc b/core/Bitstring.cc
index 94d8382bf103df479259ab489746750de814eba1..3491fa74f4d12ca973dce266fd4bfcc9928014aa 100644
--- a/core/Bitstring.cc
+++ b/core/Bitstring.cc
@@ -1836,6 +1836,15 @@ void* BITSTRING_template::get_decmatch_dec_res() const
   return dec_match->instance->get_dec_res();
 }
 
+const TTCN_Typedescriptor_t* BITSTRING_template::get_decmatch_type_descr() const
+{
+  if (template_selection != DECODE_MATCH) {
+    TTCN_error("Retrieving the decoded type's descriptor in a non-decmatch "
+      "bitstring template.");
+  }
+  return dec_match->instance->get_type_descr();
+}
+
 static const char patterns[] = { '0', '1', '?', '*' };
 
 void BITSTRING_template::log() const
diff --git a/core/Bitstring.hh b/core/Bitstring.hh
index a8a69dcfe19e023e35a7a83ded5b651828f65edd..95db2ab6a5aa01d46e72d613243347de7d5c7792 100644
--- a/core/Bitstring.hh
+++ b/core/Bitstring.hh
@@ -301,6 +301,7 @@ public:
   void set_decmatch(Dec_Match_Interface* new_instance);
   
   void* get_decmatch_dec_res() const;
+  const TTCN_Typedescriptor_t* get_decmatch_type_descr() const;
 
   void log() const;
   void log_match(const BITSTRING& match_value, boolean legacy = FALSE) const;
diff --git a/core/Charstring.cc b/core/Charstring.cc
index 6123430c3118a81c0b8583ee500519f9dc7bdf2b..286b4f246ece70cf2c92d03ab9eaa0b107d95ec4 100644
--- a/core/Charstring.cc
+++ b/core/Charstring.cc
@@ -2454,6 +2454,15 @@ void* CHARSTRING_template::get_decmatch_dec_res() const
   return dec_match->instance->get_dec_res();
 }
 
+const TTCN_Typedescriptor_t* CHARSTRING_template::get_decmatch_type_descr() const
+{
+  if (template_selection != DECODE_MATCH) {
+    TTCN_error("Retrieving the decoded type's descriptor in a non-decmatch "
+      "charstring template.");
+  }
+  return dec_match->instance->get_type_descr();
+}
+
 void CHARSTRING_template::log_pattern(int n_chars, const char *chars_ptr)
 {
   TTCN_Logger::log_event_str("pattern \"");
diff --git a/core/Charstring.hh b/core/Charstring.hh
index a6bf883f6607c8a454686a427edd5ea2ca3c64b8..a74ae9ea75484d583a788dc1a380b7cec31f7237 100644
--- a/core/Charstring.hh
+++ b/core/Charstring.hh
@@ -432,6 +432,7 @@ public:
   void set_decmatch(Dec_Match_Interface* new_instance);
   
   void* get_decmatch_dec_res() const;
+  const TTCN_Typedescriptor_t* get_decmatch_type_descr() const;
 
   void log() const;
   void log_match(const CHARSTRING& match_value, boolean legacy = FALSE) const;
diff --git a/core/Hexstring.cc b/core/Hexstring.cc
index 07826fe1c27a262747775e0472454eed1102bf9f..6bfa8b05f492b436e4eb66813e909aef62de628d 100644
--- a/core/Hexstring.cc
+++ b/core/Hexstring.cc
@@ -1722,6 +1722,15 @@ void* HEXSTRING_template::get_decmatch_dec_res() const
   return dec_match->instance->get_dec_res();
 }
 
+const TTCN_Typedescriptor_t* HEXSTRING_template::get_decmatch_type_descr() const
+{
+  if (template_selection != DECODE_MATCH) {
+    TTCN_error("Retrieving the decoded type's descriptor in a non-decmatch "
+      "hexstring template.");
+  }
+  return dec_match->instance->get_type_descr();
+}
+
 void HEXSTRING_template::log() const
 {
   switch (template_selection) {
diff --git a/core/Hexstring.hh b/core/Hexstring.hh
index ed620bfa41a34c1283b8f6d25eb168022413f8ba..c8b8816b8e6080829bdc2a574589231861108a71 100644
--- a/core/Hexstring.hh
+++ b/core/Hexstring.hh
@@ -255,6 +255,7 @@ public:
   void set_decmatch(Dec_Match_Interface* new_instance);
   
   void* get_decmatch_dec_res() const;
+  const TTCN_Typedescriptor_t* get_decmatch_type_descr() const;
 
   void log() const;
   void log_match(const HEXSTRING& match_value, boolean legacy = FALSE) const;
diff --git a/core/Octetstring.cc b/core/Octetstring.cc
index 0f63ec381bad8e2f31132ff4a0ff00c944b6f161..fab2f843ce6c51ba3e0318e31127489fd057754a 100644
--- a/core/Octetstring.cc
+++ b/core/Octetstring.cc
@@ -1958,6 +1958,15 @@ void* OCTETSTRING_template::get_decmatch_dec_res() const
   return dec_match->instance->get_dec_res();
 }
 
+const TTCN_Typedescriptor_t* OCTETSTRING_template::get_decmatch_type_descr() const
+{
+  if (template_selection != DECODE_MATCH) {
+    TTCN_error("Retrieving the decoded type's descriptor in a non-decmatch "
+      "octetstring template.");
+  }
+  return dec_match->instance->get_type_descr();
+}
+
 void OCTETSTRING_template::log() const
 {
   switch (template_selection) {
diff --git a/core/Octetstring.hh b/core/Octetstring.hh
index 631993e34329b64ca816edc928fa91957b59f7dd..2988df311ed11665b6cb1149033299be19fcce97 100644
--- a/core/Octetstring.hh
+++ b/core/Octetstring.hh
@@ -286,6 +286,7 @@ public:
   void set_decmatch(Dec_Match_Interface* new_instance);
   
   void* get_decmatch_dec_res() const;
+  const TTCN_Typedescriptor_t* get_decmatch_type_descr() const;
 
   void log() const;
   void log_match(const OCTETSTRING& match_value, boolean legacy = FALSE) const;
diff --git a/core/Universal_charstring.cc b/core/Universal_charstring.cc
index 747b0c3bdbcac4a72ca5f19e3d6a1d59bc9c3c17..c8668206e341921a740566a037d63d247b0e18e8 100644
--- a/core/Universal_charstring.cc
+++ b/core/Universal_charstring.cc
@@ -4223,6 +4223,15 @@ CharCoding::CharCodingType UNIVERSAL_CHARSTRING_template::get_decmatch_str_enc()
   return dec_match->coding;
 }
 
+const TTCN_Typedescriptor_t* UNIVERSAL_CHARSTRING_template::get_decmatch_type_descr() const
+{
+  if (template_selection != DECODE_MATCH) {
+    TTCN_error("Retrieving the decoded type's descriptor in a non-decmatch "
+      "universal charstring template.");
+  }
+  return dec_match->instance->get_type_descr();
+}
+
 void UNIVERSAL_CHARSTRING_template::log() const
 {
   switch (template_selection) {
diff --git a/core/Universal_charstring.hh b/core/Universal_charstring.hh
index f771fdeb92185ffc516577e402225ea62085df68..8a48df6b45a64c64cadf4cce4d97ac17e766f46c 100644
--- a/core/Universal_charstring.hh
+++ b/core/Universal_charstring.hh
@@ -613,6 +613,7 @@ public:
   
   void* get_decmatch_dec_res() const;
   CharCoding::CharCodingType get_decmatch_str_enc() const;
+  const TTCN_Typedescriptor_t* get_decmatch_type_descr() const;
 
   void log() const;
   void log_match(const UNIVERSAL_CHARSTRING& match_value, boolean legacy = FALSE) const;
diff --git a/regression_test/commProcedure/ProcPort.ttcn b/regression_test/commProcedure/ProcPort.ttcn
index fb9870309c9e8d7551814673192d45366d3de45d..c15fb44d6d2300a1e03d838bf8967955cfb45520 100644
--- a/regression_test/commProcedure/ProcPort.ttcn
+++ b/regression_test/commProcedure/ProcPort.ttcn
@@ -33,6 +33,18 @@ type record MyRecord3 {
   record of MyRecord2 elems
 }
 
+type record MyRecord4 {
+  charstring attr,
+  octetstring val
+}
+with {
+  encode "XML";
+  variant "name as 'MyRecord2'";
+  variant (attr) "attribute";
+  variant (attr) "name as 'num'";
+  variant (val) "untagged";
+}
+
 type octetstring MyOctetstring with { encode "RAW"; }
 
 signature MyProc(in integer Par1,inout charstring Par2,out float Par3)
@@ -722,10 +734,99 @@ testcase tc_MultiValueRedirect() runs on ProcComponent4 {
 }
 
 // tests for decoded parameter and value redirects
+// (in these tests the received parameters and values are not matched with a 'decmatch' template)
+function DecodedRedirect_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 {
+  timer tmr := 1.0;
+  var universal charstring val_enc := encvalue_unichar(val);
+  var MyRecord2 redir;
+  
+  // testing parameter redirect in getcall:
+  tmr.start;
+  alt {
+    [] Port4.getcall(MyProc7: { val_enc }) -> param (redir := @decoded x) {
+      if (redir != val) { setverdict(fail, "Getcall parameter redirect failed: ", redir); }
+      else {
+        var MyRecord2 reply_rec := { num := -1, str := reply_val };
+        Port4.reply(MyProc7: { reply_val } value reply_rec);
+        Port4.raise(MyProc7, reply_rec);
+      }
+    }
+    [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); }
+    [] tmr.timeout { setverdict(fail, "Getcall timed out."); }
+  }
+}
+
+testcase tc_DecodedRedirect() runs on ProcComponent4 {
+  var ProcComponent4 ct := ProcComponent4.create;
+  connect(ct:Port4, mtc:Port4);
+  var MyRecord2 val := { num := 4, str := "stuff" };
+  // use this string instead of an actual encoded value for reply/getreply and raise/catch,
+  // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult
+  // (after this string is decoded into an octetstring, only the octetstring's length is matched)
+  var universal charstring reply_val := "payload";
+  ct.start(DecodedRedirect_behav(val, reply_val));
+  var universal charstring val_enc := encvalue_unichar(val);
+  var MyOctetstring redir[3];
+  // these encoding strings are not known at compile-time (the code generated for them is different)
+  var charstring str_enc8 := "UTF-8", str_enc16 := "UTF-16", str_enc32 := "UTF-32LE";
+  
+  // testing parameter and (return) value redirect in getreply:
+  Port4.call(MyProc7: { val_enc }, 1.0) {
+    [] Port4.getreply(MyProc7: { reply_val }
+                      value MyRecord2: { num := ?, str := reply_val })
+                      -> value (redir[0] := @decoded("UTF-8") str)
+                      param (redir[1] := @decoded(str_enc16) x) {
+      if (redir[0] != unichar2oct(reply_val, "UTF-8")) {
+        setverdict(fail, "Getreply parameter redirect failed: ", redir[0]);
+      }
+      if (redir[1] != unichar2oct(reply_val, str_enc16)) {
+        setverdict(fail, "Getreply value redirect failed: ", redir[1]);
+      }
+    }
+    [] Port4.getreply(MyProc7: { decmatch(str_enc16) MyOctetstring: ? length (16) } value MyRecord2: ?) {
+      setverdict(fail, "Invalid getreply return value.");
+    }
+    [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) {
+      setverdict(fail, "Invalid getreply parameter.");
+    }
+    [] Port4.catch(MyProc7, MyRecord2: ?) {
+      setverdict(fail, "Exception (MyRecord2) caught in getreply test.");
+    }
+    [] Port4.catch(MyProc7, MyRecord3: ?) {
+      setverdict(fail, "Exception (MyRecord3) caught in getreply test.");
+    }
+    [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); }
+  }
+  
+  // testing (exception) value redirect in catch:
+  timer tmr := 1.0;
+  tmr.start;
+  alt {
+    [] Port4.catch(MyProc7, MyRecord2: { num := ?, str := reply_val })
+                   -> value (redir[2] := @decoded(str_enc32) str) {
+      if (redir[2] != unichar2oct(reply_val, str_enc32)) {
+        setverdict(fail, "Exception value redirect failed: ", redir[2]);
+      }
+    }
+    [] Port4.catch(MyProc7, MyRecord2: ?) {
+      setverdict(fail, "Invalid exception value caught.");
+    }
+    [] Port4.catch(MyProc7, MyRecord3: ?) {
+      setverdict(fail, "Invalid type of exception caught.");
+    }
+    [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) {
+      setverdict(fail, "Reply received in exception test.");
+    }
+    [] tmr.timeout { setverdict(fail, "Exception test timed out."); }
+  }
+  setverdict(pass);
+}
+
+// additional tests for decoded parameter and value redirects
 // (in these tests the value and parameter redirects with the '@decoded' modifier
 // are optimized to reuse the decoding result in the 'decmatch' template instead of
 // decoding the same string twice)
-function DecodedRedirect_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 {
+function DecodedRedirect2_behav(in MyRecord2 val, in universal charstring reply_val) runs on ProcComponent4 {
   timer tmr := 1.0;
   var MyRecord2 redir;
   
@@ -745,7 +846,7 @@ function DecodedRedirect_behav(in MyRecord2 val, in universal charstring reply_v
   }
 }
 
-testcase tc_DecodedRedirect() runs on ProcComponent4 {
+testcase tc_DecodedRedirect2() runs on ProcComponent4 {
   var ProcComponent4 ct := ProcComponent4.create;
   connect(ct:Port4, mtc:Port4);
   var MyRecord2 val := { num := 4, str := "stuff" };
@@ -753,7 +854,7 @@ testcase tc_DecodedRedirect() runs on ProcComponent4 {
   // because finding a value that can be encoded with UTF-16 or UTF-32 is difficult
   // (after this string is decoded into an octetstring, only the octetstring's length is matched)
   var universal charstring reply_val := "payload";
-  ct.start(DecodedRedirect_behav(val, reply_val));
+  ct.start(DecodedRedirect2_behav(val, reply_val));
   var universal charstring val_enc := encvalue_unichar(val);
   var MyOctetstring redir[3];
   // these encoding strings are not known at compile-time (the code generated for them is different)
@@ -811,11 +912,11 @@ testcase tc_DecodedRedirect() runs on ProcComponent4 {
   setverdict(pass);
 }
 
-// additional tests for decoded parameter and value redirects
+// further tests for decoded parameter and value redirects
 // (in these tests the 'decmatch' templates cannot be identified at compile-time,
 // so the decision of whether to decode the redirected value again or use the
 // decoding result in the matched template is made at runtime)
-function DecodedRedirect2_behav(in MyRecord2 val) runs on ProcComponent4 {
+function DecodedRedirect3_behav(in MyRecord2 val) runs on ProcComponent4 {
   timer tmr := 1.0;
   var MyRecord2 redir;
   var template MyProc7 vt_proc7 := { x := decmatch MyRecord2: val };
@@ -838,11 +939,11 @@ function DecodedRedirect2_behav(in MyRecord2 val) runs on ProcComponent4 {
   }
 }
 
-testcase tc_DecodedRedirect2() runs on ProcComponent4 {
+testcase tc_DecodedRedirect3() runs on ProcComponent4 {
   var ProcComponent4 ct := ProcComponent4.create;
   connect(ct:Port4, mtc:Port4);
   var MyRecord2 val := { num := 4, str := "stuff" };
-  ct.start(DecodedRedirect2_behav(val));
+  ct.start(DecodedRedirect3_behav(val));
   var universal charstring val_enc := encvalue_unichar(val);
   var MyRecord2 redir[3];
   var template MyRecord2 vt_rec2 := { num := ?, str := decmatch MyRecord2: val };
@@ -900,6 +1001,95 @@ testcase tc_DecodedRedirect2() runs on ProcComponent4 {
   setverdict(pass);
 }
 
+// even more tests for decoded parameter and value redirects
+// (in these tests the sent/received strings are decoded into 2 different types:
+// the matching 'decmatch' templates decode the strings into MyRecord2, while the
+// value and parameter redirects decode the string into MyRecord4)
+function DecodedRedirect4_behav(in MyRecord2 val2, in MyRecord4 val4) runs on ProcComponent4 {
+  timer tmr := 1.0;
+  var MyRecord4 redir;
+  
+  // testing parameter redirect in getcall:
+  tmr.start;
+  alt {
+    [] Port4.getcall(MyProc7: { decmatch MyRecord2: val2 }) -> param (redir := @decoded x) {
+      if (redir != val4) { 
+        setverdict(fail, "Getcall parameter redirect failed: ", redir);
+      }
+      else {
+        var universal charstring val_enc := encvalue_unichar(val2);
+        var MyRecord2 reply_val := { num := val2.num, str := val_enc };
+        var MyRecord3 raise_val := { elems := { reply_val } };
+        Port4.reply(MyProc7: { val_enc } value reply_val);
+        Port4.raise(MyProc7, raise_val);
+      }
+    }
+    [] Port4.getcall(MyProc7: { ? }) { setverdict(fail, "Invalid getcall parameter."); }
+    [] tmr.timeout { setverdict(fail, "Getcall timed out."); }
+  }
+}
+
+testcase tc_DecodedRedirect4() runs on ProcComponent4 {
+  var ProcComponent4 ct := ProcComponent4.create;
+  connect(ct:Port4, mtc:Port4);
+  var MyRecord2 val2 := { num := 4, str := "ADDC" };
+  var MyRecord4 val4 := { attr := "4", val := 'ADDC'O };
+  ct.start(DecodedRedirect4_behav(val2, val4));
+  var universal charstring val_enc := encvalue_unichar(val2);
+  var MyRecord4 redir[3];
+  
+  // testing parameter and (return) value redirect in getreply:
+  Port4.call(MyProc7: { val_enc }, 1.0) {
+    [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2)
+                      value MyRecord2: { num := ?, str := decmatch MyRecord2: val2 })
+                      -> value (redir[0] := @decoded str)
+                      param (redir[1] := @decoded x) {
+      if (redir[0] != val4) {
+        setverdict(fail, "Getreply parameter redirect failed: ", redir[0]);
+      }
+      if (redir[1] != val4) {
+        setverdict(fail, "Getreply value redirect failed: ", redir[1]);
+      }
+    }
+    [] Port4.getreply(MyProc7TemplatePard(decmatch MyRecord2: val2) value MyRecord2: ?) {
+      setverdict(fail, "Invalid getreply return value.");
+    }
+    [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) {
+      setverdict(fail, "Invalid getreply parameter.");
+    }
+    [] Port4.catch(MyProc7, MyRecord2: ?) {
+      setverdict(fail, "Exception (MyRecord2) caught in getreply test.");
+    }
+    [] Port4.catch(MyProc7, MyRecord3: ?) {
+      setverdict(fail, "Exception (MyRecord3) caught in getreply test.");
+    }
+    [] Port4.catch(timeout) { setverdict(fail, "Getreply test timed out."); }
+  }
+  
+  // testing (exception) value redirect in catch:
+  var template MyRecord3 vt_rec3 := { elems := { { num := ?, str := decmatch MyRecord2: val2 } } };
+  timer tmr := 1.0;
+  tmr.start;
+  alt {
+    [] Port4.catch(MyProc7, vt_rec3) -> value (redir[2] := @decoded elems[0].str) {
+      if (redir[2] != val4) {
+        setverdict(fail, "Exception value redirect failed: ", redir[2]);
+      }
+    }
+    [] Port4.catch(MyProc7, MyRecord3: ?) {
+      setverdict(fail, "Invalid exception value caught.");
+    }
+    [] Port4.catch(MyProc7, MyRecord2: ?) {
+      setverdict(fail, "Invalid type of exception caught.");
+    }
+    [] Port4.getreply(MyProc7: { ? } value MyRecord2: ?) {
+      setverdict(fail, "Reply received in exception test.");
+    }
+    [] tmr.timeout { setverdict(fail, "Exception test timed out."); }
+  }
+  setverdict(pass);
+}
+
 control {
   execute(tc1_Call());
   execute(tc2_Call());
@@ -917,5 +1107,7 @@ control {
   execute(tc_MultiValueRedirect());
   execute(tc_DecodedRedirect());
   execute(tc_DecodedRedirect2());
+  execute(tc_DecodedRedirect3());
+  execute(tc_DecodedRedirect4());
 }
 }