diff --git a/compiler2/Constraint.cc b/compiler2/Constraint.cc
index d56158103f59345e05a858f7b2213bd7d5cf8810..5c88f69f061d9d773006a0e09ed39846973f48d3 100644
--- a/compiler2/Constraint.cc
+++ b/compiler2/Constraint.cc
@@ -62,12 +62,14 @@ namespace Common {
     if (my_type) p_con->set_my_type(my_type);
   }
 
-  Constraint* Constraints::get_tableconstraint() const
+  const Constraint* Constraints::get_tableconstraint() const
   {
     size_t nof_cons = cons.size();
     for (size_t i = 0; i < nof_cons; i++) {
       Constraint *con = cons[i];
-      if (con->get_constrtype() == Constraint::CT_TABLE) return con;
+      if (con->get_constrtype() == Constraint::CT_TABLE) {
+        return con->get_tableconstraint();
+      }
     }
     return 0;
   }
@@ -116,15 +118,18 @@ namespace Common {
         extension = 0;
       }
       if (subtype) {
-        if (sc->is_subset(subtype)==TFALSE) {
-          cons[i]->error("Constraint #%lu is %s, this is not a subset of %s",
+        if (sc->can_intersect(subtype)==TFALSE) {
+          cons[i]->error("Constraint #%lu is %s, intersecting this with %s "
+            "results in an empty set (no values satisfy the type's restrictions)",
             (unsigned long) (i + 1),
             sc->to_string().c_str(),
             subtype->to_string().c_str());
           break; // stop on error
         }
-        if (sc_ext && (sc_ext->is_subset(subtype)==TFALSE)) {
-          cons[i]->error("Extension addition of constraint #%lu is %s, this is not a subset of %s",
+        if (sc_ext && (sc_ext->can_intersect(subtype)==TFALSE)) {
+          cons[i]->error("Extension addition of constraint #%lu is %s, "
+            "intersecting this with %s results in an empty set (no values "
+            "satisfy the type's restrictions)",
             (unsigned long) (i + 1),
             sc_ext->to_string().c_str(),
             subtype->to_string().c_str());
@@ -218,7 +223,12 @@ namespace Common {
     }
     return false;
   }
-
+  
+  const Constraint* Constraint::get_tableconstraint() const
+  {
+    FATAL_ERROR("Constraint::get_tableconstraint()");
+  }
+  
   // =================================
   // ===== ElementSetSpecsConstraint
   // =================================
@@ -1145,5 +1155,128 @@ namespace Common {
     block->set_fullname(p_fullname);
     if (constraint) constraint->set_fullname(p_fullname);
   }
+  
+  // =================================
+  // ===== UndefinedBlockConstraint
+  // =================================
+
+  UndefinedBlockConstraint::UndefinedBlockConstraint(const UndefinedBlockConstraint& p)
+    : Constraint(p)
+  {
+    switch (constrtype) {
+    case CT_UNDEFINEDBLOCK:
+      block = p.block->clone();
+      break;
+    case CT_SINGLEVALUE:
+      single = p.single->clone();
+      break;
+    case CT_TABLE:
+      table = p.table->clone();
+      break;
+    default:
+      FATAL_ERROR("UndefinedBlockConstraint::UndefinedBlockConstraint");
+    }
+  }
+
+  UndefinedBlockConstraint::UndefinedBlockConstraint(Block* p_block)
+    : Constraint(CT_UNDEFINEDBLOCK), block(p_block)
+  {
+    if (p_block == NULL) {
+      FATAL_ERROR("UndefinedBlockConstraint::UndefinedBlockConstraint()");
+    }
+  }
+
+  UndefinedBlockConstraint::~UndefinedBlockConstraint()
+  {
+    switch (constrtype) {
+    case CT_UNDEFINEDBLOCK:
+      delete block;
+      break;
+    case CT_SINGLEVALUE:
+      delete single;
+      break;
+    case CT_TABLE:
+      delete table;
+      break;
+    default:
+      FATAL_ERROR("UndefinedBlockConstraint::~UndefinedBlockConstraint");
+    }
+  }
+
+  void UndefinedBlockConstraint::chk()
+  {
+    if (checked) return;
+    checked = true;
+    if (my_parent != NULL && my_parent->get_constrtype() == CT_SETOPERATION) {
+      single = new SingleValueConstraint(new Value(Value::V_UNDEF_BLOCK, block));
+      constrtype = CT_SINGLEVALUE;
+      single->set_my_type(my_type);
+      single->set_my_scope(my_scope);
+      single->set_my_parent(my_parent);
+      single->chk();
+      extendable = single->is_extendable();
+    }
+    else {
+      table = new Asn::TableConstraint(block, NULL);
+      constrtype = CT_TABLE;
+      table->set_my_type(my_type);
+      table->set_my_scope(my_scope);
+      table->set_my_parent(my_parent);
+      table->chk();
+      extendable = table->is_extendable();
+    }
+  }
+
+  void UndefinedBlockConstraint::set_fullname(const string& p_fullname)
+  {
+    Node::set_fullname(p_fullname);
+    switch (constrtype) {
+    case CT_UNDEFINEDBLOCK:
+      block->set_fullname(p_fullname + ".<block>");
+      break;
+    case CT_SINGLEVALUE:
+      single->set_fullname(p_fullname);
+      break;
+    case CT_TABLE:
+      table->set_fullname(p_fullname);
+      break;
+    default:
+      FATAL_ERROR("UndefinedBlockConstraint::UndefinedBlockConstraint");
+    }
+  }
+  
+  SubtypeConstraint* UndefinedBlockConstraint::get_subtype() const
+  {
+    switch (constrtype) {
+    case CT_SINGLEVALUE:
+      return single->get_subtype();
+    case CT_TABLE:
+      return table->get_subtype();
+    case CT_UNDEFINEDBLOCK:
+    default:
+      FATAL_ERROR("UndefinedBlockConstraint::get_subtype");
+    }
+  }
+  
+  SubtypeConstraint* UndefinedBlockConstraint::get_extension() const
+  {
+    switch (constrtype) {
+    case CT_SINGLEVALUE:
+      return single->get_extension();
+    case CT_TABLE:
+      return table->get_extension();
+    case CT_UNDEFINEDBLOCK:
+    default:
+      FATAL_ERROR("UndefinedBlockConstraint::get_extension");
+    }
+  }
+  
+  const Constraint* UndefinedBlockConstraint::get_tableconstraint() const
+  {
+    if (constrtype != CT_TABLE) {
+      FATAL_ERROR("UndefinedBlockConstraint::get_tableconstraint()");
+    }
+    return table;
+  }
 
 } // namespace Common
diff --git a/compiler2/Constraint.hh b/compiler2/Constraint.hh
index de70f84c2ada64e7c59500663a2c30c5db2ae35f..5557b10437f69a45cc0d419bdeee6e0075a582fd 100644
--- a/compiler2/Constraint.hh
+++ b/compiler2/Constraint.hh
@@ -20,6 +20,7 @@
 
 namespace Asn {
   class Block;
+  class TableConstraint;
 }
 
 namespace Common {
@@ -42,7 +43,7 @@ namespace Common {
   class Value;
   class SubtypeConstraint;
   class Identifier;
-
+  
   using Asn::Block;
 
   /**
@@ -51,6 +52,7 @@ namespace Common {
   class Constraint : public Node, public Location {
   public:
     enum constrtype_t {
+      CT_UNDEFINEDBLOCK, /** UndefinedBlockConstraint (turns into CT_TABLE or CT_SINGLEVALUE after semantic analysis) */
       CT_ELEMENTSETSPEC, /** ElementSetSpecsConstraint */
       CT_IGNORE, /**< Constraint : used if erroneous or not yet supported */
       CT_TABLE, /**< TableConstraint */
@@ -96,9 +98,9 @@ namespace Common {
     Constraints* get_my_cons();
     virtual void chk() = 0;
     /** return the subtype constraint */
-    SubtypeConstraint* get_subtype() const { return subtype; }
+    virtual SubtypeConstraint* get_subtype() const { return subtype; }
     bool is_extendable() const { return extendable; }
-    SubtypeConstraint* get_extension() const { return extension; }
+    virtual SubtypeConstraint* get_extension() const { return extension; }
     /** returns the name of this constraint which can be used in error messages */
     virtual const char* get_name() const = 0;
     /** if this constraint is inside a FROM() constraint then we are in
@@ -112,6 +114,11 @@ namespace Common {
              somehow drop or simplify their constraint, example: (inner subtype) EXCEPT (inner subtype)
     */
     virtual bool is_ignored() const { return false; }
+    
+    /** Returns this (for TableConstraints) or the embedded TableConstraint
+      * object (for UndefinedBlockConstraints that contain a TableConstraint
+      * after semantic analysis) */
+    virtual const Constraint* get_tableconstraint() const;
   };
 
   /**
@@ -135,7 +142,7 @@ namespace Common {
     void add_con(Constraint *p_con);
     size_t get_nof_cons() const {return cons.size();}
     Constraint* get_con_byIndex(size_t p_i) const { return cons[p_i]; }
-    Constraint* get_tableconstraint() const;
+    const Constraint* get_tableconstraint() const;
     void set_my_type(Type *p_my_type);
     Type* get_my_type() const { return my_type; }
     void chk(SubtypeConstraint* parent_subtype);
@@ -488,6 +495,36 @@ namespace Common {
     const char* get_name() const { return "inner type constraint"; }
     bool is_ignored() const { return true; }
   };
+  
+  
+  // =================================
+  // ===== UndefinedBlockConstraint
+  // =================================
+  
+  /** This class represents a constraint containing a block.
+    * During semantic analysis the block is parsed and causes this object to act
+    * as either a SingleValueConstraint or a TableConstraint afterwards. */
+  class UndefinedBlockConstraint : public Constraint
+  {
+    union {
+      Block* block; // CT_UNDEFINEDBLOCK, before chk()
+      SingleValueConstraint* single; // CT_SINGLEVALUE, after chk()
+      Asn::TableConstraint* table; // CT_TABLE, after chk()
+    };
+    UndefinedBlockConstraint(const UndefinedBlockConstraint& p);
+    /// Assignment disabled
+    UndefinedBlockConstraint& operator=(const UndefinedBlockConstraint& p);
+  public:
+    UndefinedBlockConstraint(Block* p_block);
+    virtual ~UndefinedBlockConstraint();
+    UndefinedBlockConstraint* clone() const { return new UndefinedBlockConstraint(*this); }
+    void chk();
+    const char* get_name() const { return "Undefined block constraint"; }
+    void set_fullname(const string& p_fullname);
+    SubtypeConstraint* get_subtype() const;
+    SubtypeConstraint* get_extension() const;
+    const Constraint* get_tableconstraint() const;
+  };
 
 } // namespace Common
 
diff --git a/compiler2/Value.hh b/compiler2/Value.hh
index ba7f960456b6f87be00a128027c20d4eca6f6f7b..a886290e8e5785cf7f5c660cf4d0b5682ca04eb4 100644
--- a/compiler2/Value.hh
+++ b/compiler2/Value.hh
@@ -315,7 +315,7 @@ namespace Common {
       ttcn3float val_Real;
       struct {
         string *val_str;
-	map<size_t, Value> *str_elements;
+        map<size_t, Value> *str_elements;
       } str;
       struct {
         ustring *val_ustr;
diff --git a/compiler2/asn1/TableConstraint.cc b/compiler2/asn1/TableConstraint.cc
index a799bf75b95988760868489d33748dbfb3b74b4f..6228ab539465e10a6f8124ea9068deb4068e1907 100644
--- a/compiler2/asn1/TableConstraint.cc
+++ b/compiler2/asn1/TableConstraint.cc
@@ -225,7 +225,7 @@ namespace Asn {
             Constraints *t_cons=t_type->get_constraints();
             if(!t_cons) break;
             t_cons->chk_table();
-            TableConstraint *t_tc=dynamic_cast<TableConstraint*>
+            const TableConstraint *t_tc=dynamic_cast<const TableConstraint*>
               (t_cons->get_tableconstraint());
             if(!t_tc) break;
             Type *t_ocft=t_tc->consdtype;
diff --git a/compiler2/asn1/TableConstraint.hh b/compiler2/asn1/TableConstraint.hh
index d16b3eedbe8ff0ccbb369edadd3cee116b881b48..7ad7233bd17b0fd7afa98a24879161be4d747e26 100644
--- a/compiler2/asn1/TableConstraint.hh
+++ b/compiler2/asn1/TableConstraint.hh
@@ -103,6 +103,7 @@ namespace Asn {
     ObjectSet* get_os() const {return os;}
     const Identifier* get_oc_fieldname() const {return oc_fieldname;}
     const char* get_name() const { return "table constraint"; }
+    const Constraint* get_tableconstraint() const { return this; }
   private:
     void parse_blocks();
   };
diff --git a/compiler2/asn1/asn1p.y b/compiler2/asn1/asn1p.y
index 8407f8221877de13954c0a67e9b579b1e8e1253a..25e6f654de339c3c4ab03dd95b4b5b5f0b78bf35 100644
--- a/compiler2/asn1/asn1p.y
+++ b/compiler2/asn1/asn1p.y
@@ -2780,10 +2780,9 @@ SingleValue:
   }
 | TOK_Block
   {
-    /** \todo: It would be more straightforward to create an undefined
-     * constraint here and classify it later on during parsing or semantic
-     * analysis to SimpleTableConstraint or SingleValue. */
-    $$ = new TableConstraint($1, 0);
+    /* Create an undefined constraint for now, and classify it later on during
+       semantic analysis to TableConstraint or SingleValueConstraint. */
+    $$ = new UndefinedBlockConstraint($1);
     $$->set_location(asn1_infile, @1.first_line);
   }
 | ReferencedValue_reg
diff --git a/compiler2/subtype.cc b/compiler2/subtype.cc
index d45497c7f3cfc23f84d7cfe16de2fb0c8b6d870b..de5568798de8fb8a74c6c64f6e7ade3d3ccd965d 100644
--- a/compiler2/subtype.cc
+++ b/compiler2/subtype.cc
@@ -934,7 +934,7 @@ SubtypeConstraint* SubtypeConstraint::create_asn_size_constraint(
     static const int_val_t zero((Int)0);
     static const int_limit_t ilt0(zero);
     IntegerRangeListConstraint valid_range(ilt0, int_limit_t::maximum);
-    if (integer_stc->integer_st->is_subset(valid_range)==TFALSE) {
+    if (integer_stc->integer_st->can_intersect(valid_range)==TFALSE) {
       loc->error("Range %s is not a valid range for a size constraint", integer_stc->to_string().c_str());
     } else {
       bool success = convert_int_to_size(*(integer_stc->integer_st), size_constraint);
@@ -1707,38 +1707,38 @@ void SubtypeConstraint::intersection(const SubtypeConstraint* other)
   }
 }
 
-tribool SubtypeConstraint::is_subset(const SubtypeConstraint* other) const
+tribool SubtypeConstraint::can_intersect(const SubtypeConstraint* other) const
 {
   if (other==NULL) return TTRUE;
-  if (other->subtype!=subtype) FATAL_ERROR("SubtypeConstraint::is_subset()");
+  if (other->subtype!=subtype) FATAL_ERROR("SubtypeConstraint::can_intersect()");
   switch (subtype) {
   case ST_INTEGER:
     if (other->integer_st==NULL) return TTRUE;
-    return integer_st ? integer_st->is_subset(*(other->integer_st)) : TTRUE;
+    return integer_st ? integer_st->can_intersect(*(other->integer_st)) : TTRUE;
   case ST_FLOAT:
     if (other->float_st==NULL) return TTRUE;
-    return float_st ? float_st->is_subset(*(other->float_st)) : TTRUE;
+    return float_st ? float_st->can_intersect(*(other->float_st)) : TTRUE;
   case ST_BOOLEAN:
     if (other->boolean_st==NULL) return TTRUE;
-    return boolean_st ? boolean_st->is_subset(*(other->boolean_st)) : TTRUE;
+    return boolean_st ? boolean_st->can_intersect(*(other->boolean_st)) : TTRUE;
   case ST_VERDICTTYPE:
     if (other->verdict_st==NULL) return TTRUE;
-    return verdict_st ? verdict_st->is_subset(*(other->verdict_st)) : TTRUE;
+    return verdict_st ? verdict_st->can_intersect(*(other->verdict_st)) : TTRUE;
   case ST_BITSTRING:
     if (other->bitstring_st==NULL) return TTRUE;
-    return bitstring_st ? bitstring_st->is_subset(*(other->bitstring_st)) : TTRUE;
+    return bitstring_st ? bitstring_st->can_intersect(*(other->bitstring_st)) : TTRUE;
   case ST_HEXSTRING:
     if (other->hexstring_st==NULL) return TTRUE;
-    return hexstring_st ? hexstring_st->is_subset(*(other->hexstring_st)) : TTRUE;
+    return hexstring_st ? hexstring_st->can_intersect(*(other->hexstring_st)) : TTRUE;
   case ST_OCTETSTRING:
     if (other->octetstring_st==NULL) return TTRUE;
-    return octetstring_st ? octetstring_st->is_subset(*(other->octetstring_st)) : TTRUE;
+    return octetstring_st ? octetstring_st->can_intersect(*(other->octetstring_st)) : TTRUE;
   case ST_CHARSTRING:
     if (other->charstring_st==NULL) return TTRUE;
-    return charstring_st ? charstring_st->is_subset(other->charstring_st) : TTRUE;
+    return charstring_st ? charstring_st->can_intersect(other->charstring_st) : TTRUE;
   case ST_UNIVERSAL_CHARSTRING:
     if (other->universal_charstring_st==NULL) return TTRUE;
-    return universal_charstring_st ? universal_charstring_st->is_subset(other->universal_charstring_st) : TTRUE;
+    return universal_charstring_st ? universal_charstring_st->can_intersect(other->universal_charstring_st) : TTRUE;
   case ST_OBJID:
   case ST_RECORD:
   case ST_SET:
@@ -1748,13 +1748,13 @@ tribool SubtypeConstraint::is_subset(const SubtypeConstraint* other) const
   case ST_ALTSTEP:
   case ST_TESTCASE:
     if (other->value_st==NULL) return TTRUE;
-    return value_st ? value_st->is_subset(*(other->value_st)) : TTRUE;
+    return value_st ? value_st->can_intersect(*(other->value_st)) : TTRUE;
   case ST_RECORDOF:
   case ST_SETOF:
     if (other->recof_st==NULL) return TTRUE;
-    return recof_st ? recof_st->is_subset(*(other->recof_st)) : TTRUE;
+    return recof_st ? recof_st->can_intersect(*(other->recof_st)) : TTRUE;
   default:
-    FATAL_ERROR("SubtypeConstraint::is_subset()");
+    FATAL_ERROR("SubtypeConstraint::can_intersect()");
   }
   return TUNKNOWN;
 }
@@ -2857,9 +2857,11 @@ void SubType::chk()
     if (subtype==ST_ERROR) { checked = STC_YES; return; }
 
     if (parent_subtype) {
-      if (is_subset(parent_subtype->get_root())==TFALSE) {
-        my_owner->error("The subtype restriction is not a subset of the restriction on the parent type. "
-          "Subtype %s is not subset of subtype %s", to_string().c_str(), parent_subtype->get_root()->to_string().c_str());
+      if (can_intersect(parent_subtype->get_root())==TFALSE) {
+        my_owner->error("The intersection between the subtype restriction, %s, "
+          "and the parent type's restriction, %s, is empty. (No values satisfy "
+          "the type's restrictions.)",
+          to_string().c_str(), parent_subtype->get_root()->to_string().c_str());
         set_to_error();
         checked = STC_YES;
         return;
diff --git a/compiler2/subtype.hh b/compiler2/subtype.hh
index cb1a36221c6764acea3fe2a0dc8ff6a26df525a1..a610a08762a19cd8b9a64c0792df2b267ec6dec3 100644
--- a/compiler2/subtype.hh
+++ b/compiler2/subtype.hh
@@ -189,7 +189,7 @@ public:
   void union_(const SubtypeConstraint* other);
   void except(const SubtypeConstraint* other);
 
-  tribool is_subset(const SubtypeConstraint* other) const;
+  tribool can_intersect(const SubtypeConstraint* other) const;
 
   /** special ASN.1 types (NumericString, etc.) have default subtype constraints,
       return default constraint or NULL */
diff --git a/compiler2/subtypestuff.hh b/compiler2/subtypestuff.hh
index 8c17ad30b11b4a9f5d2f3483df366dc514167279..c60f5a5374c45185fc8f51075ef029ccc5af9ea9 100644
--- a/compiler2/subtypestuff.hh
+++ b/compiler2/subtypestuff.hh
@@ -260,7 +260,7 @@ public:
   RangeListConstraint operator*(const RangeListConstraint& other) const { return set_operation(other, false); } // intersection
   RangeListConstraint operator~() const; // complement
 
-  tribool is_subset(const RangeListConstraint& other) const { return (*this*~other).is_empty(); }
+  tribool can_intersect(const RangeListConstraint& other) const { return !(*this * other).is_empty(); }
   RangeListConstraint operator-(const RangeListConstraint& other) const { return ( *this * ~other ); } // except
 
   // will return the minimal value that is part of the interval,
@@ -616,7 +616,7 @@ public:
   RealRangeListConstraint operator*(const RealRangeListConstraint& other) const { return set_operation(other, false); } // intersection
   RealRangeListConstraint operator~() const; // complement
 
-  tribool is_subset(const RealRangeListConstraint& other) const { return (*this*~other).is_empty(); }
+  tribool can_intersect(const RealRangeListConstraint& other) const { return !(*this * other).is_empty(); }
   RealRangeListConstraint operator-(const RealRangeListConstraint& other) const { return ( *this * ~other ); } // except
 
   tribool is_range_empty() const { return rlc.is_empty(); }
@@ -656,7 +656,7 @@ public:
   BooleanListConstraint operator*(const BooleanListConstraint& other) const { BooleanListConstraint rv; rv.values = values & other.values; return rv; }
   BooleanListConstraint operator~() const { BooleanListConstraint rv; rv.values = values ^ BC_ALL; return rv; }
 
-  tribool is_subset(const BooleanListConstraint& other) const { return (*this*~other).is_empty(); }
+  tribool can_intersect(const BooleanListConstraint& other) const { return !(*this * other).is_empty(); }
 
   BooleanListConstraint operator-(const BooleanListConstraint& other) const { return ( *this * ~other ); }
 
@@ -695,7 +695,7 @@ public:
   VerdicttypeListConstraint operator*(const VerdicttypeListConstraint& other) const { VerdicttypeListConstraint rv; rv.values = values & other.values; return rv; }
   VerdicttypeListConstraint operator~() const { VerdicttypeListConstraint rv; rv.values = values ^ VC_ALL; return rv; }
 
-  tribool is_subset(const VerdicttypeListConstraint& other) const { return (*this*~other).is_empty(); }
+  tribool can_intersect(const VerdicttypeListConstraint& other) const { return !(*this * other).is_empty(); }
 
   VerdicttypeListConstraint operator-(const VerdicttypeListConstraint& other) const { return ( *this * ~other ); }
 
@@ -745,7 +745,7 @@ public:
   StringSizeAndValueListConstraint operator*(const StringSizeAndValueListConstraint& other) const { return set_operation(other, false); } // intersection
   StringSizeAndValueListConstraint operator~() const; // complement
 
-  tribool is_subset(const StringSizeAndValueListConstraint& other) const { return (*this*~other).is_empty(); }
+  tribool can_intersect(const StringSizeAndValueListConstraint& other) const { return !(*this * other).is_empty(); }
   StringSizeAndValueListConstraint operator-(const StringSizeAndValueListConstraint& other) const { return ( *this * ~other ); } // except
 
   tribool get_size_limit(bool is_upper, size_limit_t& limit) const;
@@ -1067,7 +1067,7 @@ public:
   StringPatternConstraint operator*(const StringPatternConstraint& other) const { return set_operation(other, false); } // intersection
   StringPatternConstraint operator~() const { FATAL_ERROR("StringPatternConstraint::operator~(): not implemented"); }
 
-  tribool is_subset(const StringPatternConstraint&) const { return TUNKNOWN; }
+  tribool can_intersect(const StringPatternConstraint&) const { return TUNKNOWN; }
   StringPatternConstraint operator-(const StringPatternConstraint& other) const { return ( *this * ~other ); } // except
 
   string to_string() const;
@@ -1101,7 +1101,7 @@ public:
   StringValueConstraint operator+(const StringValueConstraint& other) const { return set_operation(other, true); } // union
   StringValueConstraint operator*(const StringValueConstraint& other) const { return set_operation(other, false); } // intersection
 
-  tribool is_subset(const StringValueConstraint& other) const { return (*this-other).is_empty(); }
+  tribool can_intersect(const StringValueConstraint& other) const { return !(*this * other).is_empty(); }
   StringValueConstraint operator-(const StringValueConstraint& other) const; // except
 
   // remove strings that are or are not elements of the set defined by the XXX_constraint object,
@@ -1301,7 +1301,7 @@ public:
   tribool is_full() const;
   tribool is_equal(const StringSubtypeTreeElement* other) const;
   bool is_element(const STRINGTYPE& s) const;
-  tribool is_subset(const StringSubtypeTreeElement* other) const;
+  tribool can_intersect(const StringSubtypeTreeElement* other) const;
 
   bool is_single_constraint() const { return ( (elementtype==ET_CONSTRAINT) || (elementtype==ET_NONE) || (elementtype==ET_ALL) ); }
   void set_none() { clean_up(); elementtype = ET_NONE; }
@@ -1803,9 +1803,9 @@ bool StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>::is_element(const STRING
 // if the constraints are ortogonal (e.g. size and alphabet) or just different then return TUNKNOWN
 // in case of ortogonal constraints we should return TFALSE (if other is not full set)
 // but it seems that the standard wants to ignore such trivial cases, example:
-//   length(1..4) is_subset ('a'..'z') shall not report an error
+//   length(1..4) can_intersect ('a'..'z') shall not report an error
 template <class STRINGTYPE, class CHARLIMITTYPE>
-tribool StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>::is_subset(const StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>* other) const
+tribool StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>::can_intersect(const StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>* other) const
 {
   switch (elementtype) {
   case ET_NONE:
@@ -1817,18 +1817,18 @@ tribool StringSubtypeTreeElement<STRINGTYPE,CHARLIMITTYPE>::is_subset(const Stri
     if (elementtype!=other->elementtype) return TUNKNOWN;
     if (u.cs.constrainttype!=other->u.cs.constrainttype) return TUNKNOWN;
     switch (u.cs.constrainttype) {
-    case CT_SIZE: return u.cs.s->is_subset(*(other->u.cs.s));
-    case CT_ALPHABET: return u.cs.a.c->is_subset(*(other->u.cs.a.c));
-    case CT_VALUES: return u.cs.v->is_subset(*(other->u.cs.v));
-    case CT_PATTERN: return u.cs.p->is_subset(*(other->u.cs.p));
-    default: FATAL_ERROR("StringSubtypeTreeElement::is_subset()");
+    case CT_SIZE: return u.cs.s->can_intersect(*(other->u.cs.s));
+    case CT_ALPHABET: return u.cs.a.c->can_intersect(*(other->u.cs.a.c));
+    case CT_VALUES: return u.cs.v->can_intersect(*(other->u.cs.v));
+    case CT_PATTERN: return u.cs.p->can_intersect(*(other->u.cs.p));
+    default: FATAL_ERROR("StringSubtypeTreeElement::can_intersect()");
     }
   case ET_INTERSECTION:
   case ET_UNION:
   case ET_EXCEPT:
     return TUNKNOWN;
   default:
-    FATAL_ERROR("StringSubtypeTreeElement::is_subset()");
+    FATAL_ERROR("StringSubtypeTreeElement::can_intersect()");
   }
   return TUNKNOWN;
 }
@@ -2197,7 +2197,7 @@ public:
   ValueList operator*(const ValueList& other) const { return set_operation(other, false); } // intersection
   ValueList operator-(const ValueList& other) const; // except
 
-  tribool is_subset(const ValueList& other) const { return (*this-other).is_empty(); }
+  tribool can_intersect(const ValueList& other) const { return !(*this * other).is_empty(); }
 
   string to_string() const;
 };
@@ -2222,8 +2222,8 @@ public:
   ValueListConstraint operator*(const ValueListConstraint& other) const; // intersection
   ValueListConstraint operator~() const; // complement
 
-  inline tribool is_subset(const ValueListConstraint& other) const
-    { return (*this*~other).is_empty(); }
+  inline tribool can_intersect(const ValueListConstraint& other) const
+    { return !(*this * other).is_empty(); }
   inline ValueListConstraint operator-(const ValueListConstraint& other) const
     { return ( *this * ~other ); } // except
 
@@ -2257,7 +2257,7 @@ public:
   inline RecofConstraint operator*(const RecofConstraint& other) const { return set_operation(other, false); } // intersection
   RecofConstraint operator~() const; // complement
 
-  inline tribool is_subset(const RecofConstraint& other) const { return (*this*~other).is_empty(); }
+  inline tribool can_intersect(const RecofConstraint& other) const { return !(*this * other).is_empty(); }
   inline RecofConstraint operator-(const RecofConstraint& other) const { return ( *this * ~other ); } // except
 
   tribool get_size_limit(bool is_upper, size_limit_t& limit) const;
diff --git a/function_test/Semantic_Analyser/ASN_SA_1_TD.script b/function_test/Semantic_Analyser/ASN_SA_1_TD.script
index a8dfb57fc44b70d088aa3283959e3b97ef185a3a..7d34d22ea342d8f47d4c295dda7b3d3df7f3547d 100644
--- a/function_test/Semantic_Analyser/ASN_SA_1_TD.script
+++ b/function_test/Semantic_Analyser/ASN_SA_1_TD.script
@@ -6337,7 +6337,7 @@ MyInt3 ::= INTEGER ( SIZE(10) EXCEPT FROM(1..10) )
 MyInt4 ::= MyInt2 (MyInt3)
 MyInt5 ::= INTEGER ( PATTERN "abc" EXCEPT 5 )
 MyInt6 ::= INTEGER ( ALL EXCEPT ((MIN..0) UNION (0..MAX)) )
-MyInt7 ::= INTEGER (1..10) (5..15)
+MyInt7 ::= INTEGER (1..10) (12..15)
 MyInt9 ::= INTEGER (5..6 EXCEPT 1..10)
 MyInt10::= INTEGER ( MIN..MAX )
 MyInt11::= INTEGER ( INTEGER )
@@ -6363,7 +6363,7 @@ END
 (?im)\berror: The subtype is an empty set
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #2 is \(5..15\), this is not a subset of \(1..10\)
+(?im)\berror: Constraint #2 is \(12..15\), intersecting this with \(1..10\) results in an empty set \(no values satisfy the type's restrictions\)
 <END_RESULT>
 <RESULT COUNT 1>
 (?im)\bwarning: The subtype of type `integer' is a full set, it does not constrain the root type.
@@ -6559,12 +6559,6 @@ END
 (?im)\berror: 0 is not a valid value for type `integer' which has subtype \(-100..-11,11..100\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #1 is \(-100..100\), this is not a subset of \(-100..-11,11..100\)
-<END_RESULT>
-<RESULT COUNT 1>
-(?im)\berror: Constraint #1 is from\(" ".."6"\), this is not a subset of from\(" ","0".."9"\)
-<END_RESULT>
-<RESULT COUNT 1>
 (?im)\berror: "abc" is not a valid value for type `NumericString' which has subtype from\("3".."9"\)
 <END_RESULT>
 <RESULT COUNT 1>
@@ -6583,7 +6577,7 @@ END
 (?im)\berror: Cannot determine the value of MAX: the parent subtype has no range
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #2 is \(-INF..INF\), this is not a subset of \(NaN\)
+(?im)\berror: Constraint #2 is \(-INF..INF\), intersecting this with \(NaN\) results in an empty set \(no values satisfy the type's restrictions\)
 <END_RESULT>
 <RESULT COUNT 1>
 (?im)\berror: Cannot determine the value of MAX: the parent subtype does not define a maximal size value
@@ -6591,7 +6585,7 @@ END
 <RESULT COUNT 1>
 (?im)\berror: Cannot determine the value of MIN: the parent subtype does not define a minimal size value
 <END_RESULT>
-<RESULT COUNT 11>
+<RESULT COUNT 9>
 (?is)\berror:
 <END_RESULT>
 <RESULT COUNT 2>
@@ -6644,9 +6638,6 @@ END
 (?im)\berror: Size constraint is not allowed for type `integer'
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #2 is \(1..20\), this is not a subset of \(1..10\)
-<END_RESULT>
-<RESULT COUNT 1>
 (?im)\berror: 22 is not a valid value for type `integer' which has subtype \(1..20\)
 <END_RESULT>
 <RESULT COUNT 1>
@@ -6655,7 +6646,7 @@ END
 <RESULT COUNT 1>
 (?im)\berror: 222 is not a valid value for type `integer' which has subtype \(1..20\)
 <END_RESULT>
-<RESULT COUNT 6>
+<RESULT COUNT 5>
 (?is)\berror: 
 <END_RESULT>
 <END_TC>
@@ -6715,12 +6706,9 @@ END
 (?im)\berror: INF is not a valid value for type `float' which has subtype \(0.0e0..!INF,NaN\)
 <END_RESULT>
 <RESULT IF_PASS COUNT 1>
-(?im)\berror: Constraint #1 is \(1..20\), this is not a subset of \(1..10\)
-<END_RESULT>
-<RESULT IF_PASS COUNT 1>
 (?im)\berror: 21 is not a valid value for type `integer' which has subtype \(1..20\)
 <END_RESULT>
-<RESULT IF_PASS COUNT 6>
+<RESULT IF_PASS COUNT 5>
 (?is)\berror:
 <END_RESULT>
 <END_TC>
@@ -6823,12 +6811,6 @@ B3 ::= B (FALSE,...,TRUE)
 END
 <END_MODULE>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #1 is \(1..128\), this is not a subset of \(1..32\)
-<END_RESULT>
-<RESULT COUNT 1>
-(?im)\berror: Constraint #2 is \(1..128\), this is not a subset of \(1..32\)
-<END_RESULT>
-<RESULT COUNT 1>
 (?im)\berror: -1 is not a valid value for type `integer' which has subtype \(1..256\)
 <END_RESULT>
 <RESULT COUNT 1>
@@ -6838,7 +6820,7 @@ END
 (?im)\bwarning: The subtype of type `integer' is a full set, it does not constrain the root type.
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Constraint #1 is \(73\), this is not a subset of \(1..6\)
+(?im)\berror: Constraint #1 is \(73\), intersecting this with \(1..6\) results in an empty set \(no values satisfy the type's restrictions\)
 <END_RESULT>
 <RESULT COUNT 1>
 (?im)\berror: 99 is not a valid value for type `integer' which has subtype \(1..6\), ..., \(73..80\)
@@ -6862,9 +6844,9 @@ END
 (?im)\bwarning: The subtype of type `boolean' is a full set, it does not constrain the root type.
 <END_RESULT>
 <RESULT COUNT 1>
-(?im)\berror: Extension addition of constraint #1 is \(true\), this is not a subset of \(false\)
+(?im)\berror: Extension addition of constraint #1 is \(true\), intersecting this with \(false\) results in an empty set \(no values satisfy the type's restrictions\)
 <END_RESULT>
-<RESULT COUNT 12>
+<RESULT COUNT 10>
 (?is)\berror: 
 <END_RESULT>
 <RESULT COUNT 2>
diff --git a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
index 2b68de2107d28e6faa88bfc1d5d94fa0a6df1b7b..f6cd793a053cd9f3ebe920e61fa8f9b7e0af3d74 100644
--- a/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
+++ b/function_test/Semantic_Analyser/TTCN3_SA_ttcn3adhoc_TD.script
@@ -5403,7 +5403,7 @@ module module1
 (?is)\berror: inconc is not a valid value for type `verdicttype' which has subtype \(none,pass,fail\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(inconc\) is not subset of subtype \(none,pass,fail\)
+(?is)\berror: The intersection between the subtype restriction, \(inconc\), and the parent type's restriction, \(none,pass,fail\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 9>
 (?is)\berror:
@@ -5449,7 +5449,7 @@ module module1
 (?is)\berror: false is not a valid value for type `boolean' which has subtype \(true\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(false\) is not subset of subtype \(true\)
+(?is)\berror: The intersection between the subtype restriction, \(false\), and the parent type's restriction, \(true\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 9>
 (?is)\berror:
@@ -5511,13 +5511,13 @@ module module1
 (?is)\berror: 4 is not a valid value for type `integer' which has subtype \(1..3\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4\) is not subset of subtype \(1..3\)
+(?is)\berror: The intersection between the subtype restriction, \(4\), and the parent type's restriction, \(1..3\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4..8\) is not subset of subtype \(1..3\)
+(?is)\berror: The intersection between the subtype restriction, \(4..8\), and the parent type's restriction, \(1..3\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4..8,16\) is not subset of subtype \(1..3\)
+(?is)\berror: The intersection between the subtype restriction, \(4..8,16\), and the parent type's restriction, \(1..3\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 1>
 (?is)\berror: While checking circular type references in subtype definitions: Circular reference: `\@module1.myi6' -> `\@module1.myi7' -> `\@module1.myi6'
@@ -5571,13 +5571,13 @@ module module1
 (?is)\berror: 4.0e0 is not a valid value for type `float' which has subtype \(1.0e0,2.0e0,3.0e0\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4.0e0\) is not subset of subtype \(1.0e0,2.0e0,3.0e0\)
+(?is)\berror: The intersection between the subtype restriction, \(4.0e0\), and the parent type's restriction, \(1.0e0,2.0e0,3.0e0\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4.0e0..8.0e0\) is not subset of subtype \(1.0e0,2.0e0,3.0e0\)
+(?is)\berror: The intersection between the subtype restriction, \(4.0e0..8.0e0\), and the parent type's restriction, \(1.0e0,2.0e0,3.0e0\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(4.0e0..8.0e0,1.6e1\) is not subset of subtype \(1.0e0,2.0e0,3.0e0\)
+(?is)\berror: The intersection between the subtype restriction, \(4.0e0..8.0e0,1.6e1\), and the parent type's restriction, \(1.0e0,2.0e0,3.0e0\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 11>
 (?is)\berror:
@@ -5744,7 +5744,7 @@ module module1
 (?is)\berror: '10'B is not a valid value for type `bitstring' which has subtype length\(1\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype length\(1\) is not subset of subtype \('00'B,'01'B\)
+(?is)\berror: The intersection between the subtype restriction, length\(1\), and the parent type's restriction, \('00'B,'01'B\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 3>
 (?is)\berror: Subtype mismatch: subtype length\(1\) has no common value with subtype \('00'B,'01'B\)
@@ -5796,7 +5796,7 @@ module module1
 (?is)\berror: '10'H is not a valid value for type `hexstring' which has subtype length\(1\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype length\(1\) is not subset of subtype \('00'H,'01'H\)
+(?is)\berror: The intersection between the subtype restriction, length\(1\), and the parent type's restriction, \('00'H,'01'H\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 3>
 (?is)\berror: Subtype mismatch: subtype length\(1\) has no common value with subtype \('00'H,'01'H\)
@@ -5852,7 +5852,7 @@ module module1
 (?is)\berror: '1010'O is not a valid value for type `octetstring' which has subtype length\(1\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype length\(2\) is not subset of subtype \('00'O,'01'O\)
+(?is)\berror: The intersection between the subtype restriction, length\(2\), and the parent type's restriction, \('00'O,'01'O\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 2>
 (?is)\berror: '1010'O is not a valid value for type `octetstring' which has subtype \('00'O,'01'O\)
@@ -6157,9 +6157,6 @@ module module1
   }
 }
 <END_MODULE>
-<RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(\{ 1, 2 \}\) union length\(1\) is not subset of subtype length\(1\)
-<END_RESULT>
 <RESULT COUNT 2>
 (?is)\berror: There must not be more than 1 elements in the list
 <END_RESULT>
@@ -6173,7 +6170,7 @@ module module1
 (?is)\berror: At least 4 elements must be present in the list
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(\{ <erroneous> \},\{ <erroneous> \}\) is not subset of subtype length\(5\)
+(?is)\berror: The intersection between the subtype restriction, \(\{ <erroneous> \},\{ <erroneous> \}\), and the parent type's restriction, length\(5\), is empty. \(No values satisfy the type's restrictions.\)
 <END_RESULT>
 <RESULT COUNT 2>
 (?is)\berror: record of value was expected
@@ -6187,7 +6184,7 @@ module module1
 <RESULT COUNT 1>
 (?is)\berror: Reference `myro2' must refer to a type which has the same root type as this type
 <END_RESULT>
-<RESULT COUNT 21>
+<RESULT COUNT 20>
 (?is)\berror:
 <END_RESULT>
 <END_TC>
@@ -6243,9 +6240,6 @@ module module1
 <RESULT COUNT 2>
 (?is)\berror: Reference `myso2' must refer to a type which has the same root type as this type
 <END_RESULT>
-<RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(\{ 1, 2 \}\) union length\(1\) is not subset of subtype length\(1\)
-<END_RESULT>
 <RESULT COUNT 2>
 (?is)\berror: There must not be more than 1 elements in the list
 <END_RESULT>
@@ -6264,7 +6258,7 @@ module module1
 <RESULT COUNT 3>
 (?is)\berror: Type mismatch: `\@module1.myso1' and `\@module1.myso2' are not compatible: Incompatible set of/SET OF subtypes
 <END_RESULT>
-<RESULT COUNT 20>
+<RESULT COUNT 19>
 (?is)\berror:
 <END_RESULT>
 <END_TC>
@@ -6397,12 +6391,9 @@ module module1
 (?is)\berror: 10 is not a valid value for type `integer' which has subtype \(2..9,11..19\)
 <END_RESULT>
 <RESULT COUNT 1>
-(?is)\berror: The subtype restriction is not a subset of the restriction on the parent type. Subtype \(2..19\) is not subset of subtype \(2..9,11..19\)
-<END_RESULT>
-<RESULT COUNT 1>
 (?is)\berror: 20 is not a valid value for type `integer' which has subtype \(2..19\)
 <END_RESULT>
-<RESULT COUNT 6>
+<RESULT COUNT 5>
 (?is)\berror:
 <END_RESULT>
 <END_TC>
diff --git a/function_test/Semantic_Analyser/float/subtype_SE.ttcn b/function_test/Semantic_Analyser/float/subtype_SE.ttcn
index 4900780ee24cd8313973d44fd75636a99ae2b66e..c87810647f97836eb15e57cef2e4e5401b309bcc 100644
--- a/function_test/Semantic_Analyser/float/subtype_SE.ttcn
+++ b/function_test/Semantic_Analyser/float/subtype_SE.ttcn
@@ -29,8 +29,8 @@ type float myf9     (myf123, minf_to_zero)
 type myf9 myf10 (myf123)
 type two31_32 myf11 (2147483648.0..4294967296.0, 4294967296.0..4294967300.0)
 
-type myf123 su2 (3.14);        //^In type definition//    //^error\: The subtype restriction is not a subset of the restriction on the parent type\. Subtype \(3\.14e0\) is not subset of subtype \(1\.0e0,2\.0e0,3\.0e0\)$//
-type minf_to_zero su3 (!6.0 .. 10.0); //^In type definition//    //^error\: The subtype restriction is not a subset of the restriction on the parent type\. Subtype \(\!6\.0e0\.\.1\.0e1\) is not subset of subtype \(\-INF\.\.0\.0e0\)$//
+type myf123 su2 (3.14);        //^In type definition//    //^error\: The intersection between the subtype restriction, \(3\.14e0\), and the parent type's restriction, \(1\.0e0,2\.0e0,3\.0e0\), is empty. \(No values satisfy the type's restrictions.\)$//
+type minf_to_zero su3 (!6.0 .. 10.0); //^In type definition//    //^error\: The intersection between the subtype restriction, \(\!6\.0e0\.\.1\.0e1\), and the parent type's restriction, \(\-INF\.\.0\.0e0\), is empty. \(No values satisfy the type's restrictions.\)$//
 
 type float buzz_lightyear (infinity .. not_a_number) //^In type definition//    //^error: upper boundary cannot be not_a_number in float subtype range$//
 // to infinity and beyond
diff --git a/regression_test/ASN1/parse/Test1.asn b/regression_test/ASN1/parse/Test1.asn
index 602f04a4e1a15f32c49c96c51e5278961eb51c82..5d0f29262f1d317de9391018384a4dc6557aeee2 100644
--- a/regression_test/ASN1/parse/Test1.asn
+++ b/regression_test/ASN1/parse/Test1.asn
@@ -937,6 +937,14 @@ MyElementSetType9-String2   ::= IA5String ( FROM ("A".. "Z" UNION "a".. "z"))
 
 MyElementSetType10 ::= INTEGER (0|1|4|6)
 
+MyElementSetType11 ::= BIT STRING { bit0 (0), bit1 (1) } (SIZE (8)) (ALL EXCEPT {})
+
+MyElementSetType12 ::= BIT STRING { bit0 (0), bit1 (1) } (SIZE (8)) (ALL EXCEPT { bit0 })
+
+MyElementSetType13 ::= BIT STRING { bit0 (0), bit1 (1) } (SIZE (8)) (ALL EXCEPT { bit1 })
+
+MyElementSetType14 ::= BIT STRING { bit0 (0), bit1 (1) } (SIZE (8)) (ALL EXCEPT { bit0, bit1 })
+
 -- 46 SUBTYPE ELEMENTS  *******************************************************************
 -- to be added later