schema compile FEATURE status checks for deviated definitions

Fixes #1718
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 9642efb..74444ab 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -53,6 +53,105 @@
 }
 
 /**
+ * @brief Add a node with must(s) to unres.
+ *
+ * @param[in] ctx Compile context.
+ * @param[in] node Compiled node with must(s).
+ * @param[in] pnode Parsed ndoe with must(s).
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lysc_unres_must_add(struct lysc_ctx *ctx, struct lysc_node *node, struct lysp_node *pnode)
+{
+    struct lysc_unres_must *m = NULL;
+    LY_ARRAY_COUNT_TYPE u;
+    struct lysc_must *musts;
+    struct lysp_restr *pmusts;
+    LY_ERR ret;
+
+    /* do not check must(s) in a grouping */
+    if (ctx->compile_opts & LYS_COMPILE_GROUPING) {
+        return LY_SUCCESS;
+    }
+
+    musts = lysc_node_musts(node);
+    pmusts = lysp_node_musts(pnode);
+    assert(LY_ARRAY_COUNT(musts) == LY_ARRAY_COUNT(pmusts));
+
+    if (!musts) {
+        /* no must */
+        return LY_SUCCESS;
+    }
+
+    /* add new unres must */
+    m = calloc(1, sizeof *m);
+    LY_CHECK_ERR_GOTO(!m, ret = LY_EMEM, error);
+    m->node = node;
+
+    /* add must local modules */
+    LY_ARRAY_CREATE_GOTO(ctx->ctx, m->local_mods, LY_ARRAY_COUNT(pmusts), ret, error);
+    LY_ARRAY_FOR(pmusts, u) {
+        m->local_mods[u] = pmusts[u].arg.mod;
+        LY_ARRAY_INCREMENT(m->local_mods);
+    }
+
+    LY_CHECK_ERR_GOTO(ly_set_add(&ctx->unres->musts, m, 1, NULL), ret = LY_EMEM, error);
+
+    return LY_SUCCESS;
+
+error:
+    if (m) {
+        LY_ARRAY_FREE(m->local_mods);
+        free(m);
+    }
+    LOGMEM(ctx->ctx);
+    return ret;
+}
+
+static LY_ERR
+lysc_unres_leafref_add(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, const struct lysp_module *local_mod)
+{
+    struct lysc_unres_leafref *l = NULL;
+    struct ly_set *leafrefs_set;
+    LY_ARRAY_COUNT_TYPE u;
+    int is_lref = 0;
+
+    if (ctx->compile_opts & LYS_COMPILE_GROUPING) {
+        /* do not check leafrefs in groupings */
+        return LY_SUCCESS;
+    }
+
+    /* use special set for disabled leafrefs */
+    leafrefs_set = ctx->compile_opts & LYS_COMPILE_DISABLED ? &ctx->unres->disabled_leafrefs : &ctx->unres->leafrefs;
+
+    if (leaf->type->basetype == LY_TYPE_LEAFREF) {
+        /* leafref */
+        is_lref = 1;
+    } else if (leaf->type->basetype == LY_TYPE_UNION) {
+        /* union with leafrefs */
+        LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
+            if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
+                is_lref = 1;
+                break;
+            }
+        }
+    }
+
+    if (is_lref) {
+        /* add new unresolved leafref node */
+        l = calloc(1, sizeof *l);
+        LY_CHECK_ERR_RET(!l, LOGMEM(ctx->ctx), LY_EMEM);
+
+        l->node = &leaf->node;
+        l->local_mod = local_mod;
+
+        LY_CHECK_ERR_RET(ly_set_add(leafrefs_set, l, 1, NULL), free(l); LOGMEM(ctx->ctx), LY_EMEM);
+    }
+
+    return LY_SUCCESS;
+}
+
+/**
  * @brief Add/replace a leaf default value in unres.
  * Can also be used for a single leaf-list default value.
  *
@@ -337,7 +436,7 @@
     if (!(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
         /* do not check "when" semantics in a grouping, but repeat the check for different node because
          * of dummy node check */
-        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, node, 0, NULL));
+        LY_CHECK_RET(ly_set_add(&ctx->unres->whens, node, 0, NULL));
     }
 
     return LY_SUCCESS;
@@ -2567,6 +2666,10 @@
     lysc_update_path(ctx, NULL, NULL);
     LY_CHECK_GOTO(ret, done);
 
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, &action->input.node, &input->node);
+    LY_CHECK_GOTO(ret, done);
+
     /* output */
     lysc_update_path(ctx, action->module, "output");
     if (action_p->output.nodetype == LYS_UNKNOWN) {
@@ -2578,11 +2681,9 @@
     lysc_update_path(ctx, NULL, NULL);
     LY_CHECK_GOTO(ret, done);
 
-    /* do not check "must" semantics in a grouping */
-    if ((action->input.musts || action->output.musts) && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, &action->output.node, &output->node);
+    LY_CHECK_GOTO(ret, done);
 
 done:
     return ret;
@@ -2605,11 +2706,10 @@
     struct lysp_node *child_p;
 
     COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, done);
-    if (notif_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, notif, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
 
     LY_LIST_FOR(notif_p->child, child_p) {
         ret = lys_compile_node(ctx, child_p, node, 0, NULL);
@@ -2652,11 +2752,10 @@
     }
 
     COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, lys_compile_must, ret, done);
-    if (cont_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, cont, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
 
     LY_LIST_FOR((struct lysp_node *)cont_p->actions, child_p) {
         ret = lys_compile_node(ctx, child_p, node, 0, NULL);
@@ -2684,7 +2783,6 @@
         struct lysc_node_leaf *leaf)
 {
     struct lysp_qname *dflt;
-    struct ly_set *leafrefs_set;
 
     LY_CHECK_RET(lys_compile_type(ctx, context_node, leaf->flags, leaf->name, type_p, &leaf->type,
             leaf->units ? NULL : &leaf->units, &dflt));
@@ -2694,19 +2792,10 @@
         LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, dflt));
     }
 
-    leafrefs_set = ctx->compile_opts & LYS_COMPILE_DISABLED ? &ctx->unres->disabled_leafrefs : &ctx->unres->leafrefs;
-    if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
-        LY_CHECK_RET(ly_set_add(leafrefs_set, leaf, 0, NULL));
-    } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        LY_ARRAY_COUNT_TYPE u;
-        LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
-            if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
-                /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
-                LY_CHECK_RET(ly_set_add(leafrefs_set, leaf, 0, NULL));
-            }
-        }
-    } else if (leaf->type->basetype == LY_TYPE_EMPTY) {
+    /* store leafref(s) to be resolved */
+    LY_CHECK_RET(lysc_unres_leafref_add(ctx, leaf, type_p->pmod));
+
+    if (leaf->type->basetype == LY_TYPE_EMPTY) {
         if ((leaf->nodetype == LYS_LEAFLIST) && (ctx->pmod->version < LYS_VERSION_1_1)) {
             LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
             return LY_EVALID;
@@ -2732,11 +2821,11 @@
     LY_ERR ret = LY_SUCCESS;
 
     COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, lys_compile_must, ret, done);
-    if (leaf_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, leaf, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
+
     if (leaf_p->units) {
         LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, leaf_p->units, 0, &leaf->units), done);
         leaf->flags |= LYS_SET_UNITS;
@@ -2778,11 +2867,11 @@
     LY_ERR ret = LY_SUCCESS;
 
     COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, lys_compile_must, ret, done);
-    if (llist_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, llist, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
+
     if (llist_p->units) {
         LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, llist_p->units, 0, &llist->units), done);
         llist->flags |= LYS_SET_UNITS;
@@ -3044,7 +3133,7 @@
             }
 
             /* check status */
-            LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
+            LY_CHECK_RET(lysc_check_status(ctx, list->flags, uniques[v].mod->mod, list->name,
                     (*key)->flags, (*key)->module, (*key)->name));
 
             /* mark leaf as unique */
@@ -3089,10 +3178,10 @@
     }
 
     COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, lys_compile_must, ret, done);
-    if (list_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, list, 0, NULL));
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
 
     /* keys */
     if ((list->flags & LYS_CONFIG_W) && (!list_p->key || !list_p->key[0])) {
@@ -3400,11 +3489,10 @@
     LY_ERR ret = LY_SUCCESS;
 
     COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, lys_compile_must, ret, done);
-    if (any_p->musts && !(ctx->compile_opts & LYS_COMPILE_GROUPING)) {
-        /* do not check "must" semantics in a grouping */
-        ret = ly_set_add(&ctx->unres->xpath, any, 0, NULL);
-        LY_CHECK_GOTO(ret, done);
-    }
+
+    /* add must(s) to unres */
+    ret = lysc_unres_must_add(ctx, node, pnode);
+    LY_CHECK_GOTO(ret, done);
 
     if (any->flags & LYS_CONFIG_W) {
         LOGVRB("Use of %s to define configuration data is not recommended. %s",