libyang FEATURE new flags for schema nodes in operations

Fixes #1372
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 2d70b8d..643d144 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1628,7 +1628,7 @@
     }
 
     /* resolve it on schema tree */
-    ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, lysc_is_output(ctx_node) ?
+    ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, (ctx_node->flags & LYS_IS_OUTPUT) ?
             LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, unres, &path);
     if (ret) {
         rc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, value);
diff --git a/src/printer_lyb.c b/src/printer_lyb.c
index 3b5b901..83730f8 100644
--- a/src/printer_lyb.c
+++ b/src/printer_lyb.c
@@ -129,7 +129,7 @@
     LY_CHECK_ERR_RET(!ht, LOGMEM(sibling->module->ctx), LY_EMEM);
 
     getnext_opts = 0;
-    if (sibling->flags & LYS_CONFIG_R) {
+    if (sibling->flags & LYS_IS_OUTPUT) {
         getnext_opts = LYS_GETNEXT_OUTPUT;
     }
 
@@ -853,7 +853,7 @@
     if (!*sibling_ht) {
         /* get first schema data sibling */
         first_sibling = (struct lysc_node *)lys_getnext(NULL, lysc_data_parent(schema), schema->module->compiled,
-                (schema->flags & LYS_CONFIG_R) ? LYS_GETNEXT_OUTPUT : 0);
+                (schema->flags & LYS_IS_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0);
         LY_ARRAY_FOR(lybctx->sib_hts, u) {
             if (lybctx->sib_hts[u].first_sibling == first_sibling) {
                 /* we have already created a hash table for these siblings */
diff --git a/src/schema_compile.c b/src/schema_compile.c
index bf8fc29..6891ef2 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -927,20 +927,12 @@
     struct lysc_when **whens = NULL;
     struct lysc_must *musts = NULL;
     LY_ERR ret = LY_SUCCESS;
-    const struct lysc_node *op;
     const struct lys_module *mod;
 
     LOG_LOCSET(node, NULL, NULL, NULL);
 
     memset(&tmp_set, 0, sizeof tmp_set);
-    opts = LYXP_SCNODE_SCHEMA;
-    if (node->flags & LYS_CONFIG_R) {
-        for (op = node->parent; op && !(op->nodetype & (LYS_RPC | LYS_ACTION)); op = op->parent) {}
-        if (op) {
-            /* we are actually in output */
-            opts = LYXP_SCNODE_OUTPUT;
-        }
-    }
+    opts = LYXP_SCNODE_SCHEMA | ((node->flags & LYS_IS_OUTPUT) ? LYXP_SCNODE_OUTPUT : 0);
 
     whens = lysc_node_when(node);
     musts = lysc_node_musts(node);
@@ -1059,16 +1051,16 @@
 lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, struct lysc_type_leafref *lref,
         struct lys_glob_unres *unres)
 {
-    const struct lysc_node *target = NULL, *siter;
+    const struct lysc_node *target = NULL;
     struct ly_path *p;
     struct lysc_type *type;
 
     assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
 
     /* try to find the target */
-    LY_CHECK_RET(ly_path_compile(ctx->ctx, lref->cur_mod, node, lref->path, LY_PATH_LREF_TRUE, lysc_is_output(node) ?
-            LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_PREF_SCHEMA_RESOLVED, lref->prefixes,
-            unres, &p));
+    LY_CHECK_RET(ly_path_compile(ctx->ctx, lref->cur_mod, node, lref->path, LY_PATH_LREF_TRUE,
+            (node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
+            LY_PREF_SCHEMA_RESOLVED, lref->prefixes, unres, &p));
 
     /* get the target node */
     target = p[LY_ARRAY_COUNT(p) - 1].node;
@@ -1092,8 +1084,7 @@
 
     /* check config */
     if (lref->require_instance) {
-        for (siter = node->parent; siter && !(siter->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); siter = siter->parent) {}
-        if (!siter && (node->flags & LYS_CONFIG_W) && (target->flags & LYS_CONFIG_R)) {
+        if ((node->flags & LYS_CONFIG_W) && (target->flags & LYS_CONFIG_R)) {
             LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target is supposed"
                     " to represent configuration data (as the leafref does), but it does not.", lref->path->expr);
             return LY_EVALID;
diff --git a/src/schema_compile.h b/src/schema_compile.h
index 17f8105..1a30037 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -37,10 +37,9 @@
  *
  * @{
  */
-#define LYS_COMPILE_RPC_INPUT       LYS_CONFIG_W    /**< Internal option when compiling schema tree of RPC/action input */
-#define LYS_COMPILE_RPC_OUTPUT      LYS_CONFIG_R    /**< Internal option when compiling schema tree of RPC/action output */
-#define LYS_COMPILE_RPC_MASK        LYS_CONFIG_MASK /**< mask for the internal RPC options */
-#define LYS_COMPILE_NOTIFICATION    0x04            /**< Internal option when compiling schema tree of Notification */
+#define LYS_COMPILE_RPC_INPUT       LYS_IS_INPUT    /**< Internal option when compiling schema tree of RPC/action input */
+#define LYS_COMPILE_RPC_OUTPUT      LYS_IS_OUTPUT   /**< Internal option when compiling schema tree of RPC/action output */
+#define LYS_COMPILE_NOTIFICATION    LYS_IS_NOTIF    /**< Internal option when compiling schema tree of Notification */
 
 #define LYS_COMPILE_GROUPING        0x08            /**< Compiling (validation) of a non-instantiated grouping.
                                                       In this case not all the restrictions are checked since they can
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index e64b54d..9d26abe 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -1274,7 +1274,7 @@
         DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
         DUP_STRING_GOTO(ctx->ctx, enums_p[u].dsc, e->dsc, ret, done);
         DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
-        e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) | (basetype == LY_TYPE_ENUM ? LYS_ISENUM : 0);
+        e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) | (basetype == LY_TYPE_ENUM ? LYS_IS_ENUM : 0);
         if (basetype == LY_TYPE_ENUM) {
             e->value = cur_val;
         } else {
@@ -2029,7 +2029,7 @@
     }
 
     getnext_flags = LYS_GETNEXT_WITHCHOICE;
-    if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION)) && (exclude->flags & LYS_CONFIG_R)) {
+    if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION)) && (exclude->flags & LYS_IS_OUTPUT)) {
         getnext_flags |= LYS_GETNEXT_OUTPUT;
     }
 
@@ -2211,10 +2211,10 @@
 }
 
 /**
- * @brief Set config flags for a node.
+ * @brief Set config and operation flags for a node.
  *
  * @param[in] ctx Compile context.
- * @param[in] node Compiled node config to set.
+ * @param[in] node Compiled node flags to set.
  * @param[in] parent Parent of @p node.
  * @return LY_ERR value.
  */
@@ -2230,11 +2230,11 @@
     } else if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
         /* ignore config statements inside RPC/action data */
         node->flags &= ~LYS_CONFIG_MASK;
-        node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
+        node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_IS_INPUT : LYS_IS_OUTPUT;
     } else if (ctx->options & LYS_COMPILE_NOTIFICATION) {
         /* ignore config statements inside Notification data */
         node->flags &= ~LYS_CONFIG_MASK;
-        node->flags |= LYS_CONFIG_R;
+        node->flags |= LYS_IS_NOTIF;
     } else if (!(node->flags & LYS_CONFIG_MASK)) {
         /* config not explicitly set, inherit it from parent */
         if (parent) {
@@ -2249,8 +2249,7 @@
     }
 
     if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
-        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
-                "Configuration node cannot be child of any state data node.");
+        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Configuration node cannot be child of any state data node.");
         return LY_EVALID;
     }
 
@@ -2294,7 +2293,7 @@
 
     /* list ordering */
     if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
-        if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
+        if ((node->flags & (LYS_CONFIG_R | LYS_IS_OUTPUT | LYS_IS_NOTIF)) && (node->flags & LYS_ORDBY_MASK)) {
             LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
                     (ctx->options & LYS_COMPILE_RPC_OUTPUT) ? "RPC/action output parameters" :
                     (ctx->options & LYS_COMPILE_NOTIFICATION) ? "notification content" : "state data", ctx->path);
@@ -3261,7 +3260,8 @@
         LY_CHECK_GOTO(ret, done);
     }
 
-    if (!(ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) && (any->flags & LYS_CONFIG_W)) {
+    if (!(ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT | LYS_COMPILE_NOTIFICATION)) &&
+            (any->flags & LYS_CONFIG_W)) {
         LOGWRN(ctx->ctx, "Use of %s to define configuration data is not recommended. %s",
                 ly_stmt2str(any->nodetype == LYS_ANYDATA ? LY_STMT_ANYDATA : LY_STMT_ANYXML), ctx->path);
     }
@@ -3736,20 +3736,20 @@
         break;
     case LYS_RPC:
     case LYS_ACTION:
-        if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+        if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT | LYS_COMPILE_NOTIFICATION)) {
             LOGVAL(ctx->ctx, LYVE_SEMANTICS,
                     "Action \"%s\" is placed inside %s.", pnode->name,
-                    ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
+                    ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT) ? "another RPC/action" : "notification");
             return LY_EVALID;
         }
         node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_action));
         node_compile_spec = lys_compile_node_action;
         break;
     case LYS_NOTIF:
-        if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+        if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT | LYS_COMPILE_NOTIFICATION)) {
             LOGVAL(ctx->ctx, LYVE_SEMANTICS,
                     "Notification \"%s\" is placed inside %s.", pnode->name,
-                    ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
+                    ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT) ? "RPC/action" : "another notification");
             return LY_EVALID;
         }
         node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_notif));
diff --git a/src/tree_data.c b/src/tree_data.c
index 93e3d99..01218b3 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1485,7 +1485,7 @@
         struct lyd_node **diff)
 {
     LY_ERR ret;
-    const struct lysc_node *iter = NULL, *sp;
+    const struct lysc_node *iter = NULL;
     struct lyd_node *node = NULL;
     struct lyd_value **dflts;
     LY_ARRAY_COUNT_TYPE u;
@@ -1497,13 +1497,6 @@
         sparent = parent->schema;
     }
 
-    for (sp = sparent; sp && !(sp->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); sp = sp->parent) {}
-    if (sp) {
-        /* these options lose meaning in operations and could cause skipping some nodes
-         * (because LYS_CONFIG* flags are set in the schema nodes with a different meaning) */
-        impl_opts &= ~(LYD_IMPLICIT_NO_STATE | LYD_IMPLICIT_NO_CONFIG);
-    }
-
     getnext_opts = LYS_GETNEXT_WITHCHOICE;
     if (impl_opts & LYD_IMPLICIT_OUTPUT) {
         getnext_opts |= LYS_GETNEXT_OUTPUT;
@@ -1746,7 +1739,7 @@
     }
 
     getnext_opts = 0;
-    if (new_node->schema->flags & LYS_CONFIG_R) {
+    if (new_node->schema->flags & LYS_IS_OUTPUT) {
         getnext_opts = LYS_GETNEXT_OUTPUT;
     }
 
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 25325e3..031dc33 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -141,17 +141,7 @@
         /* get know where to start */
         if (parent) {
             /* schema subtree */
-            if ((parent->nodetype == LYS_CHOICE) && (options & LYS_GETNEXT_WITHCASE)) {
-                if (((struct lysc_node_choice *)parent)->cases) {
-                    next = last = (const struct lysc_node *)((struct lysc_node_choice *)parent)->cases;
-                }
-            } else {
-                snode = lysc_node_children_p(parent, (options & LYS_GETNEXT_OUTPUT) ? LYS_CONFIG_R : LYS_CONFIG_W);
-                /* do not return anything if the node does not have any children */
-                if (snode && *snode) {
-                    next = last = *snode;
-                }
-            }
+            next = last = lysc_node_children(parent, (options & LYS_GETNEXT_OUTPUT) ? LYS_IS_OUTPUT : LYS_IS_INPUT);
         } else {
             /* top level data */
             next = last = module->data;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index b5e62ce..eea2f4b 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -226,7 +226,7 @@
     } \
     if ((ELEM)->nodetype == LYS_INPUT) { \
         /* after input, get output */ \
-        (NEXT) = (struct lysc_node *)lysc_node_children((ELEM)->parent, LYS_CONFIG_R); \
+        (NEXT) = (struct lysc_node *)lysc_node_children((ELEM)->parent, LYS_IS_OUTPUT); \
     } else if ((ELEM)->nodetype == LYS_OUTPUT) { \
         /* no sibling of output */ \
         (NEXT) = NULL; \
@@ -829,12 +829,18 @@
  *       9 LYS_KEY          | | |x| | | | | | | | | | | |
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *      10 LYS_SET_DFLT     | | |x|x| | |x| | | | | | | |
- *         LYS_ISENUM       | | | | | | | | | | | | |x| |
+ *         LYS_IS_ENUM      | | | | | | | | | | | | |x| |
  *         LYS_KEYLESS      | | | | |x| | | | | | | | | |
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *      11 LYS_SET_UNITS    | | |x|x| | | | | | | | | | |
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *      12 LYS_SET_CONFIG   |x|x|x|x|x|x| | | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      13 LYS_IS_INPUT     |x|x|x|x|x|x|x| | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      14 LYS_IS_OUTPUT    |x|x|x|x|x|x|x| | | | | | | |
+ *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      15 LYS_IS_NOTIF     |x|x|x|x|x|x|x| | | | | | | |
  *     ---------------------+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  */
@@ -846,8 +852,8 @@
  *
  * @{
  */
-#define LYS_CONFIG_W     0x01        /**< config true; also set for input children nodes */
-#define LYS_CONFIG_R     0x02        /**< config false; also set for output and notification children nodes */
+#define LYS_CONFIG_W     0x01        /**< config true; */
+#define LYS_CONFIG_R     0x02        /**< config false; */
 #define LYS_CONFIG_MASK  0x03        /**< mask for config value */
 #define LYS_STATUS_CURR  0x04        /**< status current; */
 #define LYS_STATUS_DEPRC 0x08        /**< status deprecated; */
@@ -866,8 +872,8 @@
                                           containers, but also for NP containers with some meaning, applicable only to
                                           ::lysc_node_container */
 #define LYS_UNIQUE       0x80        /**< flag for leafs being part of a unique set, applicable only to ::lysc_node_leaf */
-#define LYS_KEY          0x100       /**< flag for leafs being a key of a list, applicable only to ::lysc_node_leaf */
-#define LYS_KEYLESS      0x200       /**< flag for list without any key, applicable only to ::lysc_node_list */
+#define LYS_KEY          0x0100      /**< flag for leafs being a key of a list, applicable only to ::lysc_node_leaf */
+#define LYS_KEYLESS      0x0200      /**< flag for list without any key, applicable only to ::lysc_node_list */
 #define LYS_FENABLED     0x20        /**< feature enabled flag, applicable only to ::lysp_feature. */
 #define LYS_ORDBY_SYSTEM 0x80        /**< ordered-by user lists, applicable only to ::lysc_node_leaflist/::lysp_node_leaflist and
                                           ::lysc_node_list/::lysp_node_list */
@@ -875,13 +881,13 @@
                                           ::lysc_node_list/::lysp_node_list */
 #define LYS_ORDBY_MASK   0x60        /**< mask for ordered-by values */
 #define LYS_YINELEM_TRUE 0x80        /**< yin-element true for extension's argument */
-#define LYS_YINELEM_FALSE 0x100      /**< yin-element false for extension's argument */
-#define LYS_YINELEM_MASK 0x180       /**< mask for yin-element value */
-#define LYS_USED_GRP     0x400       /**< internal flag for validating not-instantiated groupings
+#define LYS_YINELEM_FALSE 0x0100     /**< yin-element false for extension's argument */
+#define LYS_YINELEM_MASK 0x0180      /**< mask for yin-element value */
+#define LYS_USED_GRP     0x0400      /**< internal flag for validating not-instantiated groupings
                                           (resp. do not validate again the instantiated groupings). */
-#define LYS_SET_VALUE    0x200       /**< value attribute is set */
-#define LYS_SET_MIN      0x200       /**< min attribute is set */
-#define LYS_SET_MAX      0x400       /**< max attribute is set */
+#define LYS_SET_VALUE    0x0200      /**< value attribute is set */
+#define LYS_SET_MIN      0x0200      /**< min attribute is set */
+#define LYS_SET_MAX      0x0400      /**< max attribute is set */
 
 #define LYS_SET_BASE     0x0001      /**< type's flag for present base substatement */
 #define LYS_SET_BIT      0x0002      /**< type's flag for present bit substatement */
@@ -901,15 +907,21 @@
 #define LYS_SET_UNITS    0x0400      /**< flag to know if the leaf's/leaflist's units are their own (flag set) or it is taken from the type. */
 #define LYS_SET_CONFIG   0x0800      /**< flag to know if the config property was set explicitly (flag set) or it is inherited. */
 
-#define LYS_SINGLEQUOTED 0x100       /**< flag for single-quoted argument of an extension instance's substatement, only when the source is YANG */
-#define LYS_DOUBLEQUOTED 0x200       /**< flag for double-quoted argument of an extension instance's substatement, only when the source is YANG */
+#define LYS_SINGLEQUOTED 0x0100      /**< flag for single-quoted argument of an extension instance's substatement, only when the source is YANG */
+#define LYS_DOUBLEQUOTED 0x0200      /**< flag for double-quoted argument of an extension instance's substatement, only when the source is YANG */
 
-#define LYS_YIN_ATTR     0x400       /**< flag to identify YIN attribute parsed as extension's substatement, only when the source is YIN */
-#define LYS_YIN_ARGUMENT 0x800       /**< flag to identify statement representing extension's argument, only when the source is YIN */
+#define LYS_YIN_ATTR     0x0400      /**< flag to identify YIN attribute parsed as extension's substatement, only when the source is YIN */
+#define LYS_YIN_ARGUMENT 0x0800      /**< flag to identify statement representing extension's argument, only when the source is YIN */
 
 #define LYS_INTERNAL     0x1000      /**< flag to identify internal parsed statements that should not be printed */
 
-#define LYS_ISENUM       0x200       /**< flag to simply distinguish type in struct lysc_type_bitenum_item */
+#define LYS_IS_ENUM      0x0200      /**< flag to simply distinguish type in struct lysc_type_bitenum_item */
+
+#define LYS_IS_INPUT     0x1000      /**< flag for nodes that are in the subtree of an input statement */
+
+#define LYS_IS_OUTPUT    0x2000      /**< flag for nodes that are in the subtree of an output statement */
+
+#define LYS_IS_NOTIF     0x4000      /**< flag for nodes that are in the subtree of a notification statement */
 
 #define LYS_FLAGS_COMPILED_MASK 0xff /**< mask for flags that maps to the compiled structures */
 /** @} snodeflags */
@@ -2005,7 +2017,7 @@
  * @brief Get the children linked list of the given (compiled) schema node.
  *
  * @param[in] node Node to examine.
- * @param[in] flags Config flag to distinguish input (LYS_CONFIG_W) and output (LYS_CONFIG_R) child in case of RPC/action node.
+ * @param[in] flags Flag to distinguish input (LYS_IS_INPUT) and output (LYS_IS_OUTPUT) child in case of RPC/action node.
  * @return Children linked list if any,
  * @return NULL otherwise.
  */
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 47e1a99..679327f 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -881,7 +881,7 @@
                 } else if (node->nodetype == LYS_NOTIF) {
                     iter = (struct lysc_node *)lysc_node_notifs(node->parent);
                 } else {
-                    iter = (struct lysc_node *)lysc_node_children(node->parent, node->flags & LYS_CONFIG_MASK);
+                    iter = (struct lysc_node *)lysc_node_children(node->parent, node->flags & LYS_IS_OUTPUT);
                 }
                 LY_CHECK_ERR_RET(!iter, LOGINT(ctx), );
             } else if (node->nodetype == LYS_RPC) {
@@ -902,7 +902,7 @@
             } else if (node->nodetype == LYS_NOTIF) {
                 child_p = (struct lysc_node **)lysc_node_notifs_p(node->parent);
             } else {
-                child_p = lysc_node_children_p(node->parent, node->flags & LYS_CONFIG_MASK);
+                child_p = lysc_node_children_p(node->parent, node->flags & LYS_IS_OUTPUT);
             }
         } else if (node->nodetype == LYS_RPC) {
             child_p = (struct lysc_node **)&node->module->compiled->rpcs;
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 36b2c50..042798a 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1429,10 +1429,10 @@
         return &((struct lysc_node_list *)node)->child;
     case LYS_RPC:
     case LYS_ACTION:
-        if (flags & LYS_CONFIG_R) {
+        if (flags & LYS_IS_OUTPUT) {
             return &((struct lysc_node_action *)node)->output.child;
         } else {
-            /* LYS_CONFIG_W, but also the default case */
+            /* LYS_IS_INPUT, but also the default case */
             return &((struct lysc_node_action *)node)->input.child;
         }
     case LYS_INPUT:
@@ -1455,10 +1455,10 @@
     }
 
     if ((node->nodetype == LYS_RPC) || (node->nodetype == LYS_ACTION)) {
-        if (flags & LYS_CONFIG_R) {
+        if (flags & LYS_IN_OUTPUT) {
             return (struct lysc_node *)&((struct lysc_node_action *)node)->output;
         } else {
-            /* LYS_CONFIG_W, but also the default case */
+            /* LYS_IN_INPUT, but also the default case */
             return (struct lysc_node *)&((struct lysc_node_action *)node)->input;
         }
     } else {
@@ -1820,17 +1820,3 @@
 
     return parent;
 }
-
-ly_bool
-lysc_is_output(const struct lysc_node *schema)
-{
-    const struct lysc_node *parent;
-
-    assert(schema);
-
-    for (parent = schema->parent; parent && !(parent->nodetype & (LYS_RPC | LYS_ACTION)); parent = parent->parent) {}
-    if (parent && (schema->flags & LYS_CONFIG_R)) {
-        return 1;
-    }
-    return 0;
-}
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index c92269b..4828e82 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -383,7 +383,7 @@
  *
  * Decides the node's type and in case it has a children list, returns its address.
  * @param[in] node Node to check.
- * @param[in] flags Config flag to distinguish input (LYS_CONFIG_W) and output (LYS_CONFIG_R) data in case of RPC/action node.
+ * @param[in] flags Flag to distinguish input (LYS_IN_INPUT) and output (LYS_IN_OUTPUT) data in case of RPC/action node.
  * @return Address of the node's child member if any, NULL otherwise.
  */
 struct lysc_node **lysc_node_children_p(const struct lysc_node *node, uint16_t flags);
@@ -729,14 +729,6 @@
 #define lysc_data_parent(SCHEMA) lysc_data_node((SCHEMA)->parent)
 
 /**
- * @brief Learn whether a node is inside an operation output.
- *
- * @param[in] schema Schema node to examine.
- * @return Boolean value whether the node is under an operation output or not.
- */
-ly_bool lysc_is_output(const struct lysc_node *schema);
-
-/**
  * @brief Get format-specific prefix for a module.
  *
  * For type plugins available as ::ly_type_print_get_prefix().
diff --git a/src/validation.c b/src/validation.c
index 5f26751..4aa4fdb 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1231,10 +1231,10 @@
         if ((val_opts & LYD_VALIDATE_NO_STATE) && (node->schema->flags & LYS_CONFIG_R)) {
             innode = "state";
             goto invalid_node;
-        } else if ((op == LYD_VALIDATE_OP_RPC) && (node->schema->flags & LYS_CONFIG_R)) {
+        } else if ((op == LYD_VALIDATE_OP_RPC) && (node->schema->flags & LYS_IS_OUTPUT)) {
             innode = "output";
             goto invalid_node;
-        } else if ((op == LYD_VALIDATE_OP_REPLY) && (node->schema->flags & LYS_CONFIG_W)) {
+        } else if ((op == LYD_VALIDATE_OP_REPLY) && (node->schema->flags & LYS_IS_INPUT)) {
             innode = "input";
             goto invalid_node;
         }
@@ -1316,7 +1316,7 @@
                     NULL, impl_opts, diff));
         }
 
-        if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && lysc_node_when(node->schema)) {
+        if (lysc_node_when(node->schema)) {
             /* when evaluation */
             LY_CHECK_RET(ly_set_add(node_when, (void *)node, 1, NULL));
         }
diff --git a/src/xpath.c b/src/xpath.c
index 3d9a635..b08e47b 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -3700,7 +3700,7 @@
         set_scnode_clear_ctx(set);
         if (sleaf && (sleaf->type->basetype == LY_TYPE_LEAFREF)) {
             lref = (struct lysc_type_leafref *)sleaf->type;
-            oper = lysc_is_output((struct lysc_node *)sleaf) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
+            oper = (sleaf->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
 
             /* it was already evaluated on schema, it must succeed */
             rc = ly_path_compile(set->ctx, lref->cur_mod, (struct lysc_node *)sleaf, lref->path,
@@ -5858,7 +5858,7 @@
 next_iter:
             /* TREE DFS NEXT ELEM */
             /* select element for the next run - children first */
-            next = lysc_node_children(elem, options & LYXP_SCNODE_OUTPUT ? LYS_CONFIG_R : LYS_CONFIG_W);
+            next = lysc_node_children(elem, options & LYXP_SCNODE_OUTPUT ? LYS_IS_OUTPUT : LYS_IS_INPUT);
             if (!next) {
 skip_children:
                 /* no children, so try siblings, but only if it's not the start,