tree schema FEATURE compile identities
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 42067d8..874ca01 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1091,6 +1091,68 @@
 }
 
 static LY_ERR
+lys_compile_identity(struct lysc_ctx *ctx, struct lysp_ident *ident_p, int options, struct lysc_ident *ident)
+{
+    unsigned int u;
+    LY_ERR ret = LY_SUCCESS;
+
+    if (options & LYSC_OPT_FREE_SP) {
+        /* just switch the pointers */
+        ident->name = ident_p->name;
+    } else {
+        /* keep refcounts correct for lysp_module_free() */
+        ident->name = lydict_insert(ctx->mod->ctx, ident_p->name, 0);
+    }
+    COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
+    /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
+    COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
+    ident->flags = ident_p->flags;
+
+done:
+    return ret;
+}
+
+static LY_ERR
+lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
+{
+    unsigned int i, u, v;
+    const char *s, *name;
+    struct lysc_module *mod;
+    struct lysc_ident **dident;
+
+    for (i = 0; i < LY_ARRAY_SIZE(idents_p); ++i) {
+        for (u = 0; u < LY_ARRAY_SIZE(idents_p[i].bases); ++u) {
+            s = strchr(idents_p[i].bases[u], ':');
+            if (s) {
+                /* prefixed identity */
+                name = &s[1];
+                mod = lysc_module_find_prefix(ctx->mod, idents_p[i].bases[u], s - idents_p[i].bases[u])->compiled;
+            } else {
+                name = idents_p[i].bases[u];
+                mod = ctx->mod;
+            }
+            LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+                                          "Invalid prefix used for base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
+                             LY_EVALID);
+            if (mod->identities) {
+                for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
+                    if (!strcmp(name, mod->identities[v].name)) {
+                        /* we have match! store the backlink */
+                        LY_ARRAY_NEW_RET(ctx->mod->ctx, mod->identities[v].derived, dident, LY_EMEM);
+                        *dident = &idents[i];
+                        break;
+                    }
+                }
+            }
+            LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+                                             "Unable to find base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
+                             LY_EVALID);
+        }
+    }
+    return LY_SUCCESS;
+}
+
+static LY_ERR
 lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
 {
     unsigned int u, v;
@@ -1158,6 +1220,10 @@
 
     COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
     COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
+    COMPILE_ARRAY_GOTO(&ctx, sp->identities, mod_c->identities, options, u, lys_compile_identity, ret, error);
+    if (sp->identities) {
+        LY_CHECK_RET(lys_compile_identities_derived(&ctx, sp->identities, mod_c->identities));
+    }
 
     COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
 
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 5c634c3..8971864 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -752,15 +752,15 @@
     LYEXT_SUBSTMT insubstmt;         /**< value identifying placement of the extension instance */
     uint32_t insubstmt_index;        /**< in case the instance is in a substatement that can appear multiple times,
                                           this identifies the index of the substatement for this extension instance */
+    LYEXT_PARENT parent_type;        /**< type of the parent structure */
 #if 0
-    uint8_t parent_type;             /**< #LYEXT_PAR - type of the parent structure */
     uint8_t ext_type;                /**< extension type (#LYEXT_TYPE) */
     uint8_t padding;                 /**< 32b padding */
-    struct lys_ext_instance **ext;   /**< array of pointers to the extension instances */
-    void *priv;                      /**< private caller's data, not used by libyang */
     struct lys_module *module;       /**< pointer to the extension instance's module (mandatory) */
     LYS_NODE nodetype;               /**< LYS_EXT */
 #endif
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    void *priv;                      /**< private caller's data, not used by libyang */
 };
 
 /**
@@ -781,6 +781,17 @@
 };
 
 /**
+ * @brief YANG identity-stmt
+ */
+struct lysc_ident {
+    const char *name;                /**< identity name (mandatory), including possible prefix */
+    struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+    struct lysc_ident **derived;     /**< list of (pointers to the) derived identities ([sized array](@ref sizedarrays)) */
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    uint16_t flags;                  /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_ values are allowed */
+};
+
+/**
  * @brief YANG feature-stmt
  */
 struct lysc_feature {
@@ -853,7 +864,10 @@
     struct lysc_import *imports;     /**< list of imported modules ([sized array](@ref sizedarrays)) */
 
     struct lysc_feature *features;   /**< list of feature definitions ([sized array](@ref sizedarrays)) */
-
+    struct lysc_ident *identities;   /**< list of identities ([sized array](@ref sizedarrays)) */
+    struct lysc_node *data;          /**< list of module's top-level data nodes (linked list) */
+    struct lysc_action *rpcs;        /**< list of RPCs ([sized array](@ref sizedarrays)) */
+    struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 
     uint8_t implemented:1;           /**< flag if the module is implemented, not just imported */