generate runtime information object set tables
diff --git a/libasn1compiler/Makefile.am b/libasn1compiler/Makefile.am
index 86c0488..096fc2b 100644
--- a/libasn1compiler/Makefile.am
+++ b/libasn1compiler/Makefile.am
@@ -16,5 +16,6 @@
 	asn1c_C.c asn1c_C.h			\
 	asn1c_constraint.c asn1c_constraint.h	\
 	asn1c_compat.c asn1c_compat.h		\
+	asn1c_ioc.c asn1c_ioc.h		\
 	asn1c_fdeps.c asn1c_fdeps.h		\
 	asn1c_internal.h
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 2a8544f..7b30eef 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -7,6 +7,7 @@
 #include "asn1c_constraint.h"
 #include "asn1c_out.h"
 #include "asn1c_misc.h"
+#include "asn1c_ioc.h"
 #include <asn1fix_crange.h>	/* constraint groker from libasn1fix */
 #include <asn1fix_export.h>	/* other exportables from libasn1fix */
 #include <asn1parser.h>
@@ -298,90 +299,22 @@
 	return asn1c_lang_C_type_SIMPLE_TYPE(arg);
 }
 
-/*
- * Given the table constraint or component relation constraint
- * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference.
- */
-static const asn1p_ref_t *
-asn1c_get_information_object_set_reference_from_constraint(
-    const asn1p_constraint_t *ct) {
-
-    if(!ct) return NULL;
-    assert(ct->type == ACT_CA_CRC);
-    assert(ct->el_count >= 1);
-
-    assert(ct->elements[0]->type == ACT_EL_VALUE);
-
-    asn1p_value_t *val = ct->elements[0]->value;
-    assert(val->type == ATV_REFERENCED);
-
-    return val->value.reference;
-}
-
-static asn1p_ioc_table_t *
-asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
-    (void)objset_ref;
-
-    if(objset->ioc_table) {
-        return objset->ioc_table;
-    } else {
-        FATAL("Information Object Set %s contains no objects at line %d",
-              objset->Identifier, objset->_lineno);
-        errno = EINVAL;
-        return NULL;
-    }
-};
-
-static asn1p_ioc_table_t *
-asn1c_get_ioc_table(arg_t *arg) {
-    asn1p_expr_t *expr = arg->expr;
-	asn1p_expr_t *memb;
-    asn1p_expr_t *objset = 0;
-    const asn1p_ref_t *objset_ref = NULL;
-
-    TQ_FOR(memb, &(expr->members), next) {
-        const asn1p_ref_t *tmpref =
-            asn1c_get_information_object_set_reference_from_constraint(
-                asn1p_get_component_relation_constraint(memb->constraints));
-        if(tmpref) {
-            if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) {
-                FATAL(
-                    "Object set reference on line %d differs from object set "
-                    "reference on line %d",
-                    objset_ref->_lineno, tmpref->_lineno);
-                errno = EINVAL;
-                return NULL;
-            }
-            objset_ref = tmpref;
-        }
-    }
-
-    if(!objset_ref) {
-        errno = 0;  /* "Safe" error. */
-        return NULL;
-    }
-
-    objset = asn1f_lookup_symbol_ex(arg->asn, arg->expr, objset_ref);
-    if(!objset) {
-        FATAL("Cannot found %s", asn1p_ref_string(objset_ref));
-        return NULL;
-    }
-
-    return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset);
-}
-
 int
 asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
 	asn1p_expr_t *v;
 	int comp_mode = 0;	/* {root,ext=1,root,root,...} */
 	int saved_target = arg->target->target;
-    asn1p_ioc_table_t *itable = NULL;
+    asn1c_ioc_table_and_objset_t ioc_tao;
 
 	DEPENDENCIES;
 
-    itable = asn1c_get_ioc_table(arg);
-    if(!itable && errno != 0) {
+    ioc_tao = asn1c_get_ioc_table(arg);
+    if(ioc_tao.ioct) {
+        if(emit_ioc_table(arg, expr, ioc_tao)) {
+            return -1;
+        }
+    } else if(ioc_tao.fatal_error) {
         return -1;
     }
 
diff --git a/libasn1compiler/asn1c_ioc.c b/libasn1compiler/asn1c_ioc.c
new file mode 100644
index 0000000..ccb0dd3
--- /dev/null
+++ b/libasn1compiler/asn1c_ioc.c
@@ -0,0 +1,261 @@
+#include "asn1c_internal.h"
+#include "asn1c_ioc.h"
+#include "asn1c_out.h"
+#include "asn1c_misc.h"
+#include <asn1fix_export.h>
+
+/*
+ * Given the table constraint or component relation constraint
+ * ({ObjectSetName}{...}) returns "ObjectSetName" as a reference.
+ */
+static const asn1p_ref_t *
+asn1c_get_information_object_set_reference_from_constraint(
+    const asn1p_constraint_t *ct) {
+
+    if(!ct) return NULL;
+    assert(ct->type == ACT_CA_CRC);
+    assert(ct->el_count >= 1);
+
+    assert(ct->elements[0]->type == ACT_EL_VALUE);
+
+    asn1p_value_t *val = ct->elements[0]->value;
+    assert(val->type == ATV_REFERENCED);
+
+    return val->value.reference;
+}
+
+static asn1c_ioc_table_and_objset_t
+asn1c_get_ioc_table_from_objset(arg_t *arg, const asn1p_ref_t *objset_ref, asn1p_expr_t *objset) {
+    asn1c_ioc_table_and_objset_t ioc_tao = { 0, 0, 1 };
+
+    (void)objset_ref;
+
+    if(objset->ioc_table) {
+        ioc_tao.ioct = objset->ioc_table;
+        ioc_tao.objset = objset;
+        ioc_tao.fatal_error = 0;
+    } else {
+        FATAL("Information Object Set %s contains no objects at line %d",
+              objset->Identifier, objset->_lineno);
+    }
+
+    return ioc_tao;
+}
+
+asn1c_ioc_table_and_objset_t
+asn1c_get_ioc_table(arg_t *arg) {
+    asn1p_expr_t *expr = arg->expr;
+	asn1p_expr_t *memb;
+    asn1p_expr_t *objset = 0;
+    const asn1p_ref_t *objset_ref = NULL;
+    asn1c_ioc_table_and_objset_t safe_ioc_tao = {0, 0, 0};
+    asn1c_ioc_table_and_objset_t failed_ioc_tao = { 0, 0, 1 };
+
+    TQ_FOR(memb, &(expr->members), next) {
+        const asn1p_ref_t *tmpref =
+            asn1c_get_information_object_set_reference_from_constraint(
+                asn1p_get_component_relation_constraint(memb->constraints));
+        if(tmpref) {
+            if(objset_ref && asn1p_ref_compare(objset_ref, tmpref) != 0) {
+                FATAL(
+                    "Object set reference on line %d differs from object set "
+                    "reference on line %d",
+                    objset_ref->_lineno, tmpref->_lineno);
+                return failed_ioc_tao;
+            }
+            objset_ref = tmpref;
+        }
+    }
+
+    if(!objset_ref) {
+        return safe_ioc_tao;
+    }
+
+    objset = asn1f_lookup_symbol_ex(arg->asn, arg->expr, objset_ref);
+    if(!objset) {
+        FATAL("Cannot found %s", asn1p_ref_string(objset_ref));
+        return failed_ioc_tao;
+    }
+
+    return asn1c_get_ioc_table_from_objset(arg, objset_ref, objset);
+}
+
+#define MKID(expr) asn1c_make_identifier(0, (expr), 0)
+
+static int
+emit_ioc_value(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
+
+    if(cell->value && cell->value->meta_type == AMT_VALUE) {
+        const char *prim_type = NULL;
+        int primitive_representation = 0;
+
+        switch(cell->value->expr_type) {
+        case ASN_BASIC_INTEGER:
+        case ASN_BASIC_ENUMERATED:
+            switch(asn1c_type_fits_long(arg, cell->value)) {
+            case FL_NOTFIT:
+                GEN_INCLUDE_STD("INTEGER");
+                prim_type = "INTEGER_t";
+                break;
+            case FL_PRESUMED:
+            case FL_FITS_SIGNED:
+                primitive_representation = 1;
+                prim_type = "long";
+                break;
+            case FL_FITS_UNSIGN:
+                prim_type = "unsigned long";
+                primitive_representation = 1;
+                break;
+            }
+            break;
+        case ASN_BASIC_OBJECT_IDENTIFIER:
+            prim_type = "OBJECT_IDENTIFIER_t";
+            break;
+        case ASN_BASIC_RELATIVE_OID:
+            prim_type = "RELATIVE_OID_t";
+            break;
+        default: {
+            char *p = strdup(MKID(cell->value));
+            FATAL("Unsupported type %s for value %s",
+                  asn1c_type_name(arg, cell->value, TNF_UNMODIFIED), p);
+            free(p);
+            return -1;
+        }
+        }
+        OUT("static const %s asn_VAL_%s_%d = ", prim_type, MKID(cell->value),
+            cell->value->_type_unique_index);
+
+        asn1p_expr_t *expr_value = cell->value;
+        while(expr_value->value->type == ATV_REFERENCED) {
+            expr_value = asn1f_lookup_symbol_ex(
+                arg->asn, expr_value, expr_value->value->value.reference);
+            if(!expr_value) {
+                FATAL("Unrecognized value type for %s", MKID(cell->value));
+                return -1;
+            }
+        }
+
+        if(!primitive_representation) OUT("{ ");
+
+        switch(expr_value->value->type) {
+        case ATV_INTEGER:
+            if(primitive_representation) {
+                OUT("%s", asn1p_itoa(expr_value->value->value.v_integer));
+                break;
+            } else {
+                asn1c_integer_t v = expr_value->value->value.v_integer;
+                if(v >= 0) {
+                    if(v <= 127) {
+                        OUT("\"\\x%02x\", 1", v);
+                        break;
+                    } else if(v <= 32767) {
+                        OUT("\"\\x%02x\\x%02x\", 2", (v >> 8), (v & 0xff));
+                        break;
+                    }
+                }
+                FATAL("Unsupported value %s range for type %s",
+                      asn1f_printable_value(expr_value->value),
+                      MKID(cell->value));
+                return -1;
+            }
+        case ATV_UNPARSED:
+            OUT("\"not supported\", 0 };\n");
+            FATAL("Inappropriate value %s for type %s",
+                  asn1f_printable_value(expr_value->value), MKID(cell->value));
+            return 0;   /* TEMPORARY FIXME FIXME */
+        default:
+            FATAL("Inappropriate value %s for type %s",
+                  asn1f_printable_value(expr_value->value), MKID(cell->value));
+            return -1;
+        }
+
+        if(primitive_representation) {
+            OUT(";\n");
+        } else {
+            OUT(" };");
+            OUT(" /* %s */\n", asn1f_printable_value(expr_value->value));
+        }
+    }
+
+    return 0;
+}
+
+static int
+emit_ioc_cell(arg_t *arg, struct asn1p_ioc_cell_s *cell) {
+    OUT("{ \"%s\", ", cell->field->Identifier);
+
+    if(cell->value->meta_type == AMT_VALUE) {
+        GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
+        OUT("aioc__value, ");
+        OUT("&asn_DEF_%s, ", asn1c_type_name(arg, cell->value, TNF_SAFE));
+        OUT("&asn_VAL_%s_%d", MKID(cell->value),
+            cell->value->_type_unique_index);
+
+    } else if(cell->value->meta_type == AMT_TYPEREF) {
+        GEN_INCLUDE(asn1c_type_name(arg, cell->value, TNF_INCLUDE));
+        OUT("aioc__type, &asn_DEF_%s", MKID(cell->value));
+    } else {
+        return -1;
+    }
+
+    OUT(" }");
+
+    return 0;
+}
+
+/*
+ * Refer to skeletons/asn_ioc.h
+ */
+int
+emit_ioc_table(arg_t *arg, asn1p_expr_t *context, asn1c_ioc_table_and_objset_t ioc_tao) {
+    size_t columns = 0;
+
+    (void)context;
+    GEN_INCLUDE_STD("asn_ioc");
+
+    REDIR(OT_STAT_DEFS);
+
+    /* Emit values that are used in the Information Object Set table first */
+    for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
+        asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
+        for(size_t cn = 0; cn < row->columns; cn++) {
+            if(emit_ioc_value(arg, &row->column[cn])) {
+                return -1;
+            }
+        }
+    }
+
+    /* Emit the Information Object Set */
+    OUT("static const asn_ioc_cell_t asn_IOS_%s_%d_rows[] = {\n",
+        MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
+    INDENT(+1);
+
+    for(size_t rn = 0; rn < ioc_tao.ioct->rows; rn++) {
+        asn1p_ioc_row_t *row = ioc_tao.ioct->row[rn];
+        columns = columns ? columns : row->columns;
+        if(columns != row->columns) {
+            FATAL("Information Object Set %s row column mismatch on line %d",
+                  ioc_tao.objset->Identifier, ioc_tao.objset->_lineno);
+            return -1;
+        }
+        for(size_t cn = 0; cn < row->columns; cn++) {
+            if(rn || cn) OUT(",\n");
+            emit_ioc_cell(arg, &row->column[cn]);
+        }
+    }
+    OUT("\n");
+
+    INDENT(-1);
+    OUT("};\n");
+
+    OUT("static asn_ioc_set_t asn_IOS_%s_%d[] = {\n", MKID(ioc_tao.objset),
+        ioc_tao.objset->_type_unique_index);
+    INDENT(+1);
+    OUT("%zu, %zu, asn_IOS_%s_%d_rows\n", ioc_tao.ioct->rows, columns,
+        MKID(ioc_tao.objset), ioc_tao.objset->_type_unique_index);
+    INDENT(-1);
+    OUT("};\n");
+
+    return 0;
+}
+
diff --git a/libasn1compiler/asn1c_ioc.h b/libasn1compiler/asn1c_ioc.h
new file mode 100644
index 0000000..face3a1
--- /dev/null
+++ b/libasn1compiler/asn1c_ioc.h
@@ -0,0 +1,19 @@
+#ifndef	ASN1_IOC_H
+#define	ASN1_IOC_H
+
+#include "asn1compiler.h"
+#include "asn1p_class.h"
+
+typedef struct asn1c_ioc_table_and_objset_s {
+    asn1p_ioc_table_t *ioct;
+    asn1p_expr_t *objset;
+    int fatal_error; /* if ioct == NULL then specifies error or 0. */
+} asn1c_ioc_table_and_objset_t;
+
+asn1c_ioc_table_and_objset_t asn1c_get_ioc_table(arg_t *arg);
+
+int emit_ioc_table(arg_t *arg, asn1p_expr_t *context,
+                    asn1c_ioc_table_and_objset_t);
+
+
+#endif	/* ASN1_IOC_H */
diff --git a/skeletons/asn_ioc.h b/skeletons/asn_ioc.h
new file mode 100644
index 0000000..0a5d013
--- /dev/null
+++ b/skeletons/asn_ioc.h
@@ -0,0 +1,50 @@
+/*
+ * Run-time support for Information Object Classes.
+ * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are oermitted subject to BSD license.
+ */
+#ifndef	ASN_IOC_H
+#define	ASN_IOC_H
+
+#include <asn_system.h>		/* Platform-specific types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asn_TYPE_descriptor_s;
+struct asn_ioc_cell_s;
+
+/*
+ * X.681, #13
+ */
+struct asn_ioc_set_s {
+    size_t rows_count;
+    size_t columns_count;
+    struct asn_ioc_set_cell_s *rows;
+} asn_ioc_set_t;
+
+
+typedef struct asn_ioc_cell_s {
+    const char *field_name; /* Is equal to corresponding column_name */
+    enum {
+        aioc__value,
+        aioc__type,
+        aioc__open_type,
+    } cell_kind;
+    struct asn_TYPE_descriptor_s *type_descriptor;
+    const void *value_sptr;
+    struct {
+        size_t types_count;
+        struct {
+            unsigned choice_position;
+        } *types;
+    } open_type;
+} asn_ioc_cell_s;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* ASN_IOC_H */
diff --git a/tests/139-component-relation-OK.asn1.-P b/tests/139-component-relation-OK.asn1.-P
new file mode 100644
index 0000000..bddcb14
--- /dev/null
+++ b/tests/139-component-relation-OK.asn1.-P
@@ -0,0 +1,259 @@
+
+/*** <<< INCLUDES [Frame] >>> ***/
+
+#include <NativeInteger.h>
+#include <ANY.h>
+#include <asn_ioc.h>
+#include "PrimitiveMessage.h"
+#include "ComplexMessage.h"
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [Frame] >>> ***/
+
+typedef struct Frame {
+	long	 ident;
+	ANY_t	 value;
+	/*
+	 * This type is extensible,
+	 * possible extensions are below.
+	 */
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} Frame_t;
+
+/*** <<< FUNC-DECLS [Frame] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_Frame;
+
+/*** <<< CODE [Frame] >>> ***/
+
+static int
+memb_ident_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+	
+	
+	if(1 /* No applicable constraints whatsoever */) {
+		/* Nothing is here. See below */
+	}
+	
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+static int
+memb_value_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+	
+	
+	if(1 /* No applicable constraints whatsoever */) {
+		/* Nothing is here. See below */
+	}
+	
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+
+/*** <<< STAT-DEFS [Frame] >>> ***/
+
+static const long asn_VAL_basicMessage_0 = 1;
+static const long asn_VAL_2_0 = 2;
+static const asn_ioc_cell_t asn_IOS_FrameTypes_1_rows[] = {
+	{ "&id", aioc__value, &asn_DEF_NativeInteger, &asn_VAL_basicMessage_0 },
+	{ "&Type", aioc__type, &asn_DEF_PrimitiveMessage },
+	{ "&id", aioc__value, &asn_DEF_NativeInteger, &asn_VAL_2_0 },
+	{ "&Type", aioc__type, &asn_DEF_ComplexMessage }
+};
+static asn_ioc_set_t asn_IOS_FrameTypes_1[] = {
+	2, 2, asn_IOS_FrameTypes_1_rows
+};
+static asn_TYPE_member_t asn_MBR_Frame_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct Frame, ident),
+		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
+		.tag_mode = 0,
+		.type = &asn_DEF_NativeInteger,
+		.memb_constraints = memb_ident_constraint_1,
+		.oer_constraints = 0,	/* OER is not compiled, use -gen-OER */
+		.per_constraints = 0,	/* PER is not compiled, use -gen-PER */
+		.default_value = 0,
+		.name = "ident"
+		},
+	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct Frame, value),
+		.tag = -1 /* Ambiguous tag (ANY?) */,
+		.tag_mode = 0,
+		.type = &asn_DEF_ANY,
+		.memb_constraints = memb_value_constraint_1,
+		.oer_constraints = 0,	/* OER is not compiled, use -gen-OER */
+		.per_constraints = 0,	/* PER is not compiled, use -gen-PER */
+		.default_value = 0,
+		.name = "value"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_Frame_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_Frame_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 } /* ident */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_Frame_specs_1 = {
+	sizeof(struct Frame),
+	offsetof(struct Frame, _asn_ctx),
+	asn_MAP_Frame_tag2el_1,
+	1,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	1,	/* Start extensions */
+	3	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_Frame = {
+	"Frame",
+	"Frame",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_Frame_tags_1,
+	sizeof(asn_DEF_Frame_tags_1)
+		/sizeof(asn_DEF_Frame_tags_1[0]), /* 1 */
+	asn_DEF_Frame_tags_1,	/* Same as above */
+	sizeof(asn_DEF_Frame_tags_1)
+		/sizeof(asn_DEF_Frame_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	asn_MBR_Frame_1,
+	2,	/* Elements count */
+	&asn_SPC_Frame_specs_1	/* Additional specs */
+};
+
+
+/*** <<< INCLUDES [PrimitiveMessage] >>> ***/
+
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [PrimitiveMessage] >>> ***/
+
+typedef struct PrimitiveMessage {
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} PrimitiveMessage_t;
+
+/*** <<< FUNC-DECLS [PrimitiveMessage] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_PrimitiveMessage;
+extern asn_SEQUENCE_specifics_t asn_SPC_PrimitiveMessage_specs_1;
+
+/*** <<< STAT-DEFS [PrimitiveMessage] >>> ***/
+
+static const ber_tlv_tag_t asn_DEF_PrimitiveMessage_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SEQUENCE_specifics_t asn_SPC_PrimitiveMessage_specs_1 = {
+	sizeof(struct PrimitiveMessage),
+	offsetof(struct PrimitiveMessage, _asn_ctx),
+	0,	/* No top level tags */
+	0,	/* No tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_PrimitiveMessage = {
+	"PrimitiveMessage",
+	"PrimitiveMessage",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_PrimitiveMessage_tags_1,
+	sizeof(asn_DEF_PrimitiveMessage_tags_1)
+		/sizeof(asn_DEF_PrimitiveMessage_tags_1[0]), /* 1 */
+	asn_DEF_PrimitiveMessage_tags_1,	/* Same as above */
+	sizeof(asn_DEF_PrimitiveMessage_tags_1)
+		/sizeof(asn_DEF_PrimitiveMessage_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_SPC_PrimitiveMessage_specs_1	/* Additional specs */
+};
+
+
+/*** <<< INCLUDES [ComplexMessage] >>> ***/
+
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [ComplexMessage] >>> ***/
+
+typedef struct ComplexMessage {
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} ComplexMessage_t;
+
+/*** <<< FUNC-DECLS [ComplexMessage] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_ComplexMessage;
+extern asn_SEQUENCE_specifics_t asn_SPC_ComplexMessage_specs_1;
+
+/*** <<< STAT-DEFS [ComplexMessage] >>> ***/
+
+static const ber_tlv_tag_t asn_DEF_ComplexMessage_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SEQUENCE_specifics_t asn_SPC_ComplexMessage_specs_1 = {
+	sizeof(struct ComplexMessage),
+	offsetof(struct ComplexMessage, _asn_ctx),
+	0,	/* No top level tags */
+	0,	/* No tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_ComplexMessage = {
+	"ComplexMessage",
+	"ComplexMessage",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_ComplexMessage_tags_1,
+	sizeof(asn_DEF_ComplexMessage_tags_1)
+		/sizeof(asn_DEF_ComplexMessage_tags_1[0]), /* 1 */
+	asn_DEF_ComplexMessage_tags_1,	/* Same as above */
+	sizeof(asn_DEF_ComplexMessage_tags_1)
+		/sizeof(asn_DEF_ComplexMessage_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_SPC_ComplexMessage_specs_1	/* Additional specs */
+};
+
diff --git a/tests/140-component-relation-OK.asn1.-P b/tests/140-component-relation-OK.asn1.-P
new file mode 100644
index 0000000..bddcb14
--- /dev/null
+++ b/tests/140-component-relation-OK.asn1.-P
@@ -0,0 +1,259 @@
+
+/*** <<< INCLUDES [Frame] >>> ***/
+
+#include <NativeInteger.h>
+#include <ANY.h>
+#include <asn_ioc.h>
+#include "PrimitiveMessage.h"
+#include "ComplexMessage.h"
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [Frame] >>> ***/
+
+typedef struct Frame {
+	long	 ident;
+	ANY_t	 value;
+	/*
+	 * This type is extensible,
+	 * possible extensions are below.
+	 */
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} Frame_t;
+
+/*** <<< FUNC-DECLS [Frame] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_Frame;
+
+/*** <<< CODE [Frame] >>> ***/
+
+static int
+memb_ident_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+	
+	
+	if(1 /* No applicable constraints whatsoever */) {
+		/* Nothing is here. See below */
+	}
+	
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+static int
+memb_value_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
+			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
+	
+	if(!sptr) {
+		ASN__CTFAIL(app_key, td, sptr,
+			"%s: value not given (%s:%d)",
+			td->name, __FILE__, __LINE__);
+		return -1;
+	}
+	
+	
+	if(1 /* No applicable constraints whatsoever */) {
+		/* Nothing is here. See below */
+	}
+	
+	return td->check_constraints(td, sptr, ctfailcb, app_key);
+}
+
+
+/*** <<< STAT-DEFS [Frame] >>> ***/
+
+static const long asn_VAL_basicMessage_0 = 1;
+static const long asn_VAL_2_0 = 2;
+static const asn_ioc_cell_t asn_IOS_FrameTypes_1_rows[] = {
+	{ "&id", aioc__value, &asn_DEF_NativeInteger, &asn_VAL_basicMessage_0 },
+	{ "&Type", aioc__type, &asn_DEF_PrimitiveMessage },
+	{ "&id", aioc__value, &asn_DEF_NativeInteger, &asn_VAL_2_0 },
+	{ "&Type", aioc__type, &asn_DEF_ComplexMessage }
+};
+static asn_ioc_set_t asn_IOS_FrameTypes_1[] = {
+	2, 2, asn_IOS_FrameTypes_1_rows
+};
+static asn_TYPE_member_t asn_MBR_Frame_1[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct Frame, ident),
+		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
+		.tag_mode = 0,
+		.type = &asn_DEF_NativeInteger,
+		.memb_constraints = memb_ident_constraint_1,
+		.oer_constraints = 0,	/* OER is not compiled, use -gen-OER */
+		.per_constraints = 0,	/* PER is not compiled, use -gen-PER */
+		.default_value = 0,
+		.name = "ident"
+		},
+	{ ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct Frame, value),
+		.tag = -1 /* Ambiguous tag (ANY?) */,
+		.tag_mode = 0,
+		.type = &asn_DEF_ANY,
+		.memb_constraints = memb_value_constraint_1,
+		.oer_constraints = 0,	/* OER is not compiled, use -gen-OER */
+		.per_constraints = 0,	/* PER is not compiled, use -gen-PER */
+		.default_value = 0,
+		.name = "value"
+		},
+};
+static const ber_tlv_tag_t asn_DEF_Frame_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+static const asn_TYPE_tag2member_t asn_MAP_Frame_tag2el_1[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 } /* ident */
+};
+static asn_SEQUENCE_specifics_t asn_SPC_Frame_specs_1 = {
+	sizeof(struct Frame),
+	offsetof(struct Frame, _asn_ctx),
+	asn_MAP_Frame_tag2el_1,
+	1,	/* Count of tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	1,	/* Start extensions */
+	3	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_Frame = {
+	"Frame",
+	"Frame",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_Frame_tags_1,
+	sizeof(asn_DEF_Frame_tags_1)
+		/sizeof(asn_DEF_Frame_tags_1[0]), /* 1 */
+	asn_DEF_Frame_tags_1,	/* Same as above */
+	sizeof(asn_DEF_Frame_tags_1)
+		/sizeof(asn_DEF_Frame_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	asn_MBR_Frame_1,
+	2,	/* Elements count */
+	&asn_SPC_Frame_specs_1	/* Additional specs */
+};
+
+
+/*** <<< INCLUDES [PrimitiveMessage] >>> ***/
+
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [PrimitiveMessage] >>> ***/
+
+typedef struct PrimitiveMessage {
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} PrimitiveMessage_t;
+
+/*** <<< FUNC-DECLS [PrimitiveMessage] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_PrimitiveMessage;
+extern asn_SEQUENCE_specifics_t asn_SPC_PrimitiveMessage_specs_1;
+
+/*** <<< STAT-DEFS [PrimitiveMessage] >>> ***/
+
+static const ber_tlv_tag_t asn_DEF_PrimitiveMessage_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SEQUENCE_specifics_t asn_SPC_PrimitiveMessage_specs_1 = {
+	sizeof(struct PrimitiveMessage),
+	offsetof(struct PrimitiveMessage, _asn_ctx),
+	0,	/* No top level tags */
+	0,	/* No tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_PrimitiveMessage = {
+	"PrimitiveMessage",
+	"PrimitiveMessage",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_PrimitiveMessage_tags_1,
+	sizeof(asn_DEF_PrimitiveMessage_tags_1)
+		/sizeof(asn_DEF_PrimitiveMessage_tags_1[0]), /* 1 */
+	asn_DEF_PrimitiveMessage_tags_1,	/* Same as above */
+	sizeof(asn_DEF_PrimitiveMessage_tags_1)
+		/sizeof(asn_DEF_PrimitiveMessage_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_SPC_PrimitiveMessage_specs_1	/* Additional specs */
+};
+
+
+/*** <<< INCLUDES [ComplexMessage] >>> ***/
+
+#include <constr_SEQUENCE.h>
+
+/*** <<< TYPE-DECLS [ComplexMessage] >>> ***/
+
+typedef struct ComplexMessage {
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} ComplexMessage_t;
+
+/*** <<< FUNC-DECLS [ComplexMessage] >>> ***/
+
+extern asn_TYPE_descriptor_t asn_DEF_ComplexMessage;
+extern asn_SEQUENCE_specifics_t asn_SPC_ComplexMessage_specs_1;
+
+/*** <<< STAT-DEFS [ComplexMessage] >>> ***/
+
+static const ber_tlv_tag_t asn_DEF_ComplexMessage_tags_1[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
+};
+asn_SEQUENCE_specifics_t asn_SPC_ComplexMessage_specs_1 = {
+	sizeof(struct ComplexMessage),
+	offsetof(struct ComplexMessage, _asn_ctx),
+	0,	/* No top level tags */
+	0,	/* No tags in the map */
+	0, 0, 0,	/* Optional elements (not needed) */
+	-1,	/* Start extensions */
+	-1	/* Stop extensions */
+};
+asn_TYPE_descriptor_t asn_DEF_ComplexMessage = {
+	"ComplexMessage",
+	"ComplexMessage",
+	SEQUENCE_free,
+	SEQUENCE_print,
+	SEQUENCE_constraint,
+	SEQUENCE_decode_ber,
+	SEQUENCE_encode_der,
+	SEQUENCE_decode_xer,
+	SEQUENCE_encode_xer,
+	0, 0,	/* No OER support, use "-gen-OER" to enable */
+	0, 0,	/* No PER support, use "-gen-PER" to enable */
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_ComplexMessage_tags_1,
+	sizeof(asn_DEF_ComplexMessage_tags_1)
+		/sizeof(asn_DEF_ComplexMessage_tags_1[0]), /* 1 */
+	asn_DEF_ComplexMessage_tags_1,	/* Same as above */
+	sizeof(asn_DEF_ComplexMessage_tags_1)
+		/sizeof(asn_DEF_ComplexMessage_tags_1[0]), /* 1 */
+	0,	/* No OER visible constraints */
+	0,	/* No PER visible constraints */
+	0, 0,	/* No members */
+	&asn_SPC_ComplexMessage_specs_1	/* Additional specs */
+};
+
diff --git a/tests/98-attribute-class-OK.asn1.-P b/tests/98-attribute-class-OK.asn1.-P
index ad70a9a..06cd2eb 100644
--- a/tests/98-attribute-class-OK.asn1.-P
+++ b/tests/98-attribute-class-OK.asn1.-P
@@ -3,6 +3,7 @@
 
 #include <RELATIVE-OID.h>
 #include <IA5String.h>
+#include <asn_ioc.h>
 #include <constr_SEQUENCE.h>
 
 /*** <<< TYPE-DECLS [Attribute] >>> ***/
@@ -43,6 +44,15 @@
 
 /*** <<< STAT-DEFS [Attribute] >>> ***/
 
+static const RELATIVE_OID_t asn_VAL_raf_0 = { "not supported", 0 };
+static const RELATIVE_OID_t asn_VAL_rcf_0 = { "not supported", 0 };
+static const asn_ioc_cell_t asn_IOS_Attributes_1_rows[] = {
+	{ "&id", aioc__value, &asn_DEF_RELATIVE_OID, &asn_VAL_raf_0 },
+	{ "&id", aioc__value, &asn_DEF_RELATIVE_OID, &asn_VAL_rcf_0 }
+};
+static asn_ioc_set_t asn_IOS_Attributes_1[] = {
+	2, 1, asn_IOS_Attributes_1_rows
+};
 static asn_TYPE_member_t asn_MBR_Attribute_1[] = {
 	{ ATF_NOFLAGS, 0, offsetof(struct Attribute, identifier),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (13 << 2)),