schema CHANGE remove private_destructor parameter from ly_ctx_destroy()

The mechanism was not reliable and not used often. libyang provide
function to traverse the schema and free the set data manually or the
caller can maintain some information to free the set data directly.

This commit changes API.
diff --git a/doc/transition.dox b/doc/transition.dox
index 0dbc8fd..ff0c375 100644
--- a/doc/transition.dox
+++ b/doc/transition.dox
@@ -103,6 +103,15 @@
  * introduce some kind of context lock to completely abandon any change of the YANG modules after starting work with the
  * instantiated data.
  *
+ * Another change to note is the removed destructor of private data (::lysc_node.priv) in ::ly_ctx_destroy(). The mechanism
+ * was not reliable with the context recompilation and the splitted parsed and compiled schema trees or the complexity of
+ * YANG extensions. It is better to let the caller maintain the allocated data directly via some memory pool or using
+ * ::lysc_tree_dfs_full() since he is the best to know where the additional data were added.
+ * 
+ * The meaining of the ::lysc_node.priv pointer can be now also changed by ::LY_CTX_SET_PRIV_PARSED context option, which
+ * makes libyang to connect the original parsed schema node structure (::lysp_node) into the compiled nodes via their 'priv'
+ * pointer. 
+ *
  * Other significant changes connected with the context are depicted in the following table.
  *
  * libyang 1.x               | libyang 2.0                          | Notes
@@ -126,6 +135,7 @@
  * ly_ctx_unset_searchdirs() | ::ly_ctx_unset_searchdir()           | Simplify API and instead of index numbers, work with the values themselves.
  * ly_ctx_set*()             | ::ly_ctx_set_options()               | API simplification.
  * ly_ctx_unset*()           | ::ly_ctx_unset_options()             | ^
+ * ly_ctx_destroy()          | ::ly_ctx_destroy()                   | The destructor callback parameter was removed, see the notes above.
  *
  *
  * @section transitionSchemas YANG Modules (Schema)
diff --git a/src/context.c b/src/context.c
index de6e4c3..7c9a93c 100644
--- a/src/context.c
+++ b/src/context.c
@@ -287,7 +287,7 @@
 error:
     ly_in_free(in, 0);
     lys_compile_unres_glob_erase(ctx, &unres);
-    ly_ctx_destroy(ctx, NULL);
+    ly_ctx_destroy(ctx);
     return rc;
 }
 
@@ -438,11 +438,11 @@
     ly_set_free(set, NULL);
     ly_set_erase(&features, NULL);
     if (ctx_yl != ctx_new) {
-        ly_ctx_destroy(ctx_yl, NULL);
+        ly_ctx_destroy(ctx_yl);
     }
     *ctx = ctx_new;
     if (ret) {
-        ly_ctx_destroy(*ctx, NULL);
+        ly_ctx_destroy(*ctx);
         *ctx = NULL;
     }
 
@@ -1098,7 +1098,7 @@
 }
 
 API void
-ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lysc_node *node, void *priv))
+ly_ctx_destroy(struct ly_ctx *ctx)
 {
     if (!ctx) {
         return;
@@ -1107,7 +1107,7 @@
     /* models list */
     for ( ; ctx->list.count; ctx->list.count--) {
         /* remove the module */
-        lys_module_free(ctx->list.objs[ctx->list.count - 1], private_destructor);
+        lys_module_free(ctx->list.objs[ctx->list.count - 1]);
     }
     free(ctx->list.objs);
 
diff --git a/src/context.h b/src/context.h
index cda1212..8f0d470 100644
--- a/src/context.h
+++ b/src/context.h
@@ -593,11 +593,12 @@
  * All instance data are supposed to be freed before destroying the context.
  * Data models are destroyed automatically as part of ::ly_ctx_destroy() call.
  *
+ * Note that the data stored by user into the ::lysc_node.priv pointer are kept
+ * untouched and the caller is responsible for freeing this private data.
+ *
  * @param[in] ctx libyang context to destroy
- * @param[in] private_destructor Optional destructor function for private objects assigned
- * to the schema nodes' priv pointer. If NULL, the private objects are not freed by libyang.
  */
-void ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lysc_node *node, void *priv));
+void ly_ctx_destroy(struct ly_ctx *ctx);
 
 /** @} context */
 
diff --git a/src/schema_compile.c b/src/schema_compile.c
index ab376ec..572ea9e 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -1361,7 +1361,7 @@
 
         /* remove the module from the context and free it */
         ly_set_rm(&ctx->list, m, NULL);
-        lys_module_free(m, NULL);
+        lys_module_free(m);
     }
 
     if (unres->implementing.count) {
@@ -1545,7 +1545,7 @@
         mod = ctx->list.objs[idx];
         if (mod->compiled) {
             /* free the module */
-            lysc_module_free(mod->compiled, NULL);
+            lysc_module_free(mod->compiled);
             mod->compiled = NULL;
         }
 
@@ -1721,7 +1721,7 @@
     LOG_LOCBACK(0, 0, 1, 0);
     lys_precompile_augments_deviations_revert(ctx.ctx, mod);
     lys_compile_unres_mod_erase(&ctx, 1);
-    lysc_module_free(mod_c, NULL);
+    lysc_module_free(mod_c);
     mod->compiled = NULL;
 
     return ret;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 0840b7e..05f8bf8 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1392,7 +1392,7 @@
     goto cleanup;
 
 free_mod_cleanup:
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     if (ret) {
         mod = NULL;
     } else {
diff --git a/src/tree_schema.h b/src/tree_schema.h
index d54ac09..564be73 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -76,8 +76,8 @@
  * the ::lysc_node.priv pointers are used by libyang.
  * Note that the object is not freed by libyang when the context is being destroyed. So the caller is responsible
  * for freeing the provided structure after the context is destroyed or the private pointer is set to NULL in
- * appropriate schema nodes where the object was previously set. This can be automated via destructor function
- * to free these private objects. The destructor is passed to the ::ly_ctx_destroy() function.
+ * appropriate schema nodes where the object was previously set. Also ::lysc_tree_dfs_full() can be useful to manage
+ * the private data.
  *
  * Despite all the schema structures and their members are available as part of the libyang API and callers can use
  * it to navigate through the schema tree structure or to obtain various information, we recommend to use the following
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index c125e7f..110da25 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -927,13 +927,16 @@
     lysc_node_free_(ctx, node);
 }
 
-static void
-lysc_module_free_(struct lysc_module *module)
+void
+lysc_module_free(struct lysc_module *module)
 {
     struct ly_ctx *ctx;
     struct lysc_node *node, *node_next;
 
-    LY_CHECK_ARG_RET(NULL, module, );
+    if (!module) {
+        return;
+    }
+
     ctx = module->mod->ctx;
 
     LY_LIST_FOR_SAFE(module->data, node_next, node) {
@@ -951,28 +954,13 @@
 }
 
 void
-lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
-{
-    /* TODO use the destructor, this just suppress warning about unused parameter */
-    (void) private_destructor;
-
-    /* TODO if (module->mod->ctx->flags & LY_CTX_SET_PRIV_PARSED) is true, then
-     * don't use the destructor because private pointers are used by libyang.
-     */
-
-    if (module) {
-        lysc_module_free_(module);
-    }
-}
-
-void
-lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv))
+lys_module_free(struct lys_module *module)
 {
     if (!module) {
         return;
     }
 
-    lysc_module_free(module->compiled, private_destructor);
+    lysc_module_free(module->compiled);
     FREE_ARRAY(module->ctx, module->identities, lysc_ident_free);
     lysp_module_free(module->parsed);
 
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 8804f1b..2258c99 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -753,16 +753,14 @@
 /**
  * @brief Free the compiled schema structure.
  * @param[in,out] module Compiled schema module structure to free.
- * @param[in] private_destructor Function to remove private data from the compiled schema tree.
  */
-void lysc_module_free(struct lysc_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv));
+void lysc_module_free(struct lysc_module *module);
 
 /**
  * @brief Free the schema structure. It just frees, it does not remove the schema from its context.
  * @param[in,out] module Schema module structure to free.
- * @param[in] private_destructor Function to remove private data from the compiled schema tree.
  */
-void lys_module_free(struct lys_module *module, void (*private_destructor)(const struct lysc_node *node, void *priv));
+void lys_module_free(struct lys_module *module);
 
 /**
  * @brief match yang keyword
diff --git a/tests/fuzz/buf_add_char.c b/tests/fuzz/buf_add_char.c
index 33ca222..0f472b8 100644
--- a/tests/fuzz/buf_add_char.c
+++ b/tests/fuzz/buf_add_char.c
@@ -46,7 +46,7 @@
 
 	free(old_data);
 	free(dest);
-	ly_ctx_destroy(ctx, NULL);
+	ly_ctx_destroy(ctx);
 
 	return 0;
 }
diff --git a/tests/fuzz/lyd_parse_mem_json.c b/tests/fuzz/lyd_parse_mem_json.c
index cd4be88..912dce6 100644
--- a/tests/fuzz/lyd_parse_mem_json.c
+++ b/tests/fuzz/lyd_parse_mem_json.c
@@ -75,7 +75,7 @@
 	data[len] = 0;
 
 	lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree);
-	ly_ctx_destroy(ctx, NULL);
+	ly_ctx_destroy(ctx);
 
 	free(data);
 
diff --git a/tests/fuzz/lyd_parse_mem_xml.c b/tests/fuzz/lyd_parse_mem_xml.c
index e85d84a..f835f7f 100644
--- a/tests/fuzz/lyd_parse_mem_xml.c
+++ b/tests/fuzz/lyd_parse_mem_xml.c
@@ -75,7 +75,7 @@
 	data[len] = 0;
 
 	lyd_parse_data_mem(ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree);
-	ly_ctx_destroy(ctx, NULL);
+	ly_ctx_destroy(ctx);
 
 	free(data);
 
diff --git a/tests/fuzz/lys_parse_mem.c b/tests/fuzz/lys_parse_mem.c
index 59884f3..ea244d1 100644
--- a/tests/fuzz/lys_parse_mem.c
+++ b/tests/fuzz/lys_parse_mem.c
@@ -31,7 +31,7 @@
 	data[len] = 0;
 
 	lys_parse_mem(ctx, data, LYS_IN_YANG, NULL);
-	ly_ctx_destroy(ctx, NULL);
+	ly_ctx_destroy(ctx);
 	free(data);
 	return 0;
 }
diff --git a/tests/fuzz/yang_parse_module.c b/tests/fuzz/yang_parse_module.c
index c25a5d2..5c235a2 100644
--- a/tests/fuzz/yang_parse_module.c
+++ b/tests/fuzz/yang_parse_module.c
@@ -46,6 +46,6 @@
 
 	free(data);
 	free(mod);
-	ly_ctx_destroy(ctx, NULL);
+	ly_ctx_destroy(ctx);
 	return 0;
 }
diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c
index a66dce4..6544372 100644
--- a/tests/utests/basic/test_context.c
+++ b/tests/utests/basic/test_context.c
@@ -99,7 +99,7 @@
     assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, NULL));
 
     /* cleanup */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
 
     /* test searchdir list in ly_ctx_new() */
     assert_int_equal(LY_EINVAL, ly_ctx_new("/nonexistingfile", 0, &UTEST_LYCTX));
@@ -114,7 +114,7 @@
 test_options(void **state)
 {
     /* use own context with extra flags */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
 
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0xffff, &UTEST_LYCTX));
 
@@ -205,7 +205,7 @@
     struct lys_glob_unres unres = {0};
 
     /* use own context with extra flags */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
 
     /* invalid arguments */
     assert_int_equal(0, ly_ctx_get_change_count(NULL));
@@ -309,7 +309,7 @@
     const struct lys_module *mod1, *mod2, *import;
 
     /* use own context with extra flags */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
 
     /* import callback provides newer revision of module 'a' than present in context, so when importing 'a', the newer revision
      * from the callback should be loaded into the context and used as an import */
@@ -328,7 +328,7 @@
     assert_string_equal("2019-09-17", import->revision);
     assert_int_equal(0, import->implemented);
     assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "a", "2019-09-16"));
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
 
     /* import callback provides older revision of module 'a' than present in context, so when importing a, the newer revision
      * already present in the context should be selected and the callback's revision should not be loaded into the context */
@@ -660,7 +660,7 @@
     assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", yanglibrary_only, LYD_XML, 0, &ctx_test));
     assert_ptr_not_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-yang-library", "2019-01-04"));
     assert_null(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"));
-    ly_ctx_destroy(ctx_test, NULL);
+    ly_ctx_destroy(ctx_test);
 
     /* test loading module, should also import other module */
     assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", with_netconf, LYD_XML, 0, &ctx_test));
@@ -669,14 +669,14 @@
     assert_int_not_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14"));
     assert_int_equal(0, ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14")->implemented);
     assert_int_equal(LY_ENOT, lys_feature_value(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"), "url"));
-    ly_ctx_destroy(ctx_test, NULL);
+    ly_ctx_destroy(ctx_test);
 
     /* test loading module with feature if they are present */
     assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", with_netconf_features, LYD_XML, 0, &ctx_test));
     assert_ptr_not_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"));
     assert_ptr_not_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14"));
     assert_int_equal(LY_SUCCESS, lys_feature_value(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"), "url"));
-    ly_ctx_destroy(ctx_test, NULL);
+    ly_ctx_destroy(ctx_test);
 
     /* test with not matching revision */
     assert_int_equal(LY_EINVAL, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", garbage_revision, LYD_XML, 0, &ctx_test));
@@ -687,7 +687,7 @@
     /* test creating without ietf-yang-library */
     assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", no_yanglibrary, LYD_XML, LY_CTX_NO_YANGLIBRARY, &ctx_test));
     assert_int_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-yang-library", "2019-01-04"));
-    ly_ctx_destroy(ctx_test, NULL);
+    ly_ctx_destroy(ctx_test);
 }
 
 static LY_ERR
@@ -815,7 +815,7 @@
             "}\n";
 
     /* use own context with extra flags */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
     const char *feats[] = {"f1", NULL};
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_SET_PRIV_PARSED, &UTEST_LYCTX));
     UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, feats, NULL);
diff --git a/tests/utests/basic/test_hash_table.c b/tests/utests/basic/test_hash_table.c
index 88cabb1..6643c94 100644
--- a/tests/utests/basic/test_hash_table.c
+++ b/tests/utests/basic/test_hash_table.c
@@ -55,7 +55,7 @@
     lydict_remove(UTEST_LYCTX, "test2");
 
     /* destroy dictionary - should raise warning about data presence */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
     UTEST_LYCTX = NULL;
     CHECK_LOG("String \"test1\" not freed from the dictionary, refcount 1", NULL);
 
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index b3fe51c..f9ff619 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -57,7 +57,7 @@
     assert_non_null(OUT_NODE);
 
 #define RECREATE_CTX_WITH_MODULE(CTX, MODULE) \
-    ly_ctx_destroy(CTX, NULL); \
+    ly_ctx_destroy(CTX); \
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &CTX)); \
     assert_int_equal(LY_SUCCESS, ly_in_new_memory(MODULE, &_UC->in)); \
     assert_int_equal(LY_SUCCESS, lys_parse(CTX, _UC->in, LYS_IN_YANG, NULL, NULL)); \
@@ -258,7 +258,7 @@
     lyd_free_all(tree2);
 
     /* clean up */
-    ly_ctx_destroy(ctx2, NULL);
+    ly_ctx_destroy(ctx2);
     _UC->in = NULL;
 }
 
diff --git a/tests/utests/schema/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
index a67deed..5f29c27 100644
--- a/tests/utests/schema/test_parser_yang.c
+++ b/tests/utests/schema/test_parser_yang.c
@@ -100,7 +100,7 @@
 static int
 teardown(void **state)
 {
-    lys_module_free(YCTX->parsed_mod->mod, NULL);
+    lys_module_free(YCTX->parsed_mod->mod);
     LOG_LOCBACK(0, 0, 0, 1);
 
     free(YCTX);
@@ -546,7 +546,7 @@
 {
     struct ly_ctx *ly_ctx = ctx->parsed_mod->mod->ctx;
 
-    lys_module_free(ctx->parsed_mod->mod, NULL);
+    lys_module_free(ctx->parsed_mod->mod);
     ctx->parsed_mod = calloc(1, sizeof *ctx->parsed_mod);
     ctx->parsed_mod->mod = calloc(1, sizeof *ctx->parsed_mod->mod);
     ctx->parsed_mod->mod->parsed = ctx->parsed_mod;
@@ -562,7 +562,7 @@
 {
     struct ly_ctx *ly_ctx = ctx->parsed_mod->mod->ctx;
 
-    lys_module_free(ctx->parsed_mod->mod, NULL);
+    lys_module_free(ctx->parsed_mod->mod);
     ctx->parsed_mod = calloc(1, sizeof(struct lysp_submodule));
     ctx->parsed_mod->mod = calloc(1, sizeof *ctx->parsed_mod->mod);
     lydict_insert(ly_ctx, "name", 0, &ctx->parsed_mod->mod->name);
@@ -764,7 +764,7 @@
     assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     CHECK_LOG_CTX("Trailing garbage \"module q {names...\" after module, expected end-of-input.", "Line number 1.");
     yang_parser_ctx_free(ctx_p);
-    lys_module_free(m, NULL);
+    lys_module_free(m);
 
     in.current = "prefix " SCHEMA_BEGINNING "}";
     m = calloc(1, sizeof *m);
@@ -772,7 +772,7 @@
     assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     CHECK_LOG_CTX("Invalid keyword \"prefix\", expected \"module\" or \"submodule\".", "Line number 1.");
     yang_parser_ctx_free(ctx_p);
-    lys_module_free(m, NULL);
+    lys_module_free(m);
 
     in.current = "module " SCHEMA_BEGINNING "leaf enum {type enumeration {enum seven { position 7;}}}}";
     m = calloc(1, sizeof *m);
@@ -780,7 +780,7 @@
     assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, &in, m, &unres));
     CHECK_LOG_CTX("Invalid keyword \"position\" as a child of \"enum\".", "Line number 1.");
     yang_parser_ctx_free(ctx_p);
-    lys_module_free(m, NULL);
+    lys_module_free(m);
 
     /* extensions */
     TEST_GENERIC("prefix:test;}", mod->exts,
diff --git a/tests/utests/schema/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
index 7c726ff..c283570 100644
--- a/tests/utests/schema/test_parser_yin.c
+++ b/tests/utests/schema/test_parser_yin.c
@@ -158,7 +158,7 @@
 teardown_ctx(void **UNUSED(state))
 {
     lyxml_ctx_free(YCTX->xmlctx);
-    lys_module_free(YCTX->parsed_mod->mod, NULL);
+    lys_module_free(YCTX->parsed_mod->mod);
     free(YCTX);
     YCTX = NULL;
 
@@ -3422,7 +3422,7 @@
 {
     struct ly_ctx *ly_ctx = ctx->parsed_mod->mod->ctx;
 
-    lys_module_free(ctx->parsed_mod->mod, NULL);
+    lys_module_free(ctx->parsed_mod->mod);
     ctx->parsed_mod = calloc(1, sizeof *ctx->parsed_mod);
     ctx->parsed_mod->mod = calloc(1, sizeof *ctx->parsed_mod->mod);
     ctx->parsed_mod->mod->parsed = ctx->parsed_mod;
@@ -3550,7 +3550,7 @@
 {
     struct ly_ctx *ly_ctx = ctx->parsed_mod->mod->ctx;
 
-    lys_module_free(ctx->parsed_mod->mod, NULL);
+    lys_module_free(ctx->parsed_mod->mod);
     ctx->parsed_mod = calloc(1, sizeof(struct lysp_submodule));
     ctx->parsed_mod->mod = calloc(1, sizeof *ctx->parsed_mod->mod);
     lydict_insert(ly_ctx, belongs_to, 0, &ctx->parsed_mod->mod->name);
@@ -3710,7 +3710,7 @@
     assert_null(mod->parsed->exts->child->next->child);
     assert_string_equal(mod->parsed->exts->child->next->arg, "test");
     lys_compile_unres_glob_erase(UTEST_LYCTX, &unres);
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
     mod = NULL;
@@ -3749,7 +3749,7 @@
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
     assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_SUCCESS);
     lys_compile_unres_glob_erase(UTEST_LYCTX, &unres);
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
     mod = NULL;
@@ -3765,7 +3765,7 @@
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
     assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_SUCCESS);
     lys_compile_unres_glob_erase(UTEST_LYCTX, &unres);
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
     mod = NULL;
@@ -3778,7 +3778,7 @@
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
     assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_EINVAL);
     CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL);
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
 
@@ -3793,7 +3793,7 @@
     assert_int_equal(ly_in_new_memory(data, &in), LY_SUCCESS);
     assert_int_equal(yin_parse_module(&yin_ctx, in, mod, &unres), LY_EVALID);
     CHECK_LOG_CTX("Trailing garbage \"<module>\" after module, expected end-of-input.", "Line number 6.");
-    lys_module_free(mod, NULL);
+    lys_module_free(mod);
     yin_parser_ctx_free(yin_ctx);
     ly_in_free(in, 0);
     mod = NULL;
diff --git a/tests/utests/schema/test_schema_extensions.c b/tests/utests/schema/test_schema_extensions.c
index 7c15773..a2dad63 100644
--- a/tests/utests/schema/test_schema_extensions.c
+++ b/tests/utests/schema/test_schema_extensions.c
@@ -89,7 +89,7 @@
     free(printed);
 
     /* context reset */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
     ly_ctx_new(NULL, 0, &UTEST_LYCTX);
 
     /* from YIN */
@@ -191,7 +191,7 @@
     free(printed);
 
     /* context reset */
-    ly_ctx_destroy(UTEST_LYCTX, NULL);
+    ly_ctx_destroy(UTEST_LYCTX);
     ly_ctx_new(NULL, 0, &UTEST_LYCTX);
 
     /* from YIN */
diff --git a/tests/utests/utests.h b/tests/utests/utests.h
index e7d9da7..b606874 100644
--- a/tests/utests/utests.h
+++ b/tests/utests/utests.h
@@ -1296,7 +1296,7 @@
     *state = NULL;
 
     /* libyang context */
-    ly_ctx_destroy(current_utest_context->ctx, NULL);
+    ly_ctx_destroy(current_utest_context->ctx);
 
     /* utest context */
     ly_in_free(current_utest_context->in, 0);
diff --git a/tools/lint/cmd_clear.c b/tools/lint/cmd_clear.c
index 2a8a903..ccf6bdd 100644
--- a/tools/lint/cmd_clear.c
+++ b/tools/lint/cmd_clear.c
@@ -78,7 +78,7 @@
         goto cleanup;
     }
 
-    ly_ctx_destroy(*ctx, NULL);
+    ly_ctx_destroy(*ctx);
     *ctx = ctx_new;
 
 cleanup:
diff --git a/tools/lint/main.c b/tools/lint/main.c
index 280df8c..9f0d027 100644
--- a/tools/lint/main.c
+++ b/tools/lint/main.c
@@ -96,7 +96,7 @@
     }
 
     store_config();
-    ly_ctx_destroy(ctx, NULL);
+    ly_ctx_destroy(ctx);
 
     return 0;
 }
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index cbf0d0f..dd712ab 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -100,7 +100,7 @@
     ly_set_erase(&c->searchpaths, NULL);
 
     ly_out_free(c->out, NULL,  0);
-    ly_ctx_destroy(c->ctx, NULL);
+    ly_ctx_destroy(c->ctx);
 }
 
 static void
diff --git a/tools/re/main.c b/tools/re/main.c
index 701b0a1..9bc5cdf 100644
--- a/tools/re/main.c
+++ b/tools/re/main.c
@@ -294,7 +294,7 @@
     }
 
 cleanup:
-    ly_ctx_destroy(ctx, NULL);
+    ly_ctx_destroy(ctx);
     for (i = 0; i < patterns_count; i++) {
         free(patterns[i]);
     }