From 5f2c73dde65942a82dab96a0de62b5755f84a654 Mon Sep 17 00:00:00 2001
From: Botond Baranyi <botond.baranyi@ericsson.com>
Date: Tue, 2 May 2017 17:32:06 +0200
Subject: [PATCH] Added error messages for using two consecutive length
 restrictions

Change-Id: Iba255ddd2b713b9b5e2876f863c829746cefc73d
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
---
 compiler2/Type_chk.cc                         |  1 +
 compiler2/Value.cc                            | 87 +++++++++++--------
 compiler2/Value.hh                            |  3 +
 compiler2/ttcn3/TtcnTemplate.cc               | 25 +++++-
 compiler2/ttcn3/TtcnTemplate.hh               |  2 +
 compiler2/ttcn3/compiler.y                    |  4 +-
 .../TTCN3_SA_ttcn3adhoc_TD.script             |  6 +-
 .../template_concat/TemplateConcat_SE.ttcn    |  4 +
 8 files changed, 89 insertions(+), 43 deletions(-)

diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc
index 3e8d4c034..38be2da74 100644
--- a/compiler2/Type_chk.cc
+++ b/compiler2/Type_chk.cc
@@ -5525,6 +5525,7 @@ bool Type::chk_this_template_generic(Template *t, namedbool incomplete_allowed,
   namedbool implicit_omit, Common::Assignment *lhs)
 {
   bool self_ref = false;
+  t->chk_concat_double_length_res();
   // get_template_refd_last evaluates concatenations between templates known at
   // compile-time
   Ttcn::Template::templatetype_t tt = t->get_template_refd_last()->get_templatetype();
diff --git a/compiler2/Value.cc b/compiler2/Value.cc
index 6e712ad55..26a5e118e 100644
--- a/compiler2/Value.cc
+++ b/compiler2/Value.cc
@@ -78,6 +78,7 @@ namespace Common {
 
   Value::Value(const Value& p)
     : GovernedSimple(p), valuetype(p.valuetype), my_governor(0)
+    , in_brackets(p.in_brackets)
   {
     switch(valuetype) {
     case V_ERROR:
@@ -697,7 +698,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     switch(valuetype) {
     case V_NULL:
@@ -719,7 +720,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, bool p_val_bool)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     switch(valuetype) {
     case V_BOOL:
@@ -731,7 +732,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, const Int& p_val_Int)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     switch(valuetype) {
     case V_INT:
@@ -743,7 +744,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, int_val_t *p_val_Int)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     switch(valuetype){
     case V_INT:
@@ -755,7 +756,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, string *p_val_str)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_val_str) FATAL_ERROR("NULL parameter");
     switch(valuetype) {
@@ -772,7 +773,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, ustring *p_val_ustr)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if (p_vt != V_USTR || !p_val_ustr) FATAL_ERROR("Value::Value()");
     set_val_ustr(p_val_ustr);
@@ -780,7 +781,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, CharSyms *p_char_syms)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if (!p_char_syms) FATAL_ERROR("NULL parameter");
     switch (valuetype) {
@@ -793,7 +794,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, Identifier *p_val_id)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_val_id)
       FATAL_ERROR("NULL parameter");
@@ -809,7 +810,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, Identifier *p_id, Value *p_val)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_id || !p_val)
       FATAL_ERROR("NULL parameter");
@@ -824,7 +825,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, const Real& p_val_Real)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     switch(valuetype) {
     case V_REAL:
@@ -836,7 +837,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, Values *p_vs)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_vs) FATAL_ERROR("NULL parameter");
     switch(valuetype) {
@@ -852,7 +853,7 @@ namespace Common {
 
   Value::Value(valuetype_t p_vt, Value *p_v,
     Ttcn::ParsedActualParameters *p_t_list)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_v || !p_t_list) FATAL_ERROR("NULL parameter");
     switch(valuetype) {
@@ -868,7 +869,7 @@ namespace Common {
 
   // -
   Value::Value(operationtype_t p_optype)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -894,7 +895,7 @@ namespace Common {
 
   // v1
   Value::Value(operationtype_t p_optype, Value *p_v1)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -950,7 +951,7 @@ namespace Common {
   // v1 [r2] b4
   Value::Value(operationtype_t p_optype, Value* p_v1, Ttcn::Ref_base *p_r2,
                bool p_b4)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -971,7 +972,7 @@ namespace Common {
 
   // ti1
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -997,7 +998,7 @@ namespace Common {
 
   // r1
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1015,7 +1016,7 @@ namespace Common {
   // r1 [r2] b4
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base* p_r1, Ttcn::Ref_base* p_r2,
                bool p_b4)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1036,7 +1037,7 @@ namespace Common {
   // v1 t_list2
   Value::Value(operationtype_t p_optype, Value *p_v1,
       Ttcn::ParsedActualParameters *p_ap_list)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1054,7 +1055,7 @@ namespace Common {
   //v1 t_list2 v3
   Value::Value(operationtype_t p_optype, Value *p_v1,
     Ttcn::ParsedActualParameters *p_t_list2, Value *p_v3)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1072,7 +1073,7 @@ namespace Common {
 
   // r1 [v2] or [r1] v2
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Value *p_v2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1096,7 +1097,7 @@ namespace Common {
   // r1 [v2] [v3] b4
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1,
                Value *p_v2, Value *p_v3, bool p_b4)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1115,7 +1116,7 @@ namespace Common {
 
   // v1 v2
   Value::Value(operationtype_t p_optype, Value *p_v1, Value *p_v2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1166,7 +1167,7 @@ namespace Common {
   // ti1 v2 v3 ti4
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2,
     Value *p_v3, TemplateInstance *p_ti4) :
-      GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+      GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1185,7 +1186,7 @@ namespace Common {
 
   // v1 v2 v3
   Value::Value(operationtype_t p_optype, Value *p_v1, Value *p_v2, Value *p_v3)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1203,7 +1204,7 @@ namespace Common {
 
   // ti1 [v2]
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1,  Value *p_v2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1221,7 +1222,7 @@ namespace Common {
   
   // ti1 v2 v3
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2, Value *p_v3)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype=p_optype;
     u.expr.state=EXPR_NOT_CHECKED;
@@ -1240,7 +1241,7 @@ namespace Common {
   // ti1 t2 v3 b4
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1,
                TemplateInstance *p_t2, Value *p_v3, bool p_b4)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype=p_optype;
     u.expr.state=EXPR_NOT_CHECKED;
@@ -1259,7 +1260,7 @@ namespace Common {
 
   // v1 t2
   Value::Value(operationtype_t p_optype, Value *p_v1, TemplateInstance *p_t2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1277,7 +1278,7 @@ namespace Common {
   // r1 i2
   Value::Value(operationtype_t p_optype, Ttcn::Reference *p_r1,
                Identifier *p_i2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1293,7 +1294,7 @@ namespace Common {
   }
 
   Value::Value(operationtype_t p_optype, LogArguments *p_logargs)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1309,7 +1310,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, macrotype_t p_macrotype)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if (p_vt != V_MACRO) FATAL_ERROR("Value::Value()");
     switch (p_macrotype) {
@@ -1330,7 +1331,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, NamedValues *p_nvs)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_nvs) FATAL_ERROR("NULL parameter");
     switch(valuetype) {
@@ -1344,7 +1345,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, Reference *p_ref)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if (!p_ref) FATAL_ERROR("NULL parameter: Value::Value()");
     switch(p_vt) {
@@ -1361,7 +1362,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, Block *p_block)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if(!p_block) FATAL_ERROR("NULL parameter");
     switch(valuetype) {
@@ -1374,7 +1375,7 @@ namespace Common {
   }
 
   Value::Value(valuetype_t p_vt, verdict_t p_verdict)
-    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
+    : GovernedSimple(S_V), valuetype(p_vt), my_governor(0), in_brackets(false)
   {
     if (valuetype != V_VERDICT) FATAL_ERROR("Value::Value()");
     switch (p_verdict) {
@@ -1391,7 +1392,7 @@ namespace Common {
   }
 
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -1412,7 +1413,7 @@ namespace Common {
   // r1 r2 [v3]
   Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2,
           Value *p_v3)
-    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0), in_brackets(false)
   {
     u.expr.v_optype = p_optype;
     u.expr.state = EXPR_NOT_CHECKED;
@@ -14468,6 +14469,16 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr)
       DEBUG(level, "Value: unknown type: %d", valuetype);
     } // switch
   }
+  
+  void Value::set_is_in_brackets()
+  {
+    in_brackets = true;
+  }
+  
+  bool Value::get_is_in_brackets() const
+  {
+    return in_brackets;
+  }
 
   void Value::add_string_element(size_t index, Value *v_element,
     map<size_t, Value>*& string_elements)
diff --git a/compiler2/Value.hh b/compiler2/Value.hh
index 363142a35..df1e70d5c 100644
--- a/compiler2/Value.hh
+++ b/compiler2/Value.hh
@@ -299,6 +299,7 @@ namespace Common {
 
     valuetype_t valuetype;
     Type *my_governor;
+    bool in_brackets;
     union {
       bool val_bool;
       int_val_t  *val_Int;
@@ -1024,6 +1025,8 @@ namespace Common {
     bool needs_short_circuit();
   public:
     virtual void dump(unsigned level) const;
+    void set_is_in_brackets();
+    bool get_is_in_brackets() const;
   private:
     inline void set_val_str(string *p_val_str)
       { u.str.val_str = p_val_str; u.str.str_elements = 0; }
diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc
index 58fe369f7..ad7e6b6bc 100644
--- a/compiler2/ttcn3/TtcnTemplate.cc
+++ b/compiler2/ttcn3/TtcnTemplate.cc
@@ -102,6 +102,7 @@ namespace Ttcn {
       }
       u.concat.op1 = p.u.concat.op1->clone();
       u.concat.op2 = p.u.concat.op2->clone();
+      u.concat.in_brackets = p.u.concat.in_brackets;
       break;
 //    default:
 //      FATAL_ERROR("Template::Template()");
@@ -315,9 +316,15 @@ namespace Ttcn {
       if (!use_runtime_2) {
         FATAL_ERROR("Template::create_stringRepr()");
       }
+      if (u.concat.in_brackets) {
+        ret_val += " ( ";
+      }
       ret_val += u.concat.op1->create_stringRepr();
       ret_val += " & ";
       ret_val += u.concat.op2->create_stringRepr();
+      if (u.concat.in_brackets) {
+        ret_val += " ) ";
+      }
       break;
     default:
       ret_val += "<unknown template>";
@@ -374,6 +381,7 @@ namespace Ttcn {
         u.concat.op1->set_location(*v->get_concat_operand(true));
         u.concat.op2 = new Template(v->get_concat_operand(false)->clone());
         u.concat.op2->set_location(*v->get_concat_operand(false));
+        u.concat.in_brackets = v->get_is_in_brackets();
         delete v;
         break;
       }
@@ -1202,7 +1210,9 @@ namespace Ttcn {
   void Template::set_length_restriction(LengthRestriction *p_lr)
   {
     if (p_lr == NULL) return;
-    if (length_restriction) FATAL_ERROR("Template::set_length_restriction()");
+    if (length_restriction != NULL) {
+      p_lr->error("Two length restrictions are not allowed next to each other");
+    }
     length_restriction = p_lr;
   }
 
@@ -1721,7 +1731,7 @@ namespace Ttcn {
     }
     return first ? u.concat.op1 : u.concat.op2;
   }
-
+  
   Template* Template::get_template_refd(ReferenceChain *refch)
   {
     unsigned int const prev_err_count = get_error_count();
@@ -2440,6 +2450,17 @@ end:
       u.invoke.ap_list = parlist;
     }
   }
+  
+  void Template::chk_concat_double_length_res()
+  {
+    if (templatetype == TEMPLATE_CONCAT && length_restriction != NULL &&
+        u.concat.op2->length_restriction != NULL && !u.concat.in_brackets) {
+      length_restriction->error("Two length restrictions are not allowed next "
+        "to each other");
+      note("Try using brackets around the template concatenation");
+      set_templatetype(TEMPLATE_ERROR);
+    }
+  }
 
   Templates *Template::harbinger(Template *t, bool from_permutation, bool killer)
   {
diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh
index 16b1fa50d..f4f8ccd6f 100644
--- a/compiler2/ttcn3/TtcnTemplate.hh
+++ b/compiler2/ttcn3/TtcnTemplate.hh
@@ -132,6 +132,7 @@ namespace Ttcn {
       struct {
         Template* op1;
         Template* op2;
+        bool in_brackets;
       } concat;
     } u;
 
@@ -359,6 +360,7 @@ namespace Ttcn {
     void chk_specific_value(bool allow_omit);
     void chk_specific_value_generic();
     void chk_invoke();
+    void chk_concat_double_length_res();
 
     /** Copy template elements from the "all from" into the template.
      *
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index dcfbbc531..9cb4f35f6 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -9052,8 +9052,8 @@ Assignment: // 594
 
 /* This can not be a single CompoundExpression (as opposed to Expression) */
 SingleExpression: // 595
-  '(' SingleExpression ')' { $$ = $2; }
-| '(' error SingleExpression ')' { $$ = $3; }
+  '(' SingleExpression ')' { $$ = $2; $$->set_is_in_brackets(); }
+| '(' error SingleExpression ')' { $$ = $3; $$->set_is_in_brackets(); }
 | '(' error ')'
   {
     $$ = new Value(Value::V_ERROR);
diff --git a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
index 284efbf92..7563d2c7f 100644
--- a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
+++ b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
@@ -7309,11 +7309,15 @@ control {} with{erroneous ""}
 (?im)\berror: Type `@virag.MYREC2' and type `@virag.MYREC' have no common encoding
 <END_RESULT>
 
+RESULT FTRT COUNT 1>
+(?im)\berror: Type `VisibleString' and type `@virag.MYREC' have no common encoding
+<END_RESULT>
+
 <RESULT COUNT 3>
 (?im)\berror: The `erroneous' attribute can be used only on template and constant definitions
 <END_RESULT>
 
-<RESULT FTRT COUNT 32>
+<RESULT FTRT COUNT 33>
 (?is)\berror:
 <END_RESULT>
 
diff --git a/function_test/Semantic_Analyser/template_concat/TemplateConcat_SE.ttcn b/function_test/Semantic_Analyser/template_concat/TemplateConcat_SE.ttcn
index 95fbcc089..733eca49e 100644
--- a/function_test/Semantic_Analyser/template_concat/TemplateConcat_SE.ttcn
+++ b/function_test/Semantic_Analyser/template_concat/TemplateConcat_SE.ttcn
@@ -119,4 +119,8 @@ template HexSubtype t_hex7 := t_hex_value & * length(3) & '5'H; //^In template d
 template CharSubtype t_char7 := "abc" & c_char; //^In template definition// //is not a valid value for type `charstring' which has subtype//
 template UnicharSubtype t_unichar7 := c_char & t_unichar_value; //^In template definition// //is not a valid value for type `universal charstring' which has subtype//
 
+/* testing double length restriction (both the second operand and the concatenation result have length restrictions and they're not separated by brackets) */
+template octetstring t_oct8 := 'ABCD'O & ? length(2) length(4); //^In template definition// //Two length restrictions are not allowed next to each other// //Try using brackets around the template concatenation//
+template RecOfInt t_recof8 := t_recof & * length(2) length(4..5); //^In template definition// //Two length restrictions are not allowed next to each other// //Try using brackets around the template concatenation//
+
 }
-- 
GitLab