yin parser FEATURE support union type
diff --git a/src/parser/yin.c b/src/parser/yin.c
index a4c0f43..cc4016c 100644
--- a/src/parser/yin.c
+++ b/src/parser/yin.c
@@ -1254,8 +1254,47 @@
         break;
 
     case LY_TYPE_UNION:
-        /* TODO type, 7.4
-         * - 1..n, nerekurzivni, resp rekurzivni pro union ale bez vazby na predky, nesmi byt empty nebo leafref */
+        /* RFC 6020 7.4 - type */
+        /* count number of types in union */
+        i = 0;
+        LY_TREE_FOR(yin->child, node) {
+            if (!strcmp(node->name, "type")) {
+                i++;
+            } else {
+                LOGVAL(VE_INSTMT, LOGLINE(node), node->name);
+                goto error;
+            }
+        }
+
+        if (!i) {
+            if (type->der->type.der) {
+                /* this is just a derived type with no base specified/required */
+                break;
+            }
+            LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
+            goto error;
+        }
+
+        /* allocate array for union's types ... */
+        type->info.uni.type = calloc(i, sizeof *type->info.uni.type);
+        /* ... and fill the structures */
+        LY_TREE_FOR_SAFE(yin->child, next, node) {
+            if (fill_yin_type(module, parent, node, &type->info.uni.type[type->info.uni.count])) {
+                goto error;
+            }
+            type->info.uni.count++;
+
+            /* union's type cannot be empty or leafref */
+            if (type->info.uni.type[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
+                LOGVAL(VE_INARG, LOGLINE(node), "empty", node->name);
+                goto error;
+            } else if (type->info.uni.type[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
+                LOGVAL(VE_INARG, LOGLINE(node), "leafref", node->name);
+                goto error;
+            }
+
+            lyxml_free_elem(module->ctx, node);
+        }
         break;
 
     default:
@@ -1624,7 +1663,7 @@
     struct ly_mnode_leaf *leaf = NULL;
     struct ly_mnode_list *list = NULL;
     struct ly_type *t = NULL;
-    uint8_t *trg_must_size = 0;
+    uint8_t *trg_must_size = NULL;
     struct ly_restr **trg_must = NULL;
 
     GETVAL(value, yin, "target-node");
diff --git a/src/tree.c b/src/tree.c
index d22e36d..5f9536f 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -727,6 +727,16 @@
         new->info.str.patterns = ly_restr_dup(ctx, old->info.str.patterns, old->info.str.pat_count);
         break;
 
+    case LY_TYPE_UNION:
+        new->info.uni.count = old->info.uni.count;
+        if (new->info.uni.count) {
+            new->info.uni.type = calloc(new->info.uni.count, sizeof *new->info.uni.type);
+            for (i = 0; i < new->info.uni.count; i++) {
+                ly_type_dup(ctx, &(new->info.uni.type[i]), &(old->info.uni.type[i]));
+            }
+        }
+        break;
+
     default:
         /* TODO - remove default to make sure that all types are covered */
         break;
@@ -773,6 +783,10 @@
         free(type->info.enums.list);
         break;
 
+    case LY_TYPE_IDENT:
+        /* nothing to do */
+        break;
+
     case LY_TYPE_INT8:
     case LY_TYPE_INT16:
     case LY_TYPE_INT32:
@@ -798,8 +812,11 @@
         free(type->info.str.patterns);
         break;
 
-    case LY_TYPE_IDENT:
-        /* nothing to do */
+    case LY_TYPE_UNION:
+        for (i = 0; i < type->info.uni.count; i++) {
+            ly_type_free(ctx, &type->info.uni.type[i]);
+        }
+        free(type->info.uni.type);
         break;
 
     default: