diff --git a/compiler2/compiler.1 b/compiler2/compiler.1 index 3731ec689fee17b8054bef4adf79ac13c316d5ec..d64cc88fbcbea83bc59f522c82734370aa489637 100644 --- a/compiler2/compiler.1 +++ b/compiler2/compiler.1 @@ -69,6 +69,12 @@ Disables the generation of .I BER encoder/decoder routines for all ASN.1 types. .TP +.B \-B +Allows the selected field in a union value to be unbound, when setting module +parameters (legacy behavior). A warning is displayed whenever a union value +receives an unbound selected field and when a union with an unbound selected field +is copied. +.TP .B \-c Write out .I checksums diff --git a/compiler2/main.cc b/compiler2/main.cc index 46890454c902db3c42ff467f256e78ded52939e5..5e6cfd5bc3d2e8c2fa4eae7970a320f619a12edf 100644 --- a/compiler2/main.cc +++ b/compiler2/main.cc @@ -94,7 +94,8 @@ boolean generate_skeleton = FALSE, force_overwrite = FALSE, check_subtype = TRUE, suppress_context = FALSE, display_up_to_date = FALSE, implicit_json_encoding = FALSE, json_refs_for_all_types = TRUE, force_gen_seof = FALSE, omit_in_value_list = FALSE, - warnings_for_bad_variants = FALSE, debugger_active = FALSE; + warnings_for_bad_variants = FALSE, debugger_active = FALSE, + legacy_unbound_union_fields = FALSE; // Default code splitting mode is set to 'no splitting'. CodeGenHelper::split_type code_splitting_mode = CodeGenHelper::SPLIT_NONE; @@ -392,6 +393,7 @@ static void usage() "OPTIONS:\n" " -a: force XER in ASN.1 files\n" " -b: disable BER encoder/decoder functions\n" + " -B: allow selected union field to be unbound (legacy behavior)\n" " -c: write out checksums in case of error\n" " -d: treat default fields as omit\n" " -E: display only warnings for unrecognized encoding variants\n" @@ -479,7 +481,7 @@ int main(int argc, char *argv[]) dflag = false, Xflag = false, Rflag = false, gflag = false, aflag = false, s0flag = false, Cflag = false, yflag = false, Uflag = false, Qflag = false, Sflag = false, Kflag = false, jflag = false, zflag = false, Fflag = false, - Mflag = false, Eflag = false, nflag = false, errflag = false, + Mflag = false, Eflag = false, nflag = false, Bflag = false, errflag = false, print_usage = false, ttcn2json = false; CodeGenHelper cgh; @@ -572,7 +574,7 @@ int main(int argc, char *argv[]) if (!ttcn2json) { for ( ; ; ) { - int c = getopt(argc, argv, "aA:bcC:dEfFgijK:lLMno:pP:qQ:rRsStT:uU:vV:wxXyYz:0-"); + int c = getopt(argc, argv, "aA:bBcC:dEfFgijK:lLMno:pP:qQ:rRsStT:uU:vV:wxXyYz:0-"); if (c == -1) break; switch (c) { case 'a': @@ -747,6 +749,10 @@ int main(int argc, char *argv[]) SET_FLAG(n); debugger_active = TRUE; break; + case 'B': + SET_FLAG(B); + legacy_unbound_union_fields = TRUE; + break; case 'Q': { long max_errs; @@ -792,7 +798,7 @@ int main(int argc, char *argv[]) bflag || fflag || iflag || lflag || oflag || pflag || qflag || rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag || Uflag || yflag || Kflag || jflag || zflag || Fflag || Mflag || Eflag || - nflag) { + nflag || Bflag) { errflag = true; print_usage = true; } diff --git a/compiler2/main.hh b/compiler2/main.hh index 2192b32dfc1d51df62e85c765567a017b90692e8..f9d554259a730d3c625b90af6ad2e587f56dd837 100644 --- a/compiler2/main.hh +++ b/compiler2/main.hh @@ -49,7 +49,8 @@ extern boolean generate_skeleton, force_overwrite, include_line_info, output_only_linenum, default_as_optional, use_runtime_2, gcc_compat, asn1_xer, check_subtype, suppress_context, enable_set_bound_out_param, display_up_to_date, implicit_json_encoding, json_refs_for_all_types, force_gen_seof, - omit_in_value_list, warnings_for_bad_variants, debugger_active; + omit_in_value_list, warnings_for_bad_variants, debugger_active, + legacy_unbound_union_fields; extern const char *expected_platform; diff --git a/compiler2/union.c b/compiler2/union.c index ecb37a16a40630df1d97c5e463e1a959aaf4c4c7..72dbbd068468ffe0dc0d02281738ee9fc6a59afe 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -136,10 +136,22 @@ void defUnionClass(struct_def const *sdef, output_struct *output) "{\n" "switch (other_value.union_selection) {\n", name, name); for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "case %s_%s:\n" - "field_%s = new %s(*other_value.field_%s);\n" - "break;\n", selection_prefix, sdef->elements[i].name, + src = mputprintf(src, "case %s_%s:\n", selection_prefix, sdef->elements[i].name); + if (legacy_unbound_union_fields) { + src = mputprintf(src, "if (other_value.field_%s->is_bound()) ", + sdef->elements[i].name); + } + src = mputprintf(src, "field_%s = new %s(*other_value.field_%s);\n", sdef->elements[i].name, sdef->elements[i].type, sdef->elements[i].name); + if (legacy_unbound_union_fields) { + src = mputprintf(src, + "else {\n" + "field_%s = new %s;\n" + "TTCN_warning(\"Assignment of a union value with an unbound selected " + "alternative\");\n" + "}\n", sdef->elements[i].name, sdef->elements[i].type); + } + src = mputstr(src, "break;\n"); } src = mputprintf(src, "default:\n" "TTCN_error(\"Assignment of an unbound union value of type %s.\");\n" @@ -383,16 +395,27 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " }\n" " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n", dispname); - for (i = 0; i < sdef->nElements; i++) { + for (i = 0; i < sdef->nElements; i++) { src = mputprintf(src, " if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n" " %s%s().set_param(*mp_last);\n" + " if (!%s%s().is_bound()) " + , sdef->elements[i].dispname, at_field, sdef->elements[i].name + , at_field, sdef->elements[i].name); + if (legacy_unbound_union_fields) { + src = mputprintf(src, + "TTCN_warning(\"Alternative '%s' was selected for union of type '%s', " + "but its value is unbound\");\n" + , sdef->elements[i].dispname, sdef->dispname); + } + else { // a union's alternative cannot be unbound - " if (!%s%s().is_bound()) clean_up();\n" - " return;\n" - " }\n", sdef->elements[i].dispname, at_field, sdef->elements[i].name, - at_field, sdef->elements[i].name); + src = mputstr(src, "clean_up();\n"); } + src = mputstr(src, + " return;\n" + " }\n"); + } src = mputprintf(src, " mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n" "}\n\n", dispname); diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index b56d7638e3abceaa276e012bb5ef2690b7fc6c00..ab39bebf3e1d51cf20152dcc8d9aa2ebbfd16489 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ