diff --git a/compiler2/Type.cc b/compiler2/Type.cc
index 1f9f95a549d4dd385b6741ce6ef0dbc0ebdb4ecc..7ec627cf7e879831e34e0e8086eb52da90d500f1 100644
--- a/compiler2/Type.cc
+++ b/compiler2/Type.cc
@@ -61,7 +61,7 @@ extern Ttcn::ExtensionAttributes * parse_extattributes(
 
 namespace Common {
   
-  map<Type*, void> Type::CodingCheckTracker::types;
+  map<Type*, void> Type::RecursionTracker::types;
 
   using Ttcn::MultiWithAttrib;
   using Ttcn::SingleWithAttrib;
@@ -615,6 +615,7 @@ namespace Common {
     default_encoding.type = CODING_UNSET;
     default_decoding.type = CODING_UNSET;
     checked_incorrect_field = false;
+    encode_attrib_mod_conflict = false;
   }
 
   void Type::clean_up()
@@ -1216,6 +1217,11 @@ namespace Common {
 
   Type::truth Type::is_charenc()
   {
+    // this helps avoid infinite recursions in self-referencing types
+    if (RecursionTracker::is_happening(this)) {
+      return Maybe;
+    }
+    RecursionTracker tracker(this);
     switch(typetype) {
     case T_CHOICE_A:
     case T_CHOICE_T:
@@ -3265,12 +3271,17 @@ namespace Common {
     }
   }
   
-  void Type::add_coding(const string& name, bool silent)
+  void Type::add_coding(const string& name, Ttcn::attribute_modifier_t modifier, bool silent)
   {
     if (legacy_codec_handling) {
       FATAL_ERROR("Type::add_coding");
     }
     for (size_t i = 0; i < coding_table.size(); ++i) {
+      if (!encode_attrib_mod_conflict && modifier != coding_table[i]->modifier) {
+        encode_attrib_mod_conflict = true;
+        error("All 'encode' attributes of a type must have the same modifier "
+          "('override', '@local' or none)");
+      }
       const char* coding_name = coding_table[i]->built_in ?
         get_encoding_name(coding_table[i]->built_in_coding) :
         coding_table[i]->custom_coding.name;
@@ -3283,6 +3294,7 @@ namespace Common {
       if (get_type_refd_last()->can_have_coding(built_in_coding)) {
         coding_t* new_coding = new coding_t;
         new_coding->built_in = TRUE;
+        new_coding->modifier = modifier;
         new_coding->built_in_coding = built_in_coding;
         coding_table.add(new_coding);
         get_type_refd_last()->set_gen_coder_functions(built_in_coding);
@@ -3297,6 +3309,7 @@ namespace Common {
     else {
       coding_t* new_coding = new coding_t;
       new_coding->built_in = FALSE;
+      new_coding->modifier = modifier;
       new_coding->custom_coding.name = mcopystr(name.c_str());
       new_coding->custom_coding.encoders = new map<Type*, coder_function_t>;
       new_coding->custom_coding.decoders = new map<Type*, coder_function_t>;
@@ -3380,35 +3393,72 @@ namespace Common {
     return NULL; // not found
   }
   
-  Type* Type::get_type_w_coding_table()
+  Type* Type::get_type_w_coding_table(bool ignore_local /* = false */)
   {
-    // only return the type if it has a non-empty coding table
-    if (coding_table.size() != 0) {
+    // 1st priority: if local attributes are not ignored, and if the type 
+    // has its own 'encode' attributes (its coding table is not empty), then
+    // return the type
+    if (!ignore_local && coding_table.size() != 0) {
       return this;
     }
-    // first, check referenced types
+    
+    // 2nd priority: if this is a field or element type, and one of its parents
+    // has an 'encode' attribute with the 'override' modifier, then return the
+    // parent type
+    Type* t_parent = NULL;
+    if (parent_type != NULL && (ownertype == OT_COMP_FIELD ||
+        ownertype == OT_RECORD_OF || ownertype == OT_ARRAY)) {
+      // note: if one of the parent types has an overriding 'encode' attribute,
+      // then this returns the furthest parent with an overriding 'encode';
+      // if none of the 'encode' attributes are overriding, then the nearest
+      // parent with at least one 'encode' attribute is returned
+      t_parent = parent_type->get_type_w_coding_table(true);
+    }
+    if (t_parent != NULL) {
+      for (size_t i = 0; i < t_parent->coding_table.size(); ++i) {
+        if (t_parent->coding_table[i]->modifier == Ttcn::MOD_OVERRIDE) {
+          return t_parent;
+        }
+      }
+    }
+    
+    // 3rd priority: if local attributes are ignored, and if the type has its
+    // own (non-local) 'encode' attributes, then return the type
+    if (ignore_local && coding_table.size() != 0) {
+      bool local = false;
+      for (size_t i = 0; i < coding_table.size(); ++i) {
+        if (coding_table[i]->modifier == Ttcn::MOD_LOCAL) {
+          local = true;
+          break;
+        }
+      }
+      if (!local) {
+        return this;
+      }
+    }
+    
+    // 4th priority, if a referenced type has an 'encode' attribute, then return
+    // the referenced type
     if (is_ref()) {
-      Type* t = get_type_refd()->get_type_w_coding_table();
+      // note: this always returns the nearest referenced type with at least one
+      // 'encode' attribute
+      Type* t = get_type_refd()->get_type_w_coding_table(false);
       if (t != NULL) {
         return t;
       }
     }
-    // second, check the parent type if this is a field or element type
-    if (parent_type != NULL && (ownertype == OT_COMP_FIELD ||
-        ownertype == OT_RECORD_OF || ownertype == OT_ARRAY)) {
-      return parent_type->get_type_w_coding_table();
-    }
-    // if none of the above have a non-empty coding table, then return null
-    return NULL;
+    
+    // otherwise return the parent type pointer (whether it's null or not)
+    return t_parent;
   }
   
   bool Type::can_have_coding(MessageEncodingType_t coding)
   {
     // this helps avoid infinite recursions in self-referencing types
-    if (CodingCheckTracker::is_happening(this)) {
+    if (RecursionTracker::is_happening(this)) {
       return true;
     }
-    CodingCheckTracker tracker(this);
+    RecursionTracker tracker(this);
     
     // check whether the codec has been disabled by a compiler option or by
     // the license
diff --git a/compiler2/Type.hh b/compiler2/Type.hh
index 5cc3364f0761a1fa2dbe11679332e82ba61eabbb..b58bd84233ccb964cccb1500d373ac51bdeda6c3 100644
--- a/compiler2/Type.hh
+++ b/compiler2/Type.hh
@@ -76,6 +76,13 @@ namespace Ttcn {
   class PortTypeBody;
   class Def_Type;
   class Ref_pard;
+  
+  /** Stores the modifier of an attribute */
+  enum attribute_modifier_t {
+    MOD_NONE, ///< no modifier
+    MOD_OVERRIDE, ///< 'override' modifier
+    MOD_LOCAL ///< '@local' modifier
+  };
 } // namespace Ttcn
 
 // not defined here
@@ -303,6 +310,7 @@ namespace Common {
       * codec handling. */
     struct coding_t {
       boolean built_in; ///< built-in or user defined codec
+      Ttcn::attribute_modifier_t modifier; ///< the 'encode' attribute's modifier
       union {
         MessageEncodingType_t built_in_coding; ///< built-in codec
         struct {
@@ -478,14 +486,18 @@ namespace Common {
       * method. */
     vector<MessageEncodingType_t> coders_to_generate;
     
-    /** Helper class that tracks the execution of a type's 'can_have_coding'
-      * function to prevent infinite recursions. */
-    class CodingCheckTracker {
+    /** Indicates whether an 'encode' attribute modifier conflict error has
+      * already been displayed for the type. */
+    bool encode_attrib_mod_conflict;
+    
+    /** Helper class that tracks the execution of recursive functions in the 
+      * Type class in order to prevent infinite recursions. */
+    class RecursionTracker {
       static map<Type*, void> types;
       Type* key;
     public:
-      CodingCheckTracker(Type* t): key(t) { types.add(t, NULL); }
-      ~CodingCheckTracker() { types.erase(key); }
+      RecursionTracker(Type* t): key(t) { types.add(t, NULL); }
+      ~RecursionTracker() { types.erase(key); }
       static bool is_happening(Type* t) { return types.has_key(t); }
     };
 
@@ -512,6 +524,13 @@ namespace Common {
     static void destroy_pooltypes();
     /** Returns the TTCN-3 equivalent of \a p_tt. */
     static typetype_t get_typetype_ttcn3(typetype_t p_tt);
+    
+    /** Fills the list parameter with the types that have an empty coding table.
+      * The types considered are the type itself and its field and element types.
+      * Recursive.
+      * @param only_own_table if true, then only the type's own coding table is
+      * checked, otherwise inherited coding tables are also checked */
+    void get_types_w_no_coding_table(vector<Type>& type_list, bool only_own_table);
 
   public:
     /** @name Constructors
@@ -652,7 +671,7 @@ namespace Common {
       * if the type can have that encoding.
       * @param name name of the encoding as it appears in the 'encode' attribute;
       * this may be the name of a built-in or a user-defined encoding */
-    void add_coding(const string& name, bool silent);
+    void add_coding(const string& name, Ttcn::attribute_modifier_t modifier, bool silent);
     
     /** Sets the encoder or decoder function for the user-defined encoding with
       * the specified name (when using new codec handling). */
@@ -666,8 +685,10 @@ namespace Common {
     /** Returns the type that contains this type's coding table (since types
       * with no 'encode' attributes of their own inherit the 'encode' attributes
       * of a referenced type or a parent type).
+      * @param ignore_local indicates whether to ignore attributes with the
+      * '@local' modifier
       * Only used with new codec handling. */
-    Type* get_type_w_coding_table();
+    Type* get_type_w_coding_table(bool ignore_local = false);
     
     const vector<coding_t>& get_coding_table() const { return coding_table; }
     
diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc
index 0b760a2a5cc0d2c04709dbe6a864534e8b6a0c77..fdb15d224c5c7d14aa887643f2a599f3f00fbeaa 100644
--- a/compiler2/Type_chk.cc
+++ b/compiler2/Type_chk.cc
@@ -338,7 +338,7 @@ void Type::parse_attributes()
         // see if there's an encode with override
         for(size_t i = real_attribs.size(); i > 0 && !override_ref; i--)
         {
-          if(real_attribs[i-1]->has_override()
+          if(real_attribs[i-1]->get_modifier() == Ttcn::MOD_OVERRIDE
             && real_attribs[i-1]->get_attribKeyword()
               != SingleWithAttrib::AT_ENCODE)
             override_ref = true;
@@ -491,7 +491,7 @@ void Type::parse_attributes()
               // Copy the attribute without qualifiers
               const SingleWithAttrib* swaref = self_attribs->get_element(i);
               swa = new SingleWithAttrib(swaref->get_attribKeyword(),
-                swaref->has_override(), 0, swaref->get_attribSpec().clone());
+                swaref->get_modifier(), 0, swaref->get_attribSpec().clone());
               new_self_attribs->add_element(swa);
             }
           }
@@ -558,7 +558,7 @@ void Type::parse_attributes()
                 // A copy of temp_single, with new qualifiers
                 SingleWithAttrib* temp_single2
                 = new SingleWithAttrib(temp_single->get_attribKeyword(),
-                  temp_single->has_override(),
+                  temp_single->get_modifier(),
                   calculated_qualifiers,
                   temp_single->get_attribSpec().clone());
                 temp_single2->set_location(*temp_single);
@@ -670,6 +670,37 @@ void change_name(string &name, XerAttributes::NameChange change) {
   } // switch for NAME
 }
 
+void Type::get_types_w_no_coding_table(vector<Type>& type_list, bool only_own_table)
+{
+  // this helps avoid infinite recursions in self-referencing types
+  if (RecursionTracker::is_happening(this)) {
+    return;
+  }
+  RecursionTracker tracker(this);
+  if ((only_own_table && coding_table.size() == 0) ||
+      (!only_own_table && get_type_w_coding_table() == NULL)) {
+    type_list.add(this);
+  }
+  switch (get_typetype_ttcn3()) {
+  case T_SEQ_T:
+  case T_SET_T:
+  case T_CHOICE_T:
+  case T_ANYTYPE:
+  case T_OPENTYPE:
+    for (size_t j = 0; j < get_nof_comps(); ++j) {
+      get_comp_byIndex(j)->get_type()->get_types_w_no_coding_table(type_list, only_own_table);
+    }
+    break;
+  case T_SEQOF:
+  case T_SETOF:
+  case T_ARRAY:
+    get_ofType()->get_types_w_no_coding_table(type_list, only_own_table);
+    break;
+  default:
+    break;
+  }
+}
+
 void Type::chk_encodings()
 {
   if (legacy_codec_handling) {
@@ -703,6 +734,7 @@ void Type::chk_encodings()
           for (size_t i = 0; i < mwa->get_nof_elements(); ++i) {
             const SingleWithAttrib* swa = mwa->get_element(i);
             if (swa->get_attribKeyword() == SingleWithAttrib::AT_ENCODE) {
+              Ttcn::attribute_modifier_t mod = swa->get_modifier();
               Ttcn::Qualifiers* quals = swa->get_attribQualifiers();
               if (quals != NULL && quals->get_nof_qualifiers() != 0) {
                 for (size_t j = 0; j < quals->get_nof_qualifiers(); ++j) {
@@ -715,26 +747,75 @@ void Type::chk_encodings()
                         "refers to a type from a different type definition");
                     }
                     else {
-                      t->add_coding(swa->get_attribSpec().get_spec(), false);
+                      t->add_coding(swa->get_attribSpec().get_spec(), mod, false);
                     }
                   }
                 }
               }
               else {
-                add_coding(swa->get_attribSpec().get_spec(), false);
+                add_coding(swa->get_attribSpec().get_spec(), mod, false);
               }
             }
           }
         }
-        if (get_type_w_coding_table() == NULL) {
-          // if there are no 'encode' attributes in this type, the referenced
-          // types, or the parent type, then try the nearest group or the module
-          const vector<SingleWithAttrib>& real = ap->get_real_attrib();
+        WithAttribPath* global_ap = NULL;
+        Ttcn::Def_Type* def = static_cast<Ttcn::Def_Type*>(owner);
+        Ttcn::Group* nearest_group = def->get_parent_group();
+
+        if (nearest_group != NULL) { // there is a group
+          global_ap = nearest_group->get_attrib_path();
+        }
+        else { // no group, use the module
+          Common::Module* mymod = my_scope->get_scope_mod();
+          // OT_TYPE_DEF is always from a TTCN-3 module
+          Ttcn::Module* my_ttcn_module = static_cast<Ttcn::Module *>(mymod);
+          global_ap = my_ttcn_module->get_attrib_path();
+        }
+        if (global_ap != NULL) {
+          bool has_global_override = false;
+          bool modifier_conflict = false;
+          Ttcn::attribute_modifier_t first_mod = Ttcn::MOD_NONE;
+          const vector<SingleWithAttrib>& real = global_ap->get_real_attrib();
           for (size_t i = 0; i < real.size(); ++i) {
             const SingleWithAttrib* swa = real[i];
             if (swa->get_attribKeyword() == SingleWithAttrib::AT_ENCODE) {
-              add_coding(swa->get_attribSpec().get_spec(), true);
+              Ttcn::attribute_modifier_t mod = swa->get_modifier();
+              if (i == 0) {
+                first_mod = mod;
+              }
+              else if (!modifier_conflict && mod != first_mod) {
+                modifier_conflict = true;
+                swa->error("All 'encode' attributes of a group or module must "
+                  "have the same modifier ('override', '@local' or none)");
+              }
+              if (mod == Ttcn::MOD_OVERRIDE) {
+                has_global_override = true;
+              }
+              if (has_global_override && modifier_conflict) {
+                break;
+              }
+            }
+          }
+          // make a list of the type and its field and element types that inherit
+          // the global 'encode' attributes
+          // overriding global attributes are inherited by types with no coding
+          // table (no 'encode' attributes) of their own
+          // non-overriding global attributes are inherited by types that have
+          // no coding table of their own and cannot use the coding table of any 
+          // other type (get_type_w_coding_table() == NULL)
+          vector<Type> type_list;
+          get_types_w_no_coding_table(type_list, has_global_override);
+          if (type_list.size() != 0) {
+            for (size_t i = 0; i < real.size(); ++i) {
+              const SingleWithAttrib* swa = real[i];
+              if (swa->get_attribKeyword() == SingleWithAttrib::AT_ENCODE) {
+                for (size_t j = 0; j < type_list.size(); ++j) {
+                  type_list[j]->add_coding(swa->get_attribSpec().get_spec(),
+                    Ttcn::MOD_NONE, true);
+                }
+              }
             }
+            type_list.clear();
           }
         }
       }
@@ -746,12 +827,12 @@ void Type::chk_encodings()
       case OT_COMP_FIELD:
       case OT_SELTYPE:
         // ASN.1 types automatically have BER, PER, XER and JSON encoding
-        add_coding(string("BER:2002"), true);
-        add_coding(string(get_encoding_name(CT_PER)), true);
-        add_coding(string(get_encoding_name(CT_JSON)), true);
+        add_coding(string("BER:2002"), Ttcn::MOD_NONE, true);
+        add_coding(string(get_encoding_name(CT_PER)), Ttcn::MOD_NONE, true);
+        add_coding(string(get_encoding_name(CT_JSON)), Ttcn::MOD_NONE, true);
         if (asn1_xer) {
           // XER encoding for ASN.1 types can be disabled with a command line option
-          add_coding(string(get_encoding_name(CT_XER)), true);
+          add_coding(string(get_encoding_name(CT_XER)), Ttcn::MOD_NONE, true);
         }
         break;
       default:
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index 6ff1c4401d6c9f066906b6d059e9363f39981f82..e85cda8ad804e88408fbd1dcd2429e3839cb648e 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -6848,26 +6848,28 @@ namespace Ttcn {
             // First collect the fields of a record, set, union type which
             // does not support the encoding, then write it in the error message.
             char* message = NULL;
-            Type *t = input_type;
-            if (t->is_ref()) t = t->get_type_refd();
-            switch(t->get_typetype()) {
-              case Type::T_SEQ_T:
-              case Type::T_SET_T:
-              case Type::T_CHOICE_T: {
-                for (size_t i = 0; i < t->get_nof_comps(); i++) {
-                  if (!t->get_comp_byIndex(i)->get_type()->has_encoding(encoding_type, encoding_options)) {
-                    if (i == 0) {
-                      message = mputprintf(message, " The following fields do not support %s encoding: ",
-                        Type::get_encoding_name(encoding_type));
-                    } else {
-                      message = mputstr(message, ", ");
+            if (legacy_codec_handling) {
+              Type *t = input_type;
+              if (t->is_ref()) t = t->get_type_refd();
+              switch(t->get_typetype()) {
+                case Type::T_SEQ_T:
+                case Type::T_SET_T:
+                case Type::T_CHOICE_T: {
+                  for (size_t i = 0; i < t->get_nof_comps(); i++) {
+                    if (!t->get_comp_byIndex(i)->get_type()->has_encoding(encoding_type, encoding_options)) {
+                      if (i == 0) {
+                        message = mputprintf(message, " The following fields do not support %s encoding: ",
+                          Type::get_encoding_name(encoding_type));
+                      } else {
+                        message = mputstr(message, ", ");
+                      }
+                      message = mputstr(message, t->get_comp_id_byIndex(i).get_ttcnname().c_str());
                     }
-                    message = mputstr(message, t->get_comp_id_byIndex(i).get_ttcnname().c_str());
                   }
-                }
-                break; }
-              default:
-                break;
+                  break; }
+                default:
+                  break;
+              }
             }
             input_type->error("Input type `%s' does not support %s encoding.%s",
               input_type->get_typename().c_str(),
diff --git a/compiler2/ttcn3/Attributes.cc b/compiler2/ttcn3/Attributes.cc
index 4614bbdfd88f16f33d64286e792098e227c603f6..61f8159748ef3565667d941ce3291ae69fe60743 100644
--- a/compiler2/ttcn3/Attributes.cc
+++ b/compiler2/ttcn3/Attributes.cc
@@ -905,17 +905,17 @@ namespace Ttcn {
 
   SingleWithAttrib::SingleWithAttrib(const SingleWithAttrib& p)
     : Node(p), Location(p), attribKeyword(p.attribKeyword),
-      hasOverride(p.hasOverride)
+      modifier(p.modifier)
   {
     attribQualifiers = p.attribQualifiers ? p.attribQualifiers->clone() : 0;
     attribSpec = p.attribSpec->clone();
   }
 
   SingleWithAttrib::SingleWithAttrib(
-        attribtype_t p_attribKeyword, bool p_hasOverride,
+        attribtype_t p_attribKeyword, attribute_modifier_t p_modifier,
         Qualifiers *p_attribQualifiers, AttributeSpec* p_attribSpec)
     : Node(), Location(), attribKeyword(p_attribKeyword),
-      hasOverride(p_hasOverride), attribQualifiers(p_attribQualifiers),
+      modifier(p_modifier), attribQualifiers(p_attribQualifiers),
       attribSpec(p_attribSpec)
   {
     if(!p_attribSpec)
@@ -971,7 +971,8 @@ namespace Ttcn {
 	FATAL_ERROR("SingleWithAttrib::dump()");
     }
 
-    DEBUG(level + 1, hasOverride ? "has override" : "hasn't got override");
+    DEBUG(level + 1, "modifier: %s", modifier == MOD_NONE ? "none" :
+      (modifier == MOD_OVERRIDE ? "override" : "@local"));
 
     if(attribSpec)
       attribSpec->dump(level + 1);
@@ -1045,7 +1046,8 @@ namespace Ttcn {
 
   WithAttribPath::WithAttribPath(const WithAttribPath& p)
     : Node(p), had_global_variants(false), attributes_checked(false),
-      cached(false), s_o_encode(false), parent(p.parent)
+      global_attrib_checked(false), cached(false), s_o_encode(false),
+      parent(p.parent)
   {
     m_w_attrib = p.m_w_attrib ? p.m_w_attrib->clone() : 0;
   }
@@ -1131,7 +1133,7 @@ namespace Ttcn {
    */
   void WithAttribPath::chk_global_attrib(bool erroneous_allowed)
   {
-    if(!m_w_attrib)
+    if(!m_w_attrib || global_attrib_checked)
       return;
 
     if (!erroneous_allowed) {
@@ -1177,7 +1179,7 @@ namespace Ttcn {
         break;
         case SingleWithAttrib::AT_ERRONEOUS:
         {
-          if (temp_attrib->has_override()) {
+          if (temp_attrib->get_modifier() == MOD_OVERRIDE) {
             temp_attrib->error("Override cannot be used with erroneous");
           }
         }
@@ -1190,6 +1192,22 @@ namespace Ttcn {
     for(size_t i = 0; i < m_w_attrib->get_nof_elements();)
     {
       const SingleWithAttrib* const temp_attrib = m_w_attrib->get_element(i);
+      if (temp_attrib->get_modifier() == MOD_LOCAL) {
+        if (legacy_codec_handling) {
+          temp_attrib->error("The '@local' modifier cannot be used with legacy "
+            "codec handling");
+        }
+        else if (temp_attrib->get_attribKeyword() != SingleWithAttrib::AT_ENCODE) {
+          temp_attrib->warning("The '@local' modifier only affects 'encode' "
+            "attributes. Modifier ignored.");
+        }
+      }
+      if (!temp_attrib->get_attribSpec().get_encoding().empty() &&
+          (legacy_codec_handling ||
+           temp_attrib->get_attribKeyword() != SingleWithAttrib::AT_VARIANT)) {
+        temp_attrib->error("Invalid attribute format. Dot notation is only "
+          "allowed for variant attributes when using the new codec handling.");
+      }
       switch(temp_attrib->get_attribKeyword())
       {
         case SingleWithAttrib::AT_VARIANT:
@@ -1200,7 +1218,7 @@ namespace Ttcn {
             " variant of the with statement will have effect");
             m_w_attrib->delete_element(i);
           }else{
-            if(temp_attrib->has_override())
+            if(temp_attrib->get_modifier() == MOD_OVERRIDE)
               has_override_variant = true;
             i++;
           }
@@ -1214,7 +1232,7 @@ namespace Ttcn {
             " display of the with statement will have effect");
             m_w_attrib->delete_element(i);
           }else{
-            if(temp_attrib->has_override())
+            if(temp_attrib->get_modifier() == MOD_OVERRIDE)
               has_override_display = true;
             i++;
           }
@@ -1228,7 +1246,7 @@ namespace Ttcn {
             " extension of the with statement will have effect");
             m_w_attrib->delete_element(i);
           }else{
-            if(temp_attrib->has_override())
+            if(temp_attrib->get_modifier() == MOD_OVERRIDE)
               has_override_extension = true;
             i++;
           }
@@ -1248,7 +1266,7 @@ namespace Ttcn {
               " optional of the with statement will have effect");
             m_w_attrib->delete_element(i);
           }else{
-            if(temp_attrib->has_override())
+            if(temp_attrib->get_modifier() == MOD_OVERRIDE)
               has_override_optional = true;
             i++;
           }
@@ -1259,6 +1277,7 @@ namespace Ttcn {
         break;
       } // switch
     } // next i
+    global_attrib_checked = true;
   }
 
   void WithAttribPath::set_with_attr(MultiWithAttrib* p_m_w_attr)
@@ -1266,6 +1285,7 @@ namespace Ttcn {
     if(m_w_attrib) FATAL_ERROR("WithAttribPath::set_with_attr()");
     m_w_attrib = p_m_w_attr;
     attributes_checked = false;
+    global_attrib_checked = false;
   }
 
   /**
@@ -1370,7 +1390,7 @@ namespace Ttcn {
         {
         case SingleWithAttrib::AT_ENCODE:
           par_has_encode = true;
-          par_has_override_encode |= act_single->has_override();
+          par_has_override_encode |= act_single->get_modifier() == MOD_OVERRIDE;
           if(self_encode_index != -1)
           {
             // We also have an encode. See if they differ.
@@ -1381,16 +1401,16 @@ namespace Ttcn {
           break;
 
         case SingleWithAttrib::AT_VARIANT:
-          par_has_override_variant |= act_single->has_override();
+          par_has_override_variant |= act_single->get_modifier() == MOD_OVERRIDE;
           break;
         case SingleWithAttrib::AT_DISPLAY:
-          par_has_override_display |= act_single->has_override();
+          par_has_override_display |= act_single->get_modifier() == MOD_OVERRIDE;
           break;
         case SingleWithAttrib::AT_EXTENSION:
-          par_has_override_extension |= act_single->has_override();
+          par_has_override_extension |= act_single->get_modifier() == MOD_OVERRIDE;
           break;
         case SingleWithAttrib::AT_OPTIONAL:
-          par_has_override_optional |= act_single->has_override();
+          par_has_override_optional |= act_single->get_modifier() == MOD_OVERRIDE;
           break;
         case SingleWithAttrib::AT_ERRONEOUS:
         case SingleWithAttrib::AT_INVALID:
diff --git a/compiler2/ttcn3/Attributes.hh b/compiler2/ttcn3/Attributes.hh
index eb2a6a991ed716b232b74632d5d945348cc7b8fb..375383d1513385a4890ef83185e08c6341337284 100644
--- a/compiler2/ttcn3/Attributes.hh
+++ b/compiler2/ttcn3/Attributes.hh
@@ -267,21 +267,21 @@ namespace Ttcn {
     };
   private:
     attribtype_t attribKeyword;
-    /// True if the \c override keyword was used
-    bool hasOverride;
+    /// Attribute modifier ('override', '@local' or none)
+    attribute_modifier_t modifier;
     /// The stuff in parenthesis before the attribute text. Owned.
     Qualifiers *attribQualifiers;
     /// The attribute text (FreeText). Owned.
     AttributeSpec* attribSpec;
 
   public:
-    SingleWithAttrib(attribtype_t p_attribKeyword, bool p_hasOverride,
+    SingleWithAttrib(attribtype_t p_attribKeyword, attribute_modifier_t p_modifier,
           Qualifiers *p_attribQualifiers, AttributeSpec *p_attribSpec);
     ~SingleWithAttrib();
     virtual SingleWithAttrib* clone() const;
     virtual void set_fullname(const string& p_fullname);
     attribtype_t get_attribKeyword() const{ return attribKeyword; }
-    bool has_override() const { return hasOverride; }
+    attribute_modifier_t get_modifier() const { return modifier; }
     AttributeSpec const& get_attribSpec() const { return *attribSpec; }
     Qualifiers *get_attribQualifiers() const { return attribQualifiers; }
     virtual void dump(unsigned level) const;
@@ -333,6 +333,7 @@ namespace Ttcn {
   private:
     bool had_global_variants;
     bool attributes_checked;
+    bool global_attrib_checked;
     bool cached;
     bool s_o_encode;
     WithAttribPath* parent;
@@ -343,8 +344,8 @@ namespace Ttcn {
       bool& stepped_over_encode);
   public:
     WithAttribPath() : Node(), had_global_variants(false),
-      attributes_checked(false), cached(false), s_o_encode(false),
-      parent(0), m_w_attrib(0) { }
+      attributes_checked(false), global_attrib_checked(false), cached(false),
+      s_o_encode(false), parent(0), m_w_attrib(0) { }
     ~WithAttribPath();
     virtual WithAttribPath* clone() const;
     virtual void set_fullname(const string& p_fullname);
diff --git a/compiler2/ttcn3/compiler.l b/compiler2/ttcn3/compiler.l
index 852036dddfb5b3adcd71353b96b01bde42278c61..6035603516d76799e2664d11e6405e8f0680ef31 100644
--- a/compiler2/ttcn3/compiler.l
+++ b/compiler2/ttcn3/compiler.l
@@ -526,6 +526,7 @@ xor4b		RETURN(Xor4bKeyword);
 "@deterministic" RETURN(DeterministicKeyword);
 "@fuzzy"         RETURN(FuzzyKeyword);
 "@index"         RETURN(IndexKeyword);
+"@local"         RETURN(LocalKeyword);
 
   /* special TITAN specific keywords */
 
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index 58b2c56322ae0e9e9cc9a04ae113ac4c4eea35da..0d828c19d6a0b7e9c6ceddbb5e1098c6a9c7b67a 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -216,6 +216,7 @@ static const string anyname("anytype");
   SingleValueRedirect* single_value_redirect;
   param_eval_t eval;
   TypeMappingTargets *typemappingtargets;
+  attribute_modifier_t attrib_mod;
 
   struct {
     bool is_raw;
@@ -791,6 +792,7 @@ static const string anyname("anytype");
 %token DeterministicKeyword
 %token FuzzyKeyword
 %token IndexKeyword
+%token LocalKeyword
 
 /* TITAN specific keywords */
 %token TitanSpecificTryKeyword
@@ -922,7 +924,7 @@ static const string anyname("anytype");
  * Semantic types of nonterminals
  *********************************************************************/
 
-%type <bool_val> optAliveKeyword optOptionalKeyword optOverrideKeyword
+%type <bool_val> optAliveKeyword optOptionalKeyword
   optErrValueRaw optAllKeyword optDeterministicModifier
 %type <str> FreeText optLanguageSpec PatternChunk PatternChunkList
 %type <uchar_val> Group Plane Row Cell
@@ -935,6 +937,7 @@ static const string anyname("anytype");
 %type <typetype> PredefinedType
 %type <portoperationmode> PortOperationMode
 %type <operationtype> PredefinedOpKeyword1 PredefinedOpKeyword2 PredefinedOpKeyword3
+%type <attrib_mod> optAttributeModifier
 
 %type <activateop> ActivateOp
 %type <attribtype> AttribKeyword
@@ -8165,7 +8168,7 @@ MultiWithAttrib: // 529
 ;
 
 SingleWithAttrib: // 530
-  AttribKeyword optOverrideKeyword optAttribQualifier AttribSpec
+  AttribKeyword optAttributeModifier optAttribQualifier AttribSpec
   {
     $$ = new SingleWithAttrib($1,$2,$3,$4);
     $$->set_location(infile, @$);
@@ -8202,9 +8205,10 @@ AttribKeyword: // 531
   }
 ;
 
-optOverrideKeyword: // [536]
-  /* empty */ { $$ = false; }
-| OverrideKeyword { $$ = true; }
+optAttributeModifier: // [536]
+  /* empty */ { $$ = MOD_NONE; }
+| OverrideKeyword { $$ = MOD_OVERRIDE; }
+| LocalKeyword { $$ = MOD_LOCAL; }
 ;
 
 optAttribQualifier: // [537]
@@ -8315,15 +8319,8 @@ AttribSpec: // 542
   }
 | FreeText '.' FreeText
   {
-    if (legacy_codec_handling) {
-      Location loc(infile, @$);
-      loc.error("Invalid attribute format. Dot notation is only allowed for "
-        "variant attributes when using legacy codec handling.");
-    }
-    else {
-      $$ = new AttributeSpec(string($3), string($1));
-      $$->set_location(infile, @$);
-    }
+    $$ = new AttributeSpec(string($3), string($1));
+    $$->set_location(infile, @$);
     Free($1);
     Free($3);
   }
diff --git a/function_test/Semantic_Analyser/Makefile.semantic b/function_test/Semantic_Analyser/Makefile.semantic
index 9d22c6583214b6f9afda94a9b586f186561bfb78..5f3a543ebb7fdfe6b8d1ab328e36d4b14c694bed 100644
--- a/function_test/Semantic_Analyser/Makefile.semantic
+++ b/function_test/Semantic_Analyser/Makefile.semantic
@@ -12,6 +12,8 @@
 #   Szabo, Bence Janos
 #
 ##############################################################################
+include ../../Makefile.personal
+
 SADIRS := ver param template any_from pattern_ref float recof_index \
 port_translation mtc_and_system_clause port_map_connect deterministic
 ifdef RT2
diff --git a/function_test/Semantic_Analyser/common.mk b/function_test/Semantic_Analyser/common.mk
index 558c5f1d86a7494bc0e62919397afecabef1a3a8..d7aa71e0236d9a57604e4a7910fc43c755378a21 100644
--- a/function_test/Semantic_Analyser/common.mk
+++ b/function_test/Semantic_Analyser/common.mk
@@ -21,11 +21,6 @@ ifdef RT2
 COMPILER_FLAGS += -R
 endif
 
-# Use the legacy handling of 'encode' and 'variant' in tests.
-ifdef LEGACY_CODEC_HANDLING
-COMPILER_FLAGS += -e
-endif
-
 # TTCN-3 modules of this project:
 TTCN3_MODULES := $(sort $(wildcard *A.ttcn *S[WE].ttcn *OK.ttcn))
 
@@ -66,6 +61,11 @@ ifeq ($(DEBUG), yes)
 CPPFLAGS += -DMEMORY_DEBUG
 endif
 
+# Use the legacy handling of 'encode' and 'variant' attributes in tests.
+ifdef LEGACY_CODEC_HANDLING
+COMPILER_FLAGS += -e
+endif
+
 #
 # Rules for building the executable...
 #
diff --git a/function_test/Semantic_Analyser/encode/encode_modifier_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_modifier_SE.ttcn
new file mode 100644
index 0000000000000000000000000000000000000000..7fcc0edcb5491bdd7c6575730082ab8ece170e66
--- /dev/null
+++ b/function_test/Semantic_Analyser/encode/encode_modifier_SE.ttcn
@@ -0,0 +1,178 @@
+/******************************************************************************
+ * Copyright (c) 2000-2017 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 encode_modifier { //^In TTCN-3 module//
+
+type enumerated Enum { x1, x2 }
+with {
+  encode "RAW";
+}
+
+type record of integer RoI;
+
+group Grp1 {
+
+group Grp2 {
+
+type record Rec {
+  Enum en,
+  RoI list
+}
+with {
+  encode "XML";
+}
+
+} /* Grp2 */
+with {
+  encode "TEXT";
+}
+
+} /* Grp1 */
+with {
+  encode override "JSON";
+}
+
+type union Uni {
+  Enum en,
+  Rec.list list
+}
+with {
+  encode override "TEXT";
+}
+
+group Grp3 {
+
+type set of octetstring SoOS
+with {
+  encode @local "RAW";
+}
+
+type set Set {
+  SoOS octs,
+  RoI ints
+}
+with {
+  encode @local "JSON";
+}
+
+} /* Grp3 */
+with {
+  encode "XML";
+}
+
+external function f_enc_rec1(in Rec x) return octetstring
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+external function f_enc_rec2(in Rec x) return charstring //^In external function definition// //does not support TEXT encoding//
+  with { extension "prototype(convert) encode(TEXT)" };
+external function f_enc_rec3(in Rec x) return octetstring //^In external function definition// //does not support JSON encoding//
+  with { extension "prototype(convert) encode(JSON)" };
+
+external function f_enc_rec_en1(in Rec.en x) return octetstring //^In external function definition// //does not support RAW encoding//
+  with { extension "prototype(convert) encode(RAW)" };
+external function f_enc_rec_en2(in Rec.en x) return octetstring //^In external function definition// //does not support XER encoding//
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+external function f_enc_rec_en3(in Rec.en x) return charstring //^In external function definition// //does not support TEXT encoding//
+  with { extension "prototype(convert) encode(TEXT)" };
+external function f_enc_rec_en4(in Rec.en x) return octetstring
+  with { extension "prototype(convert) encode(JSON)" };
+
+external function f_enc_rec_list1(in Rec.list x) return octetstring //^In external function definition// //does not support XER encoding//
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+external function f_enc_rec_list2(in Rec.list x) return charstring //^In external function definition// //does not support TEXT encoding//
+  with { extension "prototype(convert) encode(TEXT)" };
+external function f_enc_rec_list3(in Rec.list x) return octetstring
+  with { extension "prototype(convert) encode(JSON)" };
+
+external function f_enc_uni_en1(in Uni.en x) return octetstring //^In external function definition// //does not support RAW encoding//
+  with { extension "prototype(convert) encode(RAW)" };
+external function f_enc_uni_en2(in Uni.en x) return charstring
+  with { extension "prototype(convert) encode(TEXT)" };
+
+external function f_enc_uni_list1(in Uni.list x) return octetstring //^In external function definition// //does not support XER encoding//
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+external function f_enc_uni_list2(in Uni.list x) return octetstring //^In external function definition// //does not support JSON encoding//
+  with { extension "prototype(convert) encode(JSON)" };
+external function f_enc_uni_list3(in Uni.list x) return charstring
+  with { extension "prototype(convert) encode(TEXT)" };
+
+external function f_enc_set1(in Set x) return octetstring
+  with { extension "prototype(convert) encode(JSON)" };
+external function f_enc_set2(in Set x) return octetstring //^In external function definition// //does not support XER encoding//
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+
+external function f_enc_set_octs1(in Set.octs x) return octetstring
+  with { extension "prototype(convert) encode(RAW)" };
+external function f_enc_set_octs2(in Set.octs x) return octetstring //^In external function definition// //does not support JSON encoding//
+  with { extension "prototype(convert) encode(JSON)" };
+external function f_enc_set_octs3(in Set.octs x) return octetstring //^In external function definition// //does not support XER encoding//
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+
+external function f_enc_set_ints1(in Set.ints x) return octetstring //^In external function definition// //does not support JSON encoding//
+  with { extension "prototype(convert) encode(JSON)" };
+external function f_enc_set_ints2(in Set.ints x) return octetstring
+  with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
+
+
+type record MixedModifiersInType { //^In type definition// //All 'encode' attributes of a type must have the same modifier//
+  integer f1, //All 'encode' attributes of a type must have the same modifier//
+  charstring f2 //All 'encode' attributes of a type must have the same modifier//
+}
+with {
+  encode "RAW";
+  encode @local "JSON";
+  encode override (f1) "RAW";
+  encode (f1) "JSON";
+  encode @local (f2) "RAW";
+  encode override (f2) "JSON";
+}
+
+group MixedModifiersInGroup1 {
+  type record of integer DummyList; //^In type definition//
+}
+with {
+  encode @local "TEXT"; //All 'encode' attributes of a group or module must have the same modifier//
+  encode "XML";
+}
+
+group MixedModifiersInGroup2 {
+  type record DummyRecord { integer f }; //^In type definition//
+}
+with {
+  encode "TEXT"; //All 'encode' attributes of a group or module must have the same modifier//
+  encode override "XML";
+}
+
+group MixedModifiersInGroup3 {
+  type union DummyUnion { integer f }; //^In type definition//
+}
+with {
+  encode override "TEXT"; //All 'encode' attributes of a group or module must have the same modifier//
+  encode @local "XML";
+}
+
+type set DummySet { //^In type definition//
+  integer f optional
+}
+with {
+  encode "XML";
+  variant @local "name as uncapitalized"; //The '@local' modifier only affects 'encode' attributes. Modifier ignored.//
+  display @local "xx"."red"; //The '@local' modifier only affects 'encode' attributes. Modifier ignored.// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+}
+
+const DummySet c_dummy := { f := - } with { optional @local "yy"."implicit omit" } //^In constant definition// //The '@local' modifier only affects 'encode' attributes. Modifier ignored.// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+
+type set of DummySet DummySetList with { //^In type definition//
+  extension @local "qw"."optimize:memalloc"; //The '@local' modifier only affects 'encode' attributes. Modifier ignored.// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+  encode "JSON"."RAW"; //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+}
+
+}
diff --git a/function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn b/function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn
index 19416d334db091ef331ebde32019858b639c22e0..607038addf66d6ae963f4544cd2d1d5534510de6 100644
--- a/function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn
+++ b/function_test/Semantic_Analyser/encode_legacy/encode_ttcn_SE.ttcn
@@ -150,6 +150,21 @@ type record C2 {
 external function f_enc_C2(in C2 x) return octetstring //^In external function definition \`f_enc_C2\'\:// //^error\: Input type \`\@encode_ttcn_SE\.C2\' does not support XER encoding\.//
   with { extension "prototype(convert) encode(XER:XER_EXTENDED)" };
 
+type set DummySet { //^In type definition//
+  integer f optional
+}
+with {
+  encode @local "XML"; //The '@local' modifier cannot be used with legacy codec handling//
+  variant @local "XML"."name as uncapitalized"; //The '@local' modifier cannot be used with legacy codec handling// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+  display @local "xx"."red"; //The '@local' modifier cannot be used with legacy codec handling// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+}
+
+const DummySet c_dummy := { f := - } with { optional @local "yy"."implicit omit" } //^In constant definition// //The '@local' modifier cannot be used with legacy codec handling// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+
+type set of DummySet DummySetList with { //^In type definition//
+  extension @local "qw"."optimize:memalloc"; //The '@local' modifier cannot be used with legacy codec handling// //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+  encode "JSON"."RAW"; //Invalid attribute format. Dot notation is only allowed for variant attributes when using the new codec handling.//
+}
 
 } with {
   encode "whatever"
diff --git a/function_test/Semantic_Analyser/xer/ifq_SE.ttcn b/function_test/Semantic_Analyser/xer/ifq_SE.ttcn
index 2e7db4d6ae7eec47b37be492652b40300ed1fe1a..3687cf7f7a9c93a1f083c5283c7176d30d4da3cb 100644
--- a/function_test/Semantic_Analyser/xer/ifq_SE.ttcn
+++ b/function_test/Semantic_Analyser/xer/ifq_SE.ttcn
@@ -14,7 +14,7 @@ module ifq_SE {	//^In TTCN-3 module `ifq_SE'://
 
 type record foo {} //^In type definition//
 with {
-  variant ([-]) "attribute" //^error: Invalid field qualifier \[-\]//
+  variant ([-]) "attribute" //^error: Type `\@ifq_SE\.foo' cannot be indexed//
 }
 
 /*  integer _0; is a syntax error