diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 2a02327609d93e9f577363f213406282d11fe261..1a403127e4647ec8e1d1b4fd376eb4df14586204 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -2129,18 +2129,36 @@ namespace Common { size_t nof_subrefs = subrefs->get_nof_refs(); if (nof_subrefs < 1) return false; Ttcn::FieldOrArrayRef *last_ref = subrefs->get_ref(nof_subrefs - 1); - if (last_ref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) return false; + if (last_ref->get_type() != Ttcn::FieldOrArrayRef::FIELD_REF) return false; // following the embedded types Type *t=get_type_refd_last(); for (size_t i = 0; i < nof_subrefs - 1; i++) { Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i); - if (ref->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF) - t = t->get_comp_byName(*ref->get_id())->get_type(); - else t = t->get_ofType(); + switch (ref->get_type()) { + case Ttcn::FieldOrArrayRef::FIELD_REF: + t = (t->typetype == T_CLASS) ? + t->get_class_type_body()->get_local_ass_byId(*ref->get_id())->get_Type() : + t->get_comp_byName(*ref->get_id())->get_type(); + break; + case Ttcn::FieldOrArrayRef::ARRAY_REF: + t = t->get_ofType(); + break; + case Ttcn::FieldOrArrayRef::FUNCTION_REF: + if (t->get_class_type_body()->has_local_ass_withId(*ref->get_id())) { + t = t->get_class_type_body()->get_local_ass_byId(*ref->get_id())->get_Type(); + } + else { + t = Ttcn::ClassTypeBody::get_object_method_return_type(ref->get_id()->get_name()); + } + break; + default: + FATAL_ERROR("Type::field_is_optional"); + } t=t->get_type_refd_last(); } // now last_ref refers to a field of t - return t->get_comp_byName(*last_ref->get_id())->get_is_optional(); + return t->typetype != T_CLASS && + t->get_comp_byName(*last_ref->get_id())->get_is_optional(); } bool Type::is_root_basic(){ @@ -5962,6 +5980,37 @@ namespace Common { else return CT_CUSTOM; } + + bool Type::contains_class() + { + // this helps avoid infinite recursions in self-referencing types + if (RecursionTracker::is_happening(this)) { + return false; + } + RecursionTracker tracker(this); + switch (typetype) { + case T_CLASS: + return true; + case T_REFD: + return get_type_refd_last()->contains_class(); + case T_SEQ_T: + case T_SET_T: + case T_CHOICE_T: + for (size_t i = 0; i < u.secho.cfm->get_nof_comps(); ++i) { + if (u.secho.cfm->get_comp_byIndex(i)->get_type()->contains_class()) { + return true; + } + } + return false; + case T_SEQOF: + case T_SETOF: + case T_ARRAY: + return get_ofType()->contains_class(); + default: + return false; + } + } + bool Type::has_ei_withName(const Identifier& p_id) const { switch (typetype) { diff --git a/compiler2/Type.hh b/compiler2/Type.hh index 7f478a1477dfa5a93dc6773ca112ece81f556f67..6b04f426f9ab48df6753971a1bb551e2e7728d13 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -864,6 +864,8 @@ namespace Common { static MessageEncodingType_t get_enc_type(const string& enc); + bool contains_class(); + private: void chk_Int_A(); void chk_Enum_A(); diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 599a5e47b3b86c8811514f6a1c982353be472c49..a955b96f272cd8054f072b9c86f4f30825716cdc 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -3807,10 +3807,6 @@ void Type::chk_embedded(bool default_allowed, const char *error_msg) case T_DEFAULT: if (!default_allowed) error("Default type cannot be %s", error_msg); break; - case T_CLASS: - error("Class type `%s' cannot be %s", t->get_typename().c_str(), - error_msg); - break; default: break; } diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index 649ae034ae8abf12ff576b54f91f5bba0723dfab..8ea087707fa0f09ba396842b64de49ae6f7aa42c 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -253,6 +253,9 @@ void Type::generate_code_embedded_after(output_struct *target) void Type::generate_code_typedescriptor(output_struct *target) { + if (contains_class()) { + return; + } bool force_xer = FALSE; switch (get_type_refd_last()->typetype) { case T_PORT: @@ -1588,8 +1591,13 @@ void Type::generate_code_Choice(output_struct *target) sdef.xerUseUnion = xerattrib->useUnion_; sdef.xerUseTypeAttr = xerattrib->useType_ || xerattrib->useUnion_; } + + sdef.containsClass = contains_class(); + defUnionClass(&sdef, target); - defUnionTemplate(&sdef, target); + if (!sdef.containsClass) { + defUnionTemplate(&sdef, target); + } free_code_ot(sdef.ot); sdef.ot=0; @@ -2262,8 +2270,12 @@ void Type::generate_code_Se(output_struct *target) } } + sdef.containsClass = contains_class(); + defRecordClass(&sdef, target); - defRecordTemplate(&sdef, target); + if (!sdef.containsClass) { + defRecordTemplate(&sdef, target); + } for(size_t i = 0; i < sdef.totalElements; i++) { // free the array but not the strings @@ -2434,12 +2446,16 @@ void Type::generate_code_SeOf(output_struct *target) } } + sofdef.containsClass = contains_class(); + if (optimized_memalloc) { defRecordOfClassMemAllocOptimized(&sofdef, target); } else { defRecordOfClass(&sofdef, target); } - defRecordOfTemplate(&sofdef, target); + if (!sofdef.containsClass) { + defRecordOfTemplate(&sofdef, target); + } if (sofdef.nFollowers) { Free(sofdef.followers); @@ -2478,10 +2494,12 @@ void Type::generate_code_Array(output_struct *target) u.array.dimension->get_value_type(u.array.element_type, my_scope).c_str(), own_name); } - target->header.typedefs = mputprintf(target->header.typedefs, - "typedef %s %s_template;\n", - u.array.dimension->get_template_type(u.array.element_type, my_scope).c_str(), - own_name); + if (!contains_class()) { + target->header.typedefs = mputprintf(target->header.typedefs, + "typedef %s %s_template;\n", + u.array.dimension->get_template_type(u.array.element_type, my_scope).c_str(), + own_name); + } } void Type::generate_code_Fat(output_struct *target) @@ -2971,6 +2989,7 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, Type *t = this; Type *next_t; bool next_o; // next is optional value + bool next_is_class; size_t nof_refs = subrefs->get_nof_refs(); subrefs->clear_string_element_ref(); char *tmp_generalid_str = mcopystr(external_id.c_str()); @@ -3037,6 +3056,7 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, next_t = cf->get_type(); next_o = !is_template && cf->get_is_optional(); } + next_is_class = next_t->get_type_refd_last()->typetype == T_CLASS; switch (t->typetype) { case T_CHOICE_A: @@ -3172,7 +3192,6 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, const string& tmp_id2 = module->get_temporary_id(); const char *tmp_id_str = tmp_id.c_str(); const char *tmp_id2_str = tmp_id2.c_str(); - bool next_is_class = next_t->get_type_refd_last()->typetype == T_CLASS; if (t->typetype == T_CLASS) { expr->expr = mputprintf(expr->expr, "%s%s%s %s = %s->%s;\n", @@ -3192,9 +3211,10 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, // If we would get the const ref of the field immediately then the // value in the const ref would be free-d instantly. expr->expr = mputprintf(expr->expr, - "const %s%s& %s = %s.%s%s();\n", + "%s%s%s%s %s = %s.%s%s();\n", + next_is_class ? "" : "const ", next_t->get_genname_value(module).c_str(), - is_template ? "_template" : "", + is_template ? "_template" : "", next_is_class ? "" : "&", tmp_id2_str, tmp_id_str, t->typetype == T_ANYTYPE ? "AT_" : "", id.get_name().c_str()); } @@ -3255,7 +3275,7 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, const string& tmp_id = module->get_temporary_id(); const char *tmp_id_str = tmp_id.c_str(); - bool next_is_class = next_t->get_type_refd_last()->typetype == T_CLASS; + next_is_class = next_t->get_type_refd_last()->typetype == T_CLASS; expr->expr = mputprintf(expr->expr, "%s%s%s %s = %s->%s(", next_is_class ? "" : "const ", next_t->get_genname_value(module).c_str(), @@ -3346,6 +3366,7 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, } next_t = embedded_type; + next_is_class = next_t->get_type_refd_last()->typetype == T_CLASS; // check the index value Value *index_value = ref->get_val(); @@ -3386,21 +3407,21 @@ void Type::generate_code_ispresentboundchosen(expression_struct *expr, } else { if (is_template) { expr->expr = mputprintf(expr->expr, - "const %s& %s = %s[%s];\n", - next_t->get_genname_template(module).c_str(), - tmp_id_str, tmp_generalid_str, + "%s%s%s %s = %s[%s];\n", + next_is_class ? "" : "const ", next_t->get_genname_template(module).c_str(), + next_is_class ? "" : "&", tmp_id_str, tmp_generalid_str, tmp_index_id_str); } else { expr->expr = mputprintf(expr->expr, - "const %s%s& %s = %s[%s];\n", - next_t->get_genname_value(module).c_str(), - is_template?"_template":"", tmp_id_str, tmp_generalid_str, + "%s%s%s%s %s = %s[%s];\n", + next_is_class ? "" : "const ", next_t->get_genname_value(module).c_str(), + is_template?"_template":"", next_is_class ? "" : "&", tmp_id_str, tmp_generalid_str, tmp_index_id_str); } if (i != nof_refs - 1 || optype == ISCHOSEN) { - expr->expr = mputprintf(expr->expr, "%s = %s.is_bound();\n", - global_id.c_str(), tmp_id_str); + expr->expr = mputprintf(expr->expr, "%s = %s.is_%s();\n", + global_id.c_str(), tmp_id_str, next_is_class ? "present" : "bound"); } if (i == nof_refs - 1) { switch (optype) { diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 7a813b8a0c44acd35dcff2abbc1ec7c5f7b525ea..d3be753553df111cb2b1b43399affe7078aa4241 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -14523,28 +14523,34 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case OPTYPE_ISBOUND: { Template::templatetype_t temp = u.expr.ti1->get_Template() ->get_templatetype(); - // TODO: use get_refd_assignment instead to determine whether it's a template? + Ttcn::Reference* reference = NULL; if (temp == Template::SPECIFIC_VALUE) { - Value* specific_value = u.expr.ti1->get_Template() - ->get_specific_value(); + Value* specific_value = u.expr.ti1->get_Template()->get_specific_value(); if (specific_value->get_valuetype() == Value::V_REFD) { - Ttcn::Reference* reference = - dynamic_cast(specific_value->get_reference()); - if (reference != NULL && !reference->has_parameters()) { - reference->generate_code_ispresentboundchosen(expr, false, - u.expr.v_optype, NULL); - break; - } - } - } else if (temp == Template::TEMPLATE_REFD) { - Ttcn::Reference* reference = - dynamic_cast(u.expr.ti1->get_Template() - ->get_reference()); - if (reference != NULL && !reference->has_parameters()) { - reference->generate_code_ispresentboundchosen(expr, true, - u.expr.v_optype, NULL); - break; - } + reference = dynamic_cast(specific_value->get_reference()); + } + } + else if (temp == Template::TEMPLATE_REFD) { + reference = dynamic_cast(u.expr.ti1->get_Template()->get_reference()); + } + if (reference != NULL && !reference->has_parameters()) { + bool is_template = false; + switch (reference->get_refd_assignment()->get_asstype()) { + case Assignment::A_TEMPLATE: + case Assignment::A_VAR_TEMPLATE: + case Assignment::A_MODULEPAR_TEMP: + case Assignment::A_FUNCTION_RTEMP: + case Assignment::A_EXT_FUNCTION_RTEMP: + case Assignment::A_PAR_TEMPL_IN: + case Assignment::A_PAR_TEMPL_INOUT: + case Assignment::A_PAR_TEMPL_OUT: + is_template = true; + break; + default: + break; + } + reference->generate_code_ispresentboundchosen(expr, is_template, u.expr.v_optype, NULL); + break; } } // no break @@ -16813,7 +16819,6 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case V_NAMEDBITS: case V_UNDEF_LOWERID: case V_UNDEF_BLOCK: - case V_TTCN3_NULL: // these values cannot occur during code generation FATAL_ERROR("Value::needs_temp_ref()"); case V_INT: diff --git a/compiler2/datatypes.h b/compiler2/datatypes.h index 000ebdb298ceb1d668c144a039730ad0cf33a60c..2bbc51e932652d14c372182ba737460a3e8c516a 100644 --- a/compiler2/datatypes.h +++ b/compiler2/datatypes.h @@ -134,6 +134,7 @@ typedef struct { boolean opentype_outermost; Opentype_t *ot; boolean isOptional; /**< this structure is an optional field in a record/set */ + boolean containsClass; } struct_def; /** record of, set of descriptor for code generation */ @@ -161,6 +162,7 @@ typedef struct { const char *oftypedescrname; /**< Type descr. variable of the elements */ size_t nFollowers; /**< number of optional fields following the record-of */ struct_field *followers; /**< information about following optional siblings */ + boolean containsClass; } struct_of_def; /* for processing enumerated type definitions */ diff --git a/compiler2/record.c b/compiler2/record.c index f054413d7b2c96be42b009883a1216528fdd3dcc..9b58b03e5728128043e5e83db6d2c35628b4a000 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -54,7 +54,7 @@ static void defRecordTemplate2(const struct_def *sdef, output_struct *output); void defRecordClass(const struct_def *sdef, output_struct *output) { - if (use_runtime_2) defRecordClass2(sdef, output); + if (use_runtime_2 && !sdef->containsClass) defRecordClass2(sdef, output); else defRecordClass1(sdef, output); } @@ -3643,12 +3643,12 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) const char *name = sdef->name, *dispname = sdef->dispname; const char* kind_str = sdef->kind == SET ? "set" : "record"; char *def = NULL, *src = NULL; - boolean ber_needed = sdef->isASN1 && enable_ber(); - boolean raw_needed = sdef->hasRaw && enable_raw(); - boolean text_needed = sdef->hasText && enable_text(); - boolean xer_needed = sdef->hasXer && enable_xer(); - boolean json_needed = sdef->hasJson && enable_json(); - boolean oer_needed = sdef->hasOer && enable_oer(); + boolean ber_needed = sdef->isASN1 && !sdef->containsClass && enable_ber(); + boolean raw_needed = sdef->hasRaw && !sdef->containsClass && enable_raw(); + boolean text_needed = sdef->hasText && !sdef->containsClass && enable_text(); + boolean xer_needed = sdef->hasXer && !sdef->containsClass && enable_xer(); + boolean json_needed = sdef->hasJson && !sdef->containsClass && enable_json(); + boolean oer_needed = sdef->hasOer && !sdef->containsClass && enable_oer(); /* class declaration code */ output->header.class_decls = mputprintf(output->header.class_decls, @@ -3755,10 +3755,15 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) src = mputstr(src, "}\n\n"); - def = mputstr(def, "const TTCN_Typedescriptor_t* get_descriptor() const;\n"); - src = mputprintf(src, - "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n", - name, name); + if (!sdef->containsClass) { + def = mputstr(def, "const TTCN_Typedescriptor_t* get_descriptor() const;\n"); + src = mputprintf(src, + "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n", + name, name); + } + else if (use_runtime_2) { // need to implement this, cause it's abstract in RT2 + def = mputstr(def, "const TTCN_Typedescriptor_t* get_descriptor() const { return NULL; }\n"); + } /* = operator */ def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name); @@ -3922,90 +3927,103 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) } src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n"); - /* set param function */ - def = mputstr(def, " void set_param(Module_Param& param);\n"); - src = mputprintf - (src, - "void %s::set_param(Module_Param& param)\n{\n" - " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n" - " switch (param.get_type()) {\n" - " case Module_Param::MP_Value_List:\n" - " if (%lunElements, kind_str, dispname, (unsigned long)sdef->nElements); - - for (i = 0; i < sdef->nElements; ++i) { - src = mputprintf(src, - " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n", - (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); - } - src = mputstr(src, - " break;\n" - " case Module_Param::MP_Assignment_List: {\n" - " Vector value_used(param.get_size());\n" - " value_used.resize(param.get_size(), FALSE);\n"); - for (i = 0; i < sdef->nElements; ++i) { - src = mputprintf(src, - " for (size_t val_idx=0; val_idxget_id()->get_name(), \"%s\")) {\n" - " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" - " %s().set_param(*curr_param);\n" - " }\n" - " value_used[val_idx]=TRUE;\n" - " }\n" - " }\n" - , sdef->elements[i].dispname, sdef->elements[i].name); - } - src = mputprintf(src, - " for (size_t val_idx=0; val_idxerror(\"Non existent field name in type %s: %%s\", curr_param->get_id()->get_name());\n" - " break;\n" - " }\n" - " } break;\n" - " default:\n" - " param.type_error(\"%s value\", \"%s\");\n" - " }\n" - "}\n\n", dispname, kind_str, dispname); - - /* set implicit omit function, recursive */ - def = mputstr(def, " void set_implicit_omit();\n"); - src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name); - for (i = 0; i < sdef->nElements; i++) { - if (sdef->elements[i].isOptional) { + if (!sdef->containsClass) { + /* set param function */ + def = mputstr(def, " void set_param(Module_Param& param);\n"); + src = mputprintf + (src, + "void %s::set_param(Module_Param& param)\n{\n" + " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n" + " switch (param.get_type()) {\n" + " case Module_Param::MP_Value_List:\n" + " if (%lunElements, kind_str, dispname, (unsigned long)sdef->nElements); + + for (i = 0; i < sdef->nElements; ++i) { src = mputprintf(src, - "if (!%s().is_bound()) %s() = OMIT_VALUE;\n" - "else %s().set_implicit_omit();\n", - sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); - } else { + " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n", + (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); + } + src = mputstr(src, + " break;\n" + " case Module_Param::MP_Assignment_List: {\n" + " Vector value_used(param.get_size());\n" + " value_used.resize(param.get_size(), FALSE);\n"); + for (i = 0; i < sdef->nElements; ++i) { src = mputprintf(src, - "if (%s().is_bound()) %s().set_implicit_omit();\n", - sdef->elements[i].name, sdef->elements[i].name); + " for (size_t val_idx=0; val_idxget_id()->get_name(), \"%s\")) {\n" + " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" + " %s().set_param(*curr_param);\n" + " }\n" + " value_used[val_idx]=TRUE;\n" + " }\n" + " }\n" + , sdef->elements[i].dispname, sdef->elements[i].name); } - } - src = mputstr(src, "}\n\n"); + src = mputprintf(src, + " for (size_t val_idx=0; val_idxerror(\"Non existent field name in type %s: %%s\", curr_param->get_id()->get_name());\n" + " break;\n" + " }\n" + " } break;\n" + " default:\n" + " param.type_error(\"%s value\", \"%s\");\n" + " }\n" + "}\n\n", dispname, kind_str, dispname); + + /* set implicit omit function, recursive */ + def = mputstr(def, " void set_implicit_omit();\n"); + src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name); + for (i = 0; i < sdef->nElements; i++) { + if (sdef->elements[i].isOptional) { + src = mputprintf(src, + "if (!%s().is_bound()) %s() = OMIT_VALUE;\n" + "else %s().set_implicit_omit();\n", + sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); + } else { + src = mputprintf(src, + "if (%s().is_bound()) %s().set_implicit_omit();\n", + sdef->elements[i].name, sdef->elements[i].name); + } + } + src = mputstr(src, "}\n\n"); - /* text encoder function */ - def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n"); - src = mputprintf(src,"void %s::encode_text(Text_Buf& text_buf) const\n{\n", - name); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "field_%s.encode_text(text_buf);\n", - sdef->elements[i].name); - } - src = mputstr(src, "}\n\n"); + /* text encoder function */ + def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n"); + src = mputprintf(src,"void %s::encode_text(Text_Buf& text_buf) const\n{\n", + name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "field_%s.encode_text(text_buf);\n", + sdef->elements[i].name); + } + src = mputstr(src, "}\n\n"); - /* text decoder function */ - def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n"); - src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n{\n", - name); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "field_%s.decode_text(text_buf);\n", - sdef->elements[i].name); + /* text decoder function */ + def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n"); + src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n{\n", + name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "field_%s.decode_text(text_buf);\n", + sdef->elements[i].name); + } + src = mputstr(src, "}\n\n"); + } + else if (use_runtime_2) { + // implement abstract functions inherited by Base_Type (these are never called) + def = mputstr(def, + " void set_param(Module_Param&) { }\n" + " Module_Param* get_param(Module_Param_Name&) const { return NULL; }\n" + " void encode_text(Text_Buf&) const { }\n" + " void decode_text(Text_Buf&) { }\n" + " boolean is_equal(const Base_Type*) const { return FALSE; }\n" + " void set_value(const Base_Type*) { }\n" + " Base_Type* clone() const { return NULL; }\n\n"); } - src = mputstr(src, "}\n\n"); /* The common "classname::encode()" and "classname::decode()" functions */ if(ber_needed || raw_needed || text_needed || xer_needed || json_needed @@ -6483,68 +6501,70 @@ void defRecordTemplate1(const struct_def *sdef, output_struct *output) "}\n" "}\n\n"); - /*encode_text function*/ - def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); - src = mputprintf(src, - "void %s_template::encode_text(Text_Buf& text_buf) const\n" - "{\n" - "encode_text_base(text_buf);\n" - "switch (template_selection) {\n" - "case SPECIFIC_VALUE:\n", name); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n", - sdef->elements[i].name); - } - src = mputprintf(src, - "case OMIT_VALUE:\n" - "case ANY_VALUE:\n" - "case ANY_OR_OMIT:\n" - "break;\n" - "case VALUE_LIST:\n" - "case COMPLEMENTED_LIST:\n" - "text_buf.push_int(value_list.n_values);\n" - "for (unsigned int list_count = 0; list_count < value_list.n_values; " - "list_count++)\n" - "value_list.list_value[list_count].encode_text(text_buf);\n" - "break;\n" - "default:\n" - "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " - "template of type %s.\");\n" - "}\n" - "}\n\n", dispname); - - /*decode_text function*/ - def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); - src = mputprintf(src, - "void %s_template::decode_text(Text_Buf& text_buf)\n" - "{\n" - "clean_up();\n" - "decode_text_base(text_buf);\n" - "switch (template_selection) {\n" - "case SPECIFIC_VALUE:\n" - "single_value = new single_value_struct;\n", name); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n", - sdef->elements[i].name); + if (!sdef->containsClass) { + /*encode_text function*/ + def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); + src = mputprintf(src, + "void %s_template::encode_text(Text_Buf& text_buf) const\n" + "{\n" + "encode_text_base(text_buf);\n" + "switch (template_selection) {\n" + "case SPECIFIC_VALUE:\n", name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n", + sdef->elements[i].name); + } + src = mputprintf(src, + "case OMIT_VALUE:\n" + "case ANY_VALUE:\n" + "case ANY_OR_OMIT:\n" + "break;\n" + "case VALUE_LIST:\n" + "case COMPLEMENTED_LIST:\n" + "text_buf.push_int(value_list.n_values);\n" + "for (unsigned int list_count = 0; list_count < value_list.n_values; " + "list_count++)\n" + "value_list.list_value[list_count].encode_text(text_buf);\n" + "break;\n" + "default:\n" + "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " + "template of type %s.\");\n" + "}\n" + "}\n\n", dispname); + + /*decode_text function*/ + def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); + src = mputprintf(src, + "void %s_template::decode_text(Text_Buf& text_buf)\n" + "{\n" + "clean_up();\n" + "decode_text_base(text_buf);\n" + "switch (template_selection) {\n" + "case SPECIFIC_VALUE:\n" + "single_value = new single_value_struct;\n", name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n", + sdef->elements[i].name); + } + src = mputprintf(src, + "case OMIT_VALUE:\n" + "case ANY_VALUE:\n" + "case ANY_OR_OMIT:\n" + "break;\n" + "case VALUE_LIST:\n" + "case COMPLEMENTED_LIST:\n" + "value_list.n_values = text_buf.pull_int().get_val();\n" + "value_list.list_value = new %s_template[value_list.n_values];\n" + "for (unsigned int list_count = 0; list_count < value_list.n_values; " + "list_count++)\n" + "value_list.list_value[list_count].decode_text(text_buf);\n" + "break;\n" + "default:\n" + "TTCN_error(\"Text decoder: An unknown/unsupported selection was " + "received in a template of type %s.\");\n" + "}\n" + "}\n\n", name, dispname); } - src = mputprintf(src, - "case OMIT_VALUE:\n" - "case ANY_VALUE:\n" - "case ANY_OR_OMIT:\n" - "break;\n" - "case VALUE_LIST:\n" - "case COMPLEMENTED_LIST:\n" - "value_list.n_values = text_buf.pull_int().get_val();\n" - "value_list.list_value = new %s_template[value_list.n_values];\n" - "for (unsigned int list_count = 0; list_count < value_list.n_values; " - "list_count++)\n" - "value_list.list_value[list_count].decode_text(text_buf);\n" - "break;\n" - "default:\n" - "TTCN_error(\"Text decoder: An unknown/unsupported selection was " - "received in a template of type %s.\");\n" - "}\n" - "}\n\n", name, dispname); /* set_param() */ def = mputstr(def, "void set_param(Module_Param& param);\n"); diff --git a/compiler2/record_of.c b/compiler2/record_of.c index 1a8a6fe043b4c6e442e26af8de35113378f9c65a..86ea63ee88e8d50d646abf38c411722144998955 100644 --- a/compiler2/record_of.c +++ b/compiler2/record_of.c @@ -38,7 +38,7 @@ static void defRecordOfTemplate2(const struct_of_def *sdef, output_struct *outpu void defRecordOfClass(const struct_of_def *sdef, output_struct *output) { - if (use_runtime_2) defRecordOfClass2(sdef, output); + if (use_runtime_2 && !sdef->containsClass) defRecordOfClass2(sdef, output); else defRecordOfClass1(sdef, output); } @@ -55,12 +55,12 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) char *def = NULL, *src = NULL; const char *name = sdef->name, *dispname = sdef->dispname; const char *type = sdef->type; - boolean ber_needed = force_gen_seof || (sdef->isASN1 && enable_ber()); - boolean raw_needed = force_gen_seof || (sdef->hasRaw && enable_raw()); - boolean text_needed = force_gen_seof || (sdef->hasText && enable_text()); - boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer()); - boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json()); - boolean oer_needed = force_gen_seof || (sdef->hasOer && enable_oer()); + boolean ber_needed = force_gen_seof || (sdef->isASN1 && !sdef->containsClass && enable_ber()); + boolean raw_needed = force_gen_seof || (sdef->hasRaw && !sdef->containsClass && enable_raw()); + boolean text_needed = force_gen_seof || (sdef->hasText && !sdef->containsClass && enable_text()); + boolean xer_needed = force_gen_seof || (sdef->hasXer && !sdef->containsClass && enable_xer()); + boolean json_needed = force_gen_seof || (sdef->hasJson && !sdef->containsClass && enable_json()); + boolean oer_needed = force_gen_seof || (sdef->hasOer && !sdef->containsClass && enable_oer()); /* Class definition and private data members */ def = mputprintf(def, @@ -467,16 +467,18 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "}\n" "return ret_val;\n" "}\n\n", name, name, name, dispname, dispname, dispname, name, type, type, type); - def = mputprintf(def, - "%s replace(int index, int len, const %s_template& repl) const;\n\n", - name, name); - src = mputprintf(src, - "%s %s::replace(int index, int len, const %s_template& repl) const\n" - "{\n" - "if (!repl.is_value()) TTCN_error(\"The fourth argument of function " - "replace() is a template with non-specific value.\");\n" - "return replace(index, len, repl.valueof());\n" - "}\n\n", name, name, name); + if (!sdef->containsClass) { + def = mputprintf(def, + "%s replace(int index, int len, const %s_template& repl) const;\n\n", + name, name); + src = mputprintf(src, + "%s %s::replace(int index, int len, const %s_template& repl) const\n" + "{\n" + "if (!repl.is_value()) TTCN_error(\"The fourth argument of function " + "replace() is a template with non-specific value.\");\n" + "return replace(index, len, repl.valueof());\n" + "}\n\n", name, name, name); + } /* set_size function */ def = mputstr(def, "void set_size(int new_size);\n"); @@ -600,111 +602,125 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output) "}\n" "}\n\n", name); - /* set_param function */ - def = mputstr(def, "void set_param(Module_Param& param);\n"); - src = mputprintf(src, - "void %s::set_param(Module_Param& param)\n" - "{\n" - " param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n" - " switch (param.get_operation_type()) {\n" - " case Module_Param::OT_ASSIGN:\n" - " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n" - " *this = NULL_VALUE;\n" - " return;\n" - " }\n" - " switch (param.get_type()) {\n" - " case Module_Param::MP_Value_List:\n" - " set_size(param.get_size());\n" - " for (size_t i=0; iget_type()!=Module_Param::MP_NotUsed) {\n" - " (*this)[i].set_param(*curr);\n" - " if (!(*this)[i].is_bound()) {\n" - " delete val_ptr->value_elements[i];\n" - " val_ptr->value_elements[i] = NULL;\n" - " }\n" - " }\n" - " }\n" - " break;\n" - " case Module_Param::MP_Indexed_List:\n" - " for (size_t i=0; iget_id()->get_index()].set_param(*curr);\n" - " if (!(*this)[curr->get_id()->get_index()].is_bound()) {\n" - " delete val_ptr->value_elements[curr->get_id()->get_index()];\n" - " val_ptr->value_elements[curr->get_id()->get_index()] = NULL;\n" - " }\n" - " }\n" - " break;\n" - " default:\n" - " param.type_error(\"%s value\", \"%s\");\n" - " }\n" - " break;\n" - " case Module_Param::OT_CONCAT:\n" - " switch (param.get_type()) {\n" - " case Module_Param::MP_Value_List: {\n" - " if (!is_bound()) *this = NULL_VALUE;\n" - " int start_idx = lengthof();\n" - " for (size_t i=0; iget_type()!=Module_Param::MP_NotUsed)) {\n" - " (*this)[start_idx+(int)i].set_param(*curr);\n" - " }\n" - " }\n" - " } break;\n" - " case Module_Param::MP_Indexed_List:\n" - " param.error(\"Cannot concatenate an indexed value list\");\n" - " break;\n" - " default:\n" - " param.type_error(\"%s value\", \"%s\");\n" - " }\n" - " break;\n" - " default:\n" - " TTCN_error(\"Internal error: Unknown operation type.\");\n" - " }\n" - "}\n\n", name, sdef->kind == RECORD_OF ? "record of" : "set of", - sdef->kind == RECORD_OF ? "record of" : "set of", dispname, - sdef->kind == RECORD_OF ? "record of" : "set of", dispname); - - /* set implicit omit function, recursive */ - def = mputstr(def, " void set_implicit_omit();\n"); - src = mputprintf(src, - "void %s::set_implicit_omit()\n{\n" - "if (val_ptr == NULL) return;\n" - "for (int i = 0; i < val_ptr->n_elements; i++) {\n" - "if (val_ptr->value_elements[i] != NULL) val_ptr->value_elements[i]->set_implicit_omit();\n" - "}\n}\n\n", name); + if (!sdef->containsClass) { + /* set_param function */ + def = mputstr(def, "void set_param(Module_Param& param);\n"); + src = mputprintf(src, + "void %s::set_param(Module_Param& param)\n" + "{\n" + " param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, \"%s value\");\n" + " switch (param.get_operation_type()) {\n" + " case Module_Param::OT_ASSIGN:\n" + " if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {\n" + " *this = NULL_VALUE;\n" + " return;\n" + " }\n" + " switch (param.get_type()) {\n" + " case Module_Param::MP_Value_List:\n" + " set_size(param.get_size());\n" + " for (size_t i=0; iget_type()!=Module_Param::MP_NotUsed) {\n" + " (*this)[i].set_param(*curr);\n" + " if (!(*this)[i].is_bound()) {\n" + " delete val_ptr->value_elements[i];\n" + " val_ptr->value_elements[i] = NULL;\n" + " }\n" + " }\n" + " }\n" + " break;\n" + " case Module_Param::MP_Indexed_List:\n" + " for (size_t i=0; iget_id()->get_index()].set_param(*curr);\n" + " if (!(*this)[curr->get_id()->get_index()].is_bound()) {\n" + " delete val_ptr->value_elements[curr->get_id()->get_index()];\n" + " val_ptr->value_elements[curr->get_id()->get_index()] = NULL;\n" + " }\n" + " }\n" + " break;\n" + " default:\n" + " param.type_error(\"%s value\", \"%s\");\n" + " }\n" + " break;\n" + " case Module_Param::OT_CONCAT:\n" + " switch (param.get_type()) {\n" + " case Module_Param::MP_Value_List: {\n" + " if (!is_bound()) *this = NULL_VALUE;\n" + " int start_idx = lengthof();\n" + " for (size_t i=0; iget_type()!=Module_Param::MP_NotUsed)) {\n" + " (*this)[start_idx+(int)i].set_param(*curr);\n" + " }\n" + " }\n" + " } break;\n" + " case Module_Param::MP_Indexed_List:\n" + " param.error(\"Cannot concatenate an indexed value list\");\n" + " break;\n" + " default:\n" + " param.type_error(\"%s value\", \"%s\");\n" + " }\n" + " break;\n" + " default:\n" + " TTCN_error(\"Internal error: Unknown operation type.\");\n" + " }\n" + "}\n\n", name, sdef->kind == RECORD_OF ? "record of" : "set of", + sdef->kind == RECORD_OF ? "record of" : "set of", dispname, + sdef->kind == RECORD_OF ? "record of" : "set of", dispname); - /* encoding / decoding functions */ - def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); - src = mputprintf(src, - "void %s::encode_text(Text_Buf& text_buf) const\n" - "{\n" - "if (val_ptr == NULL) " - "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n" - "text_buf.push_int(val_ptr->n_elements);\n" - "for (int elem_count = 0; elem_count < val_ptr->n_elements; " - "elem_count++)\n" - "(*this)[elem_count].encode_text(text_buf);\n" - "}\n\n", name, dispname); + /* set implicit omit function, recursive */ + def = mputstr(def, " void set_implicit_omit();\n"); + src = mputprintf(src, + "void %s::set_implicit_omit()\n{\n" + "if (val_ptr == NULL) return;\n" + "for (int i = 0; i < val_ptr->n_elements; i++) {\n" + "if (val_ptr->value_elements[i] != NULL) val_ptr->value_elements[i]->set_implicit_omit();\n" + "}\n}\n\n", name); + + /* encoding / decoding functions */ + def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); + src = mputprintf(src, + "void %s::encode_text(Text_Buf& text_buf) const\n" + "{\n" + "if (val_ptr == NULL) " + "TTCN_error(\"Text encoder: Encoding an unbound value of type %s.\");\n" + "text_buf.push_int(val_ptr->n_elements);\n" + "for (int elem_count = 0; elem_count < val_ptr->n_elements; " + "elem_count++)\n" + "(*this)[elem_count].encode_text(text_buf);\n" + "}\n\n", name, dispname); - def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); - src = mputprintf(src, - "void %s::decode_text(Text_Buf& text_buf)\n" - "{\n" - "clean_up();\n" - "val_ptr = new recordof_setof_struct;\n" - "val_ptr->ref_count = 1;\n" - "val_ptr->n_elements = text_buf.pull_int().get_val();\n" - "if (val_ptr->n_elements < 0) TTCN_error(\"Text decoder: Negative size " - "was received for a value of type %s.\");\n" - "val_ptr->value_elements = (%s**)allocate_pointers(val_ptr->n_elements);\n" - "for (int elem_count = 0; elem_count < val_ptr->n_elements; " - "elem_count++) {\n" - "val_ptr->value_elements[elem_count] = new %s;\n" - "val_ptr->value_elements[elem_count]->decode_text(text_buf);\n" - "}\n" - "}\n\n", name, dispname, type, type); + def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); + src = mputprintf(src, + "void %s::decode_text(Text_Buf& text_buf)\n" + "{\n" + "clean_up();\n" + "val_ptr = new recordof_setof_struct;\n" + "val_ptr->ref_count = 1;\n" + "val_ptr->n_elements = text_buf.pull_int().get_val();\n" + "if (val_ptr->n_elements < 0) TTCN_error(\"Text decoder: Negative size " + "was received for a value of type %s.\");\n" + "val_ptr->value_elements = (%s**)allocate_pointers(val_ptr->n_elements);\n" + "for (int elem_count = 0; elem_count < val_ptr->n_elements; " + "elem_count++) {\n" + "val_ptr->value_elements[elem_count] = new %s;\n" + "val_ptr->value_elements[elem_count]->decode_text(text_buf);\n" + "}\n" + "}\n\n", name, dispname, type, type); + } + else if (use_runtime_2) { + // implement abstract functions inherited by Base_Type (these are never called) + def = mputstr(def, + " void set_param(Module_Param&) { }\n" + " Module_Param* get_param(Module_Param_Name&) const { return NULL; }\n" + " void encode_text(Text_Buf&) const { }\n" + " void decode_text(Text_Buf&) { }\n" + " boolean is_equal(const Base_Type*) const { return FALSE; }\n" + " void set_value(const Base_Type*) { }\n" + " Base_Type* clone() const { return NULL; }\n" + " const TTCN_Typedescriptor_t* get_descriptor() const { return NULL; }\n\n"); + } if(ber_needed || raw_needed || text_needed || xer_needed || json_needed || oer_needed) { diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index ce7c28c9aaa4aef5aefa90c3d978f0b2fdefeee5..22c2fb691f448f584be813c83e1e93cdf3c6b100 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1230,7 +1230,7 @@ namespace Ttcn { FormalParList* fp_list = subref->get_formal_par_list(); for (size_t j = 0; j < ap_list->get_nof_pars(); ++j) { if (!ap_list->get_par(j)->has_single_expr( - fp_list != NULL ? fp_list->get_fp_byIndex(i) : NULL)) { + fp_list != NULL ? fp_list->get_fp_byIndex(j) : NULL)) { return false; } } @@ -4080,8 +4080,11 @@ namespace Ttcn { continue; } field_name = tref->get_id()->get_ttcnname(); - if (oop_features && field_name == string("object")) { - ea.error("Class type `object' cannot be added to the anytype"); + bool is_object = field_name == string("object"); + if (oop_features && (is_object || + t->get_type_refd_last()->get_typetype() == Common::Type::T_CLASS)) { + ea.error("Class type `%s' cannot be added to the anytype", + is_object ? "object" : t->get_typename().c_str()); delete t; continue; } diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 5159ddd34f247ea8e7ec2eb78bb827973986c0f0..bcd15fb1d191287f60bfec4f1f2c9bbb2490bbed 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -3615,7 +3615,7 @@ namespace Ttcn { case Common::Assignment::A_PAR_VAL_IN: case Common::Assignment::A_PAR_VAL_INOUT: case Common::Assignment::A_PAR_VAL_OUT: - if (t_ass->get_Type()->get_type_refd_last()->get_typetype() != Common::Type::T_CLASS) { + if (!t_ass->get_Type()->contains_class()) { ref_pard->error("Reference to a function or altstep was expected " "instead of %s, which cannot be invoked", t_ass->get_description().c_str()); diff --git a/compiler2/union.c b/compiler2/union.c index 8ee0cbf2b54902af9f98e6f848da755530c65052..c843a07c6a28a69819d4d79cc5ca797f233dbca5 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -77,12 +77,12 @@ void defUnionClass(struct_def const *sdef, output_struct *output) * for the anytype, otherwise the generated "INTEGER()" will look like * a constructor, upsetting the C++ compiler. AT_INTEGER() is ok. */ char *def = NULL, *src = NULL; - boolean ber_needed = sdef->isASN1 && enable_ber(); - boolean raw_needed = sdef->hasRaw && enable_raw(); - boolean text_needed = sdef->hasText && enable_text(); - boolean xer_needed = sdef->hasXer && enable_xer(); - boolean json_needed = sdef->hasJson && enable_json(); - boolean oer_needed = sdef->hasOer && enable_oer(); + boolean ber_needed = sdef->isASN1&& !sdef->containsClass && enable_ber(); + boolean raw_needed = sdef->hasRaw&& !sdef->containsClass && enable_raw(); + boolean text_needed = sdef->hasText&& !sdef->containsClass && enable_text(); + boolean xer_needed = sdef->hasXer&& !sdef->containsClass && enable_xer(); + boolean json_needed = sdef->hasJson&& !sdef->containsClass && enable_json(); + boolean oer_needed = sdef->hasOer&& !sdef->containsClass && enable_oer(); char *selection_type, *unbound_value, *selection_prefix; selection_type = mcopystr("union_selection_type"); @@ -312,7 +312,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) "union_selection = %s;\n" "}\n\n", unbound_value); - if (use_runtime_2) { + if (use_runtime_2 && !sdef->containsClass) { def = mputstr(def, "boolean is_equal(const Base_Type* other_value) const;\n" "void set_value(const Base_Type* other_value);\n" @@ -332,7 +332,8 @@ void defUnionClass(struct_def const *sdef, output_struct *output) name, name, name, name, name, name); - } else { + } + if (!use_runtime_2) { def = mputstr(def, "inline boolean is_present() const { return is_bound(); }\n"); } @@ -358,173 +359,187 @@ void defUnionClass(struct_def const *sdef, output_struct *output) } src = mputstr(src, "}\n\n"); - /* set_param function */ - def = mputstr(def, "void set_param(Module_Param& param);\n"); - src = mputprintf(src, "void %s::set_param(Module_Param& param)\n" - "{\n", name); - if (use_runtime_2) { - src = mputprintf(src, - " if (dynamic_cast(param.get_id()) != NULL &&\n" - " param.get_id()->next_name()) {\n" - // Haven't reached the end of the module parameter name - // => the name refers to one of the fields, not to the whole union - " char* param_field = param.get_id()->get_current_name();\n" - " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" - " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" - " \" name for union type `%s'\");\n" - " }\n" - " ", dispname); - for (i = 0; i < sdef->nElements; i++) { + if (!sdef->containsClass) { + /* set_param function */ + def = mputstr(def, "void set_param(Module_Param& param);\n"); + src = mputprintf(src, "void %s::set_param(Module_Param& param)\n" + "{\n", name); + if (use_runtime_2) { src = mputprintf(src, - "if (strcmp(\"%s\", param_field) == 0) {\n" - " %s%s().set_param(param);\n" - " return;\n" - " } else ", - sdef->elements[i].dispname, at_field, sdef->elements[i].name); - } - src = mputprintf(src, - "param.error(\"Field `%%s' not found in union type `%s'\", param_field);\n" - " }\n", dispname); - } - src = mputstr(src, - " param.basic_check(Module_Param::BC_VALUE, \"union value\");\n" - " Module_Param_Ptr m_p = ¶m;\n"); - if (use_runtime_2) { - src = mputstr(src, - " if (param.get_type() == Module_Param::MP_Reference) {\n" - " m_p = param.get_referenced_param();\n" - " }\n"); - } - src = mputstr(src, - " if (m_p->get_type()==Module_Param::MP_Value_List && m_p->get_size()==0) return;\n" - " if (m_p->get_type()!=Module_Param::MP_Assignment_List) {\n" - " param.error(\"union value with field name was expected\");\n" - " }\n" - " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n" - " char* last_name = mp_last->get_id()->get_name();\n"); - - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, - " if (!strcmp(last_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) { + " if (dynamic_cast(param.get_id()) != NULL &&\n" + " param.get_id()->next_name()) {\n" + // Haven't reached the end of the module parameter name + // => the name refers to one of the fields, not to the whole union + " char* param_field = param.get_id()->get_current_name();\n" + " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" + " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" + " \" name for union type `%s'\");\n" + " }\n" + " ", dispname); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, + "if (strcmp(\"%s\", param_field) == 0) {\n" + " %s%s().set_param(param);\n" + " return;\n" + " } else ", + sdef->elements[i].dispname, at_field, sdef->elements[i].name); + } 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); + "param.error(\"Field `%%s' not found in union type `%s'\", param_field);\n" + " }\n", dispname); } - else { - // a union's alternative cannot be unbound - src = mputstr(src, "clean_up();\n"); + src = mputstr(src, + " param.basic_check(Module_Param::BC_VALUE, \"union value\");\n" + " Module_Param_Ptr m_p = ¶m;\n"); + if (use_runtime_2) { + src = mputstr(src, + " if (param.get_type() == Module_Param::MP_Reference) {\n" + " m_p = param.get_referenced_param();\n" + " }\n"); } src = mputstr(src, - " return;\n" - " }\n"); - } - src = mputprintf(src, - " mp_last->error(\"Field %%s does not exist in type %s.\", last_name);\n" - "}\n\n", dispname); - - /* get param function, RT2 only */ - if (use_runtime_2) { - def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); - src = mputprintf(src, - "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n" - "{\n" - " if (!is_bound()) {\n" - " return new Module_Param_Unbound();\n" - " }\n" - " if (param_name.next_name()) {\n" - // Haven't reached the end of the module parameter name - // => the name refers to one of the fields, not to the whole union - " char* param_field = param_name.get_current_name();\n" - " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" - " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" - " \"expected a valid field name for union type `%s'\");\n" - " }\n" - " ", name, dispname); + " if (m_p->get_type()==Module_Param::MP_Value_List && m_p->get_size()==0) return;\n" + " if (m_p->get_type()!=Module_Param::MP_Assignment_List) {\n" + " param.error(\"union value with field name was expected\");\n" + " }\n" + " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n" + " char* last_name = mp_last->get_id()->get_name();\n"); + for (i = 0; i < sdef->nElements; i++) { src = mputprintf(src, - "if (strcmp(\"%s\", param_field) == 0) {\n" - " return %s%s().get_param(param_name);\n" - " } else ", - sdef->elements[i].dispname, at_field, sdef->elements[i].name); + " if (!strcmp(last_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 + src = mputstr(src, "clean_up();\n"); + } + src = mputstr(src, + " return;\n" + " }\n"); } src = mputprintf(src, - "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n" - " }\n" - " Module_Param* mp_field = NULL;\n" - " switch(union_selection) {\n" - , name); - for (i = 0; i < sdef->nElements; ++i) { - src = mputprintf(src, - " case %s_%s:\n" - " mp_field = field_%s->get_param(param_name);\n" - " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" - " break;\n" - , selection_prefix, sdef->elements[i].name - , sdef->elements[i].name, sdef->elements[i].dispname); + " mp_last->error(\"Field %%s does not exist in type %s.\", last_name);\n" + "}\n\n", dispname); + + /* get param function, RT2 only */ + if (use_runtime_2) { + def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); + src = mputprintf(src, + "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n" + "{\n" + " if (!is_bound()) {\n" + " return new Module_Param_Unbound();\n" + " }\n" + " if (param_name.next_name()) {\n" + // Haven't reached the end of the module parameter name + // => the name refers to one of the fields, not to the whole union + " char* param_field = param_name.get_current_name();\n" + " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" + " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" + " \"expected a valid field name for union type `%s'\");\n" + " }\n" + " ", name, dispname); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, + "if (strcmp(\"%s\", param_field) == 0) {\n" + " return %s%s().get_param(param_name);\n" + " } else ", + sdef->elements[i].dispname, at_field, sdef->elements[i].name); } - src = mputstr(src, - " default:\n" - " break;\n" - " }\n" - " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n" - " m_p->add_elem(mp_field);\n" - " return m_p;\n" - "}\n\n"); - } + src = mputprintf(src, + "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n" + " }\n" + " Module_Param* mp_field = NULL;\n" + " switch(union_selection) {\n" + , name); + for (i = 0; i < sdef->nElements; ++i) { + src = mputprintf(src, + " case %s_%s:\n" + " mp_field = field_%s->get_param(param_name);\n" + " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" + " break;\n" + , selection_prefix, sdef->elements[i].name + , sdef->elements[i].name, sdef->elements[i].dispname); + } + src = mputstr(src, + " default:\n" + " break;\n" + " }\n" + " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n" + " m_p->add_elem(mp_field);\n" + " return m_p;\n" + "}\n\n"); + } - /* set implicit omit function, recursive */ - def = mputstr(def, " void set_implicit_omit();\n"); - src = mputprintf(src, - "void %s::set_implicit_omit()\n{\n" - "switch (union_selection) {\n", name); - for (i = 0; i < sdef->nElements; i++) { + /* set implicit omit function, recursive */ + def = mputstr(def, " void set_implicit_omit();\n"); src = mputprintf(src, - "case %s_%s:\n" - "field_%s->set_implicit_omit(); break;\n", - selection_prefix, sdef->elements[i].name, sdef->elements[i].name); - } - src = mputstr(src, "default: break;\n}\n}\n\n"); + "void %s::set_implicit_omit()\n{\n" + "switch (union_selection) {\n", name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, + "case %s_%s:\n" + "field_%s->set_implicit_omit(); break;\n", + selection_prefix, sdef->elements[i].name, sdef->elements[i].name); + } + src = mputstr(src, "default: break;\n}\n}\n\n"); - /* encode_text function */ - def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); - src = mputprintf(src, "void %s::encode_text(Text_Buf& text_buf) const\n" - "{\n" - "text_buf.push_int(union_selection);\n" - "switch (union_selection) {\n", name); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "case %s_%s:\n" - "field_%s->encode_text(text_buf);\n" - "break;\n", selection_prefix, sdef->elements[i].name, - sdef->elements[i].name); + /* encode_text function */ + def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); + src = mputprintf(src, "void %s::encode_text(Text_Buf& text_buf) const\n" + "{\n" + "text_buf.push_int(union_selection);\n" + "switch (union_selection) {\n", name); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "case %s_%s:\n" + "field_%s->encode_text(text_buf);\n" + "break;\n", selection_prefix, sdef->elements[i].name, + sdef->elements[i].name); + } + src = mputprintf(src, "default:\n" + "TTCN_error(\"Text encoder: Encoding an unbound value of union type " + "%s.\");\n" + "}\n" + "}\n\n", dispname); + + /* decode_text function */ + def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); + src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n" + "{\n" + "switch ((%s)text_buf.pull_int().get_val()) {\n", name, selection_type); + for (i = 0; i < sdef->nElements; i++) { + src = mputprintf(src, "case %s_%s:\n" + "%s%s().decode_text(text_buf);\n" + "break;\n", selection_prefix, sdef->elements[i].name, + at_field, sdef->elements[i].name); + } + src = mputprintf(src, "default:\n" + "TTCN_error(\"Text decoder: Unrecognized union selector was received " + "for type %s.\");\n" + "}\n" + "}\n\n", dispname); } - src = mputprintf(src, "default:\n" - "TTCN_error(\"Text encoder: Encoding an unbound value of union type " - "%s.\");\n" - "}\n" - "}\n\n", dispname); - - /* decode_text function */ - def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); - src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n" - "{\n" - "switch ((%s)text_buf.pull_int().get_val()) {\n", name, selection_type); - for (i = 0; i < sdef->nElements; i++) { - src = mputprintf(src, "case %s_%s:\n" - "%s%s().decode_text(text_buf);\n" - "break;\n", selection_prefix, sdef->elements[i].name, - at_field, sdef->elements[i].name); + else if (use_runtime_2) { + // implement abstract functions inherited by Base_Type (these are never called) + def = mputstr(def, + " void set_param(Module_Param&) { }\n" + " Module_Param* get_param(Module_Param_Name&) const { return NULL; }\n" + " void encode_text(Text_Buf&) const { }\n" + " void decode_text(Text_Buf&) { }\n" + " boolean is_equal(const Base_Type*) const { return FALSE; }\n" + " void set_value(const Base_Type*) { }\n" + " Base_Type* clone() const { return NULL; }\n" + " const TTCN_Typedescriptor_t* get_descriptor() const { return NULL; }\n\n"); } - src = mputprintf(src, "default:\n" - "TTCN_error(\"Text decoder: Unrecognized union selector was received " - "for type %s.\");\n" - "}\n" - "}\n\n", dispname); if(ber_needed || raw_needed || text_needed || xer_needed || json_needed || oer_needed) { diff --git a/core/OOP.hh b/core/OOP.hh index d8a9724ff7399daed984993f45478e962e43596b..704d3b3d588013c884cf4abcdfe030ccae15ed6c 100644 --- a/core/OOP.hh +++ b/core/OOP.hh @@ -22,7 +22,11 @@ // ---------- template -class OBJECT_REF { +class OBJECT_REF +#ifdef TITAN_RUNTIME_2 + : public Base_Type +#endif +{ template friend boolean operator==(null_type, const OBJECT_REF& right_val); template @@ -188,6 +192,51 @@ public: } return new OBJECT_REF(new_ptr); } + +#ifdef TITAN_RUNTIME_2 + + boolean is_equal(const Base_Type*) const { + TTCN_error("Internal error: OBJECT_REF::is_equal called"); + return false; + } + + void set_value(const Base_Type*) { + TTCN_error("Internal error: OBJECT_REF::set_value called"); + } + + Base_Type* clone() const { + TTCN_error("Internal error: OBJECT_REF::clone called"); + return NULL; + } + + void set_param(Module_Param&) { + TTCN_error("Internal error: OBJECT_REF::set_param called"); + } + + Module_Param* get_param(Module_Param_Name&) const { + TTCN_error("Internal error: OBJECT_REF::get_param called"); + return NULL; + } + + boolean is_seof() const { + TTCN_error("Internal error: OBJECT_REF::is_seof called"); + return FALSE; + } + + void encode_text(Text_Buf&) const { + TTCN_error("Internal error: OBJECT_REF::encode_text called"); + } + + void decode_text(Text_Buf&) { + TTCN_error("Internal error: OBJECT_REF::decode_text called"); + } + + const TTCN_Typedescriptor_t* get_descriptor() const { + TTCN_error("Internal error: OBJECT_REF::get_descriptor called"); + return NULL; + } + +#endif }; template diff --git a/core/Optional.hh b/core/Optional.hh index 9b887384e6e84c6cbeda002d1c3a12d4163e6a84..906095b9e7173f466f4ec7b98a974758a721cd2d 100644 --- a/core/Optional.hh +++ b/core/Optional.hh @@ -378,11 +378,7 @@ public: template Base_Type* OPTIONAL::get_opt_value() { -#ifdef TITAN_RUNTIME_2 if (!is_present()) -#else - if (optional_selection!=OPTIONAL_PRESENT) -#endif TTCN_error("Internal error: get_opt_value() called on a non-present optional field."); return optional_value; } @@ -390,11 +386,7 @@ Base_Type* OPTIONAL::get_opt_value() template const Base_Type* OPTIONAL::get_opt_value() const { -#ifdef TITAN_RUNTIME_2 if (!is_present()) -#else - if (optional_selection!=OPTIONAL_PRESENT) -#endif TTCN_error("Internal error: get_opt_value() const called on a non-present optional field."); return optional_value; } @@ -402,25 +394,13 @@ const Base_Type* OPTIONAL::get_opt_value() const template boolean OPTIONAL::is_seof() const { - return -#ifdef TITAN_RUNTIME_2 - (is_present()) -#else - (optional_selection==OPTIONAL_PRESENT) -#endif - ? optional_value->is_seof() : T_type().is_seof(); + return (is_present()) ? optional_value->is_seof() : T_type().is_seof(); } template const TTCN_Typedescriptor_t* OPTIONAL::get_descriptor() const { - return -#ifdef TITAN_RUNTIME_2 - (is_present()) -#else - (optional_selection==OPTIONAL_PRESENT) -#endif - ? optional_value->get_descriptor() : T_type().get_descriptor(); + return (is_present()) ? optional_value->get_descriptor() : T_type().get_descriptor(); } #endif diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn index 6ea5247b4bcbaca41ed42f7186dfc0d0c241e239..6cbfc7f8c3e0111c6b31d1d5ddc6fd64bc33f549 100644 --- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn +++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn @@ -155,25 +155,25 @@ function f_defs() { //^In function definition// } -type record RecClass { //^In type definition// - C0 x, //^In record field// //Class type `@oop_SE.C0' cannot be embedded into another type// - object y //^In record field// //Class type `object' cannot be embedded into another type// +type record RecClass { + C0 x, + object y } -type set SetClass { //^In type definition// - C0 x, //^In set field// //Class type `@oop_SE.C0' cannot be embedded into another type// - object y //^In set field// //Class type `object' cannot be embedded into another type// +type set SetClass { + C0 x, + object y } -type record of C0 RecOfClass; //^In type definition// //^In embedded type of record of// //Class type `@oop_SE.C0' cannot be embedded into another type// -type record of object RecOfObject; //^In type definition// //^In embedded type of record of// //Class type `object' cannot be embedded into another type// +type record of C0 RecOfClass; +type record of object RecOfObject; -type set of C0 SetOfClass; //^In type definition// //^In embedded type of set of// //Class type `@oop_SE.C0' cannot be embedded into another type// -type set of object SetOfObject; //^In type definition// //^In embedded type of set of// //Class type `object' cannot be embedded into another type// +type set of C0 SetOfClass; +type set of object SetOfObject; -type union UniClass { //^In type definition// - C0 x, //^In union field// //Class type `@oop_SE.C0' cannot be embedded into another type// - object y //^In union field// //Class type `object' cannot be embedded into another type// +type union UniClass { + C0 x, + object y } function f_embedded_types() { //^In function definition// @@ -183,7 +183,6 @@ function f_embedded_types() { //^In function definition// var SetOfClass v_setof := { C0.create }; var UniClass v_uni := { x := C0.create }; var anytype v_any; //^In variable definition// //^In type definition// - v_any.C0 := C0.create; } @@ -833,5 +832,5 @@ control { //^In control part// } with { - extension "anytype C0, object" //^In anytype field// //Class type `@oop_SE.C0' cannot be embedded into another type// //Class type `object' cannot be added to the anytype// + extension "anytype C0, object" //Class type `@oop_SE.C0' cannot be added to the anytype// //Class type `object' cannot be added to the anytype// } diff --git a/regression_test/oop/oop.ttcn b/regression_test/oop/oop.ttcn index cf9812e7b3708b49821e4e4dd4a8c394437e7711..2b21672dac38f40f3e1cef2ddc8a7680beb236ef 100644 --- a/regression_test/oop/oop.ttcn +++ b/regression_test/oop/oop.ttcn @@ -232,6 +232,32 @@ type class InternalClass extends ExternalClass { public external function f_ext2(); } +type record RecClass { + charstring name, + object obj +} + +type record of BaseClass BaseClassList; + +type BaseClass BaseClassArray[3]; + +type union UniClass { + BaseClass base, + AbstractClass abs, + integer not_a_class +} + +type union ClassElem { + BaseClass base, + SubClass sub, + FinalClass final +} + +type record of ClassElem ClassUniList; + +type ClassElem ClassUniArray[4]; + + testcase tc_members_and_methods() runs on CT { var BaseClass v_base := BaseClass.create(4, { 1, 2, 4 }, "a", 'FF'O, (0.0 .. 10.0)); v_base.members_and_methods_test(); @@ -245,16 +271,27 @@ testcase tc_logging() runs on CT { var BaseClass v_sub := SubClass.create(4, il, "a", 'FF'O, tf); var BaseClass v_final := FinalClass.create(4, il, "a", 'FF'O, tf, 8, "x", -1.5, *); var TraitClass v_conc := ConcreteClass.create; + var RecClass v_rec_cls := { name := "sub", obj := ConcreteClass.create }; + var BaseClassList v_cls_list := { v_base, v_sub, v_final }; + var BaseClassArray v_cls_arr := { v_base, v_sub, v_final }; + var UniClass v_uni_cls := { abs := ConcreteClass.create }; log(v_base); log(v_sub); log(v_final); log(v_conc); + log(v_rec_cls); + log(v_cls_list); + log(v_cls_arr); + log(v_uni_cls); var charstring v_base_str := "BaseClass"; var charstring v_sub_str := "SubClass ( BaseClass )"; var charstring v_final_str := "FinalClass ( SubClass ( BaseClass ) )"; var charstring v_conc_str := "ConcreteClass ( AbstractClass, TraitClass )"; + var charstring v_rec_cls_str := "{ name := \"sub\", obj := " & v_conc_str & " }"; + var charstring v_cls_list_str := "{ " & v_base_str & ", " & v_sub_str & ", " & v_final_str & " }"; + var charstring v_uni_cls_str := "{ abs := " & v_conc_str & " }"; if (log2str(v_base) != v_base_str) { setverdict(fail, "v_base: ", v_base); @@ -268,6 +305,18 @@ testcase tc_logging() runs on CT { if (log2str(v_conc) != v_conc_str) { setverdict(fail, "v_conc: ", v_conc); } + if (log2str(v_rec_cls) != v_rec_cls_str) { + setverdict(fail, "v_rec_cls: ", v_rec_cls); + } + if (log2str(v_cls_list) != v_cls_list_str) { + setverdict(fail, "v_cls_list: ", v_cls_list); + } + if (log2str(v_cls_arr) != v_cls_list_str) { + setverdict(fail, "v_cls_arr: ", v_cls_arr); + } + if (log2str(v_uni_cls) != v_uni_cls_str) { + setverdict(fail, "v_uni_cls: ", v_uni_cls); + } setverdict(pass); } @@ -460,6 +509,117 @@ testcase tc_references() runs on CT { } +type union UniNode { + Node node, + octetstring raw +} + +testcase tc_references_in_structures() runs on CT { + var BaseClass v_base := BaseClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0); + var SubClass v_sub := SubClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0); + var FinalClass v_final := FinalClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0, 8, "x", -1.5, *); + var BaseClass v_null := null; + var Node v_node := Node.create(2, null); + var FinalClass v_null2 := null; + var RecClass v_rec_cls := { name := "sub", obj := ConcreteClass.create }; + var ClassUniList v_cls_list := { { base := v_base }, { sub := v_sub }, { final := v_final }, { final := null } }; + var ClassUniArray v_cls_arr := { { base := v_base }, { sub := v_sub }, { final := v_final }, { final := null } }; + var UniClass v_uni_cls := { base := null }; + var UniNode v_uni_node := { node := v_node }; + + var RecClass v_ref1; + if (v_ref1.obj != null) { + setverdict(fail, "#1"); + } + v_ref1 := v_rec_cls; + if (v_ref1.obj != v_rec_cls.obj) { + setverdict(fail, "#2"); + } + var integer v_int := v_cls_list[2].final.f(1); + if (v_int != 9) { + setverdict(fail, "#3, ", v_cls_list[2].final.f(1)); + } + v_int := v_cls_list[2].final.f(2); + if (v_int != 10) { + setverdict(fail, "#4, ", v_int); + } + if (not isbound(v_cls_list[2].final.f2(3).list[1])) { + setverdict(fail, "#5"); + } + if (not isvalue(v_cls_arr[0].base.get_var_temp())) { + setverdict(fail, "#6"); + } + if (not ispresent(v_cls_list[0].base.get_var_temp())) { + setverdict(fail, "#7"); + } + if (ischosen(v_cls_list[2].final.get_uni().cs)) { + setverdict(fail, "#8"); + } + if (not ischosen(v_cls_arr[2].final.get_uni_temp().cs)) { + setverdict(fail, "#9"); + } + if (v_cls_list[2].final.f2(3).list[1] + v_cls_arr[2].final.f(-6) != v_cls_list[0].base.f(3) * float2int(valueof(v_cls_arr[1].sub.get_var_temp()))) { + setverdict(fail, "#10, ", v_cls_list[2].final.f2(3).list[1] + v_cls_arr[2].final.f(-6) != v_cls_list[0].base.f(3) * float2int(valueof(v_cls_arr[1].sub.get_var_temp()))); + } + if (match(v_cls_list[2].final.get_uni(), v_cls_arr[2].final.get_uni_temp())) { + setverdict(fail, "#11, ", match(v_cls_list[2].final.get_uni(), v_cls_arr[2].final.get_uni_temp())); + } + if (not isbound(v_cls_list[1].sub)) { + setverdict(fail, "#12"); + } + if (not isbound(v_uni_cls.base)) { + setverdict(fail, "#13"); + } + if (not isvalue(v_cls_list[2].final)) { + setverdict(fail, "#14"); + } + if (not isvalue(v_uni_cls.base)) { + setverdict(fail, "#15"); + } + if (not ispresent(v_cls_arr[0].base)) { + setverdict(fail, "#16"); + } + if (ispresent(v_uni_cls.base)) { + setverdict(fail, "#17"); + } + var UniClass v_uni_cls2 := v_uni_cls; + if (v_uni_cls2.base != null) { + setverdict(fail, "#18"); + } + if (ispresent(v_uni_cls.base.get_var_temp())) { + setverdict(fail, "#19"); + } + if (ispresent(v_uni_node.node.get_next())) { + setverdict(fail, "#20"); + } + if (ispresent(v_uni_node.node.get_next().f())) { + setverdict(fail, "#21"); + } + if (isbound(v_uni_cls.base.get_var_temp())) { + setverdict(fail, "#22"); + } + if (not isbound(v_uni_node.node.get_next())) { + setverdict(fail, "#23"); + } + if (isbound(v_uni_node.node.get_next().f())) { + setverdict(fail, "#24"); + } + if (isvalue(v_uni_cls.base.get_var_temp())) { + setverdict(fail, "#25"); + } + if (not isvalue(v_uni_node.node.get_next())) { + setverdict(fail, "#26"); + } + if (isvalue(v_uni_node.node.get_next().f())) { + setverdict(fail, "#27"); + } + if (ischosen(v_cls_list[3].final.get_uni().cs)) { + setverdict(fail, "#28"); + } + setverdict(pass); +} + + function f_test(in Node p1, inout Node p2, out Node p3, in charstring p1_str, in charstring p2_str) return Node { if (log2str(p1) != p1_str) { @@ -787,6 +947,7 @@ control { execute(tc_null()); execute(tc_this()); execute(tc_references()); + execute(tc_references_in_structures()); execute(tc_function_pars_and_retval()); execute(tc_function_pars_in()); execute(tc_object());