distinction between an optional member and a member encoded with a pointer


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@302 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index 4d9390c..8755c2a 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -26,6 +26,7 @@
 static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
 static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
 static int check_if_extensible(asn1p_expr_t *expr);
+static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
 static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
 static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
 static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
@@ -149,8 +150,9 @@
 		if(v->expr_type == A1TC_EXTENSIBLE) {
 			if(comp_mode < 3) comp_mode++;
 		}
-		if(comp_mode == 1 && !v->marker)
-			v->marker = EM_OPTIONAL;
+		if(comp_mode == 1
+		|| expr_better_indirect(arg, v))
+			v->marker |= EM_INDIRECT;
 		EMBED(v);
 	}
 
@@ -289,8 +291,9 @@
 		if(v->expr_type == A1TC_EXTENSIBLE) {
 			if(comp_mode < 3) comp_mode++;
 		}
-		if(comp_mode == 1 && !v->marker)
-			v->marker = EM_OPTIONAL;
+		if(comp_mode == 1
+		|| expr_better_indirect(arg, v))
+			v->marker |= EM_INDIRECT;
 		EMBED(v);
 	}
 
@@ -345,15 +348,15 @@
 
 	elements = 0;
 	INDENTED(TQ_FOR(v, &(expr->members), next) {
-		if(v->expr_type != A1TC_EXTENSIBLE) {
-			if(comp_mode == 1)
-				v->marker = EM_OPTIONAL;
-		} else {
+		if(v->expr_type == A1TC_EXTENSIBLE) {
 			if(comp_mode < 3) comp_mode++;
-			continue;
+		} else {
+			if(comp_mode == 1
+			|| expr_better_indirect(arg, v))
+				v->marker |= EM_INDIRECT;
+			elements++;
+			emit_member_table(arg, v);
 		}
-		elements++;
-		emit_member_table(arg, v);
 	});
 	OUT("};\n");
 
@@ -386,7 +389,9 @@
 			} else if(el) {
 				OUT(" | ");
 			}
-			OUT("(%d << %d)", v->marker?0:1, 7 - (el % 8));
+			OUT("(%d << %d)",
+				v->marker?0:1,
+				7 - (el % 8));
 			if(el && (el % 8) == 0)
 				delimit = 1;
 			el++;
@@ -573,6 +578,8 @@
 		OUT("%s_PR present;\n", id);
 		OUT("union {\n", id);
 		TQ_FOR(v, &(expr->members), next) {
+			if(expr_better_indirect(arg, v))
+				v->marker |= EM_INDIRECT;
 			EMBED(v);
 		}
 		if(UNNAMED_UNIONS)	OUT("};\n");
@@ -621,15 +628,15 @@
 
 	elements = 0;
 	INDENTED(TQ_FOR(v, &(expr->members), next) {
-		if(v->expr_type != A1TC_EXTENSIBLE) {
-			if(comp_mode == 1)
-				v->marker = EM_OPTIONAL;
-		} else {
+		if(v->expr_type == A1TC_EXTENSIBLE) {
 			if(comp_mode < 3) comp_mode++;
-			continue;
+		} else {
+			if(comp_mode == 1
+			|| expr_better_indirect(arg, v))
+				v->marker |= EM_INDIRECT;
+			elements++;
+			emit_member_table(arg, v);
 		}
-		elements++;
-		emit_member_table(arg, v);
 	});
 	OUT("};\n");
 
@@ -731,8 +738,10 @@
 			expr->marker?TNF_RSAFE:TNF_CTYPE));
 		OUT("%s", expr->marker?"*":" ");
 		OUT("%s", MKID(expr->Identifier));
-		if(expr->marker) OUT("\t/* %s */",
-			(expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
+		if((expr->marker & EM_DEFAULT) == EM_DEFAULT)
+			OUT("\t/* DEFAULT */");
+		else if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL)
+			OUT("\t/* OPTIONAL */");
 
 		REDIR(OT_TYPE_DECLS);
 		return 0;
@@ -1195,7 +1204,8 @@
 	char *p;
 
 	OUT("{ ");
-	if(expr->marker) {
+	OUT("%s, ", expr->marker?"ATF_POINTER":"ATF_NOFLAGS");
+	if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL) {
 		asn1p_expr_t *tv;
 		int opts = 0;
 		for(tv = expr; tv && tv->marker;
@@ -1378,3 +1388,30 @@
 
 	return 0;
 }
+
+/*
+ * Check if it is better to make this type indirectly accessed via
+ * a pointer.
+ * This may be the case for the following recursive definition:
+ * Type ::= CHOICE { member Type };
+ */
+static int
+expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
+	asn1p_expr_t *top_parent;
+	asn1p_expr_t *terminal;
+
+	if(expr->expr_type != A1TC_REFERENCE)
+		return 0;
+
+	/* Rewind to the topmost parent expression */
+	if((top_parent = expr->parent_expr)) {
+		while(top_parent->parent_expr)
+			top_parent = top_parent->parent_expr;
+	} else {
+		return 0;
+	}
+
+	terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
+
+	return (terminal == top_parent);
+}
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index cec0b8a..b7d38fb 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -238,8 +238,8 @@
 		 * and also a type of containment (it may be contained
 		 * as pointer or using inline inclusion).
 		 */
-		if(elm->optional) {
-			/* Optional member, hereby, a simple pointer */
+		if(elm->flags & ATF_POINTER) {
+			/* Member is a pointer to another structure */
 			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 		} else {
 			/*
@@ -386,10 +386,17 @@
 	 * Seek over the present member of the structure.
 	 */
 	elm = &td->elements[present-1];
-	if(elm->optional) {
+	if(elm->flags & ATF_POINTER) {
 		memb_ptr = *(void **)((char *)struct_ptr + elm->memb_offset);
 		if(memb_ptr == 0) {
-			erval.encoded = 0;
+			if(elm->optional) {
+				erval.encoded = 0;
+			} else {
+				/* Mandatory element absent */
+				erval.encoded = -1;
+				erval.failed_type = td;
+				erval.structure_ptr = struct_ptr;
+			}
 			return erval;
 		}
 	} else {
@@ -458,7 +465,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)
 					((const char *)ptr + elm->memb_offset);
 		} else {
@@ -494,9 +501,16 @@
 		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
-			if(!memb_ptr) return 0;
+			if(!memb_ptr) {
+				if(elm->optional)
+					return 0;
+				_ASN_ERRLOG(app_errlog, app_key,
+					"%s: mandatory CHOICE element %s absent (%s:%d)",
+					td->name, elm->name, __FILE__, __LINE__);
+				return -1;
+			}
 		} else {
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
@@ -542,7 +556,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 			if(!memb_ptr) return cb("<absent>", 8, app_key);
 		} else {
@@ -583,7 +597,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(memb_ptr)
 				elm->type->free_struct(elm->type, memb_ptr, 0);
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 2a8a540..5bee2ed 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -197,14 +197,17 @@
 		/*
 		 * MICROPHASE 1: Synchronize decoding.
 		 */
-		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d opt=%d ec=%d",
-			td->name, (int)ctx->left,
-			edx, elements[edx].optional, td->elements_count);
+		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
+				" opt=%d ec=%d",
+			td->name, (int)ctx->left, edx,
+			elements[edx].flags, elements[edx].optional,
+			td->elements_count);
 
 		if(ctx->left == 0	/* No more stuff is expected */
 		&& (
 			/* Explicit OPTIONAL specification reaches the end */
-			(edx + elements[edx].optional == td->elements_count)
+			(edx + elements[edx].optional
+					== td->elements_count)
 			||
 			/* All extensions are optional */
 			(IN_EXTENSION_GROUP(specs, edx)
@@ -304,7 +307,8 @@
 
 			if(!IN_EXTENSION_GROUP(specs, edx)) {
 				if(elements[edx].tag == (ber_tlv_tag_t)-1
-				&& elements[edx].optional == 0) {
+				/* FIXME: any support */
+				&& (elements[edx].flags & ATF_POINTER) == 0) {
 					/*
 					 * This must be the ANY type.
 					 */
@@ -375,8 +379,8 @@
 		 * and also a type of containment (it may be contained
 		 * as pointer or using inline inclusion).
 		 */
-		if(elements[edx].optional) {
-			/* Optional member, hereby, a simple pointer */
+		if(elements[edx].flags & ATF_POINTER) {
+			/* Member is a pointer to another structure */
 			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
 		} else {
 			/*
@@ -505,7 +509,7 @@
 	for(edx = 0; edx < td->elements_count; edx++) {
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
@@ -544,7 +548,7 @@
 		der_enc_rval_t tmperval;
 		void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
@@ -589,7 +593,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
@@ -632,7 +636,7 @@
 	for(edx = 0; edx < td->elements_count; edx++) {
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
 			if(memb_ptr)
 				elm->type->free_struct(elm->type, memb_ptr, 0);
@@ -666,7 +670,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 67816a7..f103fa3 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -294,8 +294,8 @@
 		 * and also a type of containment (it may be contained
 		 * as pointer or using inline inclusion).
 		 */
-		if(elements[edx].optional) {
-			/* Optional member, hereby, a simple pointer */
+		if(elements[edx].flags & ATF_POINTER) {
+			/* Member is a pointer to another structure */
 			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
 		} else {
 			/*
@@ -475,7 +475,7 @@
 		/*
 		 * Compute the length of the encoding of this member.
 		 */
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(!memb_ptr) {
 				if(t2m_build_own) {
@@ -551,7 +551,7 @@
 		/* Encode according to the tag order */
 		elm = &td->elements[t2m[edx].el_no];
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
@@ -594,7 +594,7 @@
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 			if(!memb_ptr) continue;
 		} else {
@@ -636,7 +636,7 @@
 	for(edx = 0; edx < td->elements_count; edx++) {
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
 			if(memb_ptr)
 				elm->type->free_struct(elm->type, memb_ptr, 0);
@@ -671,19 +671,15 @@
 		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
-		if(elm->optional) {
+		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 			if(!memb_ptr) {
-				if(ASN_SET_ISPRESENT2(
-					&(specs->_mandatory_elements), edx)) {
-					_ASN_ERRLOG(app_errlog, app_key,
-						"%s: mandatory element "
-						"%s absent (%s:%d)",
-						td->name, elm->name,
-						__FILE__, __LINE__);
-					return -1;
-				}
-				continue;
+				if(elm->optional)
+					continue;
+				_ASN_ERRLOG(app_errlog, app_key,
+				"%s: mandatory element %s absent (%s:%d)",
+				td->name, elm->name, __FILE__, __LINE__);
+				return -1;
 			}
 		} else {
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index 67f9c55..3463c6c 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -94,7 +94,11 @@
  * An element of the constructed type, i.e. SEQUENCE, SET, CHOICE.
  */
 typedef struct asn1_TYPE_member_s {
-	int optional;			/* Whether the element is optional */
+	enum asn1_TYPE_flags_e {
+		ATF_NOFLAGS,
+		ATF_POINTER	= 0x01,	/* Represented by the pointer */
+	} flags;			/* Element's presentation flags */
+	int optional;	/* Following optional members, including current */
 	int memb_offset;		/* Offset of the element */
 	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
 	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
diff --git a/tests/19-param-OK.asn1.-P b/tests/19-param-OK.asn1.-P
index 5f31e82..ec393c0 100644
--- a/tests/19-param-OK.asn1.-P
+++ b/tests/19-param-OK.asn1.-P
@@ -67,21 +67,21 @@
 /*** <<< STAT-DEFS [Certificate] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_toBeSigned[] = {
-	{ 0, offsetof(struct toBeSigned, version),
+	{ ATF_NOFLAGS, 0, offsetof(struct toBeSigned, version),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "version"
 		},
-	{ 0, offsetof(struct toBeSigned, signature),
+	{ ATF_NOFLAGS, 0, offsetof(struct toBeSigned, signature),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_OBJECT_IDENTIFIER,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "signature"
 		},
-	{ 0, offsetof(struct toBeSigned, issuer),
+	{ ATF_NOFLAGS, 0, offsetof(struct toBeSigned, issuer),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Name,
@@ -125,21 +125,21 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_Certificate[] = {
-	{ 0, offsetof(struct Certificate, toBeSigned),
+	{ ATF_NOFLAGS, 0, offsetof(struct Certificate, toBeSigned),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_toBeSigned,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "toBeSigned"
 		},
-	{ 0, offsetof(struct Certificate, algorithm),
+	{ ATF_NOFLAGS, 0, offsetof(struct Certificate, algorithm),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_OBJECT_IDENTIFIER,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "algorithm"
 		},
-	{ 0, offsetof(struct Certificate, signature),
+	{ ATF_NOFLAGS, 0, offsetof(struct Certificate, signature),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_BIT_STRING,
@@ -205,7 +205,7 @@
 /*** <<< STAT-DEFS [Name] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_Name[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_RelativeDistinguishedName,
@@ -317,7 +317,7 @@
 /*** <<< STAT-DEFS [RelativeDistinguishedName] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_RelativeDistinguishedName[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_IA5String,
diff --git a/tests/31-set-of-OK.asn1.-P b/tests/31-set-of-OK.asn1.-P
index be7e123..b3c6ce6 100644
--- a/tests/31-set-of-OK.asn1.-P
+++ b/tests/31-set-of-OK.asn1.-P
@@ -22,7 +22,7 @@
 /*** <<< STAT-DEFS [Forest] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_Forest[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Tree,
@@ -79,14 +79,14 @@
 /*** <<< STAT-DEFS [Tree] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_Tree[] = {
-	{ 0, offsetof(struct Tree, height),
+	{ ATF_NOFLAGS, 0, offsetof(struct Tree, height),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "height"
 		},
-	{ 0, offsetof(struct Tree, width),
+	{ ATF_NOFLAGS, 0, offsetof(struct Tree, width),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
@@ -186,7 +186,7 @@
 /*** <<< STAT-DEFS [Stuff] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_trees[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Forest,
@@ -221,7 +221,7 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_anything_member[] = {
-	{ 0, offsetof(struct anything_member, cup_of_coffee),
+	{ ATF_NOFLAGS, 0, offsetof(struct anything_member, cup_of_coffee),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_BIT_STRING,
@@ -263,7 +263,7 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_anything[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_anything_member,
@@ -298,14 +298,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_Stuff[] = {
-	{ 2, offsetof(struct Stuff, trees),
+	{ ATF_POINTER, 2, offsetof(struct Stuff, trees),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_trees,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "trees"
 		},
-	{ 1, offsetof(struct Stuff, anything),
+	{ ATF_POINTER, 1, offsetof(struct Stuff, anything),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_anything,
diff --git a/tests/39-sequence-of-OK.asn1.-P b/tests/39-sequence-of-OK.asn1.-P
index 9a49a79..2b8df8b 100644
--- a/tests/39-sequence-of-OK.asn1.-P
+++ b/tests/39-sequence-of-OK.asn1.-P
@@ -30,7 +30,7 @@
 /*** <<< STAT-DEFS [T] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_collection[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_T2,
@@ -65,14 +65,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_T[] = {
-	{ 0, offsetof(struct T, int),
+	{ ATF_NOFLAGS, 0, offsetof(struct T, int),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "int"
 		},
-	{ 0, offsetof(struct T, collection),
+	{ ATF_NOFLAGS, 0, offsetof(struct T, collection),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_collection,
@@ -138,14 +138,14 @@
 /*** <<< STAT-DEFS [T2] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_T2[] = {
-	{ 0, offsetof(struct T2, flag),
+	{ ATF_NOFLAGS, 0, offsetof(struct T2, flag),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (1 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_BOOLEAN,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "flag"
 		},
-	{ 0, offsetof(struct T2, str),
+	{ ATF_NOFLAGS, 0, offsetof(struct T2, str),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_UTF8String,
diff --git a/tests/42-real-life-OK.asn1.-PR b/tests/42-real-life-OK.asn1.-PR
index 04ee81a..63b696d 100644
--- a/tests/42-real-life-OK.asn1.-PR
+++ b/tests/42-real-life-OK.asn1.-PR
@@ -66,7 +66,7 @@
 /*** <<< STAT-DEFS [LogLine] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_varsets[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VariablePartSet,
@@ -101,14 +101,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_LogLine[] = {
-	{ 0, offsetof(struct LogLine, line_digest),
+	{ ATF_NOFLAGS, 0, offsetof(struct LogLine, line_digest),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_IA5String,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "line-digest"
 		},
-	{ 0, offsetof(struct LogLine, varsets),
+	{ ATF_NOFLAGS, 0, offsetof(struct LogLine, varsets),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_varsets,
@@ -208,7 +208,7 @@
 /*** <<< STAT-DEFS [VariablePartSet] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_vparts[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = -1 /* Ambiguous tag (CHOICE|ANY?) */,
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VariablePart,
@@ -243,14 +243,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_VariablePartSet[] = {
-	{ 0, offsetof(struct VariablePartSet, vparts),
+	{ ATF_NOFLAGS, 0, offsetof(struct VariablePartSet, vparts),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_vparts,
 		.memb_constraints = memb_vparts_2_constraint,
 		.name = "vparts"
 		},
-	{ 0, offsetof(struct VariablePartSet, resolution),
+	{ ATF_NOFLAGS, 0, offsetof(struct VariablePartSet, resolution),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_ActionItem,
@@ -378,7 +378,7 @@
 /*** <<< STAT-DEFS [VariablePart] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_vset[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VisibleString,
@@ -413,14 +413,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_vrange[] = {
-	{ 0, offsetof(struct vrange, from),
+	{ ATF_NOFLAGS, 0, offsetof(struct vrange, from),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VisibleString,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "from"
 		},
-	{ 0, offsetof(struct vrange, to),
+	{ ATF_NOFLAGS, 0, offsetof(struct vrange, to),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VisibleString,
@@ -463,14 +463,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_VariablePart[] = {
-	{ 0, offsetof(struct VariablePart, choice.vset),
+	{ ATF_NOFLAGS, 0, offsetof(struct VariablePart, choice.vset),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_vset,
 		.memb_constraints = memb_vset_3_constraint,
 		.name = "vset"
 		},
-	{ 0, offsetof(struct VariablePart, choice.vrange),
+	{ ATF_NOFLAGS, 0, offsetof(struct VariablePart, choice.vrange),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_vrange,
@@ -563,7 +563,7 @@
 /*** <<< STAT-DEFS [ActionItem] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_email[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_VisibleString,
@@ -598,14 +598,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_notify[] = {
-	{ 0, offsetof(struct notify, critical),
+	{ ATF_NOFLAGS, 0, offsetof(struct notify, critical),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (1 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_BOOLEAN,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "critical"
 		},
-	{ 0, offsetof(struct notify, email),
+	{ ATF_NOFLAGS, 0, offsetof(struct notify, email),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_email,
@@ -648,14 +648,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_ActionItem[] = {
-	{ 0, offsetof(struct ActionItem, accept_as),
+	{ ATF_NOFLAGS, 0, offsetof(struct ActionItem, accept_as),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_ENUMERATED,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "accept-as"
 		},
-	{ 1, offsetof(struct ActionItem, notify),
+	{ ATF_POINTER, 1, offsetof(struct ActionItem, notify),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_notify,
diff --git a/tests/43-recursion-OK.asn1.-P b/tests/43-recursion-OK.asn1.-P
index a38cd02..3ff74e4 100644
--- a/tests/43-recursion-OK.asn1.-P
+++ b/tests/43-recursion-OK.asn1.-P
@@ -39,7 +39,7 @@
 /*** <<< STAT-DEFS [Test-structure-1] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_t_member1[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Test_structure_1,
@@ -74,7 +74,7 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_t_member2[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Test_structure_1,
@@ -109,28 +109,28 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_Test_structure_1[] = {
-	{ 0, offsetof(struct Test_structure_1, t_member1),
+	{ ATF_NOFLAGS, 0, offsetof(struct Test_structure_1, t_member1),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (17 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_t_member1,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "t-member1"
 		},
-	{ 0, offsetof(struct Test_structure_1, t_member2),
+	{ ATF_NOFLAGS, 0, offsetof(struct Test_structure_1, t_member2),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_t_member2,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "t-member2"
 		},
-	{ 1, offsetof(struct Test_structure_1, t_member3),
+	{ ATF_POINTER, 1, offsetof(struct Test_structure_1, t_member3),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Test_structure_1,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "t-member3"
 		},
-	{ 0, offsetof(struct Test_structure_1, t_member4),
+	{ ATF_NOFLAGS, 0, offsetof(struct Test_structure_1, t_member4),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
@@ -199,14 +199,14 @@
 typedef struct Choice_1 {
 	Choice_1_PR present;
 	union {
-		struct Choice_1	 and;
+		struct Choice_1	*and;
 		struct or {
 			A_SET_OF(struct Choice_1) list;
 			
 			/* Context for parsing across buffer boundaries */
 			ber_dec_ctx_t _ber_dec_ctx;
 		} or;
-		struct Choice_1	 not;
+		struct Choice_1	*not;
 		INTEGER_t	 other;
 	} choice;
 	
@@ -217,7 +217,7 @@
 /*** <<< STAT-DEFS [Choice-1] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_or[] = {
-	{ 0, 0,
+	{ ATF_NOFLAGS, 0, 0,
 		.tag = -1 /* Ambiguous tag (CHOICE|ANY?) */,
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_Choice_1,
@@ -252,28 +252,28 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_Choice_1[] = {
-	{ 0, offsetof(struct Choice_1, choice.and),
+	{ ATF_POINTER, 0, offsetof(struct Choice_1, choice.and),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
 		.tag_mode = +1,	/* EXPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_Choice_1,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "and"
 		},
-	{ 0, offsetof(struct Choice_1, choice.or),
+	{ ATF_NOFLAGS, 0, offsetof(struct Choice_1, choice.or),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (2 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_or,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "or"
 		},
-	{ 0, offsetof(struct Choice_1, choice.not),
+	{ ATF_POINTER, 0, offsetof(struct Choice_1, choice.not),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (3 << 2)),
 		.tag_mode = +1,	/* EXPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_Choice_1,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "not"
 		},
-	{ 0, offsetof(struct Choice_1, choice.other),
+	{ ATF_NOFLAGS, 0, offsetof(struct Choice_1, choice.other),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (4 << 2)),
 		.tag_mode = +1,	/* EXPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_INTEGER,
diff --git a/tests/44-choice-in-sequence-OK.asn1.-P b/tests/44-choice-in-sequence-OK.asn1.-P
index b4d9c71..3c6c152 100644
--- a/tests/44-choice-in-sequence-OK.asn1.-P
+++ b/tests/44-choice-in-sequence-OK.asn1.-P
@@ -69,14 +69,14 @@
 /*** <<< STAT-DEFS [T] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_e[] = {
-	{ 0, offsetof(struct e, choice.f),
+	{ ATF_NOFLAGS, 0, offsetof(struct e, choice.f),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (7 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "f"
 		},
-	{ 0, offsetof(struct e, choice.g),
+	{ ATF_NOFLAGS, 0, offsetof(struct e, choice.g),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (8 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
@@ -116,14 +116,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_h[] = {
-	{ 0, offsetof(struct h, choice.i),
+	{ ATF_NOFLAGS, 0, offsetof(struct h, choice.i),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (1 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "i"
 		},
-	{ 0, offsetof(struct h, choice.j),
+	{ ATF_NOFLAGS, 0, offsetof(struct h, choice.j),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (2 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
@@ -163,28 +163,28 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_b[] = {
-	{ 0, offsetof(struct b, choice.c),
+	{ ATF_NOFLAGS, 0, offsetof(struct b, choice.c),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (5 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "c"
 		},
-	{ 0, offsetof(struct b, choice.d),
+	{ ATF_NOFLAGS, 0, offsetof(struct b, choice.d),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (6 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "d"
 		},
-	{ 0, offsetof(struct b, choice.e),
+	{ ATF_NOFLAGS, 0, offsetof(struct b, choice.e),
 		.tag = -1 /* Ambiguous tag (CHOICE|ANY?) */,
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_e,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "e"
 		},
-	{ 0, offsetof(struct b, choice.h),
+	{ ATF_NOFLAGS, 0, offsetof(struct b, choice.h),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (9 << 2)),
 		.tag_mode = +1,	/* EXPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_h,
@@ -227,14 +227,14 @@
 };
 
 static asn1_TYPE_member_t asn1_MBR_T[] = {
-	{ 0, offsetof(struct T, a),
+	{ ATF_NOFLAGS, 0, offsetof(struct T, a),
 		.tag = (ASN_TAG_CLASS_PRIVATE | (2 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_NULL,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "a"
 		},
-	{ 0, offsetof(struct T, b),
+	{ ATF_NOFLAGS, 0, offsetof(struct T, b),
 		.tag = -1 /* Ambiguous tag (CHOICE|ANY?) */,
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_b,
diff --git a/tests/46-redefine-OK.asn1.-PR b/tests/46-redefine-OK.asn1.-PR
index ad54f87..c78b29f 100644
--- a/tests/46-redefine-OK.asn1.-PR
+++ b/tests/46-redefine-OK.asn1.-PR
@@ -121,7 +121,7 @@
 /*** <<< STAT-DEFS [ConstructedType] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_ConstructedType[] = {
-	{ 0, offsetof(struct ConstructedType, field),
+	{ ATF_NOFLAGS, 0, offsetof(struct ConstructedType, field),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (5 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn1_DEF_PrimitiveType,
diff --git a/tests/47-set-ext-OK.asn1.-P b/tests/47-set-ext-OK.asn1.-P
index 9991cf5..8354a16 100644
--- a/tests/47-set-ext-OK.asn1.-P
+++ b/tests/47-set-ext-OK.asn1.-P
@@ -36,7 +36,7 @@
 /*** <<< STAT-DEFS [T1] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_T1[] = {
-	{ 0, offsetof(struct T1, i),
+	{ ATF_NOFLAGS, 0, offsetof(struct T1, i),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
@@ -118,7 +118,7 @@
 /*** <<< STAT-DEFS [T2] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_T2[] = {
-	{ 0, offsetof(struct T2, i),
+	{ ATF_NOFLAGS, 0, offsetof(struct T2, i),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
@@ -197,7 +197,7 @@
 /*** <<< STAT-DEFS [T3] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_T3[] = {
-	{ 0, offsetof(struct T3, choice.i),
+	{ ATF_NOFLAGS, 0, offsetof(struct T3, choice.i),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,
@@ -269,7 +269,7 @@
 /*** <<< STAT-DEFS [T4] >>> ***/
 
 static asn1_TYPE_member_t asn1_MBR_T4[] = {
-	{ 0, offsetof(struct T4, choice.i),
+	{ ATF_NOFLAGS, 0, offsetof(struct T4, choice.i),
 		.tag = (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
 		.tag_mode = 0,
 		.type = (void *)&asn1_DEF_INTEGER,