diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index ed78fdc914f6bb4c64e85c4189ebddeac1971751..ba979174e45fdd2b9125abf13717aaf53037d55b 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -11498,7 +11498,7 @@ namespace Ttcn { ActualPar::ActualPar(Value *v) : Node(), selection(AP_VALUE), my_scope(0), gen_restriction_check(TR_NONE), - gen_post_restriction_check(TR_NONE) + gen_post_restriction_check(TR_NONE), is_base_ctor_param(false) { if (!v) FATAL_ERROR("ActualPar::ActualPar()"); val = v; @@ -11506,7 +11506,8 @@ namespace Ttcn { ActualPar::ActualPar(TemplateInstance *t) : Node(), selection(AP_TEMPLATE), my_scope(0), - gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE) + gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE), + is_base_ctor_param(false) { if (!t) FATAL_ERROR("ActualPar::ActualPar()"); temp = t; @@ -11514,7 +11515,7 @@ namespace Ttcn { ActualPar::ActualPar(Reference *r) : Node(), selection(AP_REF), my_scope(0), gen_restriction_check(TR_NONE), - gen_post_restriction_check(TR_NONE) + gen_post_restriction_check(TR_NONE), is_base_ctor_param(false) { if (!r) FATAL_ERROR("ActualPar::ActualPar()"); ref = r; @@ -11522,7 +11523,8 @@ namespace Ttcn { ActualPar::ActualPar(ActualPar *a) : Node(), selection(AP_DEFAULT), my_scope(0), - gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE) + gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE), + is_base_ctor_param(false) { if (!a) FATAL_ERROR("ActualPar::ActualPar()"); act = a; @@ -11531,7 +11533,8 @@ namespace Ttcn { ActualPar::ActualPar(const ActualPar& p) : Node(), selection(p.selection), my_scope(p.my_scope), gen_restriction_check(p.gen_restriction_check), - gen_post_restriction_check(p.gen_post_restriction_check) + gen_post_restriction_check(p.gen_post_restriction_check), + is_base_ctor_param(false) { switch(selection) { case AP_ERROR: @@ -11809,7 +11812,7 @@ namespace Ttcn { } } - void ActualPar::set_gen_class_base_call_postfix() + void ActualPar::set_gen_class_base_call_postfix(FormalPar* formal_par) { switch (selection) { case AP_VALUE: @@ -11824,6 +11827,9 @@ namespace Ttcn { default: break; } + is_base_ctor_param = formal_par != NULL && + formal_par->get_my_parlist()->get_my_def() != NULL && + formal_par->get_my_parlist()->get_my_def()->get_asstype() == Definition::A_CONSTRUCTOR; } void ActualPar::generate_code(expression_struct *expr, bool copy_needed, @@ -11844,18 +11850,49 @@ namespace Ttcn { // constructor call. TODO: Reduce the number of temporaries created. const string& tmp_id = val->get_temporary_id(); const char *tmp_id_str = tmp_id.c_str(); - expr->preamble = mputprintf(expr->preamble, "%s %s;\n", - val->get_my_governor()->get_genname_value(my_scope).c_str(), - tmp_id_str); + if (is_base_ctor_param) { + expr->preamble = mputprintf(expr->preamble, + "%s %s()\n" + "{\n" + "%s ret_val;\n", + val->get_my_governor()->get_genname_value(my_scope).c_str(), + tmp_id_str, val->get_my_governor()->get_genname_value(my_scope).c_str()); + } + else { + expr->preamble = mputprintf(expr->preamble, "%s %s;\n", + val->get_my_governor()->get_genname_value(my_scope).c_str(), + tmp_id_str); + } expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble, - tmp_id_str, val); - expr_expr = mputstr(expr_expr, tmp_id_str); + is_base_ctor_param ? "ret_val" : tmp_id_str, val); + if (is_base_ctor_param) { + expr->preamble = mputstr(expr->preamble, + "return ret_val;\n" + "}\n\n"); + } + expr_expr = mputprintf(expr_expr, "%s%s", tmp_id_str, is_base_ctor_param ? "()" : ""); } else { expression_struct val_expr; Code::init_expr(&val_expr); val->generate_code_expr(&val_expr); if (val_expr.preamble != NULL) { - expr->preamble = mputstr(expr->preamble, val_expr.preamble); + if (is_base_ctor_param) { + const string& tmp_id = val->get_temporary_id(); + const char *tmp_id_str = tmp_id.c_str(); + expr->preamble = mputprintf(expr->preamble, + "%s %s()\n" + "{\n" + "%s" + "return %s;\n" + "}\n\n", + val->get_my_governor()->get_genname_value(my_scope).c_str(), + tmp_id_str, val_expr.preamble, val_expr.expr); + Free(val_expr.expr); + val_expr.expr = mprintf("%s()", tmp_id_str); + } + else { + expr->preamble = mputstr(expr->preamble, val_expr.preamble); + } } if (val_expr.postamble == NULL) { if (formal_par != NULL && @@ -11899,22 +11936,54 @@ namespace Ttcn { if (use_runtime_2 && TypeConv::needs_conv_refd(temp->get_Template())) { const string& tmp_id = temp->get_Template()->get_temporary_id(); const char *tmp_id_str = tmp_id.c_str(); - expr->preamble = mputprintf(expr->preamble, "%s %s;\n", - temp->get_Template()->get_my_governor() - ->get_genname_template(my_scope).c_str(), tmp_id_str); + if (is_base_ctor_param) { + expr->preamble = mputprintf(expr->preamble, + "%s %s()\n" + "{\n" + "%s ret_val;\n", + temp->get_Template()->get_my_governor()->get_genname_template(my_scope).c_str(), + tmp_id_str, temp->get_Template()->get_my_governor() + ->get_genname_template(my_scope).c_str()); + } + else { + expr->preamble = mputprintf(expr->preamble, "%s %s;\n", + temp->get_Template()->get_my_governor() + ->get_genname_template(my_scope).c_str(), tmp_id_str); + } expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble, tmp_id_str, temp->get_Template()); // Not incorporated into gen_conv_code() yet. if (gen_restriction_check != TR_NONE) expr->preamble = Template::generate_restriction_check_code( expr->preamble, tmp_id_str, gen_restriction_check); - expr_expr = mputstr(expr_expr, tmp_id_str); + if (is_base_ctor_param) { + expr->preamble = mputstr(expr->preamble, + "return ret_val;\n" + "}\n\n"); + } + expr_expr = mputprintf(expr_expr, "%s%s", tmp_id_str, is_base_ctor_param ? "()" : ""); } else { expression_struct temp_expr; Code::init_expr(&temp_expr); temp->generate_code(&temp_expr, gen_restriction_check); if (temp_expr.preamble != NULL) { - expr->preamble = mputstr(expr->preamble, temp_expr.preamble); + if (is_base_ctor_param) { + const string& tmp_id = temp->get_Template()->get_temporary_id(); + const char *tmp_id_str = tmp_id.c_str(); + expr->preamble = mputprintf(expr->preamble, + "%s %s()\n" + "{\n" + "%s" + "return %s;\n" + "}\n\n", + temp->get_Template()->get_my_governor()->get_genname_template(my_scope).c_str(), + tmp_id_str, temp_expr.preamble, temp_expr.expr); + Free(temp_expr.expr); + temp_expr.expr = mprintf("%s()", tmp_id_str); + } + else { + expr->preamble = mputstr(expr->preamble, temp_expr.preamble); + } } if (temp_expr.postamble == NULL) { expr_expr = mputstr(expr_expr, temp_expr.expr); @@ -12298,11 +12367,11 @@ namespace Ttcn { } } - void ActualParList::set_gen_class_base_call_postfix() + void ActualParList::set_gen_class_base_call_postfix(FormalParList* fp_list) { size_t nof_pars = params.size(); for (size_t i = 0; i < nof_pars; i++) { - params[i]->set_gen_class_base_call_postfix(); + params[i]->set_gen_class_base_call_postfix(fp_list != NULL ? fp_list->get_fp_byIndex(i) : NULL); } } diff --git a/compiler2/ttcn3/AST_ttcn3.hh b/compiler2/ttcn3/AST_ttcn3.hh index 2700fc01d744c89b69a9dc3d9e5e80fd91cc475f..e0500a1d7e800abb9d19707dc172cdf8c3b49cbd 100644 --- a/compiler2/ttcn3/AST_ttcn3.hh +++ b/compiler2/ttcn3/AST_ttcn3.hh @@ -90,6 +90,8 @@ namespace Ttcn { /** if this is an actual template parameter of an external function add * runtime checks for out and inout parameters after the call */ template_restriction_t gen_post_restriction_check; + /** True if this is one of the base-constructor call's actual parameters. */ + bool is_base_ctor_param; private: /** Copy constructor */ ActualPar(const ActualPar& p); @@ -99,7 +101,7 @@ namespace Ttcn { /// Constructor for an erroneous object (fallback) ActualPar() : Node(), selection(AP_ERROR), my_scope(0), - gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE) {} + gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE), is_base_ctor_param(false) {} /// Actual par for an in value parameter ActualPar(Value *v); /// Actual par for an in template parameter @@ -131,7 +133,7 @@ namespace Ttcn { void set_code_section(GovernedSimple::code_section_t p_code_section); void set_gen_class_defpar_prefix(); - void set_gen_class_base_call_postfix(); + void set_gen_class_base_call_postfix(FormalPar* formal_par = NULL); /** Generates the C++ equivalent of \a this into \a expr. * Flag \a copy_needed indicates whether to add an extra copy constructor @@ -180,7 +182,7 @@ namespace Ttcn { void chk_class_member(ClassTypeBody* p_class); void set_gen_class_defpar_prefix(); - void set_gen_class_base_call_postfix(); + void set_gen_class_base_call_postfix(FormalParList* fp_list = NULL); /** Generates the C++ equivalent of the actual parameter list without * considering any aliasing between variables and 'in' parameters. */ void generate_code_noalias(expression_struct *expr, FormalParList *p_fpl); diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc index 16dd95b810fb3c63320af510dc2fc68b765db464..eb62de86ed78d9d50283eeac10fa92d5a8cd6c3e 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -4267,9 +4267,15 @@ namespace Ttcn { if (base_call != NULL) { ActualParList* ap_list = base_call->get_parlist(); if (ap_list != NULL) { - ap_list->set_gen_class_base_call_postfix(); + Def_Constructor* base_ctor = base_class->get_constructor(); + ap_list->set_gen_class_base_call_postfix( + base_ctor != NULL ? base_ctor->get_FormalParList() : NULL); } base_call->generate_code(&base_call_expr); + if (base_call_expr.preamble != NULL) { + local_struct->source.methods = mputstr(local_struct->source.methods, + base_call_expr.preamble); + } } // generate code for the base call first, so the formal parameter list // knows which parameters are used and which aren't diff --git a/regression_test/oop/oop2.ttcn b/regression_test/oop/oop2.ttcn index 34ecdba332e4113668e330f6a6305d842dee6e49..cae8b6031e1c767211ad749ddb3f6294f64536e1 100644 --- a/regression_test/oop/oop2.ttcn +++ b/regression_test/oop/oop2.ttcn @@ -298,6 +298,37 @@ testcase tc_constructor_param_name_clash() runs on CT { setverdict(pass); } + +type record of integer IntList; + +type class C9 { + create(Rec p1, template IntList p2) { + if (p1 != { num := 3, str := "abc" }) { + setverdict(fail, "p1: ", p1); + } + template IntList p2_exp := { 1, (1 .. 10), ? }; + if (log2str(p2) != log2str(p2_exp)) { + setverdict(fail, "p2: ", p2); + } + } +} + +template integer t_global := (1..10); + +function f_int(IntList p) return integer { + return sizeof(p); +} + +type class C10 extends C9 { + create(): C9( { f_int({ 1, 2, 3 }), "abc" }, { 1, t_global, ? } ) { } +} + +testcase tc_base_call_with_structure_parameter() runs on CT { + var C10 x := C10.create(); // the actual tests are in the constructor + setverdict(pass); +} + + control { execute(tc_constructor_default()); execute(tc_constructor_init()); @@ -307,6 +338,7 @@ control { execute(tc_references_in_default_values()); execute(tc_base_call_with_default_value_parameter()); execute(tc_constructor_param_name_clash()); + execute(tc_base_call_with_structure_parameter()); } }