diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 714a4728080c4239aeeb8cc3a74770e0b50e4ed0..bd2cf17e4b1d53de9c99e8c653288f74262dc37d 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -16928,15 +16928,15 @@ void Value::chk_expr_operand_execute_refd(Value *v1, return in_brackets; } - void Value::chk_ctor_defpar() + void Value::chk_ctor_defpar(bool default_ctor, bool in_base_call) { switch (valuetype) { case V_REFD: { Ttcn::Reference* ttcn_ref = dynamic_cast<Ttcn::Reference*>(u.ref.ref); if (ttcn_ref != NULL) { - ttcn_ref->chk_ctor_defpar(); + ttcn_ref->chk_ctor_defpar(default_ctor, in_base_call); if (ttcn_ref->has_parameters()) { - ttcn_ref->get_parlist()->chk_ctor_defpar(); + ttcn_ref->get_parlist()->chk_ctor_defpar(default_ctor, in_base_call); } } break; } @@ -16983,31 +16983,31 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case OPTYPE_GET_STRINGENCODING: case OPTYPE_REMOVE_BOM: case OPTYPE_DECODE_BASE64: - u.expr.v1->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_DECODE: { if (u.expr.r1->has_parameters()) { - u.expr.r1->get_parlist()->chk_ctor_defpar(); + u.expr.r1->get_parlist()->chk_ctor_defpar(default_ctor, in_base_call); } else { - u.expr.r1->chk_ctor_defpar(); + u.expr.r1->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.r2->has_parameters()) { - u.expr.r2->get_parlist()->chk_ctor_defpar(); + u.expr.r2->get_parlist()->chk_ctor_defpar(default_ctor, in_base_call); } else { - u.expr.r2->chk_ctor_defpar(); + u.expr.r2->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v3 != NULL) { - u.expr.v3->chk_ctor_defpar(); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v4 != NULL) { - u.expr.v4->chk_ctor_defpar(); + u.expr.v4->chk_ctor_defpar(default_ctor, in_base_call); } break; } case OPTYPE_HOSTID: if (u.expr.v1 != NULL) { - u.expr.v1->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); } break; case OPTYPE_ADD: @@ -17036,53 +17036,53 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case OPTYPE_INT2BIT: case OPTYPE_INT2HEX: case OPTYPE_INT2OCT: - u.expr.v1->chk_ctor_defpar(); - u.expr.v2->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_UNICHAR2OCT: // v1 [v2] case OPTYPE_OCT2UNICHAR: case OPTYPE_ENCODE_BASE64: - u.expr.v1->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); if (u.expr.v2 != NULL) { - u.expr.v2->chk_ctor_defpar(); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); } break; case OPTYPE_SUBSTR: case OPTYPE_ENCODE: - u.expr.ti1->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); if (u.expr.v2 != NULL) { - u.expr.v2->chk_ctor_defpar(); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v3 != NULL) { - u.expr.v3->chk_ctor_defpar(); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); } break; case OPTYPE_REGEXP: - u.expr.ti1->chk_ctor_defpar(); - u.expr.t2->chk_ctor_defpar(); - u.expr.v3->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.t2->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_DECOMP: - u.expr.v1->chk_ctor_defpar(); - u.expr.v2->chk_ctor_defpar(); - u.expr.v3->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_REPLACE: - u.expr.ti1->chk_ctor_defpar(); - u.expr.v2->chk_ctor_defpar(); - u.expr.v3->chk_ctor_defpar(); - u.expr.ti4->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.ti4->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_ISTEMPLATEKIND: - u.expr.ti1->chk_ctor_defpar(); - u.expr.v2->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); 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_ctor_defpar(); + subref->get_val()->chk_ctor_defpar(default_ctor, in_base_call); } } } @@ -17091,50 +17091,50 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case OPTYPE_SIZEOF: case OPTYPE_ISPRESENT: case OPTYPE_TTCN2STRING: - u.expr.ti1->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_ENCVALUE_UNICHAR: - u.expr.ti1->chk_ctor_defpar(); + u.expr.ti1->chk_ctor_defpar(default_ctor, in_base_call); if (u.expr.v2 != NULL) { - u.expr.v2->chk_ctor_defpar(); + u.expr.v2->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v3 != NULL) { - u.expr.v3->chk_ctor_defpar(); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v4 != NULL) { - u.expr.v4->chk_ctor_defpar(); + u.expr.v4->chk_ctor_defpar(default_ctor, in_base_call); } break; case OPTYPE_DECVALUE_UNICHAR: { if (u.expr.r1->has_parameters()) { - u.expr.r1->get_parlist()->chk_ctor_defpar(); + u.expr.r1->get_parlist()->chk_ctor_defpar(default_ctor, in_base_call); } else { - u.expr.r1->chk_ctor_defpar(); + u.expr.r1->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.r2->has_parameters()) { - u.expr.r2->get_parlist()->chk_ctor_defpar(); + u.expr.r2->get_parlist()->chk_ctor_defpar(default_ctor, in_base_call); } else { - u.expr.r2->chk_ctor_defpar(); + u.expr.r2->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v3 != NULL) { - u.expr.v3->chk_ctor_defpar(); + u.expr.v3->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v4 != NULL) { - u.expr.v4->chk_ctor_defpar(); + u.expr.v4->chk_ctor_defpar(default_ctor, in_base_call); } if (u.expr.v5 != NULL) { - u.expr.v5->chk_ctor_defpar(); + u.expr.v5->chk_ctor_defpar(default_ctor, in_base_call); } break; } case OPTYPE_ISCHOSEN_T: case OPTYPE_ISVALUE: - u.expr.t1->chk_ctor_defpar(); + u.expr.t1->chk_ctor_defpar(default_ctor, in_base_call); break; case OPTYPE_MATCH: - u.expr.v1->chk_ctor_defpar(); - u.expr.t2->chk_ctor_defpar(); + u.expr.v1->chk_ctor_defpar(default_ctor, in_base_call); + u.expr.t2->chk_ctor_defpar(default_ctor, in_base_call); break; default: break; diff --git a/compiler2/Value.hh b/compiler2/Value.hh index 2ba66d0ce6fa170e4db26adfc61d7a2063543864..5ef9c3316c51ebf02976a72fa41437828c6fa9a2 100644 --- a/compiler2/Value.hh +++ b/compiler2/Value.hh @@ -1091,7 +1091,7 @@ namespace Common { void set_is_in_brackets(); bool get_is_in_brackets() const; - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); 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 ef2edc3d80f6910edbb343eff2ee5bb8ade7a93c..5dd63417973e52a81bdfa9a29f88e2ad961b18e1 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1100,30 +1100,69 @@ namespace Ttcn { t_ass->get_description().c_str()); } - void Reference::chk_ctor_defpar() + void Reference::chk_ctor_defpar(bool default_ctor, bool in_base_call) { Common::Assignment* ass = get_refd_assignment_last(); + bool is_var = false; if (ass->get_my_scope()->is_class_scope()) { switch (ass->get_asstype()) { case Common::Assignment::A_VAR: - case Common::Assignment::A_VAR_TEMPLATE: - error("Constructor default parameter cannot contain reference to " - "%svariable class member `%s'", - ass->get_asstype() == Common::Assignment::A_VAR_TEMPLATE ? "template " : "", - ass->get_id().get_dispname().c_str()); - break; + is_var = true; + if (default_ctor) { + error("Implicit constructor default parameter cannot contain reference to " + "variable class member `%s'", + ass->get_id().get_dispname().c_str()); + break; + } + // no break case Common::Assignment::A_CONST: - if (ass->get_Value() == NULL) { + if (in_base_call) { + error("Super-constructor call cannot contain reference to %s class member `%s'", + is_var ? "variable" : "constant", ass->get_id().get_dispname().c_str()); + } + else if (ass->get_Value() == NULL) { error("Constructor default parameter cannot contain reference to " - "constant class member `%s', which has no initial value", - ass->get_id().get_dispname().c_str()); + "%s class member `%s', which has no initial value", + is_var ? "variable" : "constant", ass->get_id().get_dispname().c_str()); } break; + case Common::Assignment::A_VAR_TEMPLATE: + is_var = true; + if (default_ctor) { + error("Implicit constructor default parameter cannot contain reference to " + "template variable class member `%s'", + ass->get_id().get_dispname().c_str()); + break; + } + // no break case Common::Assignment::A_TEMPLATE: - if (ass->get_Template() == NULL) { + if (in_base_call) { + error("Super-constructor call cannot contain reference to template%s class member `%s'", + is_var ? " variable" : "", ass->get_id().get_dispname().c_str()); + } + else if (ass->get_Template() == NULL) { error("Constructor default parameter cannot contain reference to " - "template class member `%s', which has no initial value", - ass->get_id().get_dispname().c_str()); + "template%s class member `%s', which has no initial value", + is_var ? " variable" : "", ass->get_id().get_dispname().c_str()); + } + break; + case Common::Assignment::A_PAR_VAL: + 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: + case Common::Assignment::A_PAR_PORT: + if (in_base_call) { + FormalPar* fp = dynamic_cast<FormalPar*>(ass); + if (fp == NULL) { + FATAL_ERROR("Reference::chk_ctor_defpar"); + } + if (fp->has_defval()) { + fp->get_defval()->chk_ctor_defpar(default_ctor, in_base_call); + } } break; default: @@ -9351,15 +9390,16 @@ namespace Ttcn { Error_Context cntxt(this, "In constructor definition"); + ClassTypeBody* my_class = my_scope->get_scope_class(); + fp_list->chk(asstype); for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) { FormalPar* fp = fp_list->get_fp_byIndex(i); if (fp->has_defval()) { - fp->get_defval()->chk_ctor_defpar(); + fp->get_defval()->chk_ctor_defpar(my_class->has_default_constructor(), false); } } - ClassTypeBody* my_class = my_scope->get_scope_class(); ClassTypeBody* base_class = my_class->get_base_class(); if (base_call != NULL) { Error_Context cntxt2(this, "In super-constructor call"); @@ -9382,6 +9422,9 @@ namespace Ttcn { my_class->get_base_type()->get_typename().c_str(), base_call_class->get_my_def()->get_Type()->get_typename().c_str()); } + else if (base_call->has_parameters()) { + base_call->get_parlist()->chk_ctor_defpar(my_class->has_default_constructor(), true); + } } } } @@ -9635,8 +9678,9 @@ namespace Ttcn { if (default_value) { Error_Context cntxt(default_value, "In default value"); - Scope* scope = my_parlist->get_my_def()->get_my_scope(); - if (scope->is_class_scope()) { + Definition* def = my_parlist->get_my_def(); + Scope* scope = def != NULL ? def->get_my_scope() : NULL; + if (scope != NULL && scope->is_class_scope()) { switch (asstype) { case A_PAR_VAL_IN: case A_PAR_TEMPL_IN: @@ -10324,8 +10368,9 @@ namespace Ttcn { Common::Type::defpar_wapper_t FormalPar::get_defpar_wrapper() const { - if (defval.ap != NULL && - my_parlist->get_my_def()->get_my_scope()->is_class_scope()) { + Definition* def = my_parlist->get_my_def(); + if (defval.ap != NULL && def != NULL && + def->get_my_scope()->is_class_scope()) { switch (asstype) { case A_PAR_VAL_IN: case A_PAR_TEMPL_IN: @@ -10346,9 +10391,12 @@ namespace Ttcn { char* FormalPar::generate_code_defval(char* str) { - if (!defval.ap || defval_generated || !usage_found) return str; + if (!defval.ap || defval_generated) return str; defval_generated = true; Common::Type::defpar_wapper_t defpar_wrapper = get_defpar_wrapper(); + if (!usage_found && defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) { + return str; + } switch (defval.ap->get_selection()) { case ActualPar::AP_VALUE: { Value *val = defval.ap->get_Value(); @@ -10433,8 +10481,9 @@ namespace Ttcn { void FormalPar::generate_code_defval(output_struct *target, bool) { if (!defval.ap) return; - Scope* scope = my_parlist->get_my_def()->get_my_scope(); - bool defpar_wrapper = defval.ap != NULL && scope->is_class_scope(); + Definition* def = my_parlist->get_my_def(); + Scope* scope = def != NULL ? def->get_my_scope() : NULL; + bool defpar_wrapper = defval.ap != NULL && scope != NULL && scope->is_class_scope(); switch (defval.ap->get_selection()) { case ActualPar::AP_VALUE: { Value *val = defval.ap->get_Value(); @@ -10470,8 +10519,9 @@ namespace Ttcn { char *FormalPar::generate_code_fpar(char *str, bool display_unused /* = false */) { - Scope* scope = my_parlist->get_my_def()->get_my_scope(); - bool defpar_wrapper = defval.ap != NULL && scope->is_class_scope(); + Definition* def = my_parlist->get_my_def(); + Scope* scope = def != NULL ? def->get_my_scope() : NULL; + bool defpar_wrapper = defval.ap != NULL && scope != NULL && scope->is_class_scope(); // the name of the parameter should not be displayed if the parameter is not // used (to avoid a compiler warning) bool display_name = (usage_found || display_unused || debugger_active || @@ -11572,17 +11622,17 @@ namespace Ttcn { } } - void ActualPar::chk_ctor_defpar() + void ActualPar::chk_ctor_defpar(bool default_ctor, bool in_base_call) { switch (selection) { case AP_VALUE: - val->chk_ctor_defpar(); + val->chk_ctor_defpar(default_ctor, in_base_call); break; case AP_TEMPLATE: - temp->chk_ctor_defpar(); + temp->chk_ctor_defpar(default_ctor, in_base_call); break; case AP_REF: - ref->chk_ctor_defpar(); + ref->chk_ctor_defpar(default_ctor, in_base_call); break; default: break; @@ -12135,11 +12185,11 @@ namespace Ttcn { } // next } - void ActualParList::chk_ctor_defpar() + void ActualParList::chk_ctor_defpar(bool default_ctor, bool in_base_call) { size_t nof_pars = params.size(); for (size_t i = 0; i < nof_pars; i++) { - params[i]->chk_ctor_defpar(); + params[i]->chk_ctor_defpar(default_ctor, in_base_call); } } diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index 9f62540bc352374a956fff332fab10d273cd72a3..5311aa154315be624a0e0ee24f009d8c33d6bf24 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -122,7 +122,7 @@ namespace Ttcn { /** Checks the embedded recursions within the value or template instance. */ void chk_recursions(ReferenceChain& refch); - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); /** Returns whether the actual parameter can be represented by an in-line * C++ expression. */ @@ -175,7 +175,7 @@ namespace Ttcn { void chk_immutability(); - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); @@ -411,7 +411,7 @@ namespace Ttcn { * Returns the type of the component if so or NULL in case of error. */ Type *chk_comptype_ref(); bool chk_activate_argument(); - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); 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); diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index eb2ed511e687524a88b4531e6829b754603d9534..5fb1d9b36c711d9f81732b5958d0b3e339d58e4e 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -3749,24 +3749,24 @@ end: return needs_runtime_check; } - void Template::chk_ctor_defpar() + void Template::chk_ctor_defpar(bool default_ctor, bool in_base_call) { switch (templatetype) { case SPECIFIC_VALUE: - u.specific_value->chk_ctor_defpar(); + u.specific_value->chk_ctor_defpar(default_ctor, in_base_call); break; case TEMPLATE_REFD: - u.ref.ref->chk_ctor_defpar(); + u.ref.ref->chk_ctor_defpar(default_ctor, in_base_call); 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_ctor_defpar(); + u.ref.ref->get_parlist()->get_par(i)->chk_ctor_defpar(default_ctor, in_base_call); } break; case TEMPLATE_INVOKE: - u.invoke.v->chk_ctor_defpar(); + u.invoke.v->chk_ctor_defpar(default_ctor, in_base_call); 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_ctor_defpar(); + u.invoke.ap_list->get_par(i)->chk_ctor_defpar(default_ctor, in_base_call); } break; case TEMPLATE_LIST: @@ -3777,47 +3777,47 @@ end: 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_ctor_defpar(); + u.templates->get_t_byIndex(i)->chk_ctor_defpar(default_ctor, in_base_call); } 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_ctor_defpar(); + u.named_templates->get_nt_byIndex(i)->get_template()->chk_ctor_defpar(default_ctor, in_base_call); } 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_ctor_defpar(); + u.indexed_templates->get_it_byIndex(i)->get_template()->chk_ctor_defpar(default_ctor, in_base_call); } break; case VALUE_RANGE: if (u.value_range->get_min_v() != NULL) { - u.value_range->get_min_v()->chk_ctor_defpar(); + u.value_range->get_min_v()->chk_ctor_defpar(default_ctor, in_base_call); } if (u.value_range->get_max_v() != NULL) { - u.value_range->get_max_v()->chk_ctor_defpar(); + u.value_range->get_max_v()->chk_ctor_defpar(default_ctor, in_base_call); } break; case CSTR_PATTERN: case USTR_PATTERN: - //u.pstring->chk_ctor_defpar(); todo + //u.pstring->chk_ctor_defpar(default_ctor, in_base_call); todo break; case DECODE_MATCH: if (u.dec_match.str_enc != NULL) { - u.dec_match.str_enc->chk_ctor_defpar(); + u.dec_match.str_enc->chk_ctor_defpar(default_ctor, in_base_call); } - u.dec_match.target->chk_ctor_defpar(); + u.dec_match.target->chk_ctor_defpar(default_ctor, in_base_call); break; case TEMPLATE_CONCAT: if (!use_runtime_2) { - FATAL_ERROR("Template::chk_ctor_defpar()"); + FATAL_ERROR("Template::chk_ctor_defpar(bool default_ctor, bool in_base_call)"); } - u.concat.op1->chk_ctor_defpar(); - u.concat.op2->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); break; case IMPLICATION_MATCH: - u.implication.precondition->chk_ctor_defpar(); - u.implication.implied_template->chk_ctor_defpar(); + u.implication.precondition->chk_ctor_defpar(default_ctor, in_base_call); + u.implication.implied_template->chk_ctor_defpar(default_ctor, in_base_call); break; case DYNAMIC_MATCH: break; @@ -3826,13 +3826,13 @@ end: } if (length_restriction != NULL) { if (length_restriction->get_is_range()) { - length_restriction->get_lower_value()->chk_ctor_defpar(); + length_restriction->get_lower_value()->chk_ctor_defpar(default_ctor, in_base_call); if (length_restriction->get_upper_value() != NULL) { - length_restriction->get_upper_value()->chk_ctor_defpar(); + length_restriction->get_upper_value()->chk_ctor_defpar(default_ctor, in_base_call); } } else { - length_restriction->get_single_value()->chk_ctor_defpar(); + length_restriction->get_single_value()->chk_ctor_defpar(default_ctor, in_base_call); } } } @@ -6530,12 +6530,12 @@ compile_time: template_body->chk_immutability(); } - void TemplateInstance::chk_ctor_defpar() + void TemplateInstance::chk_ctor_defpar(bool default_ctor, bool in_base_call) { if (derived_reference != NULL) { - derived_reference->chk_ctor_defpar(); + derived_reference->chk_ctor_defpar(default_ctor, in_base_call); } - template_body->chk_ctor_defpar(); + template_body->chk_ctor_defpar(default_ctor, in_base_call); } void TemplateInstance::set_gen_class_defpar_prefix() diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh index 054c1b7689071c939591c89399b7a9f43dc11334..df078083809beefc848094bb381f2b260de9f9b8 100644 --- a/compiler2/ttcn3/TtcnTemplate.hh +++ b/compiler2/ttcn3/TtcnTemplate.hh @@ -463,7 +463,7 @@ namespace Ttcn { template_restriction_t template_restriction, const Location* usage_loc); - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); void set_gen_class_defpar_prefix(); void set_gen_class_base_call_postfix(); @@ -650,7 +650,7 @@ namespace Ttcn { void chk_immutability() const ; - void chk_ctor_defpar(); + void chk_ctor_defpar(bool default_ctor, bool in_base_call); 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 f9b3c4bc4229b7543ec3022d057e0a790f8fbf38..caa641a515d5405a1e66697a0e563387c0e555cb 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -3933,8 +3933,8 @@ namespace Ttcn { constructor = new Def_Constructor(fp_list, base_call, block); constructor->set_my_scope(this); constructor->set_fullname(get_fullname() + ".<default_constructor>"); - constructor->chk(); default_constructor = true; + constructor->chk(); } if (constructor != NULL && !default_constructor && !name_clash && !trait) { diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh index c9a46151e441816ba4368f7c2e20ebeee75cd0ad..1321e00cb942acf8270041081e7a418d293b2f3f 100644 --- a/compiler2/ttcn3/Ttcnstuff.hh +++ b/compiler2/ttcn3/Ttcnstuff.hh @@ -799,6 +799,7 @@ public: boolean is_abstract() const { return abstract; } boolean is_trait() const { return trait; } boolean is_external() const { return external; } + bool has_default_constructor() const { return default_constructor; } void set_fullname(const string& p_fullname); void set_my_scope(Scope* p_scope); diff --git a/function_test/Semantic_Analyser/oop/oop_SE.ttcn b/function_test/Semantic_Analyser/oop/oop_SE.ttcn index e2419145229b9a3150a2295edbbafffc7632ce1a..1edc31f3d0732465de74ee1710c1a8dba7d6eeb8 100644 --- a/function_test/Semantic_Analyser/oop/oop_SE.ttcn +++ b/function_test/Semantic_Analyser/oop/oop_SE.ttcn @@ -768,19 +768,44 @@ type class C60 { //^In type definition// } type class C61 { //^In type definition// - private var integer v := 1; + private var integer v; private const integer c; - create(template integer p1 := v, //^In constructor definition// //Constructor default parameter cannot contain reference to variable class member `v'// + create(template integer p1 := v, //^In constructor definition// //Constructor default parameter cannot contain reference to variable class member `v', which has no initial value// integer p2 := c) { } //Constructor default parameter cannot contain reference to constant class member `c', which has no initial value// public function f(inout integer p := v) { p := p + 1; } //^In function definition// //^In formal parameter list// //^In parameter// //In default value// //`out' and `inout' parameters of class functions cannot have default values// } type class C62 { //^In type definition// //^In constructor definition// private var template integer vt1 := 1; - private var template Rec vt2 := { vt1, ? }; //Constructor default parameter cannot contain reference to template variable class member `vt1'// + private var template Rec vt2 := { vt1, ? }; //Implicit constructor default parameter cannot contain reference to template variable class member `vt1'// /* default constructor */ } +type class C62_equivalent { //^In type definition// + private var template integer vt1; + private var template Rec vt2; + create(template integer vt1 := 1, template Rec vt2 := { this.vt1, ? }) { //^In constructor definition// //Constructor default parameter cannot contain reference to template variable class member `vt1', which has no initial value// + this.vt1 := vt1; + this.vt2 := vt2; + } +} + +type class C63 { + create(integer p1, template charstring p2, template integer p3, template charstring p4) { } +} + +type class C64 extends C63 { //^In type definition// + private const integer c := 1; + private var charstring v := "a"; + private template integer t := (1..5); + private var template charstring vt := ? length (1..2); + create(integer p1 := c, //^In constructor definition// //^In super-constructor call// //Super-constructor call cannot contain reference to constant class member `c'// + template charstring p2 := v, //Super-constructor call cannot contain reference to variable class member `v'// + template integer p3 := t, //Super-constructor call cannot contain reference to template class member `t'// + template charstring p4 := vt) //Super-constructor call cannot contain reference to template variable class member `vt'// + : C63(p1, p2, p3, p4) { } +} + 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 2d04d42490cf4d80265f80351dbfb92e9673ff01..0fa1f1ec08d7aac3c414b56094c1e9e95d310368 100644 --- a/regression_test/oop/oop2.ttcn +++ b/regression_test/oop/oop2.ttcn @@ -255,13 +255,17 @@ testcase tc_references_in_default_values() runs on CT { template Rec t_def := { num := 1, str := "abc" }; type class C7 extends C6 { - create(template Rec pt := t_def): C6(pt) { - if (log2str(pt) != log2str(t_def)) { - setverdict(fail, "pt: ", pt); + private var integer v1 := 6; + create(template Rec pt1 := t_def, template integer pt2 := v1): C6(pt1) { + if (log2str(pt1) != log2str(t_def)) { + setverdict(fail, "pt1: ", pt1); } if (log2str(vt1) != log2str(t_def)) { setverdict(fail, "vt1: ", vt1); } + if (not isvalue(pt2) or valueof(pt2) != 6) { + setverdict(fail, "pt2: ", pt2); + } } }