diff --git a/compiler2/Value.cc b/compiler2/Value.cc index bd2cf17e4b1d53de9c99e8c653288f74262dc37d..f0a72191f9133eb92b8285fa130ba23bab7898c4 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -13881,6 +13881,9 @@ void Value::chk_expr_operand_execute_refd(Value *v1, if (parlist) { str = parlist->rearrange_init_code(str, usage_mod); } + if (get_code_section() == CS_INIT_CLASS && get_value_refd_last() == this) { + str = rearrange_init_code_refd(str); + } break; } case V_INVOKE: { str = u.invoke.v->rearrange_init_code(str, usage_mod); @@ -14078,6 +14081,29 @@ void Value::chk_expr_operand_execute_refd(Value *v1, return str; } + char* Value::rearrange_init_code_refd(char* str) + { + Assignment* refd_ass = u.ref.ref->get_refd_assignment(); + if ((refd_ass->get_asstype() == Assignment::A_CONST || + refd_ass->get_asstype() == Assignment::A_VAR) && + refd_ass->get_my_scope()->get_parent_scope()->is_class_scope()) { + Ttcn::Reference* ttcn_ref = dynamic_cast<Ttcn::Reference*>(u.ref.ref); + if (ttcn_ref == NULL) { + FATAL_ERROR("Value::generate_code_init_refd"); + } + Value* v2 = refd_ass->get_Value(); + if (!ttcn_ref->is_gen_class_defpar_prefix() && + v2 != NULL && needs_init_precede(v2)) { + string lhs = v2->get_lhs_name(); + if (refd_ass->get_asstype() == Assignment::A_VAR) { + lhs = string("this->") + lhs; + } + str = v2->generate_code_init(str, lhs.c_str()); + } + } + return str; + } + char* Value::generate_code_tmp(char *str, const char *prefix, size_t& blockcount) { @@ -15985,19 +16011,8 @@ void Value::chk_expr_operand_execute_refd(Value *v1, { Value *v = get_value_refd_last(); if (v == this) { - Assignment* refd_ass = u.ref.ref->get_refd_assignment(); - if ((refd_ass->get_asstype() == Assignment::A_CONST || - refd_ass->get_asstype() == Assignment::A_VAR) && - refd_ass->get_my_scope()->get_parent_scope()->is_class_scope()) { - Ttcn::Reference* ttcn_ref = dynamic_cast<Ttcn::Reference*>(u.ref.ref); - if (ttcn_ref == NULL) { - FATAL_ERROR("Value::generate_code_init_refd"); - } - Value* v2 = refd_ass->get_Value(); - if (!ttcn_ref->is_gen_class_defpar_prefix() && - v2 != NULL && needs_init_precede(v2)) { // todo: defpar? - str = v2->generate_code_init(str, v2->get_lhs_name().c_str()); - } + if (get_code_section() == CS_INIT_CLASS) { + str = rearrange_init_code_refd(str); } // the referred value is not available at compile time // the code generation is based on the reference @@ -16940,6 +16955,29 @@ void Value::chk_expr_operand_execute_refd(Value *v1, } } break; } + case V_SEQ: + case V_SET: + for (size_t i = 0; i < u.val_nvs->get_nof_nvs(); ++i) { + u.val_nvs->get_nv_byIndex(i)->get_value()->chk_ctor_defpar(default_ctor, in_base_call); + } + break; + case V_SEQOF: + case V_SETOF: + case V_ARRAY: + if (u.val_vs->is_indexed()) { + for (size_t i = 0; i < u.val_vs->get_nof_ivs(); ++i) { + u.val_vs->get_iv_byIndex(i)->get_value()->chk_ctor_defpar(default_ctor, in_base_call); + } + } + else { + for (size_t i = 0; i < u.val_vs->get_nof_vs(); ++i) { + u.val_vs->get_v_byIndex(i)->chk_ctor_defpar(default_ctor, in_base_call); + } + } + break; + case V_CHOICE: + u.choice.alt_value->chk_ctor_defpar(default_ctor, in_base_call); + break; case V_EXPR: switch (u.expr.v_optype) { case OPTYPE_UNARYPLUS: @@ -17145,6 +17183,246 @@ void Value::chk_expr_operand_execute_refd(Value *v1, } } + void Value::chk_class_member(Ttcn::ClassTypeBody* p_class) + { + switch (valuetype) { + case V_REFD: { + Ttcn::Reference* ttcn_ref = dynamic_cast<Ttcn::Reference*>(u.ref.ref); + if (ttcn_ref != NULL) { + ttcn_ref->chk_class_member(p_class); + if (ttcn_ref->has_parameters()) { + ttcn_ref->get_parlist()->chk_class_member(p_class); + } + } + break; } + case V_SEQ: + case V_SET: + for (size_t i = 0; i < u.val_nvs->get_nof_nvs(); ++i) { + u.val_nvs->get_nv_byIndex(i)->get_value()->chk_class_member(p_class); + } + break; + case V_SEQOF: + case V_SETOF: + case V_ARRAY: + if (u.val_vs->is_indexed()) { + for (size_t i = 0; i < u.val_vs->get_nof_ivs(); ++i) { + u.val_vs->get_iv_byIndex(i)->get_value()->chk_class_member(p_class); + } + } + else { + for (size_t i = 0; i < u.val_vs->get_nof_vs(); ++i) { + u.val_vs->get_v_byIndex(i)->chk_class_member(p_class); + } + } + break; + case V_CHOICE: + u.choice.alt_value->chk_class_member(p_class); + break; + case V_EXPR: + switch (u.expr.v_optype) { + case OPTYPE_UNARYPLUS: + case OPTYPE_UNARYMINUS: + case OPTYPE_NOT: + case OPTYPE_NOT4B: + case OPTYPE_BIT2HEX: + case OPTYPE_BIT2INT: + case OPTYPE_BIT2OCT: + case OPTYPE_BIT2STR: + case OPTYPE_BSON2JSON: + case OPTYPE_CBOR2JSON: + case OPTYPE_CHAR2INT: + case OPTYPE_CHAR2OCT: + case OPTYPE_FLOAT2INT: + case OPTYPE_FLOAT2STR: + case OPTYPE_HEX2BIT: + case OPTYPE_HEX2INT: + case OPTYPE_HEX2OCT: + case OPTYPE_HEX2STR: + case OPTYPE_INT2CHAR: + case OPTYPE_INT2FLOAT: + case OPTYPE_INT2STR: + case OPTYPE_INT2UNICHAR: + case OPTYPE_JSON2BSON: + case OPTYPE_JSON2CBOR: + case OPTYPE_OCT2BIT: + case OPTYPE_OCT2CHAR: + case OPTYPE_OCT2HEX: + case OPTYPE_OCT2INT: + case OPTYPE_OCT2STR: + case OPTYPE_STR2BIT: + case OPTYPE_STR2FLOAT: + case OPTYPE_STR2HEX: + case OPTYPE_STR2INT: + case OPTYPE_STR2OCT: + case OPTYPE_UNICHAR2INT: + case OPTYPE_UNICHAR2CHAR: + case OPTYPE_ENUM2INT: + case OPTYPE_ISCHOSEN_V: + case OPTYPE_GET_STRINGENCODING: + case OPTYPE_REMOVE_BOM: + case OPTYPE_DECODE_BASE64: + u.expr.v1->chk_class_member(p_class); + break; + case OPTYPE_DECODE: { + if (u.expr.r1->has_parameters()) { + u.expr.r1->get_parlist()->chk_class_member(p_class); + } + else { + u.expr.r1->chk_class_member(p_class); + } + if (u.expr.r2->has_parameters()) { + u.expr.r2->get_parlist()->chk_class_member(p_class); + } + else { + u.expr.r2->chk_class_member(p_class); + } + if (u.expr.v3 != NULL) { + u.expr.v3->chk_class_member(p_class); + } + if (u.expr.v4 != NULL) { + u.expr.v4->chk_class_member(p_class); + } + break; } + case OPTYPE_HOSTID: + if (u.expr.v1 != NULL) { + u.expr.v1->chk_class_member(p_class); + } + break; + case OPTYPE_ADD: + case OPTYPE_SUBTRACT: + case OPTYPE_MULTIPLY: + case OPTYPE_DIVIDE: + case OPTYPE_MOD: + case OPTYPE_REM: + case OPTYPE_CONCAT: + case OPTYPE_EQ: + case OPTYPE_LT: + case OPTYPE_GT: + case OPTYPE_NE: + case OPTYPE_GE: + case OPTYPE_LE: + case OPTYPE_AND: + case OPTYPE_OR: + case OPTYPE_XOR: + case OPTYPE_AND4B: + case OPTYPE_OR4B: + case OPTYPE_XOR4B: + case OPTYPE_SHL: + case OPTYPE_SHR: + case OPTYPE_ROTL: + case OPTYPE_ROTR: + case OPTYPE_INT2BIT: + case OPTYPE_INT2HEX: + case OPTYPE_INT2OCT: + u.expr.v1->chk_class_member(p_class); + u.expr.v2->chk_class_member(p_class); + break; + case OPTYPE_UNICHAR2OCT: // v1 [v2] + case OPTYPE_OCT2UNICHAR: + case OPTYPE_ENCODE_BASE64: + u.expr.v1->chk_class_member(p_class); + if (u.expr.v2 != NULL) { + u.expr.v2->chk_class_member(p_class); + } + break; + case OPTYPE_SUBSTR: + case OPTYPE_ENCODE: + u.expr.ti1->chk_class_member(p_class); + if (u.expr.v2 != NULL) { + u.expr.v2->chk_class_member(p_class); + } + if (u.expr.v3 != NULL) { + u.expr.v3->chk_class_member(p_class); + } + break; + case OPTYPE_REGEXP: + u.expr.ti1->chk_class_member(p_class); + u.expr.t2->chk_class_member(p_class); + u.expr.v3->chk_class_member(p_class); + break; + case OPTYPE_DECOMP: + u.expr.v1->chk_class_member(p_class); + u.expr.v2->chk_class_member(p_class); + u.expr.v3->chk_class_member(p_class); + break; + case OPTYPE_REPLACE: + u.expr.ti1->chk_class_member(p_class); + u.expr.v2->chk_class_member(p_class); + u.expr.v3->chk_class_member(p_class); + u.expr.ti4->chk_class_member(p_class); + break; + case OPTYPE_ISTEMPLATEKIND: + u.expr.ti1->chk_class_member(p_class); + u.expr.v2->chk_class_member(p_class); + break; + case OPTYPE_VALUEOF: + if (u.expr.subrefs2 != NULL) { + for (size_t i = 0; i < u.expr.subrefs2->get_nof_refs(); ++i) { + Ttcn::FieldOrArrayRef* subref = u.expr.subrefs2->get_ref(i); + if (subref->get_type() == Ttcn::FieldOrArrayRef::ARRAY_REF) { + subref->get_val()->chk_class_member(p_class); + } + } + } + // fall through + case OPTYPE_LENGTHOF: + case OPTYPE_SIZEOF: + case OPTYPE_ISPRESENT: + case OPTYPE_TTCN2STRING: + u.expr.ti1->chk_class_member(p_class); + break; + case OPTYPE_ENCVALUE_UNICHAR: + u.expr.ti1->chk_class_member(p_class); + if (u.expr.v2 != NULL) { + u.expr.v2->chk_class_member(p_class); + } + if (u.expr.v3 != NULL) { + u.expr.v3->chk_class_member(p_class); + } + if (u.expr.v4 != NULL) { + u.expr.v4->chk_class_member(p_class); + } + break; + case OPTYPE_DECVALUE_UNICHAR: { + if (u.expr.r1->has_parameters()) { + u.expr.r1->get_parlist()->chk_class_member(p_class); + } + else { + u.expr.r1->chk_class_member(p_class); + } + if (u.expr.r2->has_parameters()) { + u.expr.r2->get_parlist()->chk_class_member(p_class); + } + else { + u.expr.r2->chk_class_member(p_class); + } + if (u.expr.v3 != NULL) { + u.expr.v3->chk_class_member(p_class); + } + if (u.expr.v4 != NULL) { + u.expr.v4->chk_class_member(p_class); + } + if (u.expr.v5 != NULL) { + u.expr.v5->chk_class_member(p_class); + } + break; } + case OPTYPE_ISCHOSEN_T: + case OPTYPE_ISVALUE: + u.expr.t1->chk_class_member(p_class); + break; + case OPTYPE_MATCH: + u.expr.v1->chk_class_member(p_class); + u.expr.t2->chk_class_member(p_class); + break; + default: + break; + } + break; + default: + break; + } + } + void Value::set_gen_class_defpar_prefix() { switch (valuetype) { @@ -17157,6 +17435,29 @@ void Value::chk_expr_operand_execute_refd(Value *v1, } } break; } + case V_SEQ: + case V_SET: + for (size_t i = 0; i < u.val_nvs->get_nof_nvs(); ++i) { + u.val_nvs->get_nv_byIndex(i)->get_value()->set_gen_class_defpar_prefix(); + } + break; + case V_SEQOF: + case V_SETOF: + case V_ARRAY: + if (u.val_vs->is_indexed()) { + for (size_t i = 0; i < u.val_vs->get_nof_ivs(); ++i) { + u.val_vs->get_iv_byIndex(i)->get_value()->set_gen_class_defpar_prefix(); + } + } + else { + for (size_t i = 0; i < u.val_vs->get_nof_vs(); ++i) { + u.val_vs->get_v_byIndex(i)->set_gen_class_defpar_prefix(); + } + } + break; + case V_CHOICE: + u.choice.alt_value->set_gen_class_defpar_prefix(); + break; case V_EXPR: switch (u.expr.v_optype) { case OPTYPE_UNARYPLUS: @@ -17368,6 +17669,29 @@ void Value::chk_expr_operand_execute_refd(Value *v1, } } break; } + case V_SEQ: + case V_SET: + for (size_t i = 0; i < u.val_nvs->get_nof_nvs(); ++i) { + u.val_nvs->get_nv_byIndex(i)->get_value()->set_gen_class_base_call_postfix(); + } + break; + case V_SEQOF: + case V_SETOF: + case V_ARRAY: + if (u.val_vs->is_indexed()) { + for (size_t i = 0; i < u.val_vs->get_nof_ivs(); ++i) { + u.val_vs->get_iv_byIndex(i)->get_value()->set_gen_class_base_call_postfix(); + } + } + else { + for (size_t i = 0; i < u.val_vs->get_nof_vs(); ++i) { + u.val_vs->get_v_byIndex(i)->set_gen_class_base_call_postfix(); + } + } + break; + case V_CHOICE: + u.choice.alt_value->set_gen_class_base_call_postfix(); + break; case V_EXPR: switch (u.expr.v_optype) { case OPTYPE_UNARYPLUS: diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 5ef9c3316c51ebf02976a72fa41437828c6fa9a2..14b35b8c813bbd416c3c32ea8dfe4b8741753a73 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -893,6 +893,7 @@ namespace Common { * (e.g. function calls) and in operands of valueof or match * operations. */ char *rearrange_init_code(char *str, Common::Module* usage_mod); + char* rearrange_init_code_refd(char* str); /** * Generates a value for temporary use. Example: * @@ -1092,6 +1093,7 @@ namespace Common { bool get_is_in_brackets() const; void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(Ttcn::ClassTypeBody* p_class); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 47c1c586fb1675f7210f0716b15cad0b8799feaa..39b5a28a7512162a2949dd76c77f234a9e4a6bde 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1171,6 +1171,25 @@ namespace Ttcn { } } + void Reference::chk_class_member(ClassTypeBody* p_class) + { + Common::Assignment* ass = get_refd_assignment_last(); + Scope* ass_parent_scope = refd_ass->get_my_scope()->get_parent_scope(); + switch (ass->get_asstype()) { + case Common::Assignment::A_CONST: + case Common::Assignment::A_TEMPLATE: + case Common::Assignment::A_VAR: + case Common::Assignment::A_VAR_TEMPLATE: + case Common::Assignment::A_TIMER: + if (ass_parent_scope->is_class_scope() && ass_parent_scope->get_scope_class() == p_class) { + set_reftype(Ref_simple::REF_THIS); + } + break; + default: + break; + } + } + bool Reference::has_single_expr() { if (!Ref_base::has_single_expr()) { @@ -1286,24 +1305,10 @@ namespace Ttcn { { Common::Assignment *ass = get_refd_assignment(); if (!ass) FATAL_ERROR("Reference::generate_code()"); - if (reftype == REF_THIS) { - if (id != NULL) { - expr->expr = mputstr(expr->expr, "this->"); - } - else { // no 'id' means it's just a 'this' reference - string tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id(); - expr->preamble = mputprintf(expr->preamble, "%s %s(this);\n", - ass->get_Type()->get_genname_value(my_scope).c_str(), tmp_id.c_str()); - expr->expr = mputprintf(expr->expr, "%s", tmp_id.c_str()); - return; - } - } - else if (reftype == REF_SUPER) { - Common::Type* base_type = my_scope->get_scope_class()->get_base_type()-> - get_type_refd_last(); - expr->expr = mputprintf(expr->expr, "%s::", - base_type->get_class_type_body()->is_built_in() ? "OBJECT" : - base_type->get_genname_own(my_scope).c_str()); + generate_class_specific_expr(expr); + if (reftype == REF_THIS && id == NULL) { + // 'this' with no field reference has already been handled by 'generate_class_specific_expr' + return; } if (reftype == REF_VALUE) { expr->expr = mputstr(expr->expr, ass->get_genname_from_scope(my_scope).c_str()); @@ -1318,8 +1323,6 @@ namespace Ttcn { } else { string const_prefix; // empty by default string exception_postfix; // also empty by default - string defpar_init_prefix; - string defpar_base_call_postfix; if (gen_const_prefix) { if (ass->get_asstype() == Common::Assignment::A_CONST) { const_prefix = "const_"; @@ -1328,39 +1331,14 @@ namespace Ttcn { const_prefix = "template_"; } } - if (gen_class_defpar_prefix && ass->get_my_scope()->is_class_scope()) { - defpar_init_prefix = "p_class->"; - } - if (gen_class_base_call_postfix) { - switch (ass->get_asstype()) { - case Common::Assignment::A_PAR_VAL_IN: - case Common::Assignment::A_PAR_VAL_INOUT: - case Common::Assignment::A_PAR_VAL_OUT: - case Common::Assignment::A_PAR_TEMPL_IN: - case Common::Assignment::A_PAR_TEMPL_INOUT: - case Common::Assignment::A_PAR_TEMPL_OUT: - case Common::Assignment::A_PAR_TIMER: { - FormalPar* formal_par = dynamic_cast<FormalPar*>(ass); - if (formal_par == NULL) { - FATAL_ERROR("Reference::generate_code"); - } - Definition* fp_def = formal_par->get_my_parlist()->get_my_def(); - if (fp_def->get_asstype() == Common::Assignment::A_CONSTRUCTOR && formal_par->has_defval()) { - defpar_base_call_postfix = string("_defpar(this)"); - } - break; } - default: - break; - } - } if (ass->get_asstype() == Common::Assignment::A_EXCEPTION) { exception_postfix = "()"; } expr->expr = mputstr(expr->expr, LazyFuzzyParamData::in_lazy_or_fuzzy() ? LazyFuzzyParamData::add_ref_genname(ass, my_scope).c_str() : - (defpar_init_prefix + const_prefix + ass->get_genname_from_scope(my_scope) + - defpar_base_call_postfix + exception_postfix).c_str()); + (get_class_defpar_prefix() + const_prefix + ass->get_genname_from_scope(my_scope) + + get_class_base_call_postfix() + exception_postfix).c_str()); } } if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass, my_scope); @@ -1427,14 +1405,11 @@ namespace Ttcn { refd_gov->get_genname_value(get_my_scope()).c_str()); } } + generate_class_specific_expr(&this_expr); string exception_postfix; if (ass->get_asstype() == Common::Assignment::A_EXCEPTION) { exception_postfix = "()"; } - string defpar_prefix; - if (gen_class_defpar_prefix && ass->get_my_scope()->is_class_scope()) { - defpar_prefix = "p_class->"; - } if (parlist != NULL) { // reference without parameters to a template that has only default formal parameters. // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code() @@ -1447,7 +1422,8 @@ namespace Ttcn { this_expr.expr = mputstr(this_expr.expr, LazyFuzzyParamData::in_lazy_or_fuzzy() ? LazyFuzzyParamData::add_ref_genname(ass, my_scope).c_str() : - (defpar_prefix + ass->get_genname_from_scope(my_scope) + exception_postfix).c_str()); + (get_class_defpar_prefix() + ass->get_genname_from_scope(my_scope) + + get_class_base_call_postfix() + exception_postfix).c_str()); } if (refd_gov->get_type_refd_last()->get_typetype() != Common::Type::T_CLASS) { this_expr.expr = mputstr(this_expr.expr, ")"); @@ -1635,6 +1611,80 @@ namespace Ttcn { } } + void Reference::generate_class_specific_expr(expression_struct_t *expr) + { + if (reftype != REF_THIS && reftype != REF_SUPER) { + return; + } + Common::Assignment *ass = get_refd_assignment(); + if (ass == NULL) { + FATAL_ERROR("Reference::generate_class_specific_expr()"); + } + if (reftype == REF_THIS) { + if (id != NULL && !gen_class_defpar_prefix) { + expr->expr = mputstr(expr->expr, "this->"); + } + else if (id == NULL) { // no 'id' means it's just a 'this' reference + string tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id(); + expr->preamble = mputprintf(expr->preamble, "%s %s(this);\n", + ass->get_Type()->get_genname_value(my_scope).c_str(), tmp_id.c_str()); + expr->expr = mputprintf(expr->expr, "%s", tmp_id.c_str()); + } + } + else if (reftype == REF_SUPER) { + Common::Type* base_type = my_scope->get_scope_class()->get_base_type()-> + get_type_refd_last(); + expr->expr = mputprintf(expr->expr, "%s::", + base_type->get_class_type_body()->is_built_in() ? "OBJECT" : + base_type->get_genname_own(my_scope).c_str()); + } + } + + string Reference::get_class_defpar_prefix() + { + if (gen_class_defpar_prefix) { + Common::Assignment *ass = get_refd_assignment(); + if (ass == NULL) { + FATAL_ERROR("Reference::get_class_defpar_prefix()"); + } + if (ass->get_my_scope()->is_class_scope()) { + return string("p_class->"); + } + } + return string(); + } + + string Reference::get_class_base_call_postfix() + { + if (gen_class_base_call_postfix) { + Common::Assignment *ass = get_refd_assignment(); + if (ass == NULL) { + FATAL_ERROR("Reference::get_class_base_call_postfix()"); + } + switch (ass->get_asstype()) { + case Common::Assignment::A_PAR_VAL_IN: + case Common::Assignment::A_PAR_VAL_INOUT: + case Common::Assignment::A_PAR_VAL_OUT: + case Common::Assignment::A_PAR_TEMPL_IN: + case Common::Assignment::A_PAR_TEMPL_INOUT: + case Common::Assignment::A_PAR_TEMPL_OUT: + case Common::Assignment::A_PAR_TIMER: { + FormalPar* formal_par = dynamic_cast<FormalPar*>(ass); + if (formal_par == NULL) { + FATAL_ERROR("Reference::get_class_base_call_postfix"); + } + Definition* fp_def = formal_par->get_my_parlist()->get_my_def(); + if (fp_def->get_asstype() == Common::Assignment::A_CONSTRUCTOR && formal_par->has_defval()) { + return string("_defpar(this)"); + } + break; } + default: + break; + } + } + return string(); + } + // ================================= // ===== NameBridgingScope @@ -4270,6 +4320,9 @@ namespace Ttcn { value->set_genname_recursive(get_genname()); value->set_code_section(my_scope->is_class_scope() ? GovernedSimple::CS_INIT_CLASS : GovernedSimple::CS_PRE_INIT); + if (my_scope->is_class_scope()) { + value->chk_class_member(my_scope->get_scope_class()); + } } } @@ -5068,6 +5121,9 @@ namespace Ttcn { body->set_code_section(fp_list ? GovernedSimple::CS_INLINE : (my_scope->is_class_scope() ? GovernedSimple::CS_INIT_CLASS : GovernedSimple::CS_POST_INIT)); + if (my_scope->is_class_scope()) { + body->chk_class_member(my_scope->get_scope_class()); + } } } @@ -5634,6 +5690,9 @@ namespace Ttcn { initial_value->set_genname_recursive(get_genname()); initial_value->set_code_section(my_scope->is_class_scope() ? GovernedSimple::CS_INIT_CLASS : GovernedSimple::CS_INLINE); + if (my_scope->is_class_scope()) { + initial_value->chk_class_member(my_scope->get_scope_class()); + } } } break; @@ -5907,6 +5966,9 @@ namespace Ttcn { initial_value->set_genname_recursive(get_genname()); initial_value->set_code_section(my_scope->is_class_scope() ? GovernedSimple::CS_INIT_CLASS : GovernedSimple::CS_INLINE); + if (my_scope->is_class_scope()) { + initial_value->chk_class_member(my_scope->get_scope_class()); + } } } if (w_attrib_path) { @@ -6121,6 +6183,9 @@ namespace Ttcn { if (!semantic_check_only) { default_duration->set_code_section(GovernedSimple::CS_POST_INIT); } + if (my_scope->is_class_scope()) { + default_duration->chk_class_member(my_scope->get_scope_class()); + } } checked = true; if (w_attrib_path) { @@ -10886,13 +10951,16 @@ namespace Ttcn { // check whether the parameter type is allowed switch (deftype) { case Definition::A_TEMPLATE: + case Definition::A_CONSTRUCTOR: switch (par->get_asstype()) { case Definition::A_PAR_VAL_IN: case Definition::A_PAR_TEMPL_IN: // these are allowed break; default: - par->error("A template cannot have %s", par->get_assname()); + par->error("A %s cannot have %s", + deftype == Definition::A_TEMPLATE ? "template" : "constructor", + par->get_assname()); } break; case Definition::A_TESTCASE: @@ -10901,6 +10969,7 @@ namespace Ttcn { case Definition::A_PAR_PORT: // these are forbidden par->error("A testcase cannot have %s", par->get_assname()); + break; default: break; } @@ -11639,6 +11708,23 @@ namespace Ttcn { } } + void ActualPar::chk_class_member(ClassTypeBody* p_class) + { + switch (selection) { + case AP_VALUE: + val->chk_class_member(p_class); + break; + case AP_TEMPLATE: + temp->chk_class_member(p_class); + break; + case AP_REF: + ref->chk_class_member(p_class); + break; + default: + break; + } + } + bool ActualPar::has_single_expr(FormalPar* formal_par) { switch (selection) { @@ -12194,6 +12280,14 @@ namespace Ttcn { } } + void ActualParList::chk_class_member(ClassTypeBody* p_class) + { + size_t nof_pars = params.size(); + for (size_t i = 0; i < nof_pars; i++) { + params[i]->chk_class_member(p_class); + } + } + void ActualParList::set_gen_class_defpar_prefix() { size_t nof_pars = params.size(); diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index 5311aa154315be624a0e0ee24f009d8c33d6bf24..2700fc01d744c89b69a9dc3d9e5e80fd91cc475f 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -123,6 +123,7 @@ namespace Ttcn { void chk_recursions(ReferenceChain& refch); void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(ClassTypeBody* p_class); /** Returns whether the actual parameter can be represented by an in-line * C++ expression. */ @@ -176,6 +177,7 @@ namespace Ttcn { void chk_immutability(); void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(ClassTypeBody* p_class); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); @@ -412,6 +414,7 @@ namespace Ttcn { Type *chk_comptype_ref(); bool chk_activate_argument(); void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(ClassTypeBody* p_class); virtual bool has_single_expr(); virtual void set_code_section(GovernedSimple::code_section_t p_code_section); virtual void generate_code(expression_struct_t *expr); @@ -445,6 +448,9 @@ namespace Ttcn { private: /** Detects whether the first identifier in subrefs is a module id */ void detect_modid(); + void generate_class_specific_expr(expression_struct_t *expr); + string get_class_defpar_prefix(); + string get_class_base_call_postfix(); }; /** diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 5fb1d9b36c711d9f81732b5958d0b3e339d58e4e..64a4932cb2f73701dc8fd449aa08763b0db8c2f7 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -3810,7 +3810,7 @@ end: break; case TEMPLATE_CONCAT: if (!use_runtime_2) { - FATAL_ERROR("Template::chk_ctor_defpar(bool default_ctor, bool in_base_call)"); + FATAL_ERROR("Template::chk_ctor_defpar()"); } u.concat.op1->chk_ctor_defpar(default_ctor, in_base_call); u.concat.op2->chk_ctor_defpar(default_ctor, in_base_call); @@ -3837,6 +3837,94 @@ end: } } + void Template::chk_class_member(ClassTypeBody* p_class) + { + switch (templatetype) { + case SPECIFIC_VALUE: + u.specific_value->chk_class_member(p_class); + break; + case TEMPLATE_REFD: + u.ref.ref->chk_class_member(p_class); + if (u.ref.ref->has_parameters()) { + for (size_t i = 0; i < u.ref.ref->get_parlist()->get_nof_pars(); i++) + u.ref.ref->get_parlist()->get_par(i)->chk_class_member(p_class); + } + break; + case TEMPLATE_INVOKE: + u.invoke.v->chk_class_member(p_class); + if (u.invoke.ap_list != NULL) { + for (size_t i = 0; i < u.invoke.ap_list->get_nof_pars(); i++) + u.invoke.ap_list->get_par(i)->chk_class_member(p_class); + } + break; + case TEMPLATE_LIST: + case VALUE_LIST: + case COMPLEMENTED_LIST: + case SUPERSET_MATCH: + case SUBSET_MATCH: + case PERMUTATION_MATCH: + case CONJUNCTION_MATCH: + for (size_t i = 0; i < u.templates->get_nof_ts(); i++) { + u.templates->get_t_byIndex(i)->chk_class_member(p_class); + } + break; + case NAMED_TEMPLATE_LIST: + for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++) { + u.named_templates->get_nt_byIndex(i)->get_template()->chk_class_member(p_class); + } + break; + case INDEXED_TEMPLATE_LIST: + for (size_t i = 0; i <u.indexed_templates->get_nof_its(); i++) { + u.indexed_templates->get_it_byIndex(i)->get_template()->chk_class_member(p_class); + } + break; + case VALUE_RANGE: + if (u.value_range->get_min_v() != NULL) { + u.value_range->get_min_v()->chk_class_member(p_class); + } + if (u.value_range->get_max_v() != NULL) { + u.value_range->get_max_v()->chk_class_member(p_class); + } + break; + case CSTR_PATTERN: + case USTR_PATTERN: + //u.pstring->chk_class_member(p_class); todo + break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + u.dec_match.str_enc->chk_class_member(p_class); + } + u.dec_match.target->chk_class_member(p_class); + break; + case TEMPLATE_CONCAT: + if (!use_runtime_2) { + FATAL_ERROR("Template::chk_class_member()"); + } + u.concat.op1->chk_class_member(p_class); + u.concat.op2->chk_class_member(p_class); + break; + case IMPLICATION_MATCH: + u.implication.precondition->chk_class_member(p_class); + u.implication.implied_template->chk_class_member(p_class); + break; + case DYNAMIC_MATCH: + break; + default: + break; + } + if (length_restriction != NULL) { + if (length_restriction->get_is_range()) { + length_restriction->get_lower_value()->chk_class_member(p_class); + if (length_restriction->get_upper_value() != NULL) { + length_restriction->get_upper_value()->chk_class_member(p_class); + } + } + else { + length_restriction->get_single_value()->chk_class_member(p_class); + } + } + } + void Template::set_gen_class_defpar_prefix() { switch (templatetype) { @@ -6538,6 +6626,14 @@ compile_time: template_body->chk_ctor_defpar(default_ctor, in_base_call); } + void TemplateInstance::chk_class_member(ClassTypeBody* p_class) + { + if (derived_reference != NULL) { + derived_reference->chk_class_member(p_class); + } + template_body->chk_class_member(p_class); + } + void TemplateInstance::set_gen_class_defpar_prefix() { if (derived_reference != NULL) { diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh index df078083809beefc848094bb381f2b260de9f9b8..c263ebf469abec0fb793c55b58dd38378005d1fb 100644 --- a/compiler2/ttcn3/TtcnTemplate.hh +++ b/compiler2/ttcn3/TtcnTemplate.hh @@ -464,6 +464,7 @@ namespace Ttcn { const Location* usage_loc); void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(ClassTypeBody* p_class); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); @@ -651,6 +652,7 @@ namespace Ttcn { void chk_immutability() const ; void chk_ctor_defpar(bool default_ctor, bool in_base_call); + void chk_class_member(ClassTypeBody* p_class); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc index caa641a515d5405a1e66697a0e563387c0e555cb..03e6ba37e4511687c1b848944ad6d3e56971dfc5 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -3071,7 +3071,7 @@ namespace Ttcn { Reference* p_runs_on_ref, Reference* p_mtc_ref, Reference* p_system_ref, Definitions* p_members, StatementBlock* p_finally_block) : Scope(), Location(), class_id(p_class_id), my_def(NULL), external(p_external), final(p_final), - abstract(p_abstract), trait(p_trait), built_in(FALSE), base_type(NULL), base_traits(p_base_types), base_class(NULL), + abstract(p_abstract), trait(p_trait), built_in(FALSE), base_type(NULL), base_class(NULL), base_traits(p_base_types), runs_on_ref(p_runs_on_ref), runs_on_type(NULL), mtc_ref(p_mtc_ref), mtc_type(NULL), system_ref(p_system_ref), system_type(NULL), members(p_members), finally_block(p_finally_block), constructor(NULL), checked(false), diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn index 1edc31f3d0732465de74ee1710c1a8dba7d6eeb8..c48065cd1912b739388315f0b868190f84c5513b 100644 --- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn +++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn @@ -806,6 +806,11 @@ type class C64 extends C63 { //^In type definition// : C63(p1, p2, p3, p4) { } } +type class C65 { //^In type definition// + create(inout integer p1, //^In constructor definition// //^In formal parameter list// //^In parameter// //A constructor cannot have `inout' value parameter// + out charstring p2) { } //^In parameter// //A constructor cannot have `out' value parameter// +} + control { //^In control part// var C11 x := C11.create; //^In variable definition// //A definition without `runs on' clause cannot create a value of class type `@oop_SE.C11', which runs on component type `@oop_SE.CT_RunsOn'// //Cannot create value of class type `@oop_SE.C11', which has an `mtc' clause, in the control part.// //Cannot create value of class type `@oop_SE.C11', which has a `system' clause, in the control part.// diff --git a/regression_test/oop/oop2.ttcn b/regression_test/oop/oop2.ttcn index 0fa1f1ec08d7aac3c414b56094c1e9e95d310368..34ecdba332e4113668e330f6a6305d842dee6e49 100644 --- a/regression_test/oop/oop2.ttcn +++ b/regression_test/oop/oop2.ttcn @@ -214,12 +214,12 @@ testcase tc_member_init_rearrange() runs on CT { type class C6 { private const integer c1 := 2; - private const charstring c2 := "x"; - /* protected */ var template Rec vt1 := { num := t1, str := int2str(c1) & c2 }; + private const Rec c2 := { 4, "x" }; + /* protected */ var template Rec vt1 := { num := t1, str := int2str(c1) & c2.str }; private template integer t1 := (0..100); // default constructor: - // create(template Rec vt1 := { num := t1, str := int2str(c1) & c2 }) { + // create(template Rec vt1 := { num := t1, str := int2str(c1) & c2.str }) { // this.vt1 = vt1; // } @@ -274,6 +274,30 @@ testcase tc_base_call_with_default_value_parameter() runs on CT { setverdict(pass); } +const charstring c_c8_exp := "abc"; + +type class C8 { + private var Rec v1 := { 10, "x" }; + private var template integer vt1 := (0 .. v1.num); + create(charstring v1) { + if (v1 != c_c8_exp) { + setverdict(fail, "v1 (parameter): ", v1); + } + if (this.v1 != { 10, "x" }) { + setverdict(fail, "this.v1: ", this.v1); + } + var template integer vt1_exp := (0 .. 10); + if (log2str(vt1) != log2str(vt1_exp)) { + setverdict(fail, "vt1: ", vt1); + } + } +} + +testcase tc_constructor_param_name_clash() runs on CT { + var C8 x := C8.create(c_c8_exp); // the actual tests are in the constructor + setverdict(pass); +} + control { execute(tc_constructor_default()); execute(tc_constructor_init()); @@ -282,6 +306,7 @@ control { execute(tc_member_init_rearrange()); execute(tc_references_in_default_values()); execute(tc_base_call_with_default_value_parameter()); + execute(tc_constructor_param_name_clash()); } }