diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 7e576a1e85248ae1bfdf5f5140bc1f132f4e000a..df11c19cf93f00a899982ad88e3ae6ac0213a843 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_BIT_STRING = {
 	  / sizeof(asn1_DEF_BIT_STRING_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	(void *)-1	/* Special indicator that this is a BIT STRING */
 };
 
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index d914168207e5b0e74b464c5f74830d3debe2a9a3..6b3ceeb3c3482aadb7c8e69fd07b57e142bfc835 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_BMPString = {
 	  / sizeof(asn1_DEF_BMPString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 4f9b32444a10ebd17c512276b36f9ad75fffc6ff..da38772db64af76ccf39b0cfa976d6a00ea1800c 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -22,6 +22,7 @@ asn1_TYPE_descriptor_t asn1_DEF_BOOLEAN = {
 	sizeof(asn1_DEF_BOOLEAN_tags)/sizeof(asn1_DEF_BOOLEAN_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index 3fff3682911cc5dc88c073f6459a1eb081581227..12350ef6185b3ba75eae2f657b9689a9400fb5d0 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -22,6 +22,7 @@ asn1_TYPE_descriptor_t asn1_DEF_ENUMERATED = {
 	sizeof(asn1_DEF_ENUMERATED_tags)/sizeof(asn1_DEF_ENUMERATED_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Primitive */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index 6bc7e4782819e81857f3f6db2446d937421283a5..db3b87d8dac26677c1eb169c5b5e7b102f207aa5 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_GeneralString = {
 	  / sizeof(asn1_DEF_GeneralString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 4d1b3908d54c68e4406ca53d58a8d3ae8920926c..25f2bb6e371e8efe5464b7488320ce4b4cae4888 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -88,6 +88,7 @@ asn1_TYPE_descriptor_t asn1_DEF_GeneralizedTime = {
 	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index 412f3c740810d7d35c7efe00c1d7f46ec63917e7..bd931467edc8b5d72974a66f5d8bb60d9047595a 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_GraphicString = {
 	  / sizeof(asn1_DEF_GraphicString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index c520bb295cfc82a262c8cc7b5f1e9e9fe9246365..a44a9d0f83fc2ebcf6ffd3d6e9880b6badf92c11 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_IA5String = {
 	  / sizeof(asn1_DEF_IA5String_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 9cf146e5e4697d0c3e6a730c7ac7f75d072a9b12..0c7a81afbcdc7a288c2b208cfcaaf5f3dfa709aa 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -24,6 +24,7 @@ asn1_TYPE_descriptor_t asn1_DEF_INTEGER = {
 	sizeof(asn1_DEF_INTEGER_tags)/sizeof(asn1_DEF_INTEGER_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 2df623cfab3ee49502a8d17953131813dff274b0..a86d0cec38f726233feec1c5fc1ee64091069874 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_ISO646String = {
 	  / sizeof(asn1_DEF_ISO646String_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 4ea06693409d17995c8587b9b37ecca1d9d13966..d71d90de5d8cc71d6cb6da07273d5703be2f3f33 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_NULL = {
 	sizeof(asn1_DEF_NULL_tags)/sizeof(asn1_DEF_NULL_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index bfb2bff1ab78728e9bc160bef74a010d7c60a00a..139a602b89436c3a7a80b5bdc602d55ec2b5802d 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -29,5 +29,7 @@ asn1_TYPE_descriptor_t asn1_DEF_NativeEnumerated = {
 	sizeof(asn1_DEF_NativeEnumerated_tags)/sizeof(asn1_DEF_NativeEnumerated_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
+
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index ca29049b736c1618830541a6e3c8bfbeee6f3692..759fe27e74a24276470f4e218522611894f0db61 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -31,6 +31,7 @@ asn1_TYPE_descriptor_t asn1_DEF_NativeInteger = {
 	sizeof(asn1_DEF_NativeInteger_tags)/sizeof(asn1_DEF_NativeInteger_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index a8d4ed8c79c80d3a07b509d7d5ff82eea4af5393..6c8729ff825e94f81a0f353dfb73c44dea7de1f5 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_NumericString = {
 	  / sizeof(asn1_DEF_NumericString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index 89e2e327c2d2b815d6fb480419266dd855cdfefb..063ae978e295346afd61af4e4de8c0d7f81f70f5 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -26,6 +26,7 @@ asn1_TYPE_descriptor_t asn1_DEF_OBJECT_IDENTIFIER = {
 	    / sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index e0a7bb284a7756be420111c20f3c65280ffdce90..8ea360d5f541221a3001b9b45db424ddd3e98b23 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -25,6 +25,7 @@ asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
 	  / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine (primitive and constructed) */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index db699ca02670c0dd19fee9029d90117345fca93e..3a03b978ad82d4b4498affb8536c4d1fa36239b0 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_ObjectDescriptor = {
 	  / sizeof(asn1_DEF_ObjectDescriptor_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index f894d82e4915f8b552a112600f54abb024e1aa61..8f67eddf4a73a12fbde53818e8df04f73e286f54 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_PrintableString = {
 	  / sizeof(asn1_DEF_PrintableString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index eaf98b1716d08d5bbb52dbda0d5d190ec472a759..3273ace5b6d8a1f0e541377105fc169e785a9a7b 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -26,6 +26,7 @@ asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = {
 	    / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	0,	/* Always in primitive form */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index 2ba5d324f15078bc232b23696a6a2ce594a7e4d3..2815298c29b27db667018c3eddd6e79b5fd44dac 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_T61String = {
 	  / sizeof(asn1_DEF_T61String_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index dafbd5852cd10cc48bfa3827534ddcd333e78159..3c20e2f772b7f6e9c76085e70c276fe701ca58b8 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_TeletexString = {
 	  / sizeof(asn1_DEF_TeletexString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 7d9711732572ff8005cabbd03dfea2634329bce1..8b7972c01198b65d9ff8cd8d673a3bc560e179f0 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -29,6 +29,7 @@ asn1_TYPE_descriptor_t asn1_DEF_UTCTime = {
 	  / sizeof(asn1_DEF_UTCTime_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 06e1559e8b6a9568059a941415fe11758d7e9cb7..aab4a2e951b0200cfcd0f48f6c4fac7211184850 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_UTF8String = {
 	  / sizeof(asn1_DEF_UTF8String_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 241fe673c8b2158b3298f633d4834c44bd4e714d..628ed0caad0c9d143e8f9b46a008e25ab427db0e 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_UniversalString = {
 	  / sizeof(asn1_DEF_UniversalString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index d9293beb8eb9abc0fb0da3c73f42780b87f2cf99..df21b149e26f12309cdaf347a5efcd4404e2c75d 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_VideotexString = {
 	  / sizeof(asn1_DEF_VideotexString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 4033a177d8a2999ba119c8bc3b75533495bc40e1..aa9c99b1894a52e66da6f23612f5bab8b5c5dd51 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -23,6 +23,7 @@ asn1_TYPE_descriptor_t asn1_DEF_VisibleString = {
 	  / sizeof(asn1_DEF_VisibleString_tags[0]),
 	1,	/* Single UNIVERSAL tag may be implicitly overriden */
 	-1,	/* Both ways are fine */
+	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 4aaad23916a46ae737f677539391c8fd52e7370a..3fbf194ac51f7a11e2de7ab18a5725c2e36671b7 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -93,13 +93,13 @@ _search4tag(const void *ap, const void *bp) {
  * The decoder of the CHOICE type.
  */
 ber_dec_rval_t
-CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
+CHOICE_decode_ber(asn1_TYPE_descriptor_t *td,
 	void **struct_ptr, void *ptr, size_t size, int tag_mode) {
 	/*
 	 * Bring closer parts of structure description.
 	 */
-	asn1_CHOICE_specifics_t *specs = (asn1_CHOICE_specifics_t *)sd->specifics;
-	asn1_CHOICE_element_t *elements = specs->elements;
+	asn1_CHOICE_specifics_t *specs = (asn1_CHOICE_specifics_t *)td->specifics;
+	asn1_TYPE_member_t *elements = td->elements;
 
 	/*
 	 * Parts of the structure being constructed.
@@ -114,7 +114,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
 
-	ASN_DEBUG("Decoding %s as CHOICE", sd->name);
+	ASN_DEBUG("Decoding %s as CHOICE", td->name);
 	
 	/*
 	 * Create the target structure if it is not present already.
@@ -142,12 +142,12 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * perfectly fits our expectations.
 		 */
 
-		if(tag_mode || sd->tags_count) {
-			rval = ber_check_tags(sd, ctx, ptr, size,
+		if(tag_mode || td->tags_count) {
+			rval = ber_check_tags(td, ctx, ptr, size,
 				tag_mode, &ctx->left, 0);
 			if(rval.code != RC_OK) {
 				ASN_DEBUG("%s tagging check failed: %d",
-					sd->name, rval.code);
+					td->name, rval.code);
 				consumed_myself += rval.consumed;
 				RETURN(rval.code);
 			}
@@ -172,7 +172,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * Fetch the T from TLV.
 		 */
 		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
-		ASN_DEBUG("In %s CHOICE tag length %d", sd->name, (int)tag_len);
+		ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len);
 		switch(tag_len) {
 		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 			/* Fall through */
@@ -197,7 +197,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 			} else if(specs->extensible == 0) {
 				ASN_DEBUG("Unexpected tag %s "
 					"in non-extensible CHOICE %s",
-					ber_tlv_tag_string(tlv_tag), sd->name);
+					ber_tlv_tag_string(tlv_tag), td->name);
 				RETURN(RC_FAIL);
 			} else {
 				/* Skip this tag */
@@ -227,7 +227,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * Read in the element.
 		 */
 	    do {
-		asn1_CHOICE_element_t *elm;	/* CHOICE's element */
+		asn1_TYPE_member_t *elm;/* CHOICE's element */
 		void *memb_ptr;		/* Pointer to the member */
 		void **memb_ptr2;	/* Pointer to that pointer */
 
@@ -252,6 +252,9 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		/*
 		 * Invoke the member fetch routine according to member's type
 		 */
+		printf("elm->name = %s\n", elm->name);
+		printf("elm->td = %p\n", elm->type);
+		printf("elm->td->name = %s\n", elm->type->name);
 		rval = elm->type->ber_decoder(elm->type,
 				memb_ptr2, ptr, LEFT,
 				elm->tag_mode);
@@ -278,8 +281,8 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		/* Fall through */
 	case 3:
 		ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d",
-			sd->name, (long)ctx->left, (long)size,
-			tag_mode, sd->tags_count);
+			td->name, (long)ctx->left, (long)size,
+			tag_mode, td->tags_count);
 
 		if(ctx->left > 0) {
 			/*
@@ -290,7 +293,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		}
 
 		if(ctx->left == -1
-		&& !(tag_mode || sd->tags_count)) {
+		&& !(tag_mode || td->tags_count)) {
 			/*
 			 * This is an untagged CHOICE.
 			 * It doesn't contain nothing
@@ -331,7 +334,7 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 				}
 			} else {
 				ASN_DEBUG("Unexpected continuation in %s",
-					sd->name);
+					td->name);
 				RETURN(RC_FAIL);
 			}
 
@@ -349,19 +352,19 @@ CHOICE_decode_ber(asn1_TYPE_descriptor_t *sd,
 }
 
 der_enc_rval_t
-CHOICE_encode_der(asn1_TYPE_descriptor_t *sd,
+CHOICE_encode_der(asn1_TYPE_descriptor_t *td,
 		void *struct_ptr,
 		int tag_mode, ber_tlv_tag_t tag,
 		asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_CHOICE_specifics_t *specs = (asn1_CHOICE_specifics_t *)sd->specifics;
-	asn1_CHOICE_element_t *elm;	/* CHOICE element */
+	asn1_CHOICE_specifics_t *specs = (asn1_CHOICE_specifics_t *)td->specifics;
+	asn1_TYPE_member_t *elm;	/* CHOICE element */
 	der_enc_rval_t erval;
 	void *memb_ptr;
 	size_t computed_size = 0;
 	int present;
 
 	ASN_DEBUG("%s %s as CHOICE",
-		cb?"Encoding":"Estimating", sd->name);
+		cb?"Encoding":"Estimating", td->name);
 
 	present = _fetch_present_idx(struct_ptr,
 		specs->pres_offset, specs->pres_size);
@@ -370,14 +373,14 @@ CHOICE_encode_der(asn1_TYPE_descriptor_t *sd,
 	 * If the structure was not initialized, it cannot be encoded:
 	 * can't deduce what to encode in the choice type.
 	 */
-	if(present <= 0 || present > specs->elements_count) {
-		if(present == 0 && specs->elements_count == 0) {
+	if(present <= 0 || present > td->elements_count) {
+		if(present == 0 && td->elements_count == 0) {
 			/* The CHOICE is empty?! */
 			erval.encoded = 0;
 			return erval;
 		}
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = struct_ptr;
 		return erval;
 	}
@@ -385,7 +388,7 @@ CHOICE_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Seek over the present member of the structure.
 	 */
-	elm = &specs->elements[present-1];
+	elm = &td->elements[present-1];
 	if(elm->optional) {
 		memb_ptr = *(void **)((char *)struct_ptr + elm->memb_offset);
 		if(memb_ptr == 0) {
@@ -401,7 +404,7 @@ CHOICE_encode_der(asn1_TYPE_descriptor_t *sd,
 	 * T ::= [2] EXPLICIT CHOICE { ... }
 	 * Then emit the appropriate tags.
 	 */
-	if(tag_mode == 1 || sd->tags_count) {
+	if(tag_mode == 1 || td->tags_count) {
 		/*
 		 * For this, we need to pre-compute the member.
 		 */
@@ -414,11 +417,11 @@ CHOICE_encode_der(asn1_TYPE_descriptor_t *sd,
 			return erval;
 
 		/* Encode CHOICE with parent or my own tag */
-		ret = der_write_tags(sd, erval.encoded, tag_mode, tag,
+		ret = der_write_tags(td, erval.encoded, tag_mode, tag,
 			cb, app_key);
 		if(ret == -1) {
 			erval.encoded = -1;
-			erval.failed_type = sd;
+			erval.failed_type = td;
 			erval.structure_ptr = struct_ptr;
 			return erval;
 		}
@@ -454,8 +457,8 @@ CHOICE_outmost_tag(asn1_TYPE_descriptor_t *td, const void *ptr, int tag_mode, be
 	 */
 	present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size);
 
-	if(present > 0 || present <= specs->elements_count) {
-		asn1_CHOICE_element_t *elm = &specs->elements[present-1];
+	if(present > 0 || present <= td->elements_count) {
+		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -489,8 +492,8 @@ CHOICE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 	 * Figure out which CHOICE element is encoded.
 	 */
 	present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size);
-	if(present > 0 && present <= specs->elements_count) {
-		asn1_CHOICE_element_t *elm = &specs->elements[present-1];
+	if(present > 0 && present <= td->elements_count) {
+		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -500,8 +503,19 @@ CHOICE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		return elm->type->check_constraints(elm->type, memb_ptr,
+		if(elm->memb_constraints) {
+			return elm->memb_constraints(elm->type, memb_ptr,
 				app_errlog, app_key);
+		} else {
+			int ret = elm->type->check_constraints(elm->type,
+					memb_ptr, app_errlog, app_key);
+			/*
+			 * Cannot inherit it eralier:
+			 * need to make sure we get the updated version.
+			 */
+			elm->memb_constraints = elm->type->check_constraints;
+			return ret;
+		}
 	} else {
 		_ASN_ERRLOG(app_errlog, app_key,
 			"%s: no CHOICE element given", td->name);
@@ -525,8 +539,8 @@ CHOICE_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	/*
 	 * Free that element.
 	 */
-	if(present > 0 && present <= specs->elements_count) {
-		asn1_CHOICE_element_t *elm = &specs->elements[present-1];
+	if(present > 0 && present <= td->elements_count) {
+		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -566,8 +580,8 @@ CHOICE_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 	/*
 	 * Free that element.
 	 */
-	if(present > 0 && present <= specs->elements_count) {
-		asn1_CHOICE_element_t *elm = &specs->elements[present-1];
+	if(present > 0 && present <= td->elements_count) {
+		asn1_TYPE_member_t *elm = &td->elements[present-1];
 		void *memb_ptr;
 
 		if(elm->optional) {
diff --git a/skeletons/constr_CHOICE.h b/skeletons/constr_CHOICE.h
index 1308bd4ace97609311d1eaf495f9f24aebd26be5..327bae2e458aa9933ea6c5c30e72fb1a93e128a2 100644
--- a/skeletons/constr_CHOICE.h
+++ b/skeletons/constr_CHOICE.h
@@ -7,18 +7,6 @@
 
 #include <constr_TYPE.h>
 
-/*
- * A single element of the CHOICE type.
- */
-typedef struct asn1_CHOICE_element_s {
-	int memb_offset;		/* Offset of the element */
-	int optional;			/* Whether the element is optional */
-	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
-	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
-	asn1_TYPE_descriptor_t *type;	/* Member type descriptor */
-	char *name;			/* ASN.1 identifier of the element */
-} asn1_CHOICE_element_t;
-
 typedef struct asn1_CHOICE_specifics_s {
 	/*
 	 * Target structure description.
@@ -28,12 +16,6 @@ typedef struct asn1_CHOICE_specifics_s {
 	int pres_offset;	/* Identifier of the present member */
 	int pres_size;		/* Size of the identifier (enum) */
 
-	/*
-	 * Members of the CHOICE structure.
-	 */
-	asn1_CHOICE_element_t *elements;
-	int elements_count;
-
 	/*
 	 * Tags to members mapping table.
 	 */
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 6e1747cfa19581259058d6c2212240b91170995b..06ef4e83c3a6717fed9c1400bd87e000f073cf03 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -103,13 +103,13 @@ _t2e_cmp(const void *ap, const void *bp) {
  * The decoder of the SEQUENCE type.
  */
 ber_dec_rval_t
-SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
+SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *td,
 	void **struct_ptr, void *ptr, size_t size, int tag_mode) {
 	/*
 	 * Bring closer parts of structure description.
 	 */
-	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)sd->specifics;
-	asn1_SEQUENCE_element_t *elements = specs->elements;
+	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)td->specifics;
+	asn1_TYPE_member_t *elements = td->elements;
 
 	/*
 	 * Parts of the structure being constructed.
@@ -124,7 +124,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
 	int edx;			/* SEQUENCE element's index */
 
-	ASN_DEBUG("Decoding %s as SEQUENCE", sd->name);
+	ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
 	
 	/*
 	 * Create the target structure if it is not present already.
@@ -152,11 +152,11 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * perfectly fits our expectations.
 		 */
 
-		rval = ber_check_tags(sd, ctx, ptr, size,
+		rval = ber_check_tags(td, ctx, ptr, size,
 			tag_mode, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
-				sd->name, rval.code);
+				td->name, rval.code);
 			consumed_myself += rval.consumed;
 			RETURN(rval.code);
 		}
@@ -182,7 +182,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * that member:
 		 * 	step = (<member_number> * 2 + <microphase>).
 		 */
-	  for(edx = (ctx->step >> 1); edx < specs->elements_count;
+	  for(edx = (ctx->step >> 1); edx < td->elements_count;
 			edx++, ctx->step = (ctx->step & ~1) + 2) {
 		void *memb_ptr;		/* Pointer to the member */
 		void **memb_ptr2;	/* Pointer to that pointer */
@@ -198,20 +198,20 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * MICROPHASE 1: Synchronize decoding.
 		 */
 		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d opt=%d ec=%d",
-			sd->name, (int)ctx->left,
-			edx, elements[edx].optional, specs->elements_count);
+			td->name, (int)ctx->left,
+			edx, 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 == specs->elements_count)
+			(edx + elements[edx].optional == td->elements_count)
 			||
 			/* All extensions are optional */
 			(IN_EXTENSION_GROUP(specs, edx)
-				&& specs->ext_before > specs->elements_count)
+				&& specs->ext_before > td->elements_count)
 		   )
 		) {
-			ASN_DEBUG("End of SEQUENCE %s", sd->name);
+			ASN_DEBUG("End of SEQUENCE %s", td->name);
 			/*
 			 * Found the legitimate end of the structure.
 			 */
@@ -224,7 +224,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 */
 		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
 		ASN_DEBUG("In %s SEQUENCE for %d %s next tag length %d",
-			sd->name, edx, elements[edx].name, (int)tag_len);
+			td->name, edx, elements[edx].name, (int)tag_len);
 		switch(tag_len) {
 		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 			/* Fall through */
@@ -236,8 +236,8 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 */
 		use_bsearch = 0;
 		opt_edx_end = edx + elements[edx].optional + 1;
-		if(opt_edx_end > specs->elements_count)
-			opt_edx_end = specs->elements_count;	/* Cap */
+		if(opt_edx_end > td->elements_count)
+			opt_edx_end = td->elements_count;	/* Cap */
 		else if(opt_edx_end - edx > 8) {
 			/* Limit the scope of linear search... */
 			opt_edx_end = edx + 8;
@@ -340,7 +340,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 					BER_TLV_CONSTRUCTED(ptr),
 					(char *)ptr + tag_len, LEFT - tag_len);
 				ASN_DEBUG("Skip length %d in %s",
-					(int)skip, sd->name);
+					(int)skip, td->name);
 				switch(skip) {
 				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
 					/* Fall through */
@@ -359,7 +359,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 */
 		ctx->step |= 1;		/* Confirm entering next microphase */
 	microphase2:
-		ASN_DEBUG("Inside SEQUENCE %s MF2", sd->name);
+		ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
 		
 		/*
 		 * Compute the position of the member inside a structure,
@@ -385,7 +385,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 				memb_ptr2, ptr, LEFT,
 				elements[edx].tag_mode);
 		ASN_DEBUG("In %s SEQUENCE decoded %d %s in %d bytes code %d",
-			sd->name, edx, elements[edx].type->name,
+			td->name, edx, elements[edx].type->name,
 			(int)rval.consumed, rval.code);
 		switch(rval.code) {
 		case RC_OK:
@@ -409,7 +409,7 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 	case 4:	/* only 00's expected */
 
 		ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
-			sd->name, (long)ctx->left, (long)size);
+			td->name, (long)ctx->left, (long)size);
 
 		/*
 		 * Skip everything until the end of the SEQUENCE.
@@ -445,12 +445,12 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
 				}
 			}
 
-			if(!IN_EXTENSION_GROUP(specs, specs->elements_count)
+			if(!IN_EXTENSION_GROUP(specs, td->elements_count)
 			|| ctx->phase == 4) {
 				ASN_DEBUG("Unexpected continuation "
 					"of a non-extensible type "
 					"%s (SEQUENCE): %s",
-					sd->name,
+					td->name,
 					ber_tlv_tag_string(tlv_tag));
 				RETURN(RC_FAIL);
 			}
@@ -478,23 +478,22 @@ SEQUENCE_decode_ber(asn1_TYPE_descriptor_t *sd,
  * The DER encoder of the SEQUENCE type.
  */
 der_enc_rval_t
-SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
+SEQUENCE_encode_der(asn1_TYPE_descriptor_t *td,
 	void *ptr, int tag_mode, ber_tlv_tag_t tag,
 	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)sd->specifics;
 	size_t computed_size = 0;
 	der_enc_rval_t erval;
 	ssize_t ret;
 	int edx;
 
 	ASN_DEBUG("%s %s as SEQUENCE",
-		cb?"Encoding":"Estimating", sd->name);
+		cb?"Encoding":"Estimating", td->name);
 
 	/*
 	 * Gather the length of the underlying members sequence.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SEQUENCE_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
 		if(elm->optional) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
@@ -515,11 +514,11 @@ SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	ret = der_write_tags(sd, computed_size, tag_mode, tag, cb, app_key);
+	ret = der_write_tags(td, computed_size, tag_mode, tag, cb, app_key);
 	ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
 	if(ret == -1) {
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 		return erval;
 	}
@@ -530,8 +529,8 @@ SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Encode all members.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SEQUENCE_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		der_enc_rval_t tmperval;
 		void *memb_ptr;
 
@@ -548,7 +547,7 @@ SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
 			return tmperval;
 		computed_size -= tmperval.encoded;
 		ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %d bytes",
-			edx, elm->name, sd->name, tmperval.encoded);
+			edx, elm->name, td->name, tmperval.encoded);
 	}
 
 	if(computed_size != 0) {
@@ -556,7 +555,7 @@ SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
 		 * Encoded size is not equal to the computed size.
 		 */
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 	}
 
@@ -566,7 +565,6 @@ SEQUENCE_encode_der(asn1_TYPE_descriptor_t *sd,
 int
 SEQUENCE_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 		asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)td->specifics;
 	int edx;
 	int ret;
 
@@ -577,8 +575,8 @@ SEQUENCE_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	|| cb(" ::= {\n", 7, app_key))
 		return -1;
 
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SEQUENCE_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -614,7 +612,6 @@ SEQUENCE_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
 void
 SEQUENCE_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
-	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)td->specifics;
 	int edx;
 
 	if(!td || !sptr)
@@ -622,8 +619,8 @@ SEQUENCE_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
 
 	ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
 
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SEQUENCE_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
 		if(elm->optional) {
 			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
@@ -643,7 +640,6 @@ SEQUENCE_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
 int
 SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 		asn_app_consume_bytes_f *app_errlog, void *app_key) {
-	asn1_SEQUENCE_specifics_t *specs = (asn1_SEQUENCE_specifics_t *)td->specifics;
 	int edx;
 
 	if(!sptr) {
@@ -655,8 +651,8 @@ SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 	/*
 	 * Iterate over structure members and check their validity.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SEQUENCE_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -666,8 +662,20 @@ SEQUENCE_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		return elm->type->check_constraints(elm->type, memb_ptr,
-			app_errlog, app_key);
+		if(elm->memb_constraints) {
+			int ret = elm->memb_constraints(elm->type, memb_ptr,
+				app_errlog, app_key);
+			if(ret) return ret;
+		} else {
+			int ret = elm->type->check_constraints(elm->type,
+				memb_ptr, app_errlog, app_key);
+			if(ret) return ret;
+			/*
+			 * Cannot inherit it earlier:
+			 * need to make sure we get the updated version.
+			 */
+			elm->memb_constraints = elm->type->check_constraints;
+		}
 	}
 
 	return 0;
diff --git a/skeletons/constr_SEQUENCE.h b/skeletons/constr_SEQUENCE.h
index 17754bb57baf3d2f268ba045901ac6f5781ab4d3..1e282c2b88d930cb496863ee06d72d26d723c16d 100644
--- a/skeletons/constr_SEQUENCE.h
+++ b/skeletons/constr_SEQUENCE.h
@@ -7,18 +7,6 @@
 
 #include <constr_TYPE.h>
 
-/*
- * A single element of the SEQUENCE type.
- */
-typedef struct asn1_SEQUENCE_element_s {
-	int memb_offset;		/* Offset of the element */
-	int optional;			/* Whether the element is optional */
-	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
-	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
-	asn1_TYPE_descriptor_t *type;	/* Member type descriptor */
-	char *name;			/* ASN.1 identifier of the element */
-} asn1_SEQUENCE_element_t;
-
 typedef struct asn1_SEQUENCE_specifics_s {
 	/*
 	 * Target structure description.
@@ -26,12 +14,6 @@ typedef struct asn1_SEQUENCE_specifics_s {
 	int struct_size;	/* Size of the target structure. */
 	int ctx_offset;		/* Offset of the ber_dec_ctx_t member */
 
-	/*
-	 * Members of the SEQUENCE structure.
-	 */
-	asn1_SEQUENCE_element_t *elements;
-	int elements_count;
-
 	/*
 	 * Tags to members mapping table (sorted).
 	 */
diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c
index 0370a2d91a2edb241dad6966bf1a9018bd265e93..0a58f09a175805e3acd7c9d59a06ff6545c9ced2 100644
--- a/skeletons/constr_SEQUENCE_OF.c
+++ b/skeletons/constr_SEQUENCE_OF.c
@@ -9,18 +9,17 @@
  * The DER encoder of the SEQUENCE OF type.
  */
 der_enc_rval_t
-SEQUENCE_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
+SEQUENCE_OF_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
 	int tag_mode, ber_tlv_tag_t tag,
 	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)sd->specifics;
-	asn1_SET_OF_element_t *elm = specs->element;
+	asn1_TYPE_member_t *elm = td->elements;
 	A_SEQUENCE_OF(void) *list;
 	size_t computed_size = 0;
 	ssize_t encoding_size = 0;
 	der_enc_rval_t erval;
 	int edx;
 
-	ASN_DEBUG("Estimating size of SEQUENCE OF %s", sd->name);
+	ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);
 
 	/*
 	 * Gather the length of the underlying members sequence.
@@ -39,11 +38,11 @@ SEQUENCE_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	encoding_size = der_write_tags(sd, computed_size, tag_mode, tag,
+	encoding_size = der_write_tags(td, computed_size, tag_mode, tag,
 		cb, app_key);
 	if(encoding_size == -1) {
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 		return erval;
 	}
@@ -54,7 +53,7 @@ SEQUENCE_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 		return erval;
 	}
 
-	ASN_DEBUG("Encoding members of SEQUENCE OF %s", sd->name);
+	ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);
 
 	/*
 	 * Encode all members.
@@ -74,7 +73,7 @@ SEQUENCE_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 		 * Encoded size is not equal to the computed size.
 		 */
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 	} else {
 		erval.encoded = computed_size;
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index d1036c94f2515b8d5493867ad6f879fa9b85544c..d1a81beba9df2c63d0dbdc74f92cd25897f4c212 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -93,13 +93,13 @@ _t2e_cmp(const void *ap, const void *bp) {
  * The decoder of the SET type.
  */
 ber_dec_rval_t
-SET_decode_ber(asn1_TYPE_descriptor_t *sd,
+SET_decode_ber(asn1_TYPE_descriptor_t *td,
 	void **struct_ptr, void *ptr, size_t size, int tag_mode) {
 	/*
 	 * Bring closer parts of structure description.
 	 */
-	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)sd->specifics;
-	asn1_SET_element_t *elements = specs->elements;
+	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)td->specifics;
+	asn1_TYPE_member_t *elements = td->elements;
 
 	/*
 	 * Parts of the structure being constructed.
@@ -114,7 +114,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
 	int edx;			/* SET element's index */
 
-	ASN_DEBUG("Decoding %s as SET", sd->name);
+	ASN_DEBUG("Decoding %s as SET", td->name);
 	
 	/*
 	 * Create the target structure if it is not present already.
@@ -142,11 +142,11 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * perfectly fits our expectations.
 		 */
 
-		rval = ber_check_tags(sd, ctx, ptr, size,
+		rval = ber_check_tags(td, ctx, ptr, size,
 			tag_mode, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
-				sd->name, rval.code);
+				td->name, rval.code);
 			consumed_myself += rval.consumed;
 			RETURN(rval.code);
 		}
@@ -176,7 +176,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * canonical order of their tags. So, there is a room
 		 * for optimization.
 		 */
-	  for(edx = (ctx->step >> 1); edx < specs->elements_count;
+	  for(edx = (ctx->step >> 1); edx < td->elements_count;
 			ctx->step = (ctx->step & ~1) + 2,
 				edx = (ctx->step >> 1)) {
 		void *memb_ptr;		/* Pointer to the member */
@@ -247,7 +247,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 			} else if(specs->extensible == 0) {
 				ASN_DEBUG("Unexpected tag %s "
 					"in non-extensible SET %s",
-					ber_tlv_tag_string(tlv_tag), sd->name);
+					ber_tlv_tag_string(tlv_tag), td->name);
 				RETURN(RC_FAIL);
 			} else {
 				/* Skip this tag */
@@ -285,7 +285,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 */
 		if(ASN_SET_ISPRESENT2((char *)st + specs->pres_offset, edx)) {
 			ASN_DEBUG("SET %s: Duplicate element %s (%d)",
-				sd->name, elements[edx].name, edx);
+				td->name, elements[edx].name, edx);
 			RETURN(RC_FAIL);
 		}
 		
@@ -335,7 +335,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 	case 3:
 	case 4:	/* Only 00 is expected */
 		ASN_DEBUG("SET %s Leftover: %ld, size = %ld",
-			sd->name, (long)ctx->left, (long)size);
+			td->name, (long)ctx->left, (long)size);
 
 		/*
 		 * Skip everything until the end of the SET.
@@ -374,7 +374,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 			if(specs->extensible == 0 || ctx->phase == 4) {
 				ASN_DEBUG("Unexpected continuation "
 					"of a non-extensible type %s",
-					sd->name);
+					td->name);
 				RETURN(RC_FAIL);
 			}
 
@@ -395,7 +395,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 		/*
 		 * Check that all mandatory elements are present.
 		 */
-		for(edx = 0; edx < specs->elements_count;
+		for(edx = 0; edx < td->elements_count;
 			edx += (8 * sizeof(specs->_mandatory_elements[0]))) {
 			unsigned int midx, pres, must;
 
@@ -411,7 +411,7 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
 				ASN_DEBUG("One or more mandatory elements "
 					"of a SET %s %d (%08x.%08x)=%08x "
 					"are not present",
-					sd->name,
+					td->name,
 					midx,
 					pres,
 					must,
@@ -431,13 +431,13 @@ SET_decode_ber(asn1_TYPE_descriptor_t *sd,
  * The DER encoder of the SET type.
  */
 der_enc_rval_t
-SET_encode_der(asn1_TYPE_descriptor_t *sd,
+SET_encode_der(asn1_TYPE_descriptor_t *td,
 	void *ptr, int tag_mode, ber_tlv_tag_t tag,
 	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)sd->specifics;
+	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)td->specifics;
 	size_t computed_size = 0;
 	der_enc_rval_t my_erval;
-	int t2m_build_own = (specs->tag2el_count != specs->elements_count);
+	int t2m_build_own = (specs->tag2el_count != td->elements_count);
 	asn1_TYPE_tag2member_t *t2m;
 	int t2m_count;
 	ssize_t ret;
@@ -447,10 +447,10 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 	 * Use existing, or build our own tags map.
 	 */
 	if(t2m_build_own) {
-		(void *)t2m = alloca(specs->elements_count * sizeof(t2m[0]));
+		(void *)t2m = alloca(td->elements_count * sizeof(t2m[0]));
 		if(!t2m) {	/* There are such platforms */
 			my_erval.encoded = -1;
-			my_erval.failed_type = sd;
+			my_erval.failed_type = td;
 			my_erval.structure_ptr = ptr;
 			return my_erval;
 		}
@@ -467,8 +467,8 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Gather the length of the underlying members sequence.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SET_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		der_enc_rval_t erval;
 		void *memb_ptr;
 
@@ -513,7 +513,7 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Finalize order of the components.
 	 */
-	assert(t2m_count == specs->elements_count);
+	assert(t2m_count == td->elements_count);
 	if(t2m_build_own) {
 		/*
 		 * Sort the underlying members according to their
@@ -529,10 +529,10 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	ret = der_write_tags(sd, computed_size, tag_mode, tag, cb, app_key);
+	ret = der_write_tags(td, computed_size, tag_mode, tag, cb, app_key);
 	if(ret == -1) {
 		my_erval.encoded = -1;
-		my_erval.failed_type = sd;
+		my_erval.failed_type = td;
 		my_erval.structure_ptr = ptr;
 		return my_erval;
 	}
@@ -543,13 +543,13 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 	/*
 	 * Encode all members.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SET_element_t *elm;
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm;
 		der_enc_rval_t erval;
 		void *memb_ptr;
 
 		/* Encode according to the tag order */
-		elm = &specs->elements[t2m[edx].el_no];
+		elm = &td->elements[t2m[edx].el_no];
 
 		if(elm->optional) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
@@ -570,7 +570,7 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 		 * Encoded size is not equal to the computed size.
 		 */
 		my_erval.encoded = -1;
-		my_erval.failed_type = sd;
+		my_erval.failed_type = td;
 		my_erval.structure_ptr = ptr;
 	}
 
@@ -580,7 +580,6 @@ SET_encode_der(asn1_TYPE_descriptor_t *sd,
 int
 SET_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 		asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)td->specifics;
 	int edx;
 	int ret;
 
@@ -591,8 +590,8 @@ SET_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	|| cb(" ::= {\n", 7, app_key))
 		return -1;
 
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SET_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -627,7 +626,6 @@ SET_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
 void
 SET_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
-	asn1_SET_specifics_t *specs = (asn1_SET_specifics_t *)td->specifics;
 	int edx;
 
 	if(!td || !ptr)
@@ -635,8 +633,8 @@ SET_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 
 	ASN_DEBUG("Freeing %s as SET", td->name);
 
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SET_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		void *memb_ptr;
 		if(elm->optional) {
 			memb_ptr = *(void **)((char *)ptr + elm->memb_offset);
@@ -668,8 +666,8 @@ SET_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 	/*
 	 * Iterate over structure members and check their validity.
 	 */
-	for(edx = 0; edx < specs->elements_count; edx++) {
-		asn1_SET_element_t *elm = &specs->elements[edx];
+	for(edx = 0; edx < td->elements_count; edx++) {
+		asn1_TYPE_member_t *elm = &td->elements[edx];
 		const void *memb_ptr;
 
 		if(elm->optional) {
@@ -689,8 +687,20 @@ SET_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		return elm->type->check_constraints(elm->type, memb_ptr,
-			app_errlog, app_key);
+		if(elm->memb_constraints) {
+			int ret = elm->memb_constraints(elm->type, memb_ptr,
+				app_errlog, app_key);
+			if(ret) return ret;
+		} else {
+			int ret = elm->type->check_constraints(elm->type,
+				memb_ptr, app_errlog, app_key);
+			if(ret) return ret;
+			/*
+			 * Cannot inherit it earlier:
+			 * need to make sure we get the updated version.
+			 */
+			elm->memb_constraints = elm->type->check_constraints;
+		}
 	}
 
 	return 0;
diff --git a/skeletons/constr_SET.h b/skeletons/constr_SET.h
index 8cb3fa8d31ac92b482b7b3cd49873a5af72ee254..eab2c3070b1adecca56156edf06f0fc4e61424e5 100644
--- a/skeletons/constr_SET.h
+++ b/skeletons/constr_SET.h
@@ -7,18 +7,6 @@
 
 #include <constr_TYPE.h>
 
-/*
- * Description of a single element of the SET type.
- */
-typedef struct asn1_SET_element_s {
-	int memb_offset;		/* Offset of the element */
-	int optional;			/* Whether the element is optional */
-	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
-	int tag_mode;		/* IMPLICIT/no/EXPLICIT tag at current level */
-	asn1_TYPE_descriptor_t *type;	/* Member type descriptor */
-	char *name;			/* ASN.1 identifier of the element */
-} asn1_SET_element_t;
-
 
 typedef struct asn1_SET_specifics_s {
 	/*
@@ -28,12 +16,6 @@ typedef struct asn1_SET_specifics_s {
 	int ctx_offset;		/* Offset of the ber_dec_ctx_t member */
 	int pres_offset;	/* Offset of _presence_map member */
 
-	/*
-	 * Members of the SET structure.
-	 */
-	asn1_SET_element_t *elements;
-	int elements_count;
-
 	/*
 	 * Tags to members mapping table (sorted).
 	 */
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index 511207d2a3bcb8b3ccbdf01307156f5ac67fd728..ecf16f02ff543f9e70a80bcac668a60186b8adcd 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -60,13 +60,13 @@
  * The decoder of the SET OF type.
  */
 ber_dec_rval_t
-SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
+SET_OF_decode_ber(asn1_TYPE_descriptor_t *td,
 	void **struct_ptr, void *ptr, size_t size, int tag_mode) {
 	/*
 	 * Bring closer parts of structure description.
 	 */
-	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)sd->specifics;
-	asn1_SET_OF_element_t *element = specs->element;
+	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
+	asn1_TYPE_member_t *element = td->elements;	/* Single one */
 
 	/*
 	 * Parts of the structure being constructed.
@@ -80,7 +80,7 @@ SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
 
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
 
-	ASN_DEBUG("Decoding %s as SET OF", sd->name);
+	ASN_DEBUG("Decoding %s as SET OF", td->name);
 	
 	/*
 	 * Create the target structure if it is not present already.
@@ -108,11 +108,11 @@ SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 * perfectly fits our expectations.
 		 */
 
-		rval = ber_check_tags(sd, ctx, ptr, size,
+		rval = ber_check_tags(td, ctx, ptr, size,
 			tag_mode, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
-				sd->name, rval.code);
+				td->name, rval.code);
 			consumed_myself += rval.consumed;
 			RETURN(rval.code);
 		}
@@ -143,7 +143,7 @@ SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
 		 */
 
 		if(ctx->left == 0) {
-			ASN_DEBUG("End of SET OF %s", sd->name);
+			ASN_DEBUG("End of SET OF %s", td->name);
 			/*
 			 * No more things to decode.
 			 * Exit out of here.
@@ -185,9 +185,9 @@ SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
 			 */
 		    } else {
 			ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
-				ber_tlv_tag_string(tlv_tag), sd->name);
+				ber_tlv_tag_string(tlv_tag), td->name);
 			ASN_DEBUG("%s SET OF has tag %s",
-				sd->name, ber_tlv_tag_string(element->tag));
+				td->name, ber_tlv_tag_string(element->tag));
 			RETURN(RC_FAIL);
 		    }
 		}
@@ -204,7 +204,7 @@ SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
 		rval = element->type->ber_decoder(element->type,
 				&ctx->ptr, ptr, LEFT, 0);
 		ASN_DEBUG("In %s SET OF %s code %d consumed %d",
-			sd->name, element->type->name,
+			td->name, element->type->name,
 			rval.code, (int)rval.consumed);
 		switch(rval.code) {
 		case RC_OK:
@@ -305,11 +305,10 @@ static int _el_buf_cmp(const void *ap, const void *bp) {
  * The DER encoder of the SET OF type.
  */
 der_enc_rval_t
-SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
+SET_OF_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
 	int tag_mode, ber_tlv_tag_t tag,
 	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)sd->specifics;
-	asn1_SET_OF_element_t *elm = specs->element;
+	asn1_TYPE_member_t *elm = td->elements;
 	asn1_TYPE_descriptor_t *elm_type = elm->type;
 	der_type_encoder_f *der_encoder = elm_type->der_encoder;
 	A_SET_OF(void) *list;
@@ -321,7 +320,7 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 	int ret;
 	int edx;
 
-	ASN_DEBUG("Estimating size for SET OF %s", sd->name);
+	ASN_DEBUG("Estimating size for SET OF %s", td->name);
 
 	/*
 	 * Gather the length of the underlying members sequence.
@@ -342,11 +341,11 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	encoding_size = der_write_tags(sd, computed_size, tag_mode, tag,
+	encoding_size = der_write_tags(td, computed_size, tag_mode, tag,
 		cb, app_key);
 	if(encoding_size == -1) {
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 		return erval;
 	}
@@ -365,12 +364,12 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 	(void *)encoded_els = MALLOC(list->count * sizeof(encoded_els[0]));
 	if(encoded_els == NULL) {
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 		return erval;
 	}
 
-	ASN_DEBUG("Encoding members of %s SET OF", sd->name);
+	ASN_DEBUG("Encoding members of %s SET OF", td->name);
 
 	/*
 	 * Encode all members.
@@ -391,7 +390,7 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 				FREEMEM(encoded_els[edx].buf);
 			FREEMEM(encoded_els);
 			erval.encoded = -1;
-			erval.failed_type = sd;
+			erval.failed_type = td;
 			erval.structure_ptr = ptr;
 			return erval;
 		}
@@ -436,7 +435,7 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 		 * encoded size is not equal to the computed size.
 		 */
 		erval.encoded = -1;
-		erval.failed_type = sd;
+		erval.failed_type = td;
 		erval.structure_ptr = ptr;
 	} else {
 		erval.encoded = computed_size;
@@ -448,8 +447,7 @@ SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
 int
 SET_OF_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 		asn_app_consume_bytes_f *cb, void *app_key) {
-	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
-	asn1_SET_OF_element_t *element = specs->element;
+	asn1_TYPE_member_t *element = td->elements;
 	const A_SET_OF(void) *list;
 	int ret;
 	int i;
@@ -486,8 +484,7 @@ SET_OF_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 void
 SET_OF_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 	if(td && ptr) {
-		asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
-		asn1_SET_OF_element_t *element = specs->element;
+		asn1_TYPE_member_t *element = td->elements;
 		A_SET_OF(void) *list;
 		int i;
 
@@ -514,8 +511,8 @@ SET_OF_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 int
 SET_OF_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 		asn_app_consume_bytes_f *app_errlog, void *app_key) {
-	asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
-	asn1_SET_OF_element_t *element = specs->element;
+	asn1_TYPE_member_t *element = td->elements;
+	asn_constr_check_f *constr;
 	const A_SET_OF(void) *list;
 	int i;
 
@@ -526,12 +523,30 @@ SET_OF_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 	}
 
 	(const void *)list = sptr;
+
+	constr = element->memb_constraints;
+	if(!constr) constr = element->type->check_constraints;
+
+	/*
+	 * Iterate over the members of an array.
+	 * Validate each in turn, until one fails.
+	 */
 	for(i = 0; i < list->count; i++) {
 		const void *memb_ptr = list->array[i];
+		int ret;
+
 		if(!memb_ptr) continue;
-		return element->type->check_constraints(element->type, memb_ptr,
-			app_errlog, app_key);
+
+		ret = constr(element->type, memb_ptr, app_errlog, app_key);
+		if(ret) return ret;
 	}
 
+	/*
+	 * Cannot inherit it eralier:
+	 * need to make sure we get the updated version.
+	 */
+	if(!element->memb_constraints)
+		element->memb_constraints = element->type->check_constraints;
+
 	return 0;
 }
diff --git a/skeletons/constr_SET_OF.h b/skeletons/constr_SET_OF.h
index e2c6d8fd0cc438e8870a5aa4c8399df5f572defb..0dd6040b6ce9b00770c986babd4a977455f7e16c 100644
--- a/skeletons/constr_SET_OF.h
+++ b/skeletons/constr_SET_OF.h
@@ -7,22 +7,12 @@
 
 #include <constr_TYPE.h>
 
-typedef struct asn1_SET_OF_element_s {
-	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
-	asn1_TYPE_descriptor_t *type;	/* Member type descriptor */
-} asn1_SET_OF_element_t;
-
 typedef struct asn1_SET_OF_specifics_s {
 	/*
 	 * Target structure description.
 	 */
 	int struct_size;	/* Size of the target structure. */
 	int ctx_offset;		/* Offset of the ber_dec_ctx_t member */
-
-	/*
-	 * Members of the SET OF list.
-	 */
-	asn1_SET_OF_element_t *element;
 } asn1_SET_OF_specifics_t;
 
 /*
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index da3a2db7f77a550e112e9254444db33cd05b2e36..67f9c55ec20d0fd325f5ba7438190fa23ebf59c2 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -13,6 +13,7 @@
 #include <constraints.h>
 
 struct asn1_TYPE_descriptor_s;	/* Forward declaration */
+struct asn1_TYPE_member_s;	/* Forward declaration */
 
 /*
  * Free the structure according to its specification.
@@ -43,7 +44,7 @@ typedef int (asn_struct_print_f)(
 typedef ber_tlv_tag_t (asn_outmost_tag_f)(
 		struct asn1_TYPE_descriptor_s *type_descriptor,
 		const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag);
-/* The instance of the above function type */
+/* The instance of the above function type; used internally. */
 asn_outmost_tag_f asn1_TYPE_outmost_tag;
 
 
@@ -76,6 +77,12 @@ typedef struct asn1_TYPE_descriptor_s {
 	int tags_impl_skip;	/* Tags to skip in implicit mode */
 	int last_tag_form;	/* Acceptable form of the tag (prim, constr) */
 
+	/*
+	 * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
+	 */
+	struct asn1_TYPE_member_s *elements;
+	int elements_count;
+
 	/*
 	 * Additional information describing the type, used by appropriate
 	 * functions above.
@@ -83,6 +90,19 @@ typedef struct asn1_TYPE_descriptor_s {
 	void *specifics;
 } asn1_TYPE_descriptor_t;
 
+/*
+ * An element of the constructed type, i.e. SEQUENCE, SET, CHOICE.
+ */
+typedef struct asn1_TYPE_member_s {
+	int optional;			/* Whether the element is optional */
+	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 */
+	asn1_TYPE_descriptor_t *type;	/* Member type descriptor */
+	asn_constr_check_f *memb_constraints;	/* Constraints validator */
+	char *name;			/* ASN.1 identifier of the element */
+} asn1_TYPE_member_t;
+
 /*
  * BER tag to element number mapping.
  */