schema compile CHANGE anydata and anyxml support
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 3f7477b..fbab721 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -1324,6 +1324,8 @@
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     struct lysc_when *when;          /**< when statement */
     struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
+
+    struct lysc_must *musts;         /**< list of must restrictions ([sized array](@ref sizedarrays)) */
 };
 
 /**
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index f5ed93d..cf042b6 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -2675,9 +2675,6 @@
     unsigned int u;
     LY_ERR ret = LY_SUCCESS;
 
-    COMPILE_MEMBER_GOTO(ctx, cont_p->when, cont->when, options, lys_compile_when, ret, done);
-    COMPILE_ARRAY_GOTO(ctx, cont_p->iffeatures, cont->iffeatures, options, u, lys_compile_iffeature, ret, done);
-
     LY_LIST_FOR(cont_p->child, child_p) {
         LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
     }
@@ -2707,8 +2704,6 @@
     unsigned int u;
     LY_ERR ret = LY_SUCCESS;
 
-    COMPILE_MEMBER_GOTO(ctx, leaf_p->when, leaf->when, options, lys_compile_when, ret, done);
-    COMPILE_ARRAY_GOTO(ctx, leaf_p->iffeatures, leaf->iffeatures, options, u, lys_compile_iffeature, ret, done);
     COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, options, u, lys_compile_must, ret, done);
     DUP_STRING(ctx->ctx, leaf_p->units, leaf->units);
     DUP_STRING(ctx->ctx, leaf_p->dflt, leaf->dflt);
@@ -2756,8 +2751,6 @@
     const char *dflt = NULL;
     LY_ERR ret = LY_SUCCESS;
 
-    COMPILE_MEMBER_GOTO(ctx, llist_p->when, llist->when, options, lys_compile_when, ret, done);
-    COMPILE_ARRAY_GOTO(ctx, llist_p->iffeatures, llist->iffeatures, options, u, lys_compile_iffeature, ret, done);
     COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, options, u, lys_compile_must, ret, done);
     DUP_STRING(ctx->ctx, llist_p->units, llist->units);
 
@@ -2844,8 +2837,6 @@
     int config;
     LY_ERR ret = LY_SUCCESS;
 
-    COMPILE_MEMBER_GOTO(ctx, list_p->when, list->when, options, lys_compile_when, ret, done);
-    COMPILE_ARRAY_GOTO(ctx, list_p->iffeatures, list->iffeatures, options, u, lys_compile_iffeature, ret, done);
     list->min = list_p->min;
     list->max = list_p->max ? list_p->max : (uint32_t)-1;
 
@@ -3000,15 +2991,11 @@
     struct lysc_node_choice *ch = (struct lysc_node_choice*)node;
     struct lysp_node *child_p, *case_child_p;
     struct lysc_node *iter;
-    unsigned int u;
     const char *prefix = NULL, *name;
     size_t prefix_len = 0;
     struct lys_module;
     LY_ERR ret = LY_SUCCESS;
 
-    COMPILE_MEMBER_GOTO(ctx, ch_p->when, ch->when, options, lys_compile_when, ret, done);
-    COMPILE_ARRAY_GOTO(ctx, ch_p->iffeatures, ch->iffeatures, options, u, lys_compile_iffeature, ret, done);
-
     LY_LIST_FOR(ch_p->child, child_p) {
         if (child_p->nodetype == LYS_CASE) {
             LY_LIST_FOR(((struct lysp_node_case*)child_p)->child, case_child_p) {
@@ -3053,6 +3040,32 @@
         }
     }
 
+    return ret;
+}
+
+/**
+ * @brief Compile parsed anydata or anyxml node information.
+ * @param[in] ctx Compile context
+ * @param[in] node_p Parsed anydata or anyxml node.
+ * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
+ * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
+ * is enriched with the any-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+static LY_ERR
+lys_compile_node_any(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
+{
+    struct lysp_node_anydata *any_p = (struct lysp_node_anydata*)node_p;
+    struct lysc_node_anydata *any = (struct lysc_node_anydata*)node;
+    unsigned int u;
+    LY_ERR ret = LY_SUCCESS;
+
+    COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, options, u, lys_compile_must, ret, done);
+
+    if (any->flags & LYS_CONFIG_W) {
+        LOGWRN(ctx->ctx, "Use of %s to define configuration data is not recommended.",
+               ly_stmt2str(any->nodetype == LYS_ANYDATA ? YANG_ANYDATA : YANG_ANYXML));
+    }
 done:
     return ret;
 }
@@ -3259,6 +3272,7 @@
     case LYS_ANYXML:
     case LYS_ANYDATA:
         node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
+        node_compile_spec = lys_compile_node_any;
         break;
     default:
         LOGINT(ctx->ctx);
@@ -3311,6 +3325,8 @@
         node->sp = node_p;
     }
     DUP_STRING(ctx->ctx, node_p->name, node->name);
+    COMPILE_MEMBER_GOTO(ctx, node_p->when, node->when, options, lys_compile_when, ret, error);
+    COMPILE_ARRAY_GOTO(ctx, node_p->iffeatures, node->iffeatures, options, u, lys_compile_iffeature, ret, error);
     COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
 
     /* nodetype-specific part */
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 28be01d..23e8e44 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -655,7 +655,12 @@
             lysc_node_free(ctx, child);
         }
     }
+}
 
+static void
+lysc_node_anydata_free(struct ly_ctx *ctx, struct lysc_node_anydata *node)
+{
+    FREE_ARRAY(ctx, node->musts, lysc_must_free);
 }
 
 void
@@ -684,6 +689,10 @@
     case LYS_CASE:
         /* nothing specific */
         break;
+    case LYS_ANYDATA:
+    case LYS_ANYXML:
+        lysc_node_anydata_free(ctx, (struct lysc_node_anydata*)node);
+        break;
     default:
         LOGINT(ctx);
     }
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index f3d5777..e725f4a 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -1687,6 +1687,74 @@
     ly_ctx_destroy(ctx.ctx, NULL);
 }
 
+static void
+test_any(void **state, enum yang_keyword kw)
+{
+    *state = test_any;
+
+    struct lysp_module mod = {0};
+    struct ly_parser_ctx ctx = {0};
+    struct lysp_node_anydata *any = NULL;
+    const char *str;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
+    assert_non_null(ctx.ctx);
+    ctx.line = 1;
+    ctx.mod = &mod;
+    if (kw == YANG_ANYDATA) {
+        ctx.mod->version = 2; /* simulate YANG 1.1 */
+    } else {
+        ctx.mod->version = 1; /* simulate YANG 1.0 */
+    }
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("mandatory", "true", "false");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "any {config true;description test;if-feature f;mandatory true;must 'expr';reference test;status current;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any));
+    assert_non_null(any);
+    assert_int_equal(kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML, any->nodetype);
+    assert_string_equal("any", any->name);
+    assert_string_equal("test", any->dsc);
+    assert_non_null(any->exts);
+    assert_non_null(any->iffeatures);
+    assert_non_null(any->musts);
+    assert_string_equal("test", any->ref);
+    assert_non_null(any->when);
+    assert_null(any->parent);
+    assert_null(any->next);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, any->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_anydata(void **state)
+{
+    return test_any(state, YANG_ANYDATA);
+}
+
+static void
+test_anyxml(void **state)
+{
+    return test_any(state, YANG_ANYXML);
+}
+
 int main(void)
 {
     const struct CMUnitTest tests[] = {
@@ -1706,6 +1774,8 @@
         cmocka_unit_test_setup_teardown(test_list, logger_setup, logger_teardown),
         cmocka_unit_test_setup_teardown(test_choice, logger_setup, logger_teardown),
         cmocka_unit_test_setup_teardown(test_case, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_anydata, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_anyxml, logger_setup, logger_teardown),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index a1119d9..ec02274 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -715,6 +715,43 @@
     ly_ctx_destroy(ctx, NULL);
 }
 
+static void
+test_node_anydata(void **state)
+{
+    *state = test_node_anydata;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node_anydata *any;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;"
+                                        "anydata any {config false;mandatory true;}}", LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    any = (struct lysc_node_anydata*)mod->compiled->data;
+    assert_non_null(any);
+    assert_int_equal(LYS_ANYDATA, any->nodetype);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE, any->flags);
+
+    logbuf_clean();
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
+                                        "anyxml any;}", LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    any = (struct lysc_node_anydata*)mod->compiled->data;
+    assert_non_null(any);
+    assert_int_equal(LYS_ANYXML, any->nodetype);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR, any->flags);
+    logbuf_assert("Use of anyxml to define configuration data is not recommended."); /* warning */
+
+    /* invalid */
+    assert_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;anydata any;}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"anydata\" as a child of \"module\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
 /**
  * actually the same as length restriction (tested in test_type_length()), so just check the correct handling in appropriate types,
  * do not test the expression itself
@@ -2198,6 +2235,7 @@
         cmocka_unit_test_setup_teardown(test_node_leaflist, logger_setup, logger_teardown),
         cmocka_unit_test_setup_teardown(test_node_list, logger_setup, logger_teardown),
         cmocka_unit_test_setup_teardown(test_node_choice, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_anydata, logger_setup, logger_teardown),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);